diff --git a/About.h b/About.h index 2d4b931..4eee1c9 100644 --- a/About.h +++ b/About.h @@ -27,7 +27,7 @@ class About : public BWindow { public: - About(); + About(); virtual ~About(); private: diff --git a/Buffering.h b/Buffering.h deleted file mode 100644 index 74fe880..0000000 --- a/Buffering.h +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (C) 2017 Kai Niessen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef _BUFFERING_H -#define _BUFFERING_H - - -/** - * Simple class extending an integer to roll over when reaching boundaries - */ -class rotor { -public: - rotor(int size, int initialValue = 0) - { - fMax = size - 1; - fValue = initialValue; - } - - - rotor(rotor& other) - { - fMax = other.fMax; - fValue = other.fValue; - } - - - operator int() { return fValue; } - - - rotor& operator++() - { - if (fValue == fMax) - fValue = 0; - else - fValue++; - - return *this; - } - - - rotor& operator++(int) - { - rotor* tmp = new rotor(*this); - if (fValue == fMax) - fValue = 0; - else - fValue++; - - return *tmp; - } - - - rotor& operator--() - { - if (fValue == 0) - fValue = fMax; - else - fValue--; - - return *this; - } - - - rotor& operator--(int) - { - rotor* tmp = new rotor(*this); - if (fValue == 0) - fValue = fMax; - else - fValue--; - - return *tmp; - } - - - rotor& operator=(int i) - { - fValue = i % (fMax + 1); - } - - - int operator=(rotor& r) - { - return r.fValue; - } - - - int operator-(rotor& other) - { - return (fValue - other.fValue + fMax + 1) % (fMax + 1); - } - - - bool operator==(int i) - { - return fValue == i; - } - - - bool operator!=(int i) - { - return fValue != i; - } - - - bool operator<(int i) - { - return fValue < i; - } - - - bool operator>(int i) - { - return fValue > i; - } - -private: - inline void _SetValue(int i) { fValue = i; } - inline int _GetValue() { return fValue; } - -private: - int fValue; - int fMax; -}; - - -class Buffer : public BLocker { -public: -#define limit(requested, max) (requested = (requested > max) ? max : requested) - - friend class BufferGroup; - - typedef enum {EMPTY, FILLING, FILLED, READING} bufferState; - - - Buffer(size_t size, int index) - : - BLocker("Buffer"), - fIndex(index), - fUsed(0), - fSize(size), - fData((char*)malloc(size)), - fState(EMPTY) - {}; - - ~Buffer() - { - free(fData); - } - - - // Caller handles locking! - inline size_t fillable() { return fSize - fUsed; } - inline char* fillPos() { return fData + fUsed; } - inline bool isFull() { return fUsed == fSize; } - - - inline bufferState state() { return fState; } - - void - setState(bufferState state) - { - if (state == EMPTY) - fUsed = 0; - fState = state; - } - - - inline char* data() { return fData; } - inline size_t readable() { return fUsed; } - - - size_t - fill(char* data, size_t size) - { - if (limit(size, fillable())) { - memcpy(fillPos(), data, size); - fUsed += size; - } - - return size; - } - - - size_t - read(char* data, size_t size) - { - if (limit(size, readable())) - memcpy(data, fData, size); - - return size; - } - -protected: - bufferState fState; - size_t fSize; - size_t fUsed; - char* fData; - int fIndex; -}; - - -typedef Buffer* pBuffer; - - -class BufferGroup : public BLocker { -public: - #define kNone -1 - - typedef bool (*LimitFunc)(void* cookie, float ratio, bool isOk); - - BufferGroup(int numBuffers, size_t size) - : - BLocker("BufferGroup"), - firstEmpty(numBuffers, 0), - firstFilled(numBuffers, kNone), - fNumBuffers(numBuffers) - { - fBuffers = new pBuffer[numBuffers]; - for (int i = 0; i < numBuffers; i++) - fBuffers[i] = new Buffer(size, i); - } - - - ~BufferGroup() - { - for (int i = 0; i < fNumBuffers; i++) - delete fBuffers[i]; - delete fBuffers; - } - - - inline int - IndexOf(Buffer* buffer) - { - return buffer->fIndex; - } - - - Buffer* - RequestForFilling(Buffer* previous = NULL) - { - Buffer* result = NULL; - Lock(); - - if (previous != NULL) { - if (previous->CountLocks() == 0) - previous->Lock(); - previous->fState = Buffer::FILLED; - if (firstFilled == kNone) - firstFilled = IndexOf(previous); - previous->Unlock(); - } - - if (firstEmpty != kNone) - result = fBuffers[firstEmpty++]; - result->fState = Buffer::FILLING; - - if (fBuffers[firstEmpty]->fState != Buffer::EMPTY) - firstEmpty = kNone; - - Unlock(); - return result; - } - - - Buffer* - RequestForReading(Buffer* previous = NULL) - { - Buffer* result = NULL; - Lock(); - - if (previous != NULL) { - if (previous->CountLocks() == 0) - previous->Lock(); - previous->setState(Buffer::EMPTY); - if (firstEmpty == kNone) - firstEmpty = IndexOf(previous); - previous->Unlock(); - } - - if (firstFilled != kNone) - result = fBuffers[firstFilled++]; - result->fState = Buffer::READING; - - if (fBuffers[firstFilled]->fState != Buffer::FILLED) - firstFilled = kNone; - - Unlock(); - - return result; - } - - - void - ReturnBuffer(Buffer* previous) - { - if (previous->CountLocks() == 0) - previous->Lock(); - - if (previous->fState == Buffer::FILLING && previous->fUsed == 0) - previous->setState(Buffer::EMPTY); - - Lock(); - - switch (previous->fState) { - case Buffer::READING: - case Buffer::EMPTY: - { - previous->setState(Buffer::EMPTY); - if (firstEmpty == kNone) - firstEmpty = IndexOf(previous); - break; - } - - case Buffer::FILLING: - previous->fState = Buffer::FILLED; - case Buffer::FILLED: - { - if (firstFilled == kNone) - firstFilled = previous->fIndex; - break; - } - } - - Unlock(); - previous->Unlock(); - } - - - size_t - TotalUsed() - { - size_t result = 0; - for (int i = 0; i < fNumBuffers; i++) - Buffer* b = fBuffers[i]; - if (b->fState == Buffer::FILLED || b->fState == Buffer::FILLING) - result += b->fUsed; - - return result; - } - - - size_t - TotalCapacity() - { - return fNumBuffers * fBuffers[0]->fSize; - } - - - float - FillRatio() - { - if (firstFilled == kNone) - return 0.0f; - else if (firstEmpty == kNone) - return 1.0f; - else - return float(firstEmpty - firstFilled) / fNumBuffers; - } - -private: - rotor fFirstFilled; - rotor fFirstEmpty; - int32 fNumBuffers; - pBuffer* fBuffers; -}; - - -#endif // _BUFFERING_H diff --git a/MainWindow.cpp b/MainWindow.cpp index 01761cc..2eb9347 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -47,7 +47,7 @@ MainWindow::MainWindow() : BWindow(BRect(0, 0, 400, 200), B_TRANSLATE_SYSTEM_NAME("StreamRadio"), - B_DOCUMENT_WINDOW, 0), + B_DOCUMENT_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS), fStationFinder(NULL) { fSettings = &((RadioApp*)be_app)->Settings; @@ -107,6 +107,7 @@ MainWindow::MainWindow() fStatusBar->SetExplicitAlignment( BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_VERTICAL_UNSET)); fStatusBar->SetExplicitMinSize(BSize(10, B_SIZE_UNSET)); + fStatusBar->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); ResizeToPreferred(); CenterOnScreen(); @@ -128,6 +129,7 @@ void MainWindow::MessageReceived(BMessage* message) { switch (message->what) { + case B_SIMPLE_DATA: case B_REFS_RECEIVED: { entry_ref ref; @@ -136,10 +138,10 @@ MainWindow::MessageReceived(BMessage* message) BString result; while (message->FindRef("refs", index++, &ref) == B_OK) { Station* station = Station::Load(ref.name, new BEntry(&ref)); - if ((station = Station::Load(ref.name, new BEntry(&ref)))) { + if (station != NULL) { Station* existingStation = fSettings->Stations->FindItem(station->Name()); - if (existingStation) { + if (existingStation != NULL) { delete station; station = existingStation; stationItem = fStationList->Item(station); @@ -154,6 +156,7 @@ MainWindow::MessageReceived(BMessage* message) } else result.SetToFormat(B_TRANSLATE( "File %s could not be loaded as a station")); + fStatusBar->SetText(result.String()); } @@ -179,7 +182,7 @@ MainWindow::MessageReceived(BMessage* message) char* url; ssize_t numBytes; if (data->FindData( - "text/plain", B_MIME_TYPE, (const void**) &url, &numBytes) + "text/plain", B_MIME_TYPE, (const void**)&url, &numBytes) == B_OK) url[numBytes] = 0; @@ -248,7 +251,7 @@ MainWindow::MessageReceived(BMessage* message) case MSG_ADD_STATION: { Station* station = NULL; - if (message->FindPointer("station", (void**) &station) == B_OK) { + if (message->FindPointer("station", (void**)&station) == B_OK) { fSettings->Stations->AddItem(station); fStationList->Sync(fSettings->Stations); fSettings->Stations->Save(); @@ -265,9 +268,10 @@ MainWindow::MessageReceived(BMessage* message) { int index = fStationList->CurrentSelection(); if (index >= 0) { - fStationPanel->LockLooper(); - fStationPanel->SetStation(fStationList->ItemAt(index)); - fStationPanel->UnlockLooper(); + if (fStationPanel->LockLooper()) { + fStationPanel->SetStation(fStationList->ItemAt(index)); + fStationPanel->UnlockLooper(); + } } break; @@ -276,21 +280,23 @@ MainWindow::MessageReceived(BMessage* message) case MSG_INVOKE_STATION: { int32 stationIndex = message->GetInt32("index", -1); + StationListViewItem* stationItem = fStationList->ItemAt(stationIndex); + if (stationItem != NULL) { + if (fAllowParallelPlayback == false) { + if (fActiveStations.HasItem(stationItem)) { + while (!fActiveStations.IsEmpty()) + _TogglePlay(fActiveStations.LastItem()); + } else { + while (!fActiveStations.IsEmpty()) + _TogglePlay(fActiveStations.LastItem()); - if (fAllowParallelPlayback == false) { - if (fActiveStations.HasItem(stationItem)) { - while (!fActiveStations.IsEmpty()) - _TogglePlay(fActiveStations.LastItem()); - } else { - while (!fActiveStations.IsEmpty()) - _TogglePlay(fActiveStations.LastItem()); - + _TogglePlay(stationItem); + } + } else _TogglePlay(stationItem); - } - } else if (stationItem != NULL) - _TogglePlay(stationItem); + } break; } @@ -302,7 +308,7 @@ MainWindow::MessageReceived(BMessage* message) if (player != NULL && status == B_OK) { StreamPlayer::PlayState state; - status = message->FindInt32("state", (int32*) &state); + status = message->FindInt32("state", (int32*)&state); int stationIndex = fStationList->StationIndex( player->GetStation()); @@ -311,25 +317,25 @@ MainWindow::MessageReceived(BMessage* message) = fStationList->ItemAt(stationIndex); stationItem->StateChanged(player->State()); - if (player->State() == StreamPlayer::Stopped) { - delete player; + if (player->State() == StreamPlayer::Stopped) stationItem->SetPlayer(NULL); - } if (stationIndex == fStationList->CurrentSelection()) { - fStationPanel->LockLooper(); - fStationPanel->StateChanged(state); - fStationPanel->UnlockLooper(); + if (fStationPanel->LockLooper()) { + fStationPanel->StateChanged(state); + fStationPanel->UnlockLooper(); + } } } } + break; } case MSG_PLAYER_BUFFER_LEVEL: { StreamPlayer* player = NULL; - status_t status = message->FindPointer("player", (void**) &player); + status_t status = message->FindPointer("player", (void**)&player); float level = message->GetFloat("level", 0.0f); if (player != NULL && status == B_OK) { Station* station = player->GetStation(); @@ -393,16 +399,6 @@ MainWindow::QuitRequested() } -void -MainWindow::SetVisible(bool visible) -{ - if (visible) - Show(); - else - Hide(); -}; - - void MainWindow::_TogglePlay(StationListViewItem* stationItem) { diff --git a/MainWindow.h b/MainWindow.h index b98724d..d046183 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -53,8 +53,6 @@ class MainWindow : public BWindow { virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); - virtual void SetVisible(bool visible); - private: void _TogglePlay(StationListViewItem* stationItem); diff --git a/Station.cpp b/Station.cpp index c136d4f..c30576b 100644 --- a/Station.cpp +++ b/Station.cpp @@ -155,78 +155,119 @@ Station::Save() content.UnlockBuffer(); status = stationFile.Lock(); + if (status != B_OK) + return status; + // This is pretty critical to have... status = stationFile.WriteAttrString("META:url", &fStreamUrl.UrlString()); + if (status != B_OK) { + stationFile.Unlock(); + return status; + } + status = stationFile.WriteAttr( "BEOS:TYPE", B_MIME_TYPE, 0, kMimePls, strlen(kMimePls)); + status = stationFile.WriteAttr( "META:bitrate", B_INT32_TYPE, 0, &fBitRate, sizeof(fBitRate)); + status = stationFile.WriteAttr( "META:samplerate", B_INT32_TYPE, 0, &fSampleRate, sizeof(fSampleRate)); + status = stationFile.WriteAttr( "META:channels", B_INT32_TYPE, 0, &fChannels, sizeof(fChannels)); + status = stationFile.WriteAttr( "META:framesize", B_INT32_TYPE, 0, &fFrameSize, sizeof(fFrameSize)); + status = stationFile.WriteAttr( "META:rating", B_INT32_TYPE, 0, &fRating, sizeof(fRating)); + status = stationFile.WriteAttr("META:interval", B_INT32_TYPE, 0, &fMetaInterval, sizeof(fMetaInterval)); + status = stationFile.WriteAttrString("META:genre", &fGenre); + status = stationFile.WriteAttrString("META:country", &fCountry); + status = stationFile.WriteAttrString("META:language", &fLanguage); + status = stationFile.WriteAttrString("META:source", &fSource.UrlString()); + status = stationFile.WriteAttrString( "META:stationurl", &fStationUrl.UrlString()); + BString mimeType(fMime.Type()); status = stationFile.WriteAttrString("META:mime", &mimeType); + status = stationFile.WriteAttr( "META:encoding", B_INT32_TYPE, 0, &fEncoding, sizeof(fEncoding)); + status = stationFile.WriteAttrString("META:uniqueidentifier", &fUniqueIdentifier); + status = stationFile.Unlock(); BNodeInfo stationInfo; - stationInfo.SetTo(&stationFile); - if (fLogo != NULL) { - BMessage archive; - fLogo->Archive(&archive); - ssize_t archiveSize = archive.FlattenedSize(); - char* archiveBuffer = (char*)malloc(archiveSize); - archive.Flatten(archiveBuffer, archiveSize); - stationFile.WriteAttr("logo", 'BBMP', 0LL, archiveBuffer, archiveSize); - free(archiveBuffer); - - BBitmap* icon = new BBitmap( - BRect(0, 0, B_LARGE_ICON - 1, B_LARGE_ICON - 1), B_RGB32, true); - BView* canvas = new BView(icon->Bounds(), "canvas", B_FOLLOW_NONE, 0); - - icon->AddChild(canvas); - canvas->LockLooper(); - canvas->DrawBitmap(fLogo, fLogo->Bounds(), icon->Bounds()); - canvas->UnlockLooper(); - icon->RemoveChild(canvas); - stationInfo.SetIcon(icon, B_LARGE_ICON); - - delete icon; - - icon = new BBitmap(BRect(0, 0, 15, 15), B_RGB32, true); - canvas->ResizeTo(16, 16); - icon->AddChild(canvas); - canvas->LockLooper(); - canvas->DrawBitmap( - fLogo, fLogo->Bounds(), icon->Bounds(), B_FILTER_BITMAP_BILINEAR); - canvas->UnlockLooper(); - icon->RemoveChild(canvas); - stationInfo.SetIcon(icon, B_MINI_ICON); - - delete icon; - delete canvas; - } + status = stationInfo.SetTo(&stationFile); + if (status == B_OK) { + stationInfo.SetType(kMimePls); + + if (fLogo != NULL) { + BMessage archive; + fLogo->Archive(&archive); + ssize_t archiveSize = archive.FlattenedSize(); + char* archiveBuffer = (char*)malloc(archiveSize); + if (archiveBuffer != NULL) { + archive.Flatten(archiveBuffer, archiveSize); + stationFile.WriteAttr("logo", 'BBMP', 0, archiveBuffer, + archiveSize); + free(archiveBuffer); + } + + BView* canvas = new BView(BRect(0, 0, 0, 0), "canvas", + B_FOLLOW_NONE, 0); + if (canvas == NULL) { + // I mean, this isn't ok, but not an error, so... + return B_NO_ERROR; + } - stationInfo.SetType(kMimePls); - stationFile.Unset(); + BBitmap* icon = new BBitmap( + BRect(0, 0, B_LARGE_ICON - 1, B_LARGE_ICON - 1), B_RGB32, true); + if (icon != NULL) { + canvas->ResizeTo(icon->Bounds().Width(), + icon->Bounds().Height()); + icon->AddChild(canvas); + canvas->LockLooper(); + canvas->DrawBitmap(fLogo, fLogo->Bounds(), icon->Bounds()); + canvas->UnlockLooper(); + icon->RemoveChild(canvas); + stationInfo.SetIcon(icon, B_LARGE_ICON); + + delete icon; + } - return status; + icon = new BBitmap(BRect(0, 0, B_MINI_ICON - 1, B_MINI_ICON - 1), + B_RGB32, true); + if (icon != NULL) { + canvas->ResizeTo(icon->Bounds().Width(), + icon->Bounds().Height()); + icon->AddChild(canvas); + canvas->LockLooper(); + canvas->DrawBitmap(fLogo, fLogo->Bounds(), icon->Bounds(), + B_FILTER_BITMAP_BILINEAR); + canvas->UnlockLooper(); + icon->RemoveChild(canvas); + stationInfo.SetIcon(icon, B_MINI_ICON); + + delete icon; + } + + delete canvas; + } + } + + return B_OK; } @@ -412,7 +453,7 @@ Station::ParseUrlReference(const char* body, const char* mime) const char* patterns[4] = {"^file[0-9]+=([^\r\n]*)[\r\n$]+", // ShoutcastUrl "^(http://[^\r\n]*)[\r\n]+$", // Mpeg Url; "^([^#]+[^\r\n]*)[\r\n]+$", // Mpeg Url; - "^title[0-9]+=([^\r\n]*)[\r\n$]+"}; // Shoutcast alternativ; + "^title[0-9]+=([^\r\n]*)[\r\n$]+"}; // Shoutcast alternative; for (int32 i = 0; i < 3; i++) { char* match = RegFind(body, patterns[i]); @@ -438,81 +479,125 @@ Station* Station::Load(BString name, BEntry* entry) { off_t size; - status_t status; Station* station = new Station(name); if (station == NULL) - return station; + return NULL; BFile file; - file.SetTo(entry, B_READ_ONLY); + if (file.SetTo(entry, B_READ_ONLY) != B_OK) + return NULL; + BNodeInfo stationInfo; - stationInfo.SetTo(&file); + if (stationInfo.SetTo(&file) != B_OK) + return NULL; BString readString; - status = file.ReadAttrString("META:url", &readString); + if (file.ReadAttrString("META:url", &readString) == B_OK) + station->fStreamUrl.SetUrlString(readString); + + if (!station->fStreamUrl.IsValid()) { + if (file.GetSize(&size) != B_OK || size > 10000) { + delete station; + return NULL; + } + + char* buffer = (char*)malloc(size); + if (buffer != NULL) { + if (file.Read(buffer, size) == B_OK) { + char mime[B_MIME_TYPE_LENGTH]; + stationInfo.GetType(mime); + station->ParseUrlReference(buffer, mime); + } + + free(buffer); + } else { + delete station; + return NULL; + } + } + + if (name == B_EMPTY_STRING) + station->fName.SetTo(entry->Name()); + + station->CheckFlags(); - station->fStreamUrl.SetUrlString(readString); + if (station->InitCheck() != B_OK) { + delete station; + return NULL; + } - status = file.ReadAttrString("META:genre", &station->fGenre); + if (file.ReadAttrString("META:genre", &station->fGenre) != B_OK) + station->fGenre = B_EMPTY_STRING; - status = file.ReadAttrString("META:country", &station->fCountry); + if (file.ReadAttrString("META:country", &station->fCountry) != B_OK) + station->fCountry = B_EMPTY_STRING; - status = file.ReadAttrString("META:language", &station->fLanguage); + if (file.ReadAttrString("META:language", &station->fLanguage) != B_OK) + station->fLanguage = B_EMPTY_STRING; - status = file.ReadAttr("META:bitrate", B_INT32_TYPE, 0, &station->fBitRate, - sizeof(station->fBitRate)); + if (file.ReadAttr("META:bitrate", B_INT32_TYPE, 0, &station->fBitRate, + sizeof(station->fBitRate)) < B_NO_ERROR) + station->fBitRate = 0; - status = file.ReadAttr("META:rating", B_INT32_TYPE, 0, &station->fRating, - sizeof(station->fRating)); + if (file.ReadAttr("META:rating", B_INT32_TYPE, 0, &station->fRating, + sizeof(station->fRating)) < B_NO_ERROR) + station->fRating = 0; - status = file.ReadAttr("META:interval", B_INT32_TYPE, 0, - &station->fMetaInterval, sizeof(station->fMetaInterval)); + if (file.ReadAttr("META:interval", B_INT32_TYPE, 0, &station->fMetaInterval, + sizeof(station->fMetaInterval)) < B_NO_ERROR) + station->fMetaInterval = 0; - status = file.ReadAttr("META:samplerate", B_INT32_TYPE, 0, - &station->fSampleRate, sizeof(station->fSampleRate)); + if (file.ReadAttr("META:samplerate", B_INT32_TYPE, 0, + &station->fSampleRate, sizeof(station->fSampleRate)) < B_NO_ERROR) + station->fSampleRate = 0; - status = file.ReadAttr("META:channels", B_INT32_TYPE, 0, - &station->fChannels, sizeof(station->fChannels)); + if (file.ReadAttr("META:channels", B_INT32_TYPE, 0, + &station->fChannels, sizeof(station->fChannels)) < B_NO_ERROR) + station->fChannels = 0; - status = file.ReadAttr("META:encoding", B_INT32_TYPE, 0, - &station->fEncoding, sizeof(station->fEncoding)); + if (file.ReadAttr("META:encoding", B_INT32_TYPE, 0, + &station->fEncoding, sizeof(station->fEncoding)) < B_NO_ERROR) + station->fEncoding = 0; - status = file.ReadAttr("META:framesize", B_INT32_TYPE, 0, - &station->fFrameSize, sizeof(station->fFrameSize)); + if (file.ReadAttr("META:framesize", B_INT32_TYPE, 0, + &station->fFrameSize, sizeof(station->fFrameSize)) < B_NO_ERROR) + station->fFrameSize = 0; - status = file.ReadAttrString("META:mime", &readString); - station->fMime.SetTo(readString); + if (file.ReadAttrString("META:mime", &readString) == B_OK) + station->fMime.SetTo(readString); - status = file.ReadAttrString("META:source", &readString); - station->fSource.SetUrlString(readString); + if (file.ReadAttrString("META:source", &readString) == B_OK) + station->fSource.SetUrlString(readString); - status = file.ReadAttrString("META:stationurl", &readString); - station->fStationUrl.SetUrlString(readString); + if (file.ReadAttrString("META:stationurl", &readString) == B_OK) + station->fStationUrl.SetUrlString(readString); - status = file.ReadAttrString("META:uniqueidentifier", &readString); - station->fUniqueIdentifier.SetTo(readString); + if (file.ReadAttrString("META:uniqueidentifier", &readString) == B_OK) + station->fUniqueIdentifier.SetTo(readString); attr_info attrInfo; - status = file.GetAttrInfo("logo", &attrInfo); - if (status == B_OK) { - char* archiveBuffer = (char*) malloc(attrInfo.size); - file.ReadAttr("logo", attrInfo.type, 0LL, archiveBuffer, attrInfo.size); - BMessage archive; - archive.Unflatten(archiveBuffer); - free(archiveBuffer); - station->fLogo = (BBitmap*) BBitmap::Instantiate(&archive); - } else + if (file.GetAttrInfo("logo", &attrInfo) == B_OK) { + char* archiveBuffer = (char*)malloc(attrInfo.size); + if (archiveBuffer != NULL + && file.ReadAttr("logo", attrInfo.type, 0, archiveBuffer, + attrInfo.size) == B_OK) { + BMessage archive; + archive.Unflatten(archiveBuffer); + free(archiveBuffer); + station->fLogo = (BBitmap*)BBitmap::Instantiate(&archive); + } + } + + if (station->fLogo == NULL) station->fLogo = new BBitmap(BRect(0, 0, 32, 32), B_RGB32); - status = stationInfo.GetIcon(station->fLogo, B_LARGE_ICON); - if (status != B_OK) + if (stationInfo.GetIcon(station->fLogo, B_LARGE_ICON) != B_OK) delete station->fLogo; - station->fLogo = new BBitmap(BRect(0, 0, 16, 16), B_RGB32); - status = stationInfo.GetIcon(station->fLogo, B_MINI_ICON); - if (status != B_OK) { + station->fLogo = new BBitmap(BRect(0, 0, 15, 15), B_RGB32); + if (stationInfo.GetIcon(station->fLogo, B_MINI_ICON) != B_OK) { delete station->fLogo; station->fLogo = NULL; } @@ -522,32 +607,6 @@ Station::Load(BString name, BEntry* entry) station->fSource.SetUrlString(BString("file://") << path.Path()); } - - if (!station->fStreamUrl.IsValid()) { - status = file.GetSize(&size); - if (size > 10000) - return NULL; - - char* buffer = (char*)malloc(size); - file.Read(buffer, size); - - char mime[64]; - stationInfo.GetType(mime); - station->ParseUrlReference(buffer, mime); - - free(buffer); - } - - if (name == B_EMPTY_STRING) - station->fName.SetTo(entry->Name()); - - station->CheckFlags(); - - if (station->InitCheck() != B_OK) { - delete station; - return NULL; - } - return station; } diff --git a/StationFinderRadioNetwork.cpp b/StationFinderRadioNetwork.cpp index 0ac4fd6..e94d787 100644 --- a/StationFinderRadioNetwork.cpp +++ b/StationFinderRadioNetwork.cpp @@ -94,11 +94,12 @@ StationFinderRadioNetwork::FindBy(int capabilityIndex, const char* searchFor, suspend_thread(fIconLookupThread); fIconLookupList.MakeEmpty(true); + fIconLookupNotify = resultUpdateTarget; BObjectList* result = new BObjectList(); if (result == NULL) - return result; + return NULL; if (_CheckServer() != B_OK) return result; @@ -241,7 +242,8 @@ StationFinderRadioNetwork::_IconLookupFunc(void* data) BMessage* notification = new BMessage(MSG_UPDATE_STATION); notification->AddPointer("station", item->fStation); - if (_this->fIconLookupNotify->LockLooper()) { + if (_this->fIconLookupNotify != NULL + && _this->fIconLookupNotify->LockLooper()) { _this->fIconLookupNotify->PostMessage(notification); _this->fIconLookupNotify->UnlockLooper(); } diff --git a/StreamPlayer.cpp b/StreamPlayer.cpp index 68ad66e..3d52fc4 100644 --- a/StreamPlayer.cpp +++ b/StreamPlayer.cpp @@ -98,23 +98,23 @@ StreamPlayer::Stop() case StreamPlayer::Playing: { - Lock(); - - if (fPlayer) { - fPlayer->Stop(false, true); - delete fPlayer; - fPlayer = NULL; - } - - if (fMediaFile) { - fMediaFile->CloseFile(); - delete fMediaFile; - fMediaFile = NULL; + if (Lock()) { + if (fPlayer != NULL) { + fPlayer->Stop(false, true); + delete fPlayer; + fPlayer = NULL; + } + + if (fMediaFile != NULL) { + fMediaFile->CloseFile(); + delete fMediaFile; + fMediaFile = NULL; + } + + Unlock(); + _SetState(StreamPlayer::Stopped); } - Unlock(); - _SetState(StreamPlayer::Stopped); - break; } @@ -122,6 +122,7 @@ StreamPlayer::Stop() case StreamPlayer::InActive: break; } + return B_OK; } @@ -187,7 +188,11 @@ StreamPlayer::_GetDecodedChunk(void* cookie, void* buffer, size_t size, status_t StreamPlayer::_StartPlayThreadFunc(StreamPlayer* _this) { - _this->Lock(); + if (!_this->Lock()) { + MSG("Error when attempting to lock the StreamPlayer for %s\n", + _this->fStation->StreamUrl().UrlString().String()); + return B_ERROR; + } _this->_SetState(StreamPlayer::Buffering); _this->fStopRequested = false;