diff --git a/.dep.inc b/.dep.inc
deleted file mode 100644
index 38ba445..0000000
--- a/.dep.inc
+++ /dev/null
@@ -1,5 +0,0 @@
-# This code depends on make tool being used
-DEPFILES=$(wildcard $(addsuffix .d, ${OBJECTFILES} ${TESTOBJECTFILES}))
-ifneq (${DEPFILES},)
-include ${DEPFILES}
-endif
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..dd88d9b
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,12 @@
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+
+[*.{cpp,h}]
+indent_style = tab
+indent_size = 4
+charset = utf-8
+trim_trailing_whitespace = true
+
diff --git a/.gitignore b/.gitignore
index f233604..8a1ebce 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,3 @@
-/dist/*
-/objects.*/
+dist/*
+objects*/
StreamRadio-version.rdef
diff --git a/About.cpp b/About.cpp
index ae6734d..3223927 100644
--- a/About.cpp
+++ b/About.cpp
@@ -12,19 +12,12 @@
* 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 .
+ * along with this program. If not, see .
*/
-/*
- * File: About.cpp
- * Author: Kai Niessen
- *
- * Created on March 20, 2017, 4:11 PM
- */
#include "About.h"
-#include "RadioApp.h"
-#include "Utils.h"
+
#include
#include
#include
@@ -35,6 +28,10 @@
#include
#include
+#include "RadioApp.h"
+#include "Utils.h"
+
+
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "About"
@@ -52,16 +49,19 @@ About::About()
versionView->SetViewColor(238, 238, 235, 255);
versionView->SetHighColor(134, 135, 138, 255);
versionView->SetLowColor(134, 135, 138, 0);
+
BBitmap* banner = Utils::ResourceBitmap(RES_BANNER);
- if (banner) {
+ if (banner != NULL) {
bounds = banner->Bounds();
ResizeTo(bounds.Width(),
bounds.Height() + versionView->PreferredSize().height);
+
versionView->SetFontSize(11);
versionView->SetAlignment(B_ALIGN_RIGHT);
versionView->ResizeTo(
bounds.Width(), versionView->PreferredSize().height + 2);
versionView->MoveTo(0, bounds.Height());
+
BView* bannerView = new BView(bounds, "bannerView",
B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, B_WILL_DRAW);
AddChild(bannerView, versionView);
@@ -69,9 +69,11 @@ About::About()
} else {
versionView->SetFontSize(40);
versionView->SetAlignment(B_ALIGN_CENTER);
+
BSize preferredSize = versionView->PreferredSize();
ResizeTo(preferredSize.width + 10, preferredSize.height);
}
+
CenterOnScreen();
}
@@ -97,5 +99,6 @@ About::GetAppVersion()
versionString.SetTo(versionInfo.long_info);
else
versionString = "©Fishpond 2012-2017";
+
return versionString;
}
diff --git a/About.h b/About.h
index a324539..2d4b931 100644
--- a/About.h
+++ b/About.h
@@ -12,32 +12,27 @@
* 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 .
+ * along with this program. If not, see .
*/
+#ifndef _ABOUT_H
+#define _ABOUT_H
-/*
- * File: About.h
- * Author: Kai Niessen
- *
- * Created on March 20, 2017, 4:11 PM
- */
-
-#ifndef ABOUT_H
-#define ABOUT_H
#include
#include
+
#define BANNER 4
-class About : public BWindow
-{
+
+class About : public BWindow {
public:
- About();
- virtual ~About();
+ About();
+ virtual ~About();
private:
- static BString GetAppVersion();
+ static BString GetAppVersion();
};
-#endif /* ABOUT_H */
+
+#endif // _ABOUT_H
diff --git a/Buffering.h b/Buffering.h
index cdc61d5..74fe880 100644
--- a/Buffering.h
+++ b/Buffering.h
@@ -1,38 +1,56 @@
/*
- * File: Buffering.h
- * Author: Kai Niessen
+ * Copyright (C) 2017 Kai Niessen
*
- * Created on January 31, 2016, 4:15 PM
+ * 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
-#ifndef BUFFERING_H
-#define BUFFERING_H
/**
* Simple class extending an integer to roll over when reaching boundaries
*/
-class rotor
-{
+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);
@@ -40,16 +58,22 @@ class rotor
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);
@@ -57,60 +81,122 @@ class rotor
fValue = fMax;
else
fValue--;
+
return *tmp;
}
- rotor& operator=(int i) { fValue = i % (fMax + 1); }
- int operator=(rotor& r) { return r.fValue; }
+
+
+ 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; }
+
+
+ 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:
- inline void setValue(int i) { fValue = i; }
- inline int getValue() { return fValue; }
- int fValue;
- int fMax;
+ int fValue;
+ int fMax;
};
-class Buffer : public BLocker
-{
+
+class Buffer : public BLocker {
public:
#define limit(requested, max) (requested = (requested > max) ? max : requested)
+
friend class BufferGroup;
- typedef enum { EMPTY, FILLING, FILLED, READING } bufferState;
+
+ 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)
+ :
+ BLocker("Buffer"),
+ fIndex(index),
+ fUsed(0),
+ fSize(size),
+ fData((char*)malloc(size)),
+ fState(EMPTY)
+ {};
+
+ ~Buffer()
{
+ free(fData);
}
- ~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)
+ 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)
+
+
+ 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)
+
+
+ size_t
+ read(char* data, size_t size)
{
if (limit(size, readable()))
memcpy(data, fData, size);
@@ -119,124 +205,179 @@ class Buffer : public BLocker
}
protected:
- bufferState fState;
- size_t fSize;
- size_t fUsed;
- char* fData;
- int fIndex;
+ bufferState fState;
+ size_t fSize;
+ size_t fUsed;
+ char* fData;
+ int fIndex;
};
+
+
typedef Buffer* pBuffer;
-class BufferGroup : public BLocker
-{
+
+class BufferGroup : public BLocker {
public:
-#define none -1
- typedef bool (*LimitFunc)(void* cookie, float ratio, bool isOk);
+ #define kNone -1
+
+ typedef bool (*LimitFunc)(void* cookie, float ratio, bool isOk);
+
BufferGroup(int numBuffers, size_t size)
- : BLocker("buffers"), firstEmpty(numBuffers, 0),
- firstFilled(numBuffers, none), fNumBuffers(numBuffers)
+ :
+ BLocker("BufferGroup"),
+ firstEmpty(numBuffers, 0),
+ firstFilled(numBuffers, kNone),
+ fNumBuffers(numBuffers)
{
- buffers = new pBuffer[numBuffers];
+ fBuffers = new pBuffer[numBuffers];
for (int i = 0; i < numBuffers; i++)
- buffers[i] = new Buffer(size, i);
+ fBuffers[i] = new Buffer(size, i);
}
+
+
~BufferGroup()
{
for (int i = 0; i < fNumBuffers; i++)
- delete buffers[i];
- delete buffers;
+ delete fBuffers[i];
+ delete fBuffers;
}
- inline int IndexOf(Buffer* buffer) { return buffer->fIndex; }
- Buffer* RequestForFilling(Buffer* previous = NULL)
+
+
+ inline int
+ IndexOf(Buffer* buffer)
+ {
+ return buffer->fIndex;
+ }
+
+
+ Buffer*
+ RequestForFilling(Buffer* previous = NULL)
{
Buffer* result = NULL;
Lock();
- if (previous) {
+
+ if (previous != NULL) {
if (previous->CountLocks() == 0)
previous->Lock();
previous->fState = Buffer::FILLED;
- if (firstFilled == none)
+ if (firstFilled == kNone)
firstFilled = IndexOf(previous);
previous->Unlock();
}
- if (firstEmpty != none)
- result = buffers[firstEmpty++];
+
+ if (firstEmpty != kNone)
+ result = fBuffers[firstEmpty++];
result->fState = Buffer::FILLING;
- if (buffers[firstEmpty]->fState != Buffer::EMPTY)
- firstEmpty = none;
+
+ if (fBuffers[firstEmpty]->fState != Buffer::EMPTY)
+ firstEmpty = kNone;
+
Unlock();
return result;
}
- Buffer* RequestForReading(Buffer* previous = NULL)
+
+
+ Buffer*
+ RequestForReading(Buffer* previous = NULL)
{
Buffer* result = NULL;
Lock();
- if (previous) {
+
+ if (previous != NULL) {
if (previous->CountLocks() == 0)
previous->Lock();
previous->setState(Buffer::EMPTY);
- if (firstEmpty == none)
+ if (firstEmpty == kNone)
firstEmpty = IndexOf(previous);
previous->Unlock();
}
- if (firstFilled != none)
- result = buffers[firstFilled++];
+
+ if (firstFilled != kNone)
+ result = fBuffers[firstFilled++];
result->fState = Buffer::READING;
- if (buffers[firstFilled]->fState != Buffer::FILLED)
- firstFilled = none;
+
+ if (fBuffers[firstFilled]->fState != Buffer::FILLED)
+ firstFilled = kNone;
+
Unlock();
+
return result;
}
- void ReturnBuffer(Buffer* previous)
+
+
+ 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 == none)
+ if (firstEmpty == kNone)
firstEmpty = IndexOf(previous);
break;
+ }
+
case Buffer::FILLING:
previous->fState = Buffer::FILLED;
case Buffer::FILLED:
- if (firstFilled == none)
+ {
+ if (firstFilled == kNone)
firstFilled = previous->fIndex;
break;
+ }
}
+
Unlock();
previous->Unlock();
}
- size_t TotalUsed()
+
+
+ size_t
+ TotalUsed()
{
size_t result = 0;
for (int i = 0; i < fNumBuffers; i++)
- Buffer* b = buffers[i];
+ Buffer* b = fBuffers[i];
if (b->fState == Buffer::FILLED || b->fState == Buffer::FILLING)
result += b->fUsed;
+
return result;
}
- size_t TotalCapacity() { return fNumBuffers * buffers[0]->fSize; }
- float FillRatio()
+
+
+ size_t
+ TotalCapacity()
+ {
+ return fNumBuffers * fBuffers[0]->fSize;
+ }
+
+
+ float
+ FillRatio()
{
- if (firstFilled == none)
+ if (firstFilled == kNone)
return 0.0f;
- else if (firstEmpty == none)
+ else if (firstEmpty == kNone)
return 1.0f;
else
return float(firstEmpty - firstFilled) / fNumBuffers;
}
private:
- int fNumBuffers;
- pBuffer* buffers;
- rotor firstEmpty;
- rotor firstFilled;
+ rotor fFirstFilled;
+ rotor fFirstEmpty;
+ int32 fNumBuffers;
+ pBuffer* fBuffers;
};
-#endif /* BUFFERING_H */
+
+#endif // _BUFFERING_H
diff --git a/Debug.h b/Debug.h
index 2e4724b..76af107 100644
--- a/Debug.h
+++ b/Debug.h
@@ -1,17 +1,30 @@
/*
- * File: Debug.h
- * Author: Kai Niessen
+ * Copyright (C) 2017 Kai Niessen
*
- * Created on January 16, 2016, 7:50 PM
+ * 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 _DEBUG_H
+#define _DEBUG_H
+
+
+/*
* Contains definitions for tracing, debugging, profiling and logging
*
* To enable trace / debug / rpofiling messages, uncomment the associated
* defines or configure them in your IDE / make file.
*/
-#ifndef DEBUG_H
-#define DEBUG_H
#undef TRACE
#undef DEBUG
@@ -42,4 +55,5 @@
#define PROFILE_MEASURE(action)
#endif // PROFILING
-#endif // DEBUG_H
+
+#endif // _DEBUG_H
diff --git a/Expander.cpp b/Expander.cpp
index 8001d91..baf0c2e 100644
--- a/Expander.cpp
+++ b/Expander.cpp
@@ -12,17 +12,12 @@
* 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 .
+ * along with this program. If not, see .
*/
-/*
- * File: Expander.cpp
- * Author: Kai Niessen
- *
- * Created on April 13, 2017, 4:50 PM
- */
#include "Expander.h"
+
#include
#include
#include
@@ -52,6 +47,7 @@ Expander::Draw(BRect updateRect)
StrokeShape(&shape);
shape.Clear();
+
r.InsetBy(r.Width() / 3, 2);
if (fExpanded) {
shape.MoveTo(r.LeftTop());
@@ -64,6 +60,7 @@ Expander::Draw(BRect updateRect)
shape.LineTo(r.LeftTop() + BPoint(r.Width() / 2, 0));
shape.Close();
}
+
SetHighColor(tint_color(ViewColor(), B_DARKEN_2_TINT));
FillShape(&shape);
}
@@ -98,7 +95,9 @@ Expander::SetExpanded(bool expanded)
fTarget->Show();
else
fTarget->Hide();
+
Window()->Layout(true);
+
fExpanded = expanded;
Invalidate();
}
diff --git a/Expander.h b/Expander.h
index d8a89ff..064b80f 100644
--- a/Expander.h
+++ b/Expander.h
@@ -12,38 +12,35 @@
* 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 .
+ * along with this program. If not, see .
*/
+#ifndef _EXPANDER_H
+#define _EXPANDER_H
-/*
- * File: Expander.h
- * Author: Kai Niessen
- *
- * Created on April 13, 2017, 4:50 PM
- */
-
-#ifndef EXPANDER_H
-#define EXPANDER_H
#include
+
#define MSG_EXPAND 'eEXP'
-class Expander : public BButton
-{
+
+class Expander : public BButton {
public:
- Expander(const char* name, BView* target,
- orientation orientation = B_HORIZONTAL);
- virtual ~Expander();
- void SetExpanded(bool expanded);
- bool Expanded() { return fExpanded; }
- virtual status_t Invoke(BMessage* msg);
- virtual void Draw(BRect updateRect);
+ Expander(const char* name, BView* target,
+ orientation orientation = B_HORIZONTAL);
+ virtual ~Expander();
+
+ void SetExpanded(bool expanded);
+ bool Expanded() { return fExpanded; }
+
+ virtual status_t Invoke(BMessage* msg);
+ virtual void Draw(BRect updateRect);
private:
- bool fExpanded;
- orientation fOrientation;
- BView* fTarget;
+ BView* fTarget;
+ orientation fOrientation;
+ bool fExpanded;
};
-#endif /* EXPANDER_H */
+
+#endif // _EXPANDER_H
diff --git a/HttpUtils.cpp b/HttpUtils.cpp
index 40c4b2f..ba7abaf 100644
--- a/HttpUtils.cpp
+++ b/HttpUtils.cpp
@@ -1,38 +1,60 @@
/*
- * File: HttpUtils.cpp
- * Author: user
+ * Copyright (C) 2017 Kai Niessen
*
- * Created on 12. Oktober 2015, 23:14
+ * 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 .
*/
+
#include
#include "Debug.h"
#include "HttpUtils.h"
-class HttpIOReader : public BUrlProtocolListener
-{
+
+class HttpIOReader : public BUrlProtocolListener {
public:
- HttpIOReader(BPositionIO* data, BHttpHeaders* responseHeaders, size_t limit)
- : fData(data), fLimit(limit), fHeaders(responseHeaders),
+ HttpIOReader(BPositionIO* data,
+ BHttpHeaders* responseHeaders,
+ ssize_t limit)
+ :
+ fData(data),
+ fLimit(limit),
+ fHeaders(responseHeaders),
fIsRedirect(false)
- {
- }
+ {};
+
+
+ ~HttpIOReader()
+ {};
- ~HttpIOReader() {}
- virtual void HeadersReceived(BUrlRequest* caller, const BUrlResult& result)
+ virtual void
+ HeadersReceived(BUrlRequest* caller, const BUrlResult& result)
{
- const BHttpResult* httpResult
- = dynamic_cast(&result);
- if (httpResult && fHeaders) {
+ const BHttpResult* httpResult =
+ dynamic_cast(&result);
+ if (httpResult != NULL && fHeaders != NULL) {
*fHeaders = httpResult->Headers();
fIsRedirect = BHttpRequest::IsRedirectionStatusCode(
httpResult->StatusCode());
}
}
- virtual void DataReceived(
- BUrlRequest* caller, const char* data, off_t position, ssize_t size)
+
+
+ virtual void
+ DataReceived(BUrlRequest* caller, const char* data, off_t position,
+ ssize_t size)
{
if (fIsRedirect)
return;
@@ -43,37 +65,46 @@ class HttpIOReader : public BUrlProtocolListener
}
fData->Write(data, size);
- if (fLimit) // Was fLimit < size, which could lead to fLimit = 0 and an
- // endless loop
+ if (fLimit != 0) {
+ // Was fLimit < size, which could lead to fLimit = 0 and an
+ // endless loop
if (fLimit <= size)
caller->Stop();
else
fLimit -= size;
+ }
}
private:
- BPositionIO* fData;
- BHttpHeaders* fHeaders;
- bool fIsRedirect;
-
- size_t fLimit;
+ BPositionIO* fData;
+ ssize_t fLimit;
+ BHttpHeaders* fHeaders;
+ bool fIsRedirect;
};
-class HttpHeaderReader : public BUrlProtocolListener
-{
+
+class HttpHeaderReader : public BUrlProtocolListener {
public:
HttpHeaderReader(char* buffer = NULL, ssize_t size = 0)
- : BUrlProtocolListener(), fBuffer(buffer), fSize(size), fPos(0)
- {
- }
+ :
+ BUrlProtocolListener(),
+ fBuffer(buffer),
+ fSize(size),
+ fPos(0)
+ {};
- virtual void HeadersReceived(BUrlRequest* caller)
+
+ virtual void
+ HeadersReceived(BUrlRequest* caller)
{
if (fBuffer == NULL && caller->IsRunning())
caller->Stop();
}
- virtual void DataReceived(
- BUrlRequest* caller, const char* data, off_t position, ssize_t size)
+
+
+ virtual void
+ DataReceived(BUrlRequest* caller, const char* data, off_t position,
+ ssize_t size)
{
if (fSize == 0 || fBuffer == NULL) {
if (caller->IsRunning())
@@ -91,11 +122,12 @@ class HttpHeaderReader : public BUrlProtocolListener
}
private:
- char* fBuffer;
- ssize_t fSize;
- off_t fPos;
+ char* fBuffer;
+ ssize_t fSize;
+ off_t fPos;
};
+
/**
* Loops on the DNS responses looking for connectivity on specified port.
*/
@@ -120,6 +152,7 @@ HttpUtils::CheckPort(BUrl url, BUrl* newUrl, uint32 flags)
BNetworkAddress ipAddress;
BSocket* socket;
uint32 cookie = 0;
+
status_t portStatus = B_ERROR;
while (portStatus != B_OK) {
status = resolver->GetNextAddress(AF_INET6, &cookie, ipAddress);
@@ -127,10 +160,11 @@ HttpUtils::CheckPort(BUrl url, BUrl* newUrl, uint32 flags)
status = resolver->GetNextAddress(&cookie, ipAddress);
if (status != B_OK)
return status;
- socket = new (std::nothrow) BSocket();
+ socket = new(std::nothrow) BSocket();
portStatus = socket->Connect(ipAddress);
delete socket;
}
+
// If port number is 80, do not add it to the final URL
// Then, prepend the appropiate protocol
newUrlString = ipAddress.ToString(ipAddress.Port() != 80)
@@ -139,6 +173,7 @@ HttpUtils::CheckPort(BUrl url, BUrl* newUrl, uint32 flags)
if (url.HasPath())
newUrlString.Append(url.Path());
newUrl->SetUrlString(newUrlString.String());
+
return B_OK;
}
@@ -155,28 +190,36 @@ HttpUtils::GetAll(BUrl url, BHttpHeaders* responseHeaders, bigtime_t timeOut,
BString* contentType, size_t sizeLimit)
{
BMallocIO* data = new BMallocIO();
+ if (data == NULL)
+ return data;
+
HttpIOReader reader(data, responseHeaders, sizeLimit);
HttpRequest request(url, false, "HTTP", &reader);
+
if (contentType && !contentType->IsEmpty()) {
BHttpHeaders* requestHeaders = new BHttpHeaders();
requestHeaders->AddHeader("accept", contentType->String());
request.AdoptHeaders(requestHeaders);
}
+
request.SetAutoReferrer(true);
request.SetFollowLocation(true);
request.SetTimeout(timeOut);
request.SetUserAgent("StreamRadio/0.0.4");
+
thread_id threadId = request.Run();
status_t status;
wait_for_thread(threadId, &status);
+
int32 statusCode = request.Result().StatusCode();
size_t bufferLen = data->BufferLength();
if (!(statusCode == 0 || request.IsSuccessStatusCode(statusCode))
|| bufferLen == 0) {
delete data;
data = NULL;
- } else if (contentType)
+ } else if (contentType != NULL)
contentType->SetTo(request.Result().ContentType());
+
return data;
}
@@ -186,6 +229,7 @@ HttpUtils::GetStreamHeader(BUrl url, BHttpHeaders* responseHeaders)
{
status_t status;
HttpIOReader reader(NULL, responseHeaders, 0);
+
HttpRequest request(url, false, "HTTP", &reader);
request.SetMethod("GET");
request.SetAutoReferrer(true);
@@ -193,9 +237,11 @@ HttpUtils::GetStreamHeader(BUrl url, BHttpHeaders* responseHeaders)
request.SetTimeout(10000);
request.SetDiscardData(true);
request.SetUserAgent("StreamRadio/0.0.4");
+
BHttpHeaders* requestHeaders = new BHttpHeaders();
requestHeaders->AddHeader("Icy-MetaData", 1);
request.AdoptHeaders(requestHeaders);
+
thread_id threadId = request.Run();
wait_for_thread(threadId, &status);
@@ -206,5 +252,6 @@ HttpUtils::GetStreamHeader(BUrl url, BHttpHeaders* responseHeaders)
else
status = B_ERROR;
}
+
return status;
}
diff --git a/HttpUtils.h b/HttpUtils.h
index fba6027..8121ccd 100644
--- a/HttpUtils.h
+++ b/HttpUtils.h
@@ -1,12 +1,22 @@
/*
- * File: HttpUtils.h
- * Author: user
+ * Copyright (C) 2017 Kai Niessen
*
- * Created on 12. Oktober 2015, 23:14
+ * 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 _HTTP_UTILS_H
+#define _HTTP_UTILS_H
-#ifndef HTTPUTILS_H
-#define HTTPUTILS_H
#include
#include
@@ -14,28 +24,39 @@
#include
#include
-class HttpRequest : public BHttpRequest
-{
+
+class HttpRequest : public BHttpRequest {
public:
HttpRequest(const BUrl& url, bool ssl = false,
const char* protocolName = "HTTP",
BUrlProtocolListener* listener = NULL, BUrlContext* context = NULL)
- : BHttpRequest(url, ssl, protocolName, listener, context){};
- virtual BHttpResult& Result() const
+ :
+ BHttpRequest(url, ssl, protocolName, listener, context)
+ {};
+
+
+ virtual BHttpResult&
+ Result() const
{
- return (BHttpResult&) BHttpRequest::Result();
- };
+ return (BHttpResult&)BHttpRequest::Result();
+ }
};
-class HttpUtils
-{
+
+class HttpUtils {
public:
- static status_t CheckPort(BUrl url, BUrl* newUrl, uint32 flags = 0);
- static BMallocIO* GetAll(BUrl url, BHttpHeaders* returnHeaders = NULL,
- bigtime_t timeOut = 3000, BString* contentType = NULL,
- size_t sizeLimit = 0);
- static status_t GetStreamHeader(BUrl url, BHttpHeaders* headers);
+ static status_t CheckPort(BUrl url, BUrl* newUrl,
+ uint32 flags = 0);
+
+ static BMallocIO* GetAll(BUrl url,
+ BHttpHeaders* returnHeaders = NULL,
+ bigtime_t timeOut = 3000,
+ BString* contentType = NULL,
+ size_t sizeLimit = 0);
+
+ static status_t GetStreamHeader(BUrl url,
+ BHttpHeaders* headers);
};
-#endif /* HTTPUTILS_H */
+#endif // _HTTP_UTILS_H
diff --git a/MainWindow.cpp b/MainWindow.cpp
index c244783..9ab5f1e 100644
--- a/MainWindow.cpp
+++ b/MainWindow.cpp
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2008-2010 Lukas Sommer < SommerLuk at gmail dot com >
+ Copyright (C) 2008-2010 Lukas Sommer < SommerLuk at gmail dot com >
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -15,18 +15,18 @@
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 .
+ along with this program. If not, see .
*/
+
#include "MainWindow.h"
-#include "RadioApp.h"
+
#include
#include
#include
#include
#include
#include
-#include
#include
#include
#include
@@ -35,6 +35,8 @@
#include
#include "Debug.h"
+#include "RadioApp.h"
+
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "MainWindow"
@@ -43,20 +45,20 @@
MainWindow::MainWindow()
:
BWindow(BRect(0, 0, 400, 200), B_TRANSLATE_SYSTEM_NAME("StreamRadio"),
- B_DOCUMENT_WINDOW, B_WILL_ACCEPT_FIRST_CLICK),
+ B_DOCUMENT_WINDOW, 0),
fStationFinder(NULL)
{
- fSettings = &((RadioApp*) be_app)->Settings;
+ fSettings = &((RadioApp*)be_app)->Settings;
- allowParallelPlayback = fSettings->GetAllowParallelPlayback();
- menuParallelPlayback = new BMenuItem(B_TRANSLATE("Allow parallel playback"),
+ fAllowParallelPlayback = fSettings->GetAllowParallelPlayback();
+ fMenuParallelPlayback = new BMenuItem(B_TRANSLATE("Allow parallel playback"),
new BMessage(MSG_PARALLEL_PLAYBACK));
- menuParallelPlayback->SetMarked(allowParallelPlayback);
+ fMenuParallelPlayback->SetMarked(fAllowParallelPlayback);
- // initialize central widget
- BLayoutBuilder::Menu<>(fMainMenu = new BMenuBar(Bounds(), "MainMenu"))
+ fMainMenu = new BMenuBar(Bounds(), "MainMenu");
+ BLayoutBuilder::Menu<>(fMainMenu)
.AddMenu(B_TRANSLATE("App"))
- .AddItem(menuParallelPlayback)
+ .AddItem(fMenuParallelPlayback)
.AddItem(B_TRANSLATE("Help" B_UTF8_ELLIPSIS), MSG_HELP)
.AddItem(B_TRANSLATE("About"), B_ABOUT_REQUESTED)
.AddSeparator()
@@ -70,31 +72,35 @@ MainWindow::MainWindow()
.AddMenu(B_TRANSLATE("Search"))
.AddItem(B_TRANSLATE("Find stations" B_UTF8_ELLIPSIS), MSG_SEARCH, 'S')
.End()
- .End();
+ .End();
AddChild(fMainMenu);
+
fStationList = new StationListView(true);
BScrollView* stationScroll = new BScrollView(
"scrollStation", fStationList, B_FOLLOW_ALL_SIDES, 0, false, true);
fStationPanel = new StationPanel(this);
fExpander = new Expander("expStationPanel", fStationPanel);
+ fStatusBar = new BStringView("status", B_EMPTY_STRING);
- BGroupLayout* layout
- = (BGroupLayout*) BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
- .SetExplicitAlignment(
- BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT))
- .Add(stationScroll, 1.0f)
- .Add(fExpander, 0.0f)
- .Add(fStationPanel, 0.0f)
- .Add(fStatusBar = new BStringView("status", ""), 0.0f);
+ BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
+ .SetExplicitAlignment(
+ BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT))
+ .Add(stationScroll, 1.0f)
+ .Add(fExpander, 0.0f)
+ .Add(fStationPanel, 0.0f)
+ .Add(fStatusBar, 0.0f)
+ .End();
fStationList->Sync(fSettings->Stations);
fStationList->SetInvocationMessage(new BMessage(MSG_INVOKE_STATION));
fStationList->SetSelectionMessage(new BMessage(MSG_SELECT_STATION));
fStationList->SetPlayMessage(new BMessage(MSG_INVOKE_STATION));
+
fStatusBar->SetExplicitAlignment(
BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_VERTICAL_UNSET));
fStatusBar->SetExplicitMinSize(BSize(10, B_SIZE_UNSET));
+
Layout(true);
ResizeToPreferred();
@@ -106,10 +112,10 @@ MainWindow::MainWindow()
MainWindow::~MainWindow()
{
- for (int i = 0; i < fStationList->CountItems(); i++) {
+ for (int32 i = 0; i < fStationList->CountItems(); i++) {
StationListViewItem* stationItem = fStationList->ItemAt(i);
StreamPlayer* player = stationItem->Player();
- if (player)
+ if (player != NULL)
player->Stop();
}
}
@@ -118,13 +124,11 @@ MainWindow::~MainWindow()
void
MainWindow::MessageReceived(BMessage* message)
{
- status_t status;
switch (message->what) {
case B_REFS_RECEIVED:
{
entry_ref ref;
int32 index = 0;
- Station* station;
StationListViewItem* stationItem;
BString result;
while (message->FindRef("refs", index++, &ref) == B_OK) {
@@ -136,7 +140,7 @@ MainWindow::MessageReceived(BMessage* message)
delete station;
station = existingStation;
stationItem = fStationList->Item(station);
- TogglePlay(stationItem);
+ _TogglePlay(stationItem);
} else {
stationItem = new StationListViewItem(station);
fStationList->AddItem(stationItem);
@@ -149,6 +153,7 @@ MainWindow::MessageReceived(BMessage* message)
"File %s could not be loaded as a station"));
fStatusBar->SetText(result.String());
}
+
break;
}
@@ -158,6 +163,7 @@ MainWindow::MessageReceived(BMessage* message)
fStationFinder = new StationFinderWindow(this);
fStationFinder->Show();
}
+
break;
}
@@ -166,15 +172,17 @@ MainWindow::MessageReceived(BMessage* message)
be_clipboard->Lock();
BMessage* data = be_clipboard->Data();
be_clipboard->Unlock();
+
char* url;
ssize_t numBytes;
if (data->FindData(
"text/plain", B_MIME_TYPE, (const void**) &url, &numBytes)
== B_OK)
url[numBytes] = 0;
+
BString sUrl(url);
Station* station = Station::LoadIndirectUrl(sUrl);
- if (station) {
+ if (station != NULL) {
status_t probeStatus = station->Probe();
if (probeStatus == B_OK) {
fSettings->Stations->AddItem(station);
@@ -191,6 +199,7 @@ MainWindow::MessageReceived(BMessage* message)
->Go();
}
}
+
break;
}
@@ -198,24 +207,25 @@ MainWindow::MessageReceived(BMessage* message)
{
StationListViewItem* stationItem
= fStationList->ItemAt(fStationList->CurrentSelection(0));
- Station* station
- = fStationList->StationAt(fStationList->CurrentSelection(0));
- if (stationItem) {
+ if (stationItem != NULL) {
Station* station = stationItem->GetStation();
status_t stationStatus = station->Probe();
+
BString statusText;
- if (stationStatus == B_OK)
+ if (stationStatus == B_OK) {
statusText
= B_TRANSLATE("Probing station %station% successful");
- else
+ } else {
statusText
= B_TRANSLATE("Probing station %station% failed");
+ }
statusText.ReplaceFirst("%station%", station->Name()->String());
fStatusBar->SetText(statusText);
fStationList->Invalidate();
fStationPanel->SetStation(stationItem);
}
+
break;
}
@@ -223,22 +233,24 @@ MainWindow::MessageReceived(BMessage* message)
{
Station* station
= fStationList->StationAt(fStationList->CurrentSelection(0));
- if (station) {
+ if (station != NULL) {
fSettings->Stations->RemoveItem(station);
fStationList->Sync(fSettings->Stations);
fSettings->Stations->Save();
}
+
break;
}
case MSG_ADD_STATION:
{
Station* station = NULL;
- if (B_OK == message->FindPointer("station", (void**) &station)) {
+ if (message->FindPointer("station", (void**) &station) == B_OK) {
fSettings->Stations->AddItem(station);
fStationList->Sync(fSettings->Stations);
fSettings->Stations->Save();
}
+
break;
}
@@ -254,6 +266,7 @@ MainWindow::MessageReceived(BMessage* message)
fStationPanel->SetStation(fStationList->ItemAt(index));
fStationPanel->UnlockLooper();
}
+
break;
}
@@ -262,30 +275,34 @@ MainWindow::MessageReceived(BMessage* message)
int32 stationIndex = message->GetInt32("index", -1);
StationListViewItem* stationItem
= fStationList->ItemAt(stationIndex);
- if (allowParallelPlayback == false)
- if (activeStations.HasItem(stationItem))
- while (!activeStations.IsEmpty())
- TogglePlay(activeStations.LastItem());
- else {
- while (!activeStations.IsEmpty())
- TogglePlay(activeStations.LastItem());
- TogglePlay(stationItem);
+
+ if (fAllowParallelPlayback == false) {
+ if (fActiveStations.HasItem(stationItem)) {
+ while (!fActiveStations.IsEmpty())
+ _TogglePlay(fActiveStations.LastItem());
+ } else {
+ while (!fActiveStations.IsEmpty())
+ _TogglePlay(fActiveStations.LastItem());
+
+ _TogglePlay(stationItem);
}
- else if (stationItem)
- TogglePlay(stationItem);
+ } else if (stationItem != NULL)
+ _TogglePlay(stationItem);
+
break;
}
case MSG_PLAYER_STATE_CHANGED:
{
StreamPlayer* player = NULL;
- status_t status = message->FindPointer("player", (void**) &player);
+ status_t status = message->FindPointer("player", (void**)&player);
- if (player && status == B_OK) {
+ if (player != NULL && status == B_OK) {
StreamPlayer::PlayState state;
status = message->FindInt32("state", (int32*) &state);
- int stationIndex = fStationList->StationIndex(player->GetStation());
+ int stationIndex = fStationList->StationIndex(
+ player->GetStation());
if (stationIndex >= 0) {
StationListViewItem* stationItem
= fStationList->ItemAt(stationIndex);
@@ -311,12 +328,13 @@ MainWindow::MessageReceived(BMessage* message)
StreamPlayer* player = NULL;
status_t status = message->FindPointer("player", (void**) &player);
float level = message->GetFloat("level", 0.0f);
- if (player && status == B_OK) {
+ if (player != NULL && status == B_OK) {
Station* station = player->GetStation();
StationListViewItem* stationItem = fStationList->Item(station);
- if (stationItem)
+ if (stationItem != NULL)
stationItem->SetFillRatio(level);
}
+
break;
}
@@ -329,22 +347,25 @@ MainWindow::MessageReceived(BMessage* message)
message->GetString(
"streamtitle", B_TRANSLATE("unknown title")));
fStatusBar->SetText(meta.String());
+
break;
}
case MSG_HELP:
{
BUrl userguide = BUrl("/~https://github.com/HaikuArchives/"
- "Haiku-Radio/blob/master/docs/userguide.md");
+ "StreamRadio/blob/master/docs/userguide.md");
userguide.OpenWithPreferredApplication(true);
+
break;
}
case MSG_PARALLEL_PLAYBACK:
{
- allowParallelPlayback = !allowParallelPlayback;
- fSettings->SetAllowParallelPlayback(allowParallelPlayback);
- menuParallelPlayback->SetMarked(allowParallelPlayback);
+ fAllowParallelPlayback = !fAllowParallelPlayback;
+ fSettings->SetAllowParallelPlayback(fAllowParallelPlayback);
+ fMenuParallelPlayback->SetMarked(fAllowParallelPlayback);
+
break;
}
@@ -354,6 +375,7 @@ MainWindow::MessageReceived(BMessage* message)
default:
BWindow::MessageReceived(message);
+ break;
}
}
@@ -363,6 +385,7 @@ MainWindow::QuitRequested()
{
fSettings->Save();
be_app->PostMessage(B_QUIT_REQUESTED);
+
return true;
}
@@ -378,16 +401,24 @@ MainWindow::SetVisible(bool visible)
void
-MainWindow::TogglePlay(StationListViewItem* stationItem)
+MainWindow::_TogglePlay(StationListViewItem* stationItem)
{
- status_t status;
switch (stationItem->State()) {
case StreamPlayer::Stopped:
{
+ status_t status = B_ERROR;
+
StreamPlayer* player
= new StreamPlayer(stationItem->GetStation(), this);
- status = player->InitCheck();
- if ((status == B_OK) && (status = player->Play() == B_OK)) {
+ if (player != NULL) {
+ status = player->InitCheck();
+ if (status == B_OK)
+ status = player->Play();
+ } else {
+ status = B_NO_MEMORY;
+ }
+
+ if (status == B_OK) {
stationItem->SetPlayer(player);
stationItem->StateChanged(StreamPlayer::Playing);
BString success;
@@ -395,94 +426,37 @@ MainWindow::TogglePlay(StationListViewItem* stationItem)
stationItem->GetStation()->Name()->String());
fStatusBar->SetText(success);
fStatusBar->Invalidate();
- activeStations.AddItem(stationItem);
+ fActiveStations.AddItem(stationItem);
} else {
delete player;
player = NULL;
+
BString error;
error.SetToFormat(B_TRANSLATE("Failed playing station %s: %s"),
stationItem->GetStation()->Name()->String(),
strerror(status));
fStatusBar->SetText(error);
}
+
break;
}
+
case StreamPlayer::Buffering:
case StreamPlayer::Playing:
{
StreamPlayer* player = stationItem->Player();
- if (player)
+ if (player != NULL)
player->Stop();
stationItem->StateChanged(StreamPlayer::Stopped);
fStatusBar->SetText(NULL);
- activeStations.RemoveItem(stationItem);
+ fActiveStations.RemoveItem(stationItem);
+
break;
}
- }
-}
-
-
-void
-MainWindow::DisplaySettings()
-{
- return;
-}
-
-void
-MainWindow::DisplayTipOfDay()
-{
- return;
-}
-
-
-void
-MainWindow::SetupActions()
-{
-
- /* KStandardAction::preferences(this,
- SLOT(display_global_settings_dialog()), actionCollection());
-
- KStandardAction::quit(kapp, SLOT(quit()), actionCollection());
-
- showStreamdirectoryAction = new KToggleAction(this);
- showStreamdirectoryAction->setText(m_streamDirectory->windowTitle());
- QList showStreamdirectoryAction_tempShortcutList;
- //showStreamdirectoryAction_tempShortcutList.append(Qt::Key_S);
- //showStreamdirectoryAction_tempShortcutList.append(Qt::Key_MediaRecord);
- //showStreamdirectoryAction_tempShortcutList.append(Qt::CTRL +
- Qt::Key_S);
- //showStreamdirectoryAction_tempShortcutList.append(Qt::META +
- Qt::Key_V);
- showStreamdirectoryAction->setShortcuts(showStreamdirectoryAction_tempShortcutList);
- connect(showStreamdirectoryAction, SIGNAL(toggled(bool)),
- this, SLOT(showStreamdirectory(bool)));
- connect(m_streamDirectory,
- SIGNAL(willAcceptCloseEventFromWindowSystem(bool)),
- showStreamdirectoryAction, SLOT(setChecked(bool)));
- actionCollection()->addAction("showStreamdirectory",
- showStreamdirectoryAction);
- showStreamdirectoryAction->setChecked(settings_general::showStreamdirectory());
-
- KAction *importKradioripperSettingsAction = new KAction(this);
- importKradioripperSettingsAction->setText(
- i18nc("@action:inmenu", "Import KRadioRipper settings"));
- connect(importKradioripperSettingsAction, SIGNAL(triggered(bool)),
- this, SLOT(askForKradioripperImport()));
- actionCollection()->addAction("importKradioripperSettings",
- importKradioripperSettingsAction);
-
- KStandardAction::tipOfDay(this, SLOT(displayTipOfDay()),
- actionCollection());
- */
- return;
-}
-
-
-void
-MainWindow::AskForKradioripperImport()
-{
- // importKradioripperSettings::askForImport();
- return;
+ case StreamPlayer::InActive:
+ default:
+ break;
+ }
}
diff --git a/MainWindow.h b/MainWindow.h
index a4ef641..2af9bb3 100644
--- a/MainWindow.h
+++ b/MainWindow.h
@@ -15,18 +15,12 @@
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 .
+ along with this program. If not, see .
*/
+#ifndef _MAIN_WINDOW_H
+#define _MAIN_WINDOW_H
-#ifndef MAINWINDOW_H
-#define MAINWINDOW_H
-#include "Expander.h"
-#include "RadioSettings.h"
-#include "StationFinder.h"
-#include "StationListView.h"
-#include "StationPanel.h"
-#include "StreamPlayer.h"
#include
#include
#include
@@ -34,6 +28,14 @@
#include
#include
+#include "Expander.h"
+#include "RadioSettings.h"
+#include "StationFinder.h"
+#include "StationListView.h"
+#include "StationPanel.h"
+#include "StreamPlayer.h"
+
+
#define MSG_REFS_RECEIVED 'REFS'
#define MSG_PASTE_URL 'PURL'
#define MSG_SEARCH 'mSRC'
@@ -43,58 +45,32 @@
#define MSG_HELP 'HELP'
#define MSG_PARALLEL_PLAYBACK 'mPAR'
-/** \brief The mainwindow.
- *
- * This class provides the mainwindow and handels the actions, session
- * management, the global setting dialog, the Tip of the day and so on.
- *
- * \note The desctructor of this function will not necesarily be called, so also
- * the children objects will not necesarrily be destroyed. So don't relay on the
- * desctructor of children objects to save data, the application state and so
- * on! */
-class MainWindow : public BWindow
-{
+
+class MainWindow : public BWindow {
public:
- MainWindow();
- virtual ~MainWindow();
+ MainWindow();
+ virtual ~MainWindow();
- virtual void MessageReceived(BMessage* message);
- virtual bool QuitRequested();
- virtual void SetVisible(bool visible);
+ virtual void MessageReceived(BMessage* message);
+ virtual bool QuitRequested();
+
+ virtual void SetVisible(bool visible);
+
+private:
+ void _TogglePlay(StationListViewItem* stationItem);
private:
- RadioSettings* fSettings;
- BMenuBar* fMainMenu;
- StationListView* fStationList;
- StationFinderWindow* fStationFinder;
- StationPanel* fStationPanel;
- BStringView* fStatusBar;
- Expander* fExpander;
- BObjectList activeStations;
- bool allowParallelPlayback;
- BMenuItem* menuParallelPlayback;
-
- void TogglePlay(StationListViewItem* stationItem);
-
- /** Actualizes the status in the status bar and in the tooltip of the system
- * tray icon. */
- void AskForKradioripperImport();
- /** Displays the settings_general_dialog. */
- void DisplaySettings();
- /** Displays the tip of the day (independently from if the user
- * has disabled them or not). */
- void DisplayTipOfDay();
- /** Sets the visibility of the streamdirectory and saves this value also in
- * the config file.
- * @param visible Choose \e true to show the streamdirectory and \e false to
- * hide it. \note If #MainWindow is not visible, the streamdirectory will be
- * hidden indepentendly of the parameter. */
-
- /** Sets up the actions that are supported by this class. */
- void SetupActions();
- /** Sets up the dock widget with the stream directory. */
- void SetupStreamDirectory();
- void SaveSettings();
+ RadioSettings* fSettings;
+ BMenuBar* fMainMenu;
+ StationListView* fStationList;
+ StationFinderWindow* fStationFinder;
+ StationPanel* fStationPanel;
+ BStringView* fStatusBar;
+ Expander* fExpander;
+ BObjectList fActiveStations;
+ bool fAllowParallelPlayback;
+ BMenuItem* fMenuParallelPlayback;
};
-#endif
+
+#endif // _MAIN_WINDOW_H
diff --git a/Makefile b/Makefile
index 7c3bf43..8123bcd 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-## Haiku Generic Makefile v2.6 ##
+## Haiku Generic Makefile v2.6 ##
## Fill in this file to specify the project being created, and the referenced
## Makefile-Engine will do all of the hard work for you. This handles any
@@ -14,7 +14,7 @@ V_MINOR = 4
V_VARIETY = B_APPV_DEVELOPMENT
V_BUILD = 1
-TARGET_DIR := ./dist
+TARGET_DIR := dist
PACKAGE = $(TARGET_DIR)/$(NAME)_$(VERSION)-$(ARCH).hpkg
# The type of binary, must be one of:
@@ -25,35 +25,34 @@ PACKAGE = $(TARGET_DIR)/$(NAME)_$(VERSION)-$(ARCH).hpkg
TYPE = APP
# If you plan to use localization, specify the application's MIME signature.
-APP_MIME_SIG = application/x-vnd.Fishpond-Radio
+APP_MIME_SIG = application/x-vnd.Fishpond-StreamRadio
# The following lines tell Pe and Eddie where the SRCS, RDEFS, and RSRCS are
# so that Pe and Eddie can fill them in for you.
#%{
-# @src->@
+# @src->@
-# Specify the source files to use. Full paths or paths relative to the
+# Specify the source files to use. Full paths or paths relative to the
# Makefile can be included. All files, regardless of directory, will have
# their object files created in the common object directory. Note that this
# means this Makefile will not work correctly if two source files with the
# same name (source.c or source.cpp) are included from different directories.
# Also note that spaces in folder names do not work well with this Makefile.
SRCS := About.cpp \
- Expander.cpp \
- HttpUtils.cpp \
- MainWindow.cpp \
- RadioApp.cpp \
- RadioSettings.cpp \
- Station.cpp \
- StationFinder.cpp \
- StationFinderListenLive.cpp \
- StationFinderRadioNetwork.cpp \
- StationListView.cpp \
- StationPanel.cpp \
- StreamIO.cpp \
- StreamPlayer.cpp \
- Utils.cpp
-
+ Expander.cpp \
+ HttpUtils.cpp \
+ MainWindow.cpp \
+ RadioApp.cpp \
+ RadioSettings.cpp \
+ Station.cpp \
+ StationFinder.cpp \
+ StationFinderListenLive.cpp \
+ StationFinderRadioNetwork.cpp \
+ StationListView.cpp \
+ StationPanel.cpp \
+ StreamIO.cpp \
+ StreamPlayer.cpp \
+ Utils.cpp
# Specify the resource definition files to use. Full or relative paths can be
# used.
@@ -61,10 +60,10 @@ RDEFS = StreamRadio.rdef
# Specify the resource files to use. Full or relative paths can be used.
# Both RDEFS and RSRCS can be utilized in the same Makefile.
-RSRCS =
+RSRCS =
# End Pe/Eddie support.
-# @<-src@
+# @<-src@
#%}
# Specify libraries to link against.
@@ -86,20 +85,19 @@ LIBS = $(STDCPPLIBS) be translation bnetapi media localestub shared
# to the Makefile. The paths included are not parsed recursively, so
# include all of the paths where libraries must be found. Directories where
# source files were specified are automatically included.
-LIBPATHS =
+LIBPATHS =
# Additional paths to look for system headers. These use the form
# "#include ". Directories that contain the files in SRCS are
# NOT auto-included here.
SYSTEM_INCLUDE_PATHS = /boot/system/develop/headers/private/media \
- /boot/system/develop/headers/os/codec \
- /boot/system/develop/headers/private/media/experimental \
- /boot/system/develop/headers/private/shared
+ /boot/system/develop/headers/private/media/experimental \
+ /boot/system/develop/headers/private/shared
# Additional paths paths to look for local headers. These use the form
# #include "header". Directories that contain the files in SRCS are
# automatically included.
-LOCAL_INCLUDE_PATHS =
+LOCAL_INCLUDE_PATHS =
# Specify the level of optimization that you want. Specify either NONE (O0),
# SOME (O1), FULL (O2), or leave blank (for the default optimization level).
@@ -117,25 +115,25 @@ LOCALES = ca de en_GB en es ro
# use. For example, setting DEFINES to "DEBUG=1" will cause the compiler
# option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" would pass
# "-DDEBUG" on the compiler's command line.
-DEFINES = HAIKU_TARGET_PLATFORM_HAIKU
+DEFINES =
# Specify the warning level. Either NONE (suppress all warnings),
# ALL (enable all warnings), or leave blank (enable default warnings).
-WARNINGS =
+WARNINGS = ALL
# With image symbols, stack crawls in the debugger are meaningful.
# If set to "TRUE", symbols will be created.
-SYMBOLS :=
+SYMBOLS :=
# Includes debug information, which allows the binary to be debugged easily.
# If set to "TRUE", debug info will be created.
-DEBUGGER :=
+DEBUGGER :=
# Specify any additional compiler flags to be used.
-COMPILER_FLAGS =
+COMPILER_FLAGS =
# Specify any additional linker flags to be used.
-LINKER_FLAGS =
+LINKER_FLAGS =
# Specify the version of this binary. Example:
# -app 3 4 0 d 0 -short 340 -long "340 "`echo -n -e '\302\251'`"1999 GNU GPL"
@@ -149,11 +147,11 @@ APP_VERSION := -app $(V_MAJOR) $(V_MIDDLE) $(V_MINOR) $(V_VARIETY) $(V_BUILD) -s
# will instruct the "driverinstall" rule to place a symlink to your driver's
# binary in ~/add-ons/kernel/drivers/dev/video/usb, so that your driver will
# appear at /dev/video/usb when loaded. The default is "misc".
-DRIVER_PATH =
+DRIVER_PATH =
VERSION_RDEF = $(NAME)-version.rdef
RDEFS += $(VERSION_RDEF)
-
+
## Include the Makefile-Engine
DEVEL_DIRECTORY = \
$(shell findpaths -e B_FIND_PATH_DEVELOP_DIRECTORY etc/makefile-engine)
@@ -168,7 +166,7 @@ ARCH_PACKAGE_INFO = $(OBJ_DIR)/PackageInfo_$(ARCH)
$(ARCH_PACKAGE_INFO): Makefile
cat ./PackageInfo | sed 's/$$VERSION/$(VERSION)/' | sed 's/$$ARCH/$(ARCH)/' > $(ARCH_PACKAGE_INFO)
-
+
$(PACKAGE): $(TARGET_DIR)/$(NAME) $(ARCH_PACKAGE_INFO)
mkdir -p $(PACKAGE_DIR)/apps
mkdir -p $(PACKAGE_DIR)/data/deskbar/menu/Applications
@@ -183,7 +181,7 @@ clean: rdefclean distclean
rdefclean:
-rm $(VERSION_RDEF)
-
+
distclean:
-rm $(TARGET_DIR)/$(NAME)
diff --git a/PackageInfo b/PackageInfo
index ff49442..4c67101 100644
--- a/PackageInfo
+++ b/PackageInfo
@@ -2,8 +2,8 @@ name StreamRadio
version $VERSION
summary "Find and play internet radio stations"
description "Start the application. Run a search for a radio station name. If you found one you like, add it to the main list. There you can play it, visit its homepage or change the station information.
-Searches use Radio Network, a service that offers a network API to its database (http://www.radio-browser.info).
-Stations including all their attributes are saved as Shoutcast playlist files in ~/settings/Stations so they are available for other apps.
+Searches use Radio Network, a service that offers a network API to its database (https://www.radio-browser.info/gui).
+Stations including all their attributes are saved as Shoutcast playlist files in ~/config/settings/Stations so they are available for other apps.
Please report back any bugs at /~https://github.com/HaikuArchives/StreamRadio/issues.
@@ -37,5 +37,4 @@ provides {
}
requires {
haiku
- lib:libxml2
}
diff --git a/README.md b/README.md
index dacab2a..b5092bb 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
-# Haiku-Radio
+# StreamRadio
![Screenshot](screenshot.png)
-Haiku native application to search for an listen to internet radio stations.
+An application native to Haiku to search for and listen to internet radio stations.
# [StreamRadio user guide](docs/userguide.md)
diff --git a/RadioApp.cpp b/RadioApp.cpp
index 2d8f6c0..24c1d0f 100644
--- a/RadioApp.cpp
+++ b/RadioApp.cpp
@@ -1,3 +1,21 @@
+/*
+ * 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 .
+ */
+
+
#include
#include "About.h"
@@ -6,13 +24,14 @@
#include "StationFinderListenLive.h"
#include "StationFinderRadioNetwork.h"
+
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "RadioApp"
RadioApp::RadioApp()
:
- BApplication(appSignature),
+ BApplication(kAppSignature),
fArgvMessage(NULL)
{
}
@@ -28,7 +47,7 @@ RadioApp::ReadyToRun()
{
mainWindow = new MainWindow();
mainWindow->Show();
- if (fArgvMessage)
+ if (fArgvMessage != NULL)
mainWindow->PostMessage(fArgvMessage);
}
@@ -44,6 +63,7 @@ void
RadioApp::ArgvReceived(int32 argc, char** argv)
{
fArgvMessage = new BMessage(B_REFS_RECEIVED);
+
int32 count = 0;
for (int32 i = 1; i < argc; i++) {
char* arg = argv[i];
@@ -54,6 +74,7 @@ RadioApp::ArgvReceived(int32 argc, char** argv)
"otherwise it is added.\n"));
continue;
}
+
BEntry entry(arg);
if (entry.Exists()) {
entry_ref entryRef;
@@ -62,8 +83,9 @@ RadioApp::ArgvReceived(int32 argc, char** argv)
count++;
}
}
- if (count) {
- if (mainWindow)
+
+ if (count != 0) {
+ if (mainWindow != NULL)
mainWindow->PostMessage(fArgvMessage);
} else {
delete fArgvMessage;
@@ -78,6 +100,8 @@ RadioApp::AboutRequested()
About* about = new About();
about->Show();
}
+
+
/**
* Application entry point
*/
@@ -85,9 +109,14 @@ int
main(int argc, char* argv[])
{
StationFinderRadioNetwork::RegisterSelf();
- StationFinderListenLive::RegisterSelf();
+
+ // FIXME: "listenlive.eu" no longer seems to exist, though it looks like
+ // "radiomap.eu" might be its successor? This plugin crashes after searching
+ // anyway...
+ // StationFinderListenLive::RegisterSelf();
new RadioApp();
be_app->Run();
+
delete be_app;
}
diff --git a/RadioApp.h b/RadioApp.h
index efb90d2..0738e29 100644
--- a/RadioApp.h
+++ b/RadioApp.h
@@ -1,36 +1,50 @@
/*
- * File: RadioApp.h
- * Author: Kai Niessen
+ * Copyright (C) 2017 Kai Niessen
*
- * Created on 26. Februar 2013, 02:40
+ * 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 _RADIO_APP_H
+#define _RADIO_APP_H
-#ifndef MAIN_H
-#define MAIN_H
-#include "MainWindow.h"
-#include "RadioSettings.h"
#include
#include
-#define appSignature "application/x-vnd.Fishpond-Radio"
+#include "MainWindow.h"
+#include "RadioSettings.h"
-/**
- * Application class
- */
-class RadioApp : BApplication
-{
+
+#define kAppSignature "application/x-vnd.Fishpond-StreamRadio"
+
+
+class RadioApp : BApplication {
public:
- RadioApp();
- ~RadioApp();
- virtual void ReadyToRun();
- virtual void RefsReceived(BMessage* message);
- virtual void ArgvReceived(int32 argc, char** argv);
- virtual void AboutRequested();
- MainWindow* mainWindow;
- RadioSettings Settings;
+ RadioApp();
+ ~RadioApp();
+
+ virtual void ReadyToRun();
+ virtual void RefsReceived(BMessage* message);
+ virtual void ArgvReceived(int32 argc, char** argv);
+ virtual void AboutRequested();
+
+ MainWindow* mainWindow;
+
+ RadioSettings Settings;
private:
- BMessage* fArgvMessage;
+ BMessage* fArgvMessage;
};
-#endif /* MAIN_H */
+
+
+#endif // _RADIO_APP_H
diff --git a/RadioSettings.cpp b/RadioSettings.cpp
index e6fb1c6..5968db0 100644
--- a/RadioSettings.cpp
+++ b/RadioSettings.cpp
@@ -1,9 +1,21 @@
/*
- * File: RadioSettings.cpp
- * Author: user
+ * Copyright (C) 2017 Kai Niessen
*
- * Created on 26. Februar 2013, 04:01
+ * 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 .
*/
+
+
#include
#include
#include
@@ -12,7 +24,8 @@
#include "Debug.h"
#include "RadioSettings.h"
-const char* SettingsFileName = "StreamRadio.settings";
+
+const char* kSettingsFileName = "StreamRadio.settings";
StationsList::StationsList()
@@ -24,7 +37,7 @@ StationsList::StationsList()
StationsList::~StationsList()
{
- for (int i = CountItems() - 1; i >= 0; i--)
+ for (int32 i = CountItems() - 1; i >= 0; i--)
BObjectList::RemoveItem(ItemAt(i), true);
}
@@ -34,6 +47,7 @@ StationsList::AddItem(Station* station)
{
if (FindItem(station->Name()))
return false;
+
return BObjectList::AddItem(station);
}
@@ -41,9 +55,9 @@ StationsList::AddItem(Station* station)
bool
StationsList::RemoveItem(BString* stationName)
{
- Station* s = FindItem(stationName);
- if (s)
- return BObjectList::RemoveItem(s, true);
+ Station* station = FindItem(stationName);
+ if (station != NULL)
+ return BObjectList::RemoveItem(station, true);
else
return false;
}
@@ -59,11 +73,12 @@ StationsList::RemoveItem(Station* station)
Station*
StationsList::FindItem(BString* stationName)
{
- for (int i = 0; i < CountItems(); i++) {
+ for (int32 i = 0; i < CountItems(); i++) {
Station* item = ItemAt(i);
if (stationName->Compare(item->Name()->String()) == 0)
return item;
}
+
return NULL;
}
@@ -77,9 +92,10 @@ StationsList::Load()
while ((status = stationsDir->GetNextEntry(&stationEntry)) == B_OK) {
Station* station = Station::LoadFromPlsFile(stationEntry.Name());
- if (station && FindItem(station->Name()) == NULL)
+ if (station != NULL && FindItem(station->Name()) == NULL)
AddItem(station);
}
+
return B_OK;
}
@@ -96,6 +112,7 @@ StationsList::Save()
while ((status = stationsDir->GetNextEntry(&stationEntry)) == B_OK)
stationEntry.Remove();
+
EachListItemIgnoreResult(this, &Station::Save);
}
@@ -105,7 +122,7 @@ RadioSettings::RadioSettings()
BMessage()
{
Stations = new StationsList();
- Load();
+ _Load();
}
@@ -124,6 +141,27 @@ RadioSettings::~RadioSettings()
}
+status_t
+RadioSettings::Save()
+{
+ status_t status;
+ BPath configPath;
+ BDirectory configDir;
+ BFile configFile;
+ status = find_directory(B_USER_SETTINGS_DIRECTORY, &configPath);
+ if (status != B_OK)
+ return status;
+
+ configDir.SetTo(configPath.Path());
+ status = configDir.CreateFile(kSettingsFileName, &configFile);
+ Flatten(&configFile);
+
+ Stations->Save();
+
+ return B_OK;
+}
+
+
bool
RadioSettings::GetAllowParallelPlayback()
{
@@ -154,7 +192,7 @@ RadioSettings::SetStationFinderName(const char* name)
status_t
-RadioSettings::Load()
+RadioSettings::_Load()
{
status_t status;
BPath configPath;
@@ -166,28 +204,9 @@ RadioSettings::Load()
return status;
configDir.SetTo(configPath.Path());
- status = configFile.SetTo(&configDir, SettingsFileName, B_READ_ONLY);
+ status = configFile.SetTo(&configDir, kSettingsFileName, B_READ_ONLY);
status = Unflatten(&configFile);
status = Stations->Load();
- return status;
-}
-
-
-status_t
-RadioSettings::Save()
-{
- status_t status;
- BPath configPath;
- BDirectory configDir;
- BFile configFile;
- status = find_directory(B_USER_SETTINGS_DIRECTORY, &configPath);
- if (status != B_OK)
- return status;
- configDir.SetTo(configPath.Path());
- status = configDir.CreateFile(SettingsFileName, &configFile);
- Flatten(&configFile);
-
- Stations->Save();
- return B_OK;
+ return status;
}
diff --git a/RadioSettings.h b/RadioSettings.h
index 71bd541..216036e 100644
--- a/RadioSettings.h
+++ b/RadioSettings.h
@@ -1,45 +1,63 @@
/*
- * File: RadioSettings.h
- * Author: user
+ * Copyright (C) 2017 Kai Niessen
*
- * Created on 26. Februar 2013, 04:01
+ * 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 _RADIO_SETTINGS_H
+#define _RADIO_SETTINGS_H
-#ifndef RADIOSETTINGS_H
-#define RADIOSETTINGS_H
-#include "Station.h"
#include
#include
#include
-class StationsList : public BObjectList
-{
+#include "Station.h"
+
+
+class StationsList : public BObjectList {
public:
- StationsList();
- virtual ~StationsList();
- virtual bool AddItem(Station* station);
- bool RemoveItem(Station* station);
- bool RemoveItem(BString* StationName);
- Station* FindItem(BString* Name);
- status_t Load();
- void Save();
+ StationsList();
+ virtual ~StationsList();
+
+ virtual bool AddItem(Station* station);
+ bool RemoveItem(Station* station);
+ bool RemoveItem(BString* StationName);
+ Station* FindItem(BString* Name);
+
+ status_t Load();
+ void Save();
};
-class RadioSettings : private BMessage
-{
+class RadioSettings : private BMessage {
public:
- RadioSettings();
- RadioSettings(const RadioSettings& orig);
- virtual ~RadioSettings();
- status_t Save();
- const char* StationFinderName();
- void SetStationFinderName(const char* name);
- StationsList* Stations;
- bool GetAllowParallelPlayback();
- void SetAllowParallelPlayback(bool set);
+ RadioSettings();
+ RadioSettings(const RadioSettings& orig);
+ virtual ~RadioSettings();
+
+ status_t Save();
+
+ const char* StationFinderName();
+ void SetStationFinderName(const char* name);
+
+ bool GetAllowParallelPlayback();
+ void SetAllowParallelPlayback(bool set);
+
+ StationsList* Stations;
private:
- status_t Load();
+ status_t _Load();
};
-#endif /* RADIOSETTINGS_H */
+
+
+#endif // _RADIO_SETTINGS_H
diff --git a/Station.cpp b/Station.cpp
index 41a63dc..c136d4f 100644
--- a/Station.cpp
+++ b/Station.cpp
@@ -1,17 +1,36 @@
/*
- * File: Station.cpp
- * Author: Kai Niessen, Jacob Secunda
+ * Copyright (C) 2017 Kai Niessen
+ * Copyright (C) 2020 Jacob Secunda
*
- * Created on 26. Februar 2013, 04:08
+ * 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 .
*/
+
+
#include "Station.h"
-#include "Debug.h"
-#include "HttpUtils.h"
+
+#include
+#include
+#include
+#include
+#include
+
#include
#include
#include
#include
#include
+#include
#include
#include
#include
@@ -26,18 +45,17 @@
#include
#include
#include
-#include
-#include
-#include
-#include
-#include
-#include
+
+#include "Debug.h"
+#include "HttpUtils.h"
+
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "Station"
-const char* SubDirStations = "Stations";
-const char* MimePls = "audio/x-scpls";
+
+const char* kSubDirStations = "Stations";
+const char* kMimePls = "audio/x-scpls";
Station::Station(BString name, BString uri)
@@ -46,6 +64,8 @@ Station::Station(BString name, BString uri)
fStreamUrl(uri),
fStationUrl(B_EMPTY_STRING),
fGenre(B_EMPTY_STRING),
+ fCountry(B_EMPTY_STRING),
+ fLanguage(B_EMPTY_STRING),
fSource(B_EMPTY_STRING),
fMime(B_EMPTY_STRING),
fEncoding(0),
@@ -58,7 +78,7 @@ Station::Station(BString name, BString uri)
fChannels(0),
fFlags(0)
{
- checkFlags();
+ CheckFlags();
if (Flags(STATION_URI_VALID) && !Flags(STATION_HAS_FORMAT))
Probe();
}
@@ -73,17 +93,17 @@ Station::Station(const Station& orig)
fCountry(orig.fCountry),
fLanguage(orig.fLanguage),
fSource(B_EMPTY_STRING),
+ fEncoding(orig.fEncoding),
fRating(orig.fRating),
fBitRate(orig.fBitRate),
fSampleRate(orig.fSampleRate),
fUniqueIdentifier(orig.fUniqueIdentifier),
- fChannels(orig.fChannels),
- fEncoding(orig.fEncoding),
- fMetaInterval(orig.fMetaInterval)
+ fMetaInterval(orig.fMetaInterval),
+ fChannels(orig.fChannels)
{
fMime.SetTo(orig.fMime.Type());
fLogo = (orig.fLogo) ? new BBitmap(orig.fLogo) : NULL;
- unsaved = true;
+ fUnsaved = true;
}
@@ -106,9 +126,11 @@ Station::LoadFromPlsFile(BString Name)
{
BEntry stationEntry;
stationEntry.SetTo(StationDirectory(), Name);
+
Station* station = Load(Name, &stationEntry);
- if (station)
- station->unsaved = false;
+ if (station != NULL)
+ station->fUnsaved = false;
+
return station;
}
@@ -119,22 +141,24 @@ Station::Save()
status_t status;
BFile stationFile;
BDirectory* stationDir = StationDirectory();
-
- if (!stationDir)
- return B_ERROR;
+ if (stationDir == NULL)
+ return B_NO_MEMORY;
status = stationDir->CreateFile(fName, &stationFile, false);
if (status != B_OK)
return status;
+
BString content;
content << "[playlist]\nNumberOfEntries=1\nFile1=" << fStreamUrl << "\n";
stationFile.Write(
content.LockBuffer(-1), content.CountBytes(0, content.CountChars()));
content.UnlockBuffer();
+
status = stationFile.Lock();
+
status = stationFile.WriteAttrString("META:url", &fStreamUrl.UrlString());
status = stationFile.WriteAttr(
- "BEOS:TYPE", B_MIME_TYPE, 0, MimePls, strlen(MimePls));
+ "BEOS:TYPE", B_MIME_TYPE, 0, kMimePls, strlen(kMimePls));
status = stationFile.WriteAttr(
"META:bitrate", B_INT32_TYPE, 0, &fBitRate, sizeof(fBitRate));
status = stationFile.WriteAttr(
@@ -160,13 +184,14 @@ Station::Save()
status = stationFile.WriteAttrString("META:uniqueidentifier",
&fUniqueIdentifier);
status = stationFile.Unlock();
+
BNodeInfo stationInfo;
stationInfo.SetTo(&stationFile);
- if (fLogo) {
+ if (fLogo != NULL) {
BMessage archive;
fLogo->Archive(&archive);
ssize_t archiveSize = archive.FlattenedSize();
- char* archiveBuffer = (char*) malloc(archiveSize);
+ char* archiveBuffer = (char*)malloc(archiveSize);
archive.Flatten(archiveBuffer, archiveSize);
stationFile.WriteAttr("logo", 'BBMP', 0LL, archiveBuffer, archiveSize);
free(archiveBuffer);
@@ -174,12 +199,14 @@ Station::Save()
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);
@@ -191,11 +218,14 @@ Station::Save()
canvas->UnlockLooper();
icon->RemoveChild(canvas);
stationInfo.SetIcon(icon, B_MINI_ICON);
+
delete icon;
delete canvas;
}
- stationInfo.SetType(MimePls);
+
+ stationInfo.SetType(kMimePls);
stationFile.Unset();
+
return status;
}
@@ -208,16 +238,20 @@ Station::RetrieveStreamUrl()
status_t status = B_ERROR;
BString contentType("*/*");
- BMallocIO* plsData
- = HttpUtils::GetAll(fSource, NULL, 100000, &contentType, 2000);
- if (plsData)
- status
- = parseUrlReference((const char*) plsData->Buffer(), contentType);
- delete plsData;
+
+ BMallocIO* plsData = HttpUtils::GetAll(fSource, NULL, 100000, &contentType,
+ 2000);
+ if (plsData != NULL) {
+ status = ParseUrlReference((const char*) plsData->Buffer(),
+ contentType);
+ delete plsData;
+ }
+
if (status != B_OK && contentType.StartsWith("audio/")) {
SetStreamUrl(fSource);
return B_OK;
}
+
return status;
}
@@ -254,57 +288,69 @@ Station::Probe()
// of streams using HTTPS and load balancing between two or more different
// IP's should be small, anyway.
- if (fStreamUrl.Protocol() == "https")
- buffer = HttpUtils::GetAll(
- fStreamUrl, &headers, 2 * 1000 * 1000, &contentType, 4096);
- else {
+ if (fStreamUrl.Protocol() == "https") {
+ buffer = HttpUtils::GetAll(fStreamUrl, &headers, 2 * 1000 * 1000,
+ &contentType, 4096);
+ } else {
status_t resolveStatus = HttpUtils::CheckPort(fStreamUrl, resolvedUrl);
if (resolveStatus != B_OK)
return B_ERROR;
+
buffer = HttpUtils::GetAll(
*resolvedUrl, &headers, 2 * 1000 * 1000, &contentType, 4096);
delete resolvedUrl;
}
+
#ifdef DEBUGGING
- for (int i = 0; i < headers.CountHeaders(); i++)
+ for (int32 i = 0; i < headers.CountHeaders(); i++)
TRACE("Header: %s\r\n", headers.HeaderAt(i).Header());
#endif
+
if (buffer == NULL) {
fFlags &= !STATION_URI_VALID;
return B_ERROR;
}
+
if (headers.CountHeaders() == 0) {
fFlags &= !STATION_URI_VALID;
return B_TIMED_OUT;
}
- int index;
+ int32 index;
if ((index = headers.HasHeader("content-type")) >= 0)
fMime.SetTo(headers.HeaderValue("content-type"));
+
// If the station has no name, try to use the Icy-Name header
if ((index = headers.HasHeader("Icy-Name")) >= 0 && fName.IsEmpty())
SetName(headers.HeaderValue("Icy-Name"));
+
if ((index = headers.HasHeader("Icy-Br")) >= 0)
fBitRate = atoi(headers[index].Value()) * 1000;
+
if ((index = headers.HasHeader("Icy-Genre")) >= 0)
fGenre = headers[index].Value();
+
if ((index = headers.HasHeader("Icy-Url")) >= 0
&& strlen(headers[index].Value()) > 0)
fStationUrl.SetUrlString(headers[index].Value());
+
if ((index = headers.HasHeader("Ice-Audio-Info")) >= 0) {
BString audioInfo(headers[index].Value());
BStringList audioInfoList;
if (audioInfo.Split(";", false, audioInfoList)) {
for (int32 i = 0; i < audioInfoList.CountStrings(); i++) {
BString audioInfoItem = audioInfoList.StringAt(i);
+
if (audioInfoItem.StartsWith("ice-samplerate=")) {
audioInfoItem.Remove(0, 15);
fSampleRate = atoi(audioInfoItem.String());
}
+
if (audioInfoItem.StartsWith("ice-bitrate=")) {
audioInfoItem.Remove(0, 12);
fBitRate = atoi(audioInfoItem.String()) * 1000;
}
+
if (audioInfoItem.StartsWith("ice-channels=")) {
audioInfoItem.Remove(0, 13);
fChannels = atoi(audioInfoItem.String());
@@ -312,13 +358,15 @@ Station::Probe()
}
}
}
+
if ((index = headers.HasHeader("Icy-metaint")) >= 0)
fMetaInterval = atoi(headers[index].Value());
- checkFlags();
- unsaved = true;
+ CheckFlags();
+ fUnsaved = true;
ProbeBuffer(buffer);
delete buffer;
+
return B_OK;
}
@@ -328,7 +376,9 @@ Station::ProbeBuffer(BPositionIO* buffer)
{
status_t status = B_OK;
BMediaFile mediaFile(buffer);
- if ((status = mediaFile.InitCheck()) != B_OK)
+
+ status = mediaFile.InitCheck();
+ if (status != B_OK)
return status;
if (mediaFile.CountTracks() < 1)
@@ -336,8 +386,8 @@ Station::ProbeBuffer(BPositionIO* buffer)
BMediaTrack* mediaTrack = mediaFile.TrackAt(0);
- media_format encodedFormat, decodedFormat;
- media_codec_info codecInfo;
+ media_format encodedFormat;
+ media_format decodedFormat;
status = mediaTrack->EncodedFormat(&encodedFormat);
if (status != B_OK)
@@ -350,74 +400,97 @@ Station::ProbeBuffer(BPositionIO* buffer)
fFrameSize = encodedFormat.u.encoded_audio.frame_size;
status = mediaTrack->DecodedFormat(&decodedFormat);
- checkFlags();
+ CheckFlags();
+
return status;
}
status_t
-Station::parseUrlReference(const char* body, const char* mime)
+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;
- for (int i = 0; i < 3; i++) {
- char* match = regFind(body, patterns[i]);
- if (match) {
+ for (int32 i = 0; i < 3; i++) {
+ char* match = RegFind(body, patterns[i]);
+ if (match != NULL) {
fStreamUrl.SetUrlString(match);
free(match);
- match = regFind(body, patterns[3]);
- if (match) {
+
+ match = RegFind(body, patterns[3]);
+ if (match != NULL) {
SetName(match);
free(match);
}
+
return B_OK;
}
}
+
return B_ERROR;
}
Station*
-Station::Load(BString Name, BEntry* entry)
+Station::Load(BString name, BEntry* entry)
{
off_t size;
status_t status;
- Station* station = new Station(Name);
+
+ Station* station = new Station(name);
+ if (station == NULL)
+ return station;
+
BFile file;
file.SetTo(entry, B_READ_ONLY);
BNodeInfo stationInfo;
stationInfo.SetTo(&file);
BString readString;
+
status = file.ReadAttrString("META:url", &readString);
+
station->fStreamUrl.SetUrlString(readString);
+
status = file.ReadAttrString("META:genre", &station->fGenre);
+
status = file.ReadAttrString("META:country", &station->fCountry);
+
status = file.ReadAttrString("META:language", &station->fLanguage);
+
status = file.ReadAttr("META:bitrate", B_INT32_TYPE, 0, &station->fBitRate,
sizeof(station->fBitRate));
+
status = file.ReadAttr("META:rating", B_INT32_TYPE, 0, &station->fRating,
sizeof(station->fRating));
+
status = file.ReadAttr("META:interval", B_INT32_TYPE, 0,
&station->fMetaInterval, sizeof(station->fMetaInterval));
+
status = file.ReadAttr("META:samplerate", B_INT32_TYPE, 0,
&station->fSampleRate, sizeof(station->fSampleRate));
+
status = file.ReadAttr("META:channels", B_INT32_TYPE, 0,
&station->fChannels, sizeof(station->fChannels));
+
status = file.ReadAttr("META:encoding", B_INT32_TYPE, 0,
&station->fEncoding, sizeof(station->fEncoding));
+
status = file.ReadAttr("META:framesize", B_INT32_TYPE, 0,
&station->fFrameSize, sizeof(station->fFrameSize));
+
status = file.ReadAttrString("META:mime", &readString);
station->fMime.SetTo(readString);
+
status = file.ReadAttrString("META:source", &readString);
station->fSource.SetUrlString(readString);
+
status = file.ReadAttrString("META:stationurl", &readString);
station->fStationUrl.SetUrlString(readString);
+
status = file.ReadAttrString("META:uniqueidentifier", &readString);
station->fUniqueIdentifier.SetTo(readString);
@@ -432,9 +505,11 @@ Station::Load(BString Name, BEntry* entry)
station->fLogo = (BBitmap*) BBitmap::Instantiate(&archive);
} else
station->fLogo = new BBitmap(BRect(0, 0, 32, 32), B_RGB32);
+
status = stationInfo.GetIcon(station->fLogo, B_LARGE_ICON);
if (status != 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) {
@@ -452,70 +527,86 @@ Station::Load(BString Name, BEntry* entry)
status = file.GetSize(&size);
if (size > 10000)
return NULL;
- char* buffer = (char*) malloc(size);
+
+ char* buffer = (char*)malloc(size);
file.Read(buffer, size);
+
char mime[64];
stationInfo.GetType(mime);
- station->parseUrlReference(buffer, mime);
+ station->ParseUrlReference(buffer, mime);
+
free(buffer);
}
- if (Name == B_EMPTY_STRING)
+
+ if (name == B_EMPTY_STRING)
station->fName.SetTo(entry->Name());
- station->checkFlags();
+ station->CheckFlags();
if (station->InitCheck() != B_OK) {
delete station;
return NULL;
- } else
- return station;
+ }
+
+ return station;
}
char*
-Station::regFind(const char* Text, const char* Pattern)
+Station::RegFind(const char* text, const char* pattern)
{
regex_t patternBuffer;
regmatch_t matchBuffer[20];
int result;
char* match = NULL;
+
memset(&patternBuffer, 0, sizeof(patternBuffer));
memset(matchBuffer, 0, sizeof(matchBuffer));
+
result = regcomp(
- &patternBuffer, Pattern, REG_EXTENDED | REG_NEWLINE | REG_ICASE);
- result = regexec(&patternBuffer, Text, 20, matchBuffer, 0);
- if (result == 0 && matchBuffer[1].rm_eo > -1)
- match = strndup(Text + matchBuffer[1].rm_so,
+ &patternBuffer, pattern, REG_EXTENDED | REG_NEWLINE | REG_ICASE);
+ result = regexec(&patternBuffer, text, 20, matchBuffer, 0);
+ if (result == 0 && matchBuffer[1].rm_eo > -1) {
+ match = strndup(text + matchBuffer[1].rm_so,
matchBuffer[1].rm_eo - matchBuffer[1].rm_so);
+ }
+
return match;
}
Station*
-Station::LoadIndirectUrl(BString& sUrl)
+Station::LoadIndirectUrl(BString& shoutCastUrl)
{
status_t status;
const char* patternTitle = "]*>(.*?)]*>";
const char* patternIcon
= "Write("", 1);
- const char* body = (char*) dataIO->Buffer();
+ const char* body = (char*)dataIO->Buffer();
+
int32 pos = contentType.FindFirst(';');
if (pos >= 0)
contentType.Truncate(pos);
- status = station->parseUrlReference(body, contentType.String());
+
+ status = station->ParseUrlReference(body, contentType.String());
if (status != B_OK && contentType.StartsWith(("audio/")))
station->SetStreamUrl(url);
- station->fSource.SetUrlString(sUrl);
+
+ station->fSource.SetUrlString(shoutCastUrl);
+
delete dataIO;
if (!station->fStreamUrl.IsValid()) {
@@ -527,7 +618,6 @@ Station::LoadIndirectUrl(BString& sUrl)
* Check for name and logo on same server by calling main page
*/
-
BUrl finalUrl = station->fStationUrl;
if ((!finalUrl.HasPort() || finalUrl.Port() == 80)
&& (!finalUrl.HasPath() || finalUrl.Path().IsEmpty()
@@ -536,32 +626,35 @@ Station::LoadIndirectUrl(BString& sUrl)
station->SetName("New Station");
} else
finalUrl.SetFragment(NULL);
+
finalUrl.SetRequest(NULL);
finalUrl.SetPath(NULL);
finalUrl.SetPort(80);
- sUrl.SetTo(finalUrl.UrlString());
- sUrl.RemoveCharsSet("#?");
- finalUrl.SetUrlString(sUrl);
+
+ shoutCastUrl.SetTo(finalUrl.UrlString());
+ shoutCastUrl.RemoveCharsSet("#?");
+ finalUrl.SetUrlString(shoutCastUrl);
dataIO = HttpUtils::GetAll(finalUrl);
- if (dataIO) {
+ if (dataIO != NULL) {
dataIO->Write(&"", 1);
body = (char*) dataIO->Buffer();
- char* title = regFind(body, patternTitle);
- if (title)
+ char* title = RegFind(body, patternTitle);
+ if (title != NULL)
station->fName.SetTo(title);
- char* icon = regFind(body, patternIcon);
- if (icon)
+ char* icon = RegFind(body, patternIcon);
+ if (icon != NULL)
finalUrl.SetPath(BString(icon));
contentType = "image/*";
BMallocIO* iconIO
= HttpUtils::GetAll(finalUrl, NULL, 10000, &contentType, 2000);
- if (iconIO) {
+ if (iconIO != NULL) {
iconIO->Seek(0, SEEK_SET);
station->fLogo = BTranslationUtils::GetBitmap(iconIO);
+
delete iconIO;
}
@@ -585,74 +678,85 @@ Station::SetName(BString name)
}
fName.SetTo(name);
- cleanName();
+ CleanName();
if (fName.IsEmpty())
fFlags &= !STATION_HAS_NAME;
else
fFlags |= STATION_HAS_NAME;
- if (entry) {
+ if (entry != NULL) {
entry->Rename(fName);
delete entry;
Save();
} else
- unsaved = true;
+ fUnsaved = true;
}
void
-Station::cleanName()
+Station::CleanName()
{
- if (fName.Compare("(#", 2) == 0)
- if (0 <= fName.FindFirst(')') < fName.Length())
- fName.Remove(0, fName.FindFirst(')') + 1).Trim();
+ if (fName.Compare("(#", 2) == 0
+ && fName.FindFirst(')') >= 0
+ && fName.FindFirst(')') < fName.Length())
+ fName.Remove(0, fName.FindFirst(')') + 1).Trim();
fName.RemoveCharsSet("\\/#?");
}
void
-Station::checkFlags()
+Station::CheckFlags()
{
fFlags = 0;
+
if (!fName.IsEmpty())
fFlags |= STATION_HAS_NAME;
+
if (fStreamUrl.HasHost())
fFlags |= STATION_HAS_URI;
+
if (fStreamUrl.IsValid())
fFlags |= STATION_URI_VALID;
+
if (fBitRate != 0)
fFlags |= STATION_HAS_BITRATE;
+
if (fMime.IsValid() && fEncoding != 0)
fFlags |= STATION_HAS_ENCODING;
+
if (fChannels != 0 && fSampleRate != 0)
fFlags |= STATION_HAS_FORMAT;
+
if (fMetaInterval != 0)
fFlags |= STATION_HAS_META;
+
if (!fUniqueIdentifier.IsEmpty())
fFlags |= STATION_HAS_IDENTIFIER;
}
-BDirectory* Station::fStationsDirectory = NULL;
+BDirectory* Station::sStationsDirectory = NULL;
BDirectory*
Station::StationDirectory()
{
- if (fStationsDirectory)
- return fStationsDirectory;
+ if (sStationsDirectory != NULL)
+ return sStationsDirectory;
- status_t status;
BPath configPath;
BDirectory configDir;
- status = find_directory(B_USER_SETTINGS_DIRECTORY, &configPath);
+ if (find_directory(B_USER_SETTINGS_DIRECTORY, &configPath) != B_OK)
+ configPath.SetTo("/boot/home/config/settings");
+
configDir.SetTo(configPath.Path());
- if (configDir.Contains(SubDirStations, B_DIRECTORY_NODE))
- fStationsDirectory = new BDirectory(&configDir, SubDirStations);
+ if (configDir.Contains(kSubDirStations, B_DIRECTORY_NODE))
+ sStationsDirectory = new BDirectory(&configDir, kSubDirStations);
else {
- fStationsDirectory = new BDirectory();
- configDir.CreateDirectory(SubDirStations, fStationsDirectory);
+ sStationsDirectory = new BDirectory();
+ configDir.CreateDirectory(kSubDirStations, sStationsDirectory);
+
BAlert* alert = new BAlert(B_TRANSLATE("Stations directory created"),
B_TRANSLATE(
"A directory for saving stations has been created in your "
@@ -662,5 +766,5 @@ Station::StationDirectory()
alert->Go();
}
- return fStationsDirectory;
+ return sStationsDirectory;
}
diff --git a/Station.h b/Station.h
index 5d0e0a0..eb46ca4 100644
--- a/Station.h
+++ b/Station.h
@@ -1,20 +1,33 @@
/*
- * File: Station.h
- * Author: Kai Niessen, Jacob Secunda
+ * Copyright (C) 2017 Kai Niessen
+ * Copyright (C) 2020 Jacob Secunda
*
- * Created on 26. Februar 2013, 04:08
+ * 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 _STATION_H
+#define _STATION_H
+
-#ifndef STATION_H
-#define STATION_H
-#include "HttpUtils.h"
#include
#include
#include
#include
#include
-#include
-#include
+#include
+#include
+
+#include "HttpUtils.h"
// Station flags
@@ -30,116 +43,138 @@
class StreamPlayer;
-class Station
-{
+
+class Station {
public:
- Station(BString Name, BString Uri = B_EMPTY_STRING);
- Station(const Station& orig);
- virtual ~Station();
- status_t InitCheck();
- status_t Save();
- status_t RetrieveStreamUrl();
- status_t Probe();
- status_t ProbeBuffer(BPositionIO* buffer);
-
- static class Station* LoadFromPlsFile(BString Name);
- static class Station* Load(BString Name, BEntry* entry);
- static class Station* LoadIndirectUrl(BString& ShoutCastUrl);
- static BDirectory* StationDirectory();
-
- inline BString* Name() { return &fName; }
- void SetName(BString name);
- inline BUrl StreamUrl() { return fStreamUrl; }
- inline void SetStreamUrl(BUrl uri)
+ Station(BString name,
+ BString uri = B_EMPTY_STRING);
+ Station(const Station& orig);
+ virtual ~Station();
+
+ status_t InitCheck();
+ status_t Save();
+ status_t RetrieveStreamUrl();
+ status_t Probe();
+ status_t ProbeBuffer(BPositionIO* buffer);
+
+ static class Station* LoadFromPlsFile(BString name);
+ static class Station* Load(BString name, BEntry* entry);
+ static class Station* LoadIndirectUrl(BString& shoutCastUrl);
+
+ static BDirectory* StationDirectory();
+
+ inline BString* Name() { return &fName; }
+ void SetName(BString name);
+
+ inline BUrl StreamUrl() { return fStreamUrl; }
+ inline void SetStreamUrl(BUrl uri)
{
fStreamUrl = uri;
- checkFlags();
- unsaved = true;
+ CheckFlags();
+ fUnsaved = true;
}
- inline BUrl StationUrl() { return fStationUrl; }
- inline void SetStation(BUrl sUrl)
+
+ inline BUrl StationUrl() { return fStationUrl; }
+ inline void SetStation(BUrl url)
{
- fStationUrl = sUrl;
- checkFlags();
- unsaved = true;
+ fStationUrl = url;
+ CheckFlags();
+ fUnsaved = true;
}
- inline BUrl Source() { return fSource; }
- inline void SetSource(BUrl source)
+
+ inline BUrl Source() { return fSource; }
+ inline void SetSource(BUrl source)
{
fSource = source;
- checkFlags();
- unsaved = true;
+ CheckFlags();
+ fUnsaved = true;
}
- inline BBitmap* Logo() { return fLogo; }
- void SetLogo(BBitmap* logo)
+
+ inline BBitmap* Logo() { return fLogo; }
+ inline void SetLogo(BBitmap* logo)
{
- if (fLogo)
- delete fLogo;
+ delete fLogo;
+
fLogo = logo;
- unsaved = true;
+ fUnsaved = true;
}
- inline BString Genre() { return fGenre; }
- inline void SetGenre(BString genre)
+
+ inline BString Genre() { return fGenre; }
+ inline void SetGenre(BString genre)
{
fGenre.SetTo(genre);
- unsaved = true;
+ fUnsaved = true;
}
- inline BString Country() { return fCountry; }
- inline void SetCountry(BString country)
+
+ inline BString Country() { return fCountry; }
+ inline void SetCountry(BString country)
{
fCountry.SetTo(country);
- unsaved = true;
+ fUnsaved = true;
}
- inline BString Language() { return fLanguage; }
- inline void SetLanguage(BString language)
+
+ inline BString Language() { return fLanguage; }
+ inline void SetLanguage(BString language)
{
fLanguage.SetTo(language);
- unsaved = true;
+ fUnsaved = true;
}
- inline int32 SampleRate() { return fSampleRate; }
- inline int32 BitRate() { return fBitRate; }
- void SetBitRate(int32 bitrate)
+
+ inline int32 SampleRate() { return fSampleRate; }
+ inline int32 BitRate() { return fBitRate; }
+ inline void SetBitRate(int32 bitrate)
{
fBitRate = bitrate;
- unsaved = true;
+ fUnsaved = true;
}
- inline BString UniqueIdentifier() { return fUniqueIdentifier; }
- void SetUniqueIdentifier(BString uniqueIdentifier)
+
+ inline BString UniqueIdentifier() { return fUniqueIdentifier; }
+ inline void SetUniqueIdentifier(BString uniqueIdentifier)
{
fUniqueIdentifier.SetTo(uniqueIdentifier);
- unsaved = true;
+ fUnsaved = true;
}
- inline int32 Channels() { return fChannels; }
- inline int32 Encoding() { return fEncoding; }
- inline size_t FrameSize() { return fFrameSize; }
- inline BMimeType* Mime() { return &fMime; }
- inline int32 Flags() { return fFlags; }
- inline bool Flags(int32 flags) { return (fFlags & flags) == flags; }
+
+ inline int32 Channels() { return fChannels; }
+ inline int32 Encoding() { return fEncoding; }
+ inline size_t FrameSize() { return fFrameSize; }
+ inline BMimeType* Mime() { return &fMime; }
+
+ inline int32 Flags() { return fFlags; }
+ inline bool Flags(uint32 flags)
+ { return (fFlags & flags) == flags; }
protected:
- void checkFlags();
- static char* regFind(const char* Text, const char* Pattern);
- status_t parseUrlReference(const char* body, const char* mime);
- void cleanName();
- bool unsaved;
- BString fName;
- BUrl fStreamUrl;
- BUrl fStationUrl;
- BBitmap* fLogo;
- uint32 fRating;
- BString fGenre;
- BString fCountry;
- BString fLanguage;
- BUrl fSource;
- uint32 fBitRate;
- uint32 fSampleRate;
- BString fUniqueIdentifier;
- uint32 fChannels;
- size_t fFrameSize;
- BMimeType fMime;
- uint32 fEncoding;
- uint32 fMetaInterval;
- uint32 fFlags;
- static BDirectory* fStationsDirectory;
+ void CheckFlags();
+ static char* RegFind(const char* text, const char* pattern);
+ status_t ParseUrlReference(const char* body,
+ const char* mime);
+ void CleanName();
+
+ BString fName;
+ BUrl fStreamUrl;
+ BUrl fStationUrl;
+ BString fGenre;
+ BString fCountry;
+ BString fLanguage;
+ BUrl fSource;
+ BMimeType fMime;
+ uint32 fEncoding;
+ BBitmap* fLogo;
+ uint32 fRating;
+ uint32 fBitRate;
+ uint32 fSampleRate;
+ BString fUniqueIdentifier;
+ uint32 fMetaInterval;
+ uint32 fChannels;
+ uint32 fFlags;
+ size_t fFrameSize;
+
+ static BDirectory* sStationsDirectory;
+
+private:
+ bool fUnsaved;
};
-#endif /* STATION_H */
+
+
+#endif // _STATION_H
diff --git a/StationFinder.cpp b/StationFinder.cpp
index 585e036..31fd819 100644
--- a/StationFinder.cpp
+++ b/StationFinder.cpp
@@ -11,39 +11,45 @@
#include
#include
+
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "StationFinder"
+std::vector >
+ StationFinderServices::sServices;
+
+
StationFinderServices::~StationFinderServices()
{
- fServices.clear();
+ sServices.clear();
}
void
StationFinderServices::Register(char* serviceName, InstantiateFunc instantiate)
{
- pair service(serviceName, instantiate);
- fServices.push_back(service);
+ std::pair service(serviceName, instantiate);
+ sServices.push_back(service);
}
-int
+int32
StationFinderServices::CountItems()
{
- return fServices.size();
+ return sServices.size();
}
StationFinderService*
StationFinderServices::Instantiate(char* name)
{
- for (int i = 0; i < fServices.size(); i++) {
- pair service = fServices[i];
+ for (uint32 i = 0; i < sServices.size(); i++) {
+ std::pair service = sServices[i];
if (!strcmp(service.first, name))
return service.second();
}
+
return NULL;
}
@@ -51,11 +57,9 @@ StationFinderServices::Instantiate(char* name)
char*
StationFinderServices::Name(int i)
{
- return fServices[i].first;
+ return sServices[i].first;
}
-vector > StationFinderServices::fServices;
-
FindByCapability::FindByCapability(char* name)
:
@@ -65,12 +69,12 @@ FindByCapability::FindByCapability(char* name)
}
-FindByCapability::FindByCapability(char* name, char* KeyWords, char* delimiter)
+FindByCapability::FindByCapability(char* name, char* keyWords, char* delimiter)
:
fName(name),
fKeywords()
{
- SetKeyWords(KeyWords, delimiter);
+ SetKeyWords(keyWords, delimiter);
}
@@ -102,9 +106,9 @@ FindByCapability::Name()
void
-FindByCapability::SetKeyWords(char* KeyWords, char* delimiter)
+FindByCapability::SetKeyWords(char* keyWords, char* delimiter)
{
- BString tmp(KeyWords);
+ BString tmp(keyWords);
tmp.Split(delimiter, true, fKeywords);
}
@@ -121,8 +125,7 @@ StationFinderService::StationFinderService()
StationFinderService::~StationFinderService()
{
- if (serviceLogo)
- delete serviceLogo;
+ delete serviceLogo;
findByCapabilities.MakeEmpty(true);
}
@@ -135,19 +138,20 @@ StationFinderService::Register(char* name, InstantiateFunc instantiate)
BBitmap*
-StationFinderService::logo(BUrl url)
+StationFinderService::RetrieveLogo(BUrl url)
{
BBitmap* bm = NULL;
BString contentType("image/*");
- BMallocIO* bmData = HttpUtils::GetAll(url, NULL, 3000, &contentType);
-
- if (bmData) {
+ BMallocIO* bmData = HttpUtils::GetAll(url, NULL, 3000, &contentType);
+ if (bmData != NULL) {
bm = BTranslationUtils::GetBitmap(bmData);
- if (bm == NULL || bm->InitCheck() != B_OK)
- bm == NULL;
+ if (bm != NULL && bm->InitCheck() != B_OK)
+ bm = NULL;
+
delete bmData;
}
+
return bm;
}
@@ -157,6 +161,7 @@ StationFinderService::RegisterSearchCapability(char* name)
{
FindByCapability* newCapability = new FindByCapability(name);
findByCapabilities.AddItem(newCapability);
+
return newCapability;
}
@@ -168,6 +173,7 @@ StationFinderService::RegisterSearchCapability(
FindByCapability* newCapability
= new FindByCapability(name, keywords, delimiter);
findByCapabilities.AddItem(newCapability);
+
return newCapability;
}
@@ -176,95 +182,105 @@ StationFinderWindow::StationFinderWindow(BWindow* parent)
:
BWindow(BRect(0, 0, 300, 150), B_TRANSLATE("Find stations"),
B_TITLED_WINDOW, B_CLOSE_ON_ESCAPE),
- currentService(NULL)
+ fCurrentService(NULL)
{
- messenger = new BMessenger(parent);
+ fMessenger = new BMessenger(parent);
CenterIn(parent->Frame());
- txSearch = new BTextControl(NULL, NULL, new BMessage(MSG_TXSEARCH));
- kwSearch = new BOptionPopUp("kwSearch", NULL, new BMessage(MSG_KWSEARCH));
- bnSearch = new BButton("bnSearch", NULL, new BMessage(MSG_BNSEARCH));
- bnSearch->SetIcon(Utils::ResourceBitmap(RES_BN_SEARCH));
+ fTxSearch = new BTextControl(NULL, NULL, new BMessage(MSG_TXSEARCH));
+
+ fKwSearch = new BOptionPopUp("fKwSearch", NULL, new BMessage(MSG_KWSEARCH));
+ fBnSearch = new BButton("fBnSearch", NULL, new BMessage(MSG_BNSEARCH));
+ fBnSearch->SetIcon(Utils::ResourceBitmap(RES_BN_SEARCH));
- ddServices = new BOptionPopUp(
- "ddServices", NULL, new BMessage(MSG_SELECT_SERVICE));
+ fDdServices = new BOptionPopUp(
+ "fDdServices", NULL, new BMessage(MSG_SELECT_SERVICE));
int currentServiceIndex = 0;
const char* settingsServiceName
- = ((RadioApp*) be_app)->Settings.StationFinderName();
- for (int i = 0; i < StationFinderServices::CountItems(); i++) {
+ = ((RadioApp*)be_app)->Settings.StationFinderName();
+ for (int32 i = 0; i < StationFinderServices::CountItems(); i++) {
const char* serviceName = StationFinderServices::Name(i);
if (settingsServiceName && !strcmp(serviceName, settingsServiceName))
currentServiceIndex = i;
- ddServices->AddOption(serviceName, i);
+ fDdServices->AddOption(serviceName, i);
}
- bnVisit = new BButton("bnVisit", "", new BMessage(MSG_VISIT_SERVICE));
- bnVisit->SetIcon(Utils::ResourceBitmap(RES_BN_WEB));
- ddSearchBy
- = new BOptionPopUp("ddSearchBy", NULL, new BMessage(MSG_SEARCH_BY));
- resultView = new StationListView();
- resultView->SetExplicitAlignment(
+ fBnVisit = new BButton("fBnVisit", "", new BMessage(MSG_VISIT_SERVICE));
+ fBnVisit->SetIcon(Utils::ResourceBitmap(RES_BN_WEB));
+
+ fDdSearchBy
+ = new BOptionPopUp("fDdSearchBy", NULL, new BMessage(MSG_SEARCH_BY));
+
+ fResultView = new StationListView();
+ fResultView->SetExplicitAlignment(
BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT));
- bnAdd = new BButton(
- "bnAdd", B_TRANSLATE("Add"), new BMessage(MSG_ADD_STATION));
+
+ fBnAdd = new BButton(
+ "fBnAdd", B_TRANSLATE("Add"), new BMessage(MSG_ADD_STATION));
+
BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
.AddGrid(3, 3, 0.0)
- .SetInsets(B_USE_WINDOW_INSETS)
- .Add(new BStringView("lbServices", B_TRANSLATE("Service")), 0, 0)
- .Add(ddServices, 1, 0)
- .Add(bnVisit, 2, 0)
-
- .Add(new BStringView("lbSearchBy", B_TRANSLATE("Search by")), 0, 1)
- .Add(ddSearchBy, 1, 1)
-
- .Add(new BStringView("lbSearchFor", B_TRANSLATE("Search for")), 0, 2)
- .Add(txSearch, 1, 2)
- .Add(kwSearch, 1, 2)
- .Add(bnSearch, 2, 2)
- .GetLayout(&searchGrid)
+ .SetInsets(B_USE_WINDOW_INSETS)
+ .Add(new BStringView("lbServices", B_TRANSLATE("Service")), 0, 0)
+ .Add(fDdServices, 1, 0)
+ .Add(fBnVisit, 2, 0)
+
+ .Add(new BStringView("lbSearchBy", B_TRANSLATE("Search by")), 0, 1)
+ .Add(fDdSearchBy, 1, 1)
+
+ .Add(new BStringView(
+ "lbSearchFor", B_TRANSLATE("Search for")), 0, 2)
+ .Add(fTxSearch, 1, 2)
+ .Add(fKwSearch, 1, 2)
+ .Add(fBnSearch, 2, 2)
+ .GetLayout(&fSearchGrid)
.End()
- .Add(new BScrollView(
- "srollResult", resultView, 0, B_FOLLOW_ALL_SIDES, false, true),
- 0.9)
+ .Add(new BScrollView("srollResult", fResultView, 0, false, true), 0.9)
+
.AddGrid(3, 1, 0.0)
- .SetInsets(B_USE_WINDOW_INSETS)
- .Add(bnAdd, 2, 0)
- .SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, B_ALIGN_VERTICAL_UNSET))
+ .SetInsets(B_USE_WINDOW_INSETS)
+ .Add(fBnAdd, 2, 0)
+ .SetExplicitAlignment(
+ BAlignment(B_ALIGN_RIGHT, B_ALIGN_VERTICAL_UNSET))
.End()
- .End();
+ .End();
+
+ fBnAdd->SetEnabled(false);
+
+ fResultView->SetInvocationMessage(new BMessage(MSG_ADD_STATION));
+ fResultView->SetSelectionMessage(new BMessage(MSG_SELECT_STATION));
- bnAdd->SetEnabled(false);
- resultView->SetInvocationMessage(new BMessage(MSG_ADD_STATION));
- resultView->SetSelectionMessage(new BMessage(MSG_SELECT_STATION));
Layout(true);
ResizeToPreferred();
ResizeBy(100, 0);
- txSearch->MakeFocus(true);
- bnSearch->MakeDefault(true);
- txSearch->StartWatchingAll(this);
+ fTxSearch->MakeFocus(true);
+ fBnSearch->MakeDefault(true);
+ fTxSearch->StartWatchingAll(this);
+
SelectService(currentServiceIndex);
- ddServices->SetValue(currentServiceIndex);
+ fDdServices->SetValue(currentServiceIndex);
}
StationFinderWindow::~StationFinderWindow()
{
- if (currentService)
- delete currentService;
- resultView->MakeEmpty();
- txSearch->StopWatchingAll(this);
- delete messenger;
+ delete fCurrentService;
+
+ fResultView->MakeEmpty();
+ fTxSearch->StopWatchingAll(this);
+
+ delete fMessenger;
}
bool
StationFinderWindow::QuitRequested()
{
- messenger->SendMessage(new BMessage(MSG_SEARCH_CLOSE));
+ fMessenger->SendMessage(new BMessage(MSG_SEARCH_CLOSE));
return true;
}
@@ -272,88 +288,100 @@ StationFinderWindow::QuitRequested()
void
StationFinderWindow::MessageReceived(BMessage* msg)
{
+
switch (msg->what) {
case MSG_BNSEARCH:
{
- if (txSearch->IsEnabled()) {
- if (txSearch->Text()[0]) {
- DoSearch(txSearch->Text());
- resultView->MakeFocus(true);
+ if (fTxSearch->IsEnabled()) {
+ if (fTxSearch->Text()[0]) {
+ DoSearch(fTxSearch->Text());
+ fResultView->MakeFocus(true);
}
- } else if (kwSearch->Value() >= 0)
- DoSearch(currentService->Capability(ddSearchBy->Value())
- ->KeyWords()
- ->StringAt(kwSearch->Value()));
+ } else if (fKwSearch->Value() >= 0) {
+ DoSearch(fCurrentService->Capability(fDdSearchBy->Value())
+ ->KeyWords()->StringAt(fKwSearch->Value()));
+ }
+
break;
}
+
case MSG_ADD_STATION:
{
int32 index = msg->GetInt32("index", -1);
if (index < 0)
- index = resultView->CurrentSelection(0);
+ index = fResultView->CurrentSelection(0);
+
if (index >= 0) {
- Station* station = resultView->StationAt(index);
+ Station* station = fResultView->StationAt(index);
+
status_t probeStatus = station->Probe();
if (probeStatus == B_OK) {
BMessage* dispatch = new BMessage(msg->what);
dispatch->AddPointer("station", station);
- if (messenger->SendMessage(dispatch) == B_OK)
- resultView->RemoveItem(index);
+
+ if (fMessenger->SendMessage(dispatch) == B_OK)
+ fResultView->RemoveItem(index);
} else {
BString msg;
msg.SetToFormat(
B_TRANSLATE("Station %s did not respond correctly and "
"could not be added"),
station->Name()->String());
+
(new BAlert(B_TRANSLATE("Add station failed"), msg,
B_TRANSLATE("OK")))
->Go();
}
}
+
break;
}
case MSG_UPDATE_STATION:
{
Station* st = NULL;
- status_t status = msg->FindPointer("station", (void**) &st);
- if (status == B_OK)
- resultView->InvalidateItem(
- resultView->IndexOf(resultView->Item(st)));
+ if (msg->FindPointer("station", (void**)&st) == B_OK) {
+ fResultView->InvalidateItem(
+ fResultView->IndexOf(fResultView->Item(st)));
+ }
+
break;
}
case MSG_SELECT_STATION:
{
bool inResults = (msg->GetInt32("index", -1) >= 0);
- bnAdd->SetEnabled(inResults);
- bnAdd->MakeDefault(inResults);
+ fBnAdd->SetEnabled(inResults);
+ fBnAdd->MakeDefault(inResults);
+
break;
}
case MSG_SELECT_SERVICE:
- SelectService(ddServices->Value());
+ SelectService(fDdServices->Value());
break;
case MSG_SEARCH_BY:
- SelectCapability(ddSearchBy->Value());
+ SelectCapability(fDdSearchBy->Value());
break;
case MSG_VISIT_SERVICE:
{
- if (currentService && currentService->serviceHomePage
- && currentService->serviceHomePage.IsValid())
- currentService->serviceHomePage.OpenWithPreferredApplication(
+ if (fCurrentService != NULL
+ && fCurrentService->serviceHomePage != NULL
+ && fCurrentService->serviceHomePage.IsValid())
+ fCurrentService->serviceHomePage.OpenWithPreferredApplication(
true);
break;
}
+
case B_OBSERVER_NOTICE_CHANGE:
- bnSearch->MakeDefault(true);
+ fBnSearch->MakeDefault(true);
break;
case MSG_TXSEARCH:
- bnAdd->MakeDefault(false);
- bnSearch->MakeDefault(true);
+ fBnAdd->MakeDefault(false);
+ fBnSearch->MakeDefault(true);
break;
default:
@@ -365,24 +393,31 @@ StationFinderWindow::MessageReceived(BMessage* msg)
void
StationFinderWindow::SelectService(int index)
{
- if (currentService) {
- delete currentService;
- currentService = NULL;
- }
-
char* serviceName = StationFinderServices::Name(index);
- if (!serviceName)
+ if (serviceName == NULL)
+ return;
+
+ StationFinderService* selectedService = StationFinderServices::Instantiate(
+ serviceName);
+ if (selectedService == NULL)
return;
- currentService = StationFinderServices::Instantiate(serviceName);
- ((RadioApp*) be_app)->Settings.SetStationFinderName(serviceName);
- while (ddSearchBy->CountOptions())
- ddSearchBy->RemoveOptionAt(0);
+ if (fCurrentService != NULL) {
+ delete fCurrentService;
+ fCurrentService = NULL;
+ }
+
+ fCurrentService = selectedService;
+
+ ((RadioApp*)be_app)->Settings.SetStationFinderName(serviceName);
- for (int i = 0; i < currentService->CountCapabilities(); i++)
- ddSearchBy->AddOption(currentService->Capability(i)->Name(), i);
+ while (fDdSearchBy->CountOptions() > 0)
+ fDdSearchBy->RemoveOptionAt(0);
- if (ddSearchBy->CountOptions())
+ for (int32 i = 0; i < fCurrentService->CountCapabilities(); i++)
+ fDdSearchBy->AddOption(fCurrentService->Capability(i)->Name(), i);
+
+ if (fDdSearchBy->CountOptions() != 0)
SelectCapability(0);
}
@@ -390,29 +425,34 @@ StationFinderWindow::SelectService(int index)
void
StationFinderWindow::SelectCapability(int index)
{
- if (!currentService)
+ if (fCurrentService == NULL)
return;
- FindByCapability* capability = currentService->Capability(index);
- if (!capability)
+ FindByCapability* capability = fCurrentService->Capability(index);
+ if (capability == NULL)
return;
if (capability->HasKeyWords()) {
- while (kwSearch->CountOptions())
- kwSearch->RemoveOptionAt(0);
- for (int i = 0; i < capability->KeyWords()->CountStrings(); i++)
- kwSearch->AddOption(capability->KeyWords()->StringAt(i), i);
-
- searchGrid->RemoveView(txSearch);
- searchGrid->AddView(kwSearch, 1, 2);
- kwSearch->SetEnabled(true);
- txSearch->SetEnabled(false);
+ while (fKwSearch->CountOptions() > 0)
+ fKwSearch->RemoveOptionAt(0);
+
+ for (int32 i = 0; i < capability->KeyWords()->CountStrings(); i++)
+ fKwSearch->AddOption(capability->KeyWords()->StringAt(i), i);
+
+ fSearchGrid->RemoveView(fTxSearch);
+ fSearchGrid->AddView(fKwSearch, 1, 2);
+
+ fKwSearch->SetEnabled(true);
+ fTxSearch->SetEnabled(false);
+
Layout(true);
} else {
- searchGrid->RemoveView(kwSearch);
- searchGrid->AddView(txSearch, 1, 2);
- kwSearch->SetEnabled(false);
- txSearch->SetEnabled(true);
+ fSearchGrid->RemoveView(fKwSearch);
+ fSearchGrid->AddView(fTxSearch, 1, 2);
+
+ fKwSearch->SetEnabled(false);
+ fTxSearch->SetEnabled(true);
+
Layout(true);
}
}
@@ -421,20 +461,21 @@ StationFinderWindow::SelectCapability(int index)
void
StationFinderWindow::DoSearch(const char* text)
{
- resultView->MakeEmpty();
- if (!currentService)
+ fResultView->MakeEmpty();
+ if (fCurrentService == NULL)
return;
be_app->SetCursor(new BCursor(B_CURSOR_ID_PROGRESS));
BObjectList* result
- = currentService->FindBy(ddSearchBy->Value(), text, this);
- if (result) {
- for (unsigned i = 0; i < result->CountItems(); i++)
- resultView->AddItem(new StationListViewItem(result->ItemAt(i)));
+ = fCurrentService->FindBy(fDdSearchBy->Value(), text, this);
+ if (result != NULL) {
+ for (int32 i = 0; i < result->CountItems(); i++)
+ fResultView->AddItem(new StationListViewItem(result->ItemAt(i)));
+
result->MakeEmpty(false);
delete result;
}
-
+
be_app->SetCursor(B_CURSOR_SYSTEM_DEFAULT);
}
diff --git a/StationFinder.h b/StationFinder.h
index 845a3c5..a90ffd4 100644
--- a/StationFinder.h
+++ b/StationFinder.h
@@ -1,15 +1,27 @@
/*
- * File: StationFinder.h
- * Author: Kai Niessen
+ * Copyright (C) 2017 Kai Niessen
*
- * Created on 9. Oktober 2015, 22:53
+ * 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 _STATION_FINDER_H
+#define _STATION_FINDER_H
-#ifndef STATIONFINDER_H
-#define STATIONFINDER_H
-#include "Station.h"
-#include "StationListView.h"
+#include
+#include
+#include
+
#include
#include
#include
@@ -19,9 +31,10 @@
#include
#include
#include
-#include
-#include
-#include
+
+#include "Station.h"
+#include "StationListView.h"
+
#define MSG_TXSEARCH 'tSRC'
#define MSG_KWSEARCH 'kSRC'
@@ -37,100 +50,110 @@
#define RES_BN_SEARCH 10
-using namespace std;
-
typedef class StationFinderService* (*InstantiateFunc)();
-class StationFinderServices
-{
+
+class StationFinderServices {
public:
- StationFinderServices(){};
- ~StationFinderServices();
- static void Register(char* serviceName, InstantiateFunc);
- static int CountItems();
- static StationFinderService* Instantiate(char* s);
- static char* Name(int i);
+ StationFinderServices(){};
+ ~StationFinderServices();
+
+ static void Register(char* serviceName, InstantiateFunc);
+
+ static StationFinderService* Instantiate(char* s);
+
+ static int32 CountItems();
+ static char* Name(int i);
private:
- static vector > fServices;
+ static std::vector > sServices;
};
-class FindByCapability
-{
+class FindByCapability {
public:
- FindByCapability(char* name);
- FindByCapability(char* name, char* KeyWords, char* delimiter);
- ~FindByCapability();
- bool HasKeyWords();
- void SetKeyWords(char* KeyWords, char* delimiter);
- const BStringList* KeyWords();
- const char* Name();
+ FindByCapability(char* name);
+ FindByCapability(char* name, char* keyWords,
+ char* delimiter);
+ ~FindByCapability();
+
+ bool HasKeyWords();
+ void SetKeyWords(char* keyWords, char* delimiter);
+ const BStringList* KeyWords();
+
+ const char* Name();
private:
- BString fName;
- BStringList fKeywords;
+ BString fName;
+ BStringList fKeywords;
};
-class StationFinderService
-{
+class StationFinderService {
friend class StationFinderWindow;
public:
- // To be overridden in specific StationFinder implementations
- StationFinderService();
- virtual ~StationFinderService();
- static void RegisterSelf();
- static StationFinderService* Instantiate();
- virtual BObjectList* FindBy(
- int capabilityIndex, const char* searchFor, BLooper* resultUpdateTarget)
- = 0;
+ // Overridden in specific StationFinder implementations
+ StationFinderService();
+ virtual ~StationFinderService();
+
+ static void RegisterSelf();
+ static StationFinderService* Instantiate();
+
+ virtual BObjectList* FindBy(int capabilityIndex,
+ const char* searchFor,
+ BLooper* resultUpdateTarget) = 0;
// Provided by ancestor class
- const char* Name() const { return serviceName.String(); }
- int CountCapabilities() const { return findByCapabilities.CountItems(); };
- FindByCapability* Capability(int index) const
- {
- return findByCapabilities.ItemAt(index);
- };
- static void Register(char* name, InstantiateFunc instantiate);
+ const char* Name() const { return serviceName.String(); }
+
+ int CountCapabilities() const
+ { return findByCapabilities.CountItems(); }
+ FindByCapability* Capability(int index) const
+ { return findByCapabilities.ItemAt(index); }
+
+ static void Register(char* name,
+ InstantiateFunc instantiate);
protected:
- // To be filled by specific StationFinder implementations
- BString serviceName;
- BUrl serviceHomePage;
- BBitmap* serviceLogo;
- BObjectList findByCapabilities;
-
- // Helper functions
- BBitmap* logo(BUrl url);
- FindByCapability* RegisterSearchCapability(char* name);
- FindByCapability* RegisterSearchCapability(
- char* name, char* keyWords, char* delimiter);
+ // To be filled by specific StationFinder implementations
+ BString serviceName;
+ BUrl serviceHomePage;
+ BBitmap* serviceLogo;
+ BObjectList findByCapabilities;
+
+ // Helper functions
+ BBitmap* RetrieveLogo(BUrl url);
+ FindByCapability* RegisterSearchCapability(char* name);
+ FindByCapability* RegisterSearchCapability(char* name,
+ char* keyWords, char* delimiter);
};
-class StationFinderWindow : public BWindow
-{
+class StationFinderWindow : public BWindow {
public:
- StationFinderWindow(BWindow* parent);
- virtual ~StationFinderWindow();
- void MessageReceived(BMessage* msg);
- virtual bool QuitRequested();
- void SelectService(int index);
- void SelectCapability(int index);
- void DoSearch(const char* text);
+ StationFinderWindow(BWindow* parent);
+ virtual ~StationFinderWindow();
+
+ void MessageReceived(BMessage* msg);
+ virtual bool QuitRequested();
+
+ void SelectService(int index);
+ void SelectCapability(int index);
+ void DoSearch(const char* text);
private:
- StationFinderService* currentService;
- BMessenger* messenger;
- BTextControl* txSearch;
- BOptionPopUp* kwSearch;
- BButton* bnSearch;
- StationListView* resultView;
- BButton* bnAdd;
- BButton* bnVisit;
- BOptionPopUp* ddServices;
- BOptionPopUp* ddSearchBy;
- BGridLayout* searchGrid;
+ StationFinderService* fCurrentService;
+
+ BMessenger* fMessenger;
+ BTextControl* fTxSearch;
+ BOptionPopUp* fKwSearch;
+ BButton* fBnSearch;
+ BOptionPopUp* fDdServices;
+ BButton* fBnVisit;
+ BOptionPopUp* fDdSearchBy;
+ StationListView* fResultView;
+ BButton* fBnAdd;
+
+ BGridLayout* fSearchGrid;
};
-#endif /* STATIONFINDER_H */
+
+#endif // _STATION_FINDER_H
diff --git a/StationFinderListenLive.cpp b/StationFinderListenLive.cpp
index 9bb87f8..faf864c 100644
--- a/StationFinderListenLive.cpp
+++ b/StationFinderListenLive.cpp
@@ -12,27 +12,25 @@
* 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 .
+ * along with this program. If not, see .
*/
-/*
- * File: StationFinderListenLive.cpp
- * Author: Kai Niessen
- *
- * Created on March 27, 2017, 12:16 AM
- */
#include "StationFinderListenLive.h"
+
#define __USE_GNU
-#include "Debug.h"
-#include
#include
+#include
+
+#include "Debug.h"
+
+
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "StationFinderListenLive"
-const char* genreList = "Top 40|top40\r\
+const char* kGenreList = "Top 40|top40\r\
Hot Adult Contemporary|hotac\r\
Adult Contemporary|ac\r\
Oldies/80s/90s|oldies\r\
@@ -43,8 +41,7 @@ Rock/Classic Rock|rock\r\
Alternative|alternative\r\
Chillout/Lounge|chillout";
-
-const char* countryList = "Andorra|andorra\r\
+const char* kCountryList = "Andorra|andorra\r\
Armenia|armenia\r\
Austria|austria\r\
Azerbaijan|azerbaijan\r\
@@ -96,32 +93,36 @@ Ukraine|ukraine\r\
United Kingdom|uk\r\
Vatican State|vatican";
+const char* StationFinderListenLive::kBaseUrl = "http://listenlive.eu/";
+
StationFinderListenLive::StationFinderListenLive()
:
StationFinderService(),
- countryKeywordAndPath(),
- genreKeywordAndPath(),
- fLookupThread(0),
+ fCountryKeywordAndPath(),
+ fGenreKeywordAndPath(),
+ fLookupThread(-1),
fPlsLookupList()
{
serviceName.SetTo(B_TRANSLATE("listenlive.eu [experimental]"));
serviceHomePage.SetUrlString("http://www.listenlive.eu/");
- BString tmp(countryList);
- tmp.Split("\r", true, countryKeywordAndPath);
+
+ BString tmp(kCountryList);
+ tmp.Split("\r", true, fCountryKeywordAndPath);
FindByCapability* findByCountry = RegisterSearchCapability("Country");
- BStringList* keywords = (BStringList*) findByCountry->KeyWords();
- for (int i = 0; i < countryKeywordAndPath.CountStrings(); i++) {
- BString keyword(countryKeywordAndPath.StringAt(i));
+ BStringList* keywords = (BStringList*)findByCountry->KeyWords();
+ for (int32 i = 0; i < fCountryKeywordAndPath.CountStrings(); i++) {
+ BString keyword(fCountryKeywordAndPath.StringAt(i));
keyword.Truncate(keyword.FindFirst('|'));
keywords->Add(keyword);
}
- tmp.SetTo(genreList);
- tmp.Split("\r", true, genreKeywordAndPath);
+
+ tmp.SetTo(kGenreList);
+ tmp.Split("\r", true, fGenreKeywordAndPath);
FindByCapability* findByGenre = RegisterSearchCapability("Genre");
- keywords = (BStringList*) findByGenre->KeyWords();
- for (int i = 0; i < genreKeywordAndPath.CountStrings(); i++) {
- BString keyword(genreKeywordAndPath.StringAt(i));
+ keywords = (BStringList*)findByGenre->KeyWords();
+ for (int32 i = 0; i < fGenreKeywordAndPath.CountStrings(); i++) {
+ BString keyword(fGenreKeywordAndPath.StringAt(i));
keyword.Truncate(keyword.FindFirst('|'));
keywords->Add(keyword);
}
@@ -138,62 +139,64 @@ StationFinderListenLive::Instantiate()
void
StationFinderListenLive::RegisterSelf()
{
- // FIXME: "listenlive.eu" no longer seems to exist, though it looks like
- // "radiomap.eu" might be its successor? This plugin crashes after searching
- // anyway...
-// Register(
-// "listenlive.eu [experimental]", &StationFinderListenLive::Instantiate);
+ Register(
+ "listenlive.eu [experimental]", &StationFinderListenLive::Instantiate);
}
StationFinderListenLive::~StationFinderListenLive()
{
fPlsLookupList.MakeEmpty(false);
- status_t status;
- if (fLookupThread)
- wait_for_thread(fLookupThread, &status);
+ if (fLookupThread >= 0) {
+ status_t dummy;
+ wait_for_thread(fLookupThread, &dummy);
+ }
}
BObjectList*
-StationFinderListenLive::FindBy(
- int capabilityIndex, const char* searchFor, BLooper* resultUpdateTarget)
+StationFinderListenLive::FindBy(int capabilityIndex, const char* searchFor,
+ BLooper* resultUpdateTarget)
{
- if (fLookupThread)
+ if (fLookupThread >= 0)
suspend_thread(fLookupThread);
+
fPlsLookupList.MakeEmpty(false);
fLookupNotify = resultUpdateTarget;
BObjectList* result = NULL;
- BString urlString(baseUrl);
- strlwr((char*) searchFor);
+ BString urlString(kBaseUrl);
+ strlwr((char*)searchFor);
int keywordIndex
= Capability(capabilityIndex)->KeyWords()->IndexOf(searchFor);
BStringList* keywordAndPaths
- = capabilityIndex ? &genreKeywordAndPath : &countryKeywordAndPath;
+ = capabilityIndex ? &fGenreKeywordAndPath : &fCountryKeywordAndPath;
BString path(keywordAndPaths->StringAt(keywordIndex));
path.Remove(0, path.FindFirst('|') + 1);
urlString << path << ".html";
BUrl url(urlString);
- BMallocIO* data = HttpUtils::GetAll(url);
- if (data)
+ BMallocIO* data = HttpUtils::GetAll(url);
+ if (data != NULL) {
switch (capabilityIndex) {
case 0: // findByCountry
result = ParseCountryReturn(data, searchFor);
break;
+
case 1: // findByGenre
result = ParseGenreReturn(data, searchFor);
break;
}
+ }
data->Flush();
delete data;
+
if (!fPlsLookupList.IsEmpty()) {
- if (!fLookupThread)
+ if (fLookupThread < 0)
fLookupThread = spawn_thread(
- &PlsLookupFunc, "plslookup", B_NORMAL_PRIORITY, this);
+ &_PlsLookupFunc, "plslookup", B_NORMAL_PRIORITY, this);
resume_thread(fLookupThread);
}
@@ -206,6 +209,9 @@ StationFinderListenLive::ParseCountryReturn(
BMallocIO* data, const char* searchFor)
{
BObjectList* result = new BObjectList(20, true);
+ if (result == NULL)
+ return result;
+
regmatch_t matches[10];
regex_t regex;
@@ -230,7 +236,7 @@ StationFinderListenLive::ParseCountryReturn(
RE_ICASE | RE_DOT_NEWLINE | RE_DOT_NOT_NULL | RE_NO_BK_PARENS
| RE_NO_BK_VBAR | RE_BACKSLASH_ESCAPE_IN_LISTS);
- char* doc = (char*) data->Buffer();
+ char* doc = (char*)data->Buffer();
off_t size;
data->GetSize(&size);
doc[size] = 0;
@@ -248,6 +254,9 @@ StationFinderListenLive::ParseCountryReturn(
doc + matches[6].rm_so, doc + matches[8].rm_so);
Station* station = new Station(doc + matches[2].rm_so, NULL);
+ if (station == NULL)
+ continue;
+
result->AddItem(station);
BString source(doc + matches[5].rm_so);
@@ -257,22 +266,26 @@ StationFinderListenLive::ParseCountryReturn(
} else
station->SetStreamUrl(BUrl(source));
- for (int i = matches[6].rm_so; i < matches[6].rm_eo; i++)
+ for (int32 i = matches[6].rm_so; i < matches[6].rm_eo; i++) {
if (!strchr("0123456789.", doc[i])) {
doc[i] = 0;
station->SetBitRate(atof(doc + matches[6].rm_so) * 1000);
break;
}
+ }
station->SetStation(doc + matches[1].rm_so);
station->SetGenre(doc + matches[8].rm_so);
+
BString country;
country.SetTo(searchFor);
country.Append(" - ");
country.Append(doc + matches[3].rm_so);
station->SetCountry(country);
+
doc += matches[0].rm_eo;
}
+
return result;
}
@@ -282,6 +295,9 @@ StationFinderListenLive::ParseGenreReturn(
BMallocIO* data, const char* searchFor)
{
BObjectList* result = new BObjectList(20, true);
+ if (result == NULL)
+ return result;
+
regmatch_t matches[9];
regex_t regex;
@@ -316,7 +332,7 @@ StationFinderListenLive::ParseGenreReturn(
RE_ICASE | RE_DOT_NEWLINE | RE_DOT_NOT_NULL | RE_NO_BK_PARENS
| RE_NO_BK_VBAR | RE_BACKSLASH_ESCAPE_IN_LISTS);
- char* doc = (char*) data->Buffer();
+ char* doc = (char*)data->Buffer();
off_t size;
data->GetSize(&size);
doc[size] = 0;
@@ -335,7 +351,11 @@ StationFinderListenLive::ParseGenreReturn(
doc + matches[6].rm_so, doc + matches[7].rm_so, searchFor);
Station* station = new Station(doc + matches[2].rm_so, NULL);
+ if (station == NULL)
+ continue;
+
result->AddItem(station);
+
BString source(doc + matches[6].rm_so);
if (source.EndsWith(".pls") || source.EndsWith(".m3u")) {
station->SetSource(BUrl(source));
@@ -343,47 +363,53 @@ StationFinderListenLive::ParseGenreReturn(
} else
station->SetStreamUrl(BUrl(source));
- for (int i = matches[7].rm_so; i < matches[7].rm_eo; i++)
+ for (int32 i = matches[7].rm_so; i < matches[7].rm_eo; i++) {
if (!strchr("0123456789.", doc[i])) {
doc[i] = 0;
station->SetBitRate(atof(doc + matches[7].rm_so) * 1000);
break;
}
+ }
station->SetStation(doc + matches[1].rm_so);
station->SetGenre(searchFor);
+
BString country(doc + matches[4].rm_so);
country.Append(" - ");
country.Append(doc + matches[5].rm_so);
station->SetCountry(country);
+
doc += matches[0].rm_eo;
}
+
return result;
}
int32
-StationFinderListenLive::PlsLookupFunc(void* data)
+StationFinderListenLive::_PlsLookupFunc(void* data)
{
- StationFinderListenLive* _this = (StationFinderListenLive*) data;
+ StationFinderListenLive* _this = (StationFinderListenLive*)data;
while (!_this->fPlsLookupList.IsEmpty()) {
Station* station = _this->fPlsLookupList.FirstItem();
TRACE("Looking up stream URL for station %s in %s\n",
station->Name()->String(), station->Source().UrlString().String());
+
Station* plsStation = Station::LoadIndirectUrl(
- (BString&) station->Source().UrlString());
- if (plsStation)
+ (BString&)station->Source().UrlString());
+ if (plsStation != NULL)
station->SetStreamUrl(plsStation->StreamUrl());
+
BMessage* notification = new BMessage(MSG_UPDATE_STATION);
notification->AddPointer("station", station);
if (_this->fLookupNotify->LockLooper()) {
_this->fLookupNotify->PostMessage(notification);
_this->fLookupNotify->UnlockLooper();
}
+
_this->fPlsLookupList.RemoveItem(station, false);
}
- _this->fLookupThread = 0;
+
+ _this->fLookupThread = -1;
return B_OK;
}
-
-const char* StationFinderListenLive::baseUrl = "http://listenlive.eu/";
diff --git a/StationFinderListenLive.h b/StationFinderListenLive.h
index b1e6fb9..662cb3d 100644
--- a/StationFinderListenLive.h
+++ b/StationFinderListenLive.h
@@ -12,44 +12,47 @@
* 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 .
+ * along with this program. If not, see .
*/
+#ifndef _STATION_FINDER_LISTEN_LIVE_H
+#define _STATION_FINDER_LISTEN_LIVE_H
-/*
- * File: StationFinderListenLive.h
- * Author: Kai Niessen
- *
- * Created on March 27, 2017, 12:16 AM
- */
-#ifndef STATIONFINDERLISTENLIVE_H
-#define STATIONFINDERLISTENLIVE_H
+#include
#include "StationFinder.h"
-#include
-class StationFinderListenLive : public StationFinderService
-{
+
+class StationFinderListenLive : public StationFinderService {
public:
- StationFinderListenLive();
- virtual ~StationFinderListenLive();
- static void RegisterSelf();
- static StationFinderService* Instantiate();
- virtual BObjectList* FindBy(int capabilityIndex,
- const char* searchFor, BLooper* resultUpdateTarget);
- BObjectList* ParseCountryReturn(
- BMallocIO* data, const char* country);
- BObjectList* ParseGenreReturn(BMallocIO* data, const char* genre);
+ StationFinderListenLive();
+ virtual ~StationFinderListenLive();
+
+ static void RegisterSelf();
+ static StationFinderService* Instantiate();
+
+ virtual BObjectList* FindBy(int capabilityIndex,
+ const char* searchFor,
+ BLooper* resultUpdateTarget);
+
+ BObjectList* ParseCountryReturn(BMallocIO* data,
+ const char* country);
+ BObjectList* ParseGenreReturn(BMallocIO* data,
+ const char* genre);
+
+private:
+ static int32 _PlsLookupFunc(void* data);
private:
- static const char* baseUrl;
- thread_id fLookupThread;
- BObjectList fPlsLookupList;
- BLooper* fLookupNotify;
-
- static int32 PlsLookupFunc(void* data);
- BStringList countryKeywordAndPath;
- BStringList genreKeywordAndPath;
+ static const char* kBaseUrl;
+
+ BStringList fCountryKeywordAndPath;
+ BStringList fGenreKeywordAndPath;
+ thread_id fLookupThread;
+ BObjectList fPlsLookupList;
+
+ BLooper* fLookupNotify;
};
-#endif /* STATIONFINDERLISTENLIVE_H */
+
+#endif // _STATION_FINDER_LISTEN_LIVE_H
diff --git a/StationFinderRadioNetwork.cpp b/StationFinderRadioNetwork.cpp
index 2b52552..0ac4fd6 100644
--- a/StationFinderRadioNetwork.cpp
+++ b/StationFinderRadioNetwork.cpp
@@ -1,19 +1,32 @@
/*
- * File: StationFinderRadioNetwork.cpp
- * Author: user, Jacob Secunda
+ * Copyright (C) 2017 Kai Niessen
+ * Copyright (C) 2020 Jacob Secunda
*
- * Created on 9. Oktober 2015, 22:51
+ * 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 .
*/
+
#include "StationFinderRadioNetwork.h"
-#include "Debug.h"
-#include "HttpUtils.h"
-#include "StationFinderListenLive.h"
+
#include
#include
#include
+#include "Debug.h"
+#include "HttpUtils.h"
+
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "StationFinderRadioNetwork"
@@ -36,7 +49,7 @@ IconLookup::IconLookup(Station* station, BUrl iconUrl)
StationFinderRadioNetwork::StationFinderRadioNetwork()
:
StationFinderService(),
- fIconLookupThread(0),
+ fIconLookupThread(-1),
fIconLookupList()
{
serviceName.SetTo(B_TRANSLATE("Community Radio Browser"));
@@ -74,8 +87,8 @@ StationFinderRadioNetwork::RegisterSelf()
BObjectList*
-StationFinderRadioNetwork::FindBy(
- int capabilityIndex, const char* searchFor, BLooper* resultUpdateTarget)
+StationFinderRadioNetwork::FindBy(int capabilityIndex, const char* searchFor,
+ BLooper* resultUpdateTarget)
{
if (fIconLookupThread)
suspend_thread(fIconLookupThread);
@@ -90,7 +103,7 @@ StationFinderRadioNetwork::FindBy(
if (_CheckServer() != B_OK)
return result;
- printf("Connected to server: %s \n", sCachedServerUrl.String());
+ printf("Connected to server: %s\n", sCachedServerUrl.String());
BString urlString(sCachedServerUrl);
@@ -101,24 +114,31 @@ StationFinderRadioNetwork::FindBy(
case 0: // Name search
urlString.Append("byname/");
break;
+
case 1: // Tag search
urlString.Append("bytag/");
break;
+
case 2: // Language search
urlString.Append("bylanguage/");
break;
+
case 3: // Country search
urlString.Append("bycountry/");
break;
+
case 4: // Country code search
urlString.Append("bycountrycodeexact/");
break;
+
case 5: // State/Region search
urlString.Append("bystate/");
break;
+
case 6: // Unique identifier search
urlString.Append("byuuid/");
break;
+
default: // A very bad kind of search? Just do a name search...
urlString.Append("byname/");
break;
@@ -194,9 +214,9 @@ StationFinderRadioNetwork::FindBy(
}
if (!fIconLookupList.IsEmpty()) {
- if (!fIconLookupThread) {
+ if (fIconLookupThread < 0) {
fIconLookupThread = spawn_thread(
- &IconLookupFunc, "iconlookup", B_LOW_PRIORITY, this);
+ &_IconLookupFunc, "iconlookup", B_LOW_PRIORITY, this);
}
resume_thread(fIconLookupThread);
}
@@ -210,14 +230,15 @@ StationFinderRadioNetwork::FindBy(
int32
-StationFinderRadioNetwork::IconLookupFunc(void* data)
+StationFinderRadioNetwork::_IconLookupFunc(void* data)
{
StationFinderRadioNetwork* _this = (StationFinderRadioNetwork*)data;
while (!_this->fIconLookupList.IsEmpty()) {
IconLookup* item = _this->fIconLookupList.FirstItem();
- BBitmap* logo = _this->logo(item->fIconUrl);
- if (logo)
+ BBitmap* logo = _this->RetrieveLogo(item->fIconUrl);
+ if (logo != NULL)
item->fStation->SetLogo(logo);
+
BMessage* notification = new BMessage(MSG_UPDATE_STATION);
notification->AddPointer("station", item->fStation);
if (_this->fIconLookupNotify->LockLooper()) {
@@ -227,7 +248,8 @@ StationFinderRadioNetwork::IconLookupFunc(void* data)
_this->fIconLookupList.RemoveItem(item, true);
}
- _this->fIconLookupThread = 0;
+ _this->fIconLookupThread = -1;
+
return B_OK;
}
diff --git a/StationFinderRadioNetwork.h b/StationFinderRadioNetwork.h
index 7535e59..5849cd9 100644
--- a/StationFinderRadioNetwork.h
+++ b/StationFinderRadioNetwork.h
@@ -1,43 +1,60 @@
/*
- * File: StationFinderRadioNetwork.h
- * Author: user, Jacob Secunda
+ * Copyright (C) 2017 Kai Niessen
+ * Copyright (C) 2020 Jacob Secunda
*
- * Created on 9. Oktober 2015, 22:51
+ * 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 _STATION_FINDER_RADIO_NETWORK_H
+#define _STATION_FINDER_RADIO_NETWORK_H
-#ifndef STATIONFINDERRADIONETWORK_H
-#define STATIONFINDERRADIONETWORK_H
#include "StationFinder.h"
-class IconLookup
-{
+
+class IconLookup {
public:
- IconLookup(Station* station, BUrl iconUrl);
- Station* fStation;
- BUrl fIconUrl;
+ IconLookup(Station* station, BUrl iconUrl);
+
+ Station* fStation;
+ BUrl fIconUrl;
};
-class StationFinderRadioNetwork : public StationFinderService
-{
+
+class StationFinderRadioNetwork : public StationFinderService {
public:
- StationFinderRadioNetwork();
- virtual ~StationFinderRadioNetwork();
- static void RegisterSelf();
- static StationFinderService* Instantiate();
- virtual BObjectList* FindBy(int capabilityIndex,
- const char* searchFor, BLooper* resultUpdateTarget);
+ StationFinderRadioNetwork();
+ virtual ~StationFinderRadioNetwork();
+
+ static void RegisterSelf();
+ static StationFinderService* Instantiate();
+
+ virtual BObjectList* FindBy(int capabilityIndex,
+ const char* searchFor,
+ BLooper* resultUpdateTarget);
private:
- static const char* kBaseUrl;
- static BString sCachedServerUrl;
+ static int32 _IconLookupFunc(void* data);
+ status_t _CheckServer();
- thread_id fIconLookupThread;
- BObjectList fIconLookupList;
- BLooper* fIconLookupNotify;
+private:
+ static const char* kBaseUrl;
+ static BString sCachedServerUrl;
- static int32 IconLookupFunc(void* data);
- status_t _CheckServer();
+ thread_id fIconLookupThread;
+ BObjectList fIconLookupList;
+ BLooper* fIconLookupNotify;
};
-#endif /* STATIONFINDERRADIONETWORK_H */
+
+#endif // _STATION_FINDER_RADIO_NETWORK_H
diff --git a/StationListView.cpp b/StationListView.cpp
index ae17b74..60bbb95 100644
--- a/StationListView.cpp
+++ b/StationListView.cpp
@@ -1,16 +1,31 @@
/*
- * File: StationListView.cpp
- * Author: user
+ * Copyright (C) 2017 Kai Niessen
*
- * Created on 26.02.2013, 09:22
+ * 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 .
*/
+
+
#include "StationListView.h"
-#include "StreamPlayer.h"
-#include "Utils.h"
+
#include
#include
#include
+#include "StreamPlayer.h"
+#include "Utils.h"
+
+
#define SLV_INSET 2
#define SLV_PADDING 6
#define SLV_HEIGHT 50
@@ -31,7 +46,7 @@ StationListViewItem::StationListViewItem(Station* station)
StationListViewItem::~StationListViewItem()
{
- if (fPlayer) {
+ if (fPlayer != NULL) {
fPlayer->Stop();
delete fPlayer;
}
@@ -41,7 +56,7 @@ StationListViewItem::~StationListViewItem()
StreamPlayer::PlayState
StationListViewItem::State()
{
- return (fPlayer)
+ return (fPlayer != NULL)
? fPlayer->State()
: fStation->Flags(STATION_URI_VALID) ? StreamPlayer::Stopped
: StreamPlayer::InActive;
@@ -51,8 +66,9 @@ StationListViewItem::State()
void
StationListViewItem::DrawItem(BView* owner, BRect frame, bool complete)
{
- int index = ((BListView*) owner)->IndexOf(this);
- StationListView* ownerList = (StationListView*) owner;
+ int index = ((BListView*)owner)->IndexOf(this);
+
+ StationListView* ownerList = (StationListView*)owner;
ownerList->SetHighColor(
ui_color(IsSelected() ? B_MENU_SELECTION_BACKGROUND_COLOR
: ((index % 2) ? B_MENU_BACKGROUND_COLOR
@@ -65,17 +81,22 @@ StationListViewItem::DrawItem(BView* owner, BRect frame, bool complete)
ui_color(IsSelected() ? B_MENU_SELECTION_BACKGROUND_COLOR
: ((index % 2) ? B_MENU_BACKGROUND_COLOR
: B_DOCUMENT_BACKGROUND_COLOR)));
- if (BBitmap* logo = fStation->Logo()) {
+
+ if (fStation->Logo() != NULL) {
BRect target(SLV_INSET, SLV_INSET, SLV_HEIGHT - 2 * SLV_INSET,
SLV_HEIGHT - 2 * SLV_INSET);
target.OffsetBy(frame.LeftTop());
+
owner->DrawBitmap(
- logo, logo->Bounds(), target, B_FILTER_BITMAP_BILINEAR);
+ fStation->Logo(), fStation->Logo()->Bounds(), target,
+ B_FILTER_BITMAP_BILINEAR);
}
+
owner->SetFontSize(SLV_MAIN_FONT_SIZE);
font_height fontHeight;
owner->GetFontHeight(&fontHeight);
float baseline = SLV_INSET + fontHeight.ascent + fontHeight.leading;
+
owner->DrawString(fStation->Name()->String(),
frame.LeftTop()
+ BPoint(
@@ -96,12 +117,11 @@ StationListViewItem::DrawItem(BView* owner, BRect frame, bool complete)
frame = ownerList->ItemFrame(ownerList->StationIndex(fStation));
if (ownerList->CanPlay() && fStation->Flags(STATION_URI_VALID)) {
- BBitmap* bnBitmap = getButtonBitmap(State());
+ BBitmap* bnBitmap = _GetButtonBitmap(State());
if (bnBitmap != NULL) {
owner->SetDrawingMode(B_OP_ALPHA);
- owner->DrawBitmap(bnBitmap,
- frame.LeftTop()
- + BPoint(SLV_INSET, SLV_HEIGHT - SLV_INSET - SLV_BUTTON_SIZE));
+ owner->DrawBitmap(bnBitmap, frame.LeftTop()
+ + BPoint(SLV_INSET, SLV_HEIGHT - SLV_INSET - SLV_BUTTON_SIZE));
owner->SetDrawingMode(B_OP_COPY);
}
}
@@ -117,10 +137,12 @@ StationListViewItem::DrawBufferFillBar(BView* owner, BRect frame)
frame.left = SLV_HEIGHT - SLV_INSET + SLV_PADDING;
frame.top = frame.bottom - 5;
frame.right -= SLV_PADDING;
+
owner->SetHighColor(
tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_LIGHTEN_2_TINT));
owner->FillRect(frame);
owner->SetHighColor(200, 30, 0);
+
frame.right = frame.left + frame.Width() * fFillRatio;
owner->FillRect(frame);
}
@@ -137,24 +159,26 @@ StationListViewItem::Update(BView* owner, const BFont* font)
void
StationListViewItem::StateChanged(StreamPlayer::PlayState newState)
{
- if (fList && fList->LockLooperWithTimeout(0) == B_OK) {
+ if (fList != NULL && fList->LockLooperWithTimeout(0) == B_OK) {
fList->InvalidateItem(fList->IndexOf(this));
fList->UnlockLooper();
}
}
+BBitmap* StationListViewItem::sButtonBitmap[3] = {NULL, NULL, NULL};
+
BBitmap*
-StationListViewItem::getButtonBitmap(StreamPlayer::PlayState state)
+StationListViewItem::_GetButtonBitmap(StreamPlayer::PlayState state)
{
if (state < 0)
return NULL;
- if (buttonBitmap[state] == NULL)
- buttonBitmap[state] = Utils::ResourceBitmap(RES_BN_STOPPED + state);
- return buttonBitmap[state];
-}
-BBitmap* StationListViewItem::buttonBitmap[3] = {NULL, NULL, NULL};
+ if (sButtonBitmap[state] == NULL)
+ sButtonBitmap[state] = Utils::ResourceBitmap(RES_BN_STOPPED + state);
+
+ return sButtonBitmap[state];
+}
void
@@ -176,13 +200,13 @@ StationListView::StationListView(bool canPlay)
{
SetResizingMode(B_FOLLOW_ALL_SIDES);
SetExplicitMinSize(BSize(300, 2 * SLV_HEIGHT));
- playMsg = NULL;
+ fPlayMsg = NULL;
}
StationListView::~StationListView()
{
- delete playMsg;
+ delete fPlayMsg;
}
@@ -204,9 +228,11 @@ StationListView::AddItem(Station* station)
int32
StationListView::StationIndex(Station* station)
{
- for (int32 i = 0; i < CountItems(); i++)
- if (((StationListViewItem*) ItemAt(i))->GetStation() == station)
+ for (int32 i = 0; i < CountItems(); i++) {
+ if (((StationListViewItem*)ItemAt(i))->GetStation() == station)
return i;
+ }
+
return -1;
}
@@ -214,7 +240,7 @@ StationListView::StationIndex(Station* station)
StationListViewItem*
StationListView::ItemAt(int32 index)
{
- return (StationListViewItem*) BListView::ItemAt(index);
+ return (StationListViewItem*)BListView::ItemAt(index);
}
@@ -222,7 +248,7 @@ Station*
StationListView::StationAt(int32 index)
{
StationListViewItem* item = ItemAt(index);
- return (item) ? item->GetStation() : NULL;
+ return (item != NULL) ? item->GetStation() : NULL;
}
@@ -230,10 +256,11 @@ StationListViewItem*
StationListView::Item(Station* station)
{
for (int32 i = 0; i < CountItems(); i++) {
- StationListViewItem* stationItem = (StationListViewItem*) ItemAt(i);
+ StationListViewItem* stationItem = (StationListViewItem*)ItemAt(i);
if (stationItem->GetStation() == station)
return stationItem;
}
+
return NULL;
}
@@ -242,36 +269,39 @@ void
StationListView::Sync(StationsList* stations)
{
LockLooper();
+
for (int32 i = CountItems() - 1; i >= 0; i--) {
StationListViewItem* stationItem = (StationListViewItem*) ItemAt(i);
if (!stations->HasItem(stationItem->GetStation())) {
RemoveItem(i);
delete stationItem;
- }
}
+ }
for (int32 i = 0; i < stations->CountItems(); i++) {
Station* station = stations->ItemAt(i);
if (Item(station) == NULL)
AddItem(station);
}
+
Invalidate();
+
UnlockLooper();
}
void
-StationListView::SetPlayMessage(BMessage* playMsg)
+StationListView::SetPlayMessage(BMessage* fPlayMsg)
{
- delete this->playMsg;
- this->playMsg = playMsg;
+ delete this->fPlayMsg;
+ this->fPlayMsg = fPlayMsg;
}
void
StationListView::MouseDown(BPoint where)
{
- whereDown = where;
+ fWhereDown = where;
BListView::MouseDown(where);
}
@@ -279,18 +309,22 @@ StationListView::MouseDown(BPoint where)
void
StationListView::MouseUp(BPoint where)
{
- whereDown -= where;
- if (whereDown.x * whereDown.x + whereDown.y * whereDown.y < 5 && playMsg) {
+ fWhereDown -= where;
+ if (fWhereDown.x * fWhereDown.x + fWhereDown.y * fWhereDown.y < 5
+ && fPlayMsg != NULL) {
int stationIndex = IndexOf(where);
+
BRect playFrame = ItemFrame(stationIndex);
playFrame.InsetBy(SLV_INSET, SLV_INSET);
playFrame.right = playFrame.left + SLV_BUTTON_SIZE;
playFrame.top = playFrame.bottom - SLV_BUTTON_SIZE;
+
if (playFrame.Contains(where)) {
- BMessage* clone = new BMessage(playMsg->what);
+ BMessage* clone = new BMessage(fPlayMsg->what);
clone->AddInt32("index", stationIndex);
InvokeNotify(clone);
}
}
- whereDown = BPoint(-1, -1);
+
+ fWhereDown = BPoint(-1, -1);
}
diff --git a/StationListView.h b/StationListView.h
index 67ed376..511f8be 100644
--- a/StationListView.h
+++ b/StationListView.h
@@ -1,12 +1,23 @@
/*
- * File: StationListView.h
- * Author: user
+ * Copyright (C) 2017 Kai Niessen
*
- * Created on 26. Februar 2013, 09:22
+ * 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 _STATION_LIST_VIEW_H
+#define _STATION_LIST_VIEW_H
+
-#ifndef STATIONLISTVIEW_H
-#define STATIONLISTVIEW_H
#include
#include
#include
@@ -16,58 +27,75 @@
#include "Station.h"
#include "StreamPlayer.h"
+
#define MSG_STATION_LIST 'STLS'
+
class StationListView;
-class StationListViewItem : public BListItem
-{
+
+class StationListViewItem : public BListItem {
friend class StationListView;
public:
- StationListViewItem(Station* station);
- virtual ~StationListViewItem();
- virtual void DrawItem(BView* owner, BRect frame, bool complete);
- void DrawBufferFillBar(BView* owner, BRect frame);
- virtual void Update(BView* owner, const BFont* font);
- Station* GetStation() { return fStation; }
- void StateChanged(StreamPlayer::PlayState newState);
- void SetFillRatio(float fillRatio);
- StreamPlayer* Player() { return fPlayer; }
- StreamPlayer::PlayState State();
- void SetPlayer(StreamPlayer* player) { fPlayer = player; }
+ StationListViewItem(Station* station);
+ virtual ~StationListViewItem();
+
+ virtual void DrawItem(BView* owner, BRect frame,
+ bool complete);
+
+ void DrawBufferFillBar(BView* owner, BRect frame);
+ virtual void Update(BView* owner, const BFont* font);
+ Station* GetStation() { return fStation; }
+ void StateChanged(StreamPlayer::PlayState newState);
+ void SetFillRatio(float fillRatio);
+
+ StreamPlayer* Player() { return fPlayer; }
+ StreamPlayer::PlayState State();
+ void SetPlayer(StreamPlayer* player)
+ { fPlayer = player; }
+
+private:
+ static BBitmap* _GetButtonBitmap(StreamPlayer::PlayState state);
private:
- StationListView* fList;
- class Station* fStation;
- StreamPlayer* fPlayer;
- float fFillRatio;
- static BBitmap* getButtonBitmap(StreamPlayer::PlayState state);
- static BBitmap* buttonBitmap[3];
+ static BBitmap* sButtonBitmap[3];
+
+ StreamPlayer* fPlayer;
+ class Station* fStation;
+ StationListView* fList;
+
+ float fFillRatio;
};
-class StationListView : public BListView
-{
+
+class StationListView : public BListView {
public:
- StationListView(bool canPlay = false);
- virtual ~StationListView();
- void Sync(StationsList* stations);
- virtual bool AddItem(Station* station);
- virtual bool AddItem(StationListViewItem* item);
- int32 StationIndex(Station* station);
- StationListViewItem* Item(Station* station);
- StationListViewItem* ItemAt(int32 index);
- Station* StationAt(int32 index);
- void SetPlayMessage(BMessage* playMsg);
- bool CanPlay() { return fCanPlay; }
+ StationListView(bool canPlay = false);
+ virtual ~StationListView();
+
+ void Sync(StationsList* stations);
+
+ virtual bool AddItem(Station* station);
+ virtual bool AddItem(StationListViewItem* item);
+
+ int32 StationIndex(Station* station);
+ StationListViewItem* Item(Station* station);
+ StationListViewItem* ItemAt(int32 index);
+ Station* StationAt(int32 index);
+
+ void SetPlayMessage(BMessage* playMsg);
+ bool CanPlay() { return fCanPlay; }
+
+private:
+ virtual void MouseDown(BPoint where);
+ virtual void MouseUp(BPoint where);
private:
- virtual void MouseDown(BPoint where);
- virtual void MouseUp(BPoint where);
- BPoint whereDown;
- BMessage* playMsg;
- bool fCanPlay;
+ BPoint fWhereDown;
+ BMessage* fPlayMsg;
+ bool fCanPlay;
};
-#endif /* STATIONLISTVIEW_H */
+#endif // _STATION_LIST_VIEW_H
diff --git a/StationPanel.cpp b/StationPanel.cpp
index 08f9e5c..a45c50d 100644
--- a/StationPanel.cpp
+++ b/StationPanel.cpp
@@ -12,27 +12,23 @@
* 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 .
+ * along with this program. If not, see .
*/
-/*
- * File: StationPanel.cpp
- * Author: Kai Niessen
- *
- * Created on April 13, 2017, 1:25 PM
- */
-#include
-
-#include "Debug.h"
-#include "MainWindow.h"
#include "StationPanel.h"
-#include "Utils.h"
+
#include
#include
#include
+#include
#include
+#include "Debug.h"
+#include "MainWindow.h"
+#include "Utils.h"
+
+
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "StationPanel"
@@ -46,24 +42,32 @@ StationPanel::StationPanel(MainWindow* mainWindow, bool expanded)
SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM);
SetExplicitAlignment(
BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_VERTICAL_UNSET));
+
fLogo = new BView("logo", B_WILL_DRAW);
fLogo->SetExplicitSize(BSize(96, 96));
fLogo->SetViewColor(
tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_2_TINT));
+
fName = new BTextControl(
"name", B_TRANSLATE("Name"), "-", new BMessage(MSG_CHG_NAME));
+
fUrl = new BTextControl(
"url", B_TRANSLATE("Stream URL"), "-", new BMessage(MSG_CHG_STREAMURL));
+
fGenre = new BTextControl(
"genre", B_TRANSLATE("Genre"), "-", new BMessage(MSG_CHG_GENRE));
+
fStationUrl = new BTextControl("surl", B_TRANSLATE("Station URL"), "-",
new BMessage(MSG_CHG_STATIONURL));
+
fVisitStation
= new BButton("bnVisitStation", "", new BMessage(MSG_VISIT_STATION));
fVisitStation->SetIcon(Utils::ResourceBitmap(RES_BN_WEB));
+
fVolume = new BSlider(
"volume", NULL, new BMessage(MSG_CHG_VOLUME), 0, 100, B_VERTICAL);
fVolume->SetModificationMessage(new BMessage(MSG_CHG_VOLUME));
+
BLayoutBuilder::Grid<>(this, 7, 3)
.SetInsets(B_USE_SMALL_INSETS)
.SetSpacing(B_USE_ITEM_SPACING, B_USE_SMALL_SPACING)
@@ -74,7 +78,7 @@ StationPanel::StationPanel(MainWindow* mainWindow, bool expanded)
.AddTextControl(fStationUrl, 1, 2, B_ALIGN_LEFT, 1, 3)
.Add(fVisitStation, 5, 2)
.Add(fVolume, 6, 0, 1, 3)
- .End();
+ .End();
}
@@ -93,6 +97,7 @@ StationPanel::AttachedToWindow()
fStationUrl->SetTarget(this);
fVisitStation->SetTarget(this);
fVolume->SetTarget(this);
+
SetStation(NULL);
}
@@ -103,39 +108,53 @@ StationPanel::SetStation(StationListViewItem* stationItem)
if (stationItem == NULL) {
fName->SetText(NULL);
fName->SetEnabled(false);
+
fGenre->SetText(NULL);
fGenre->SetEnabled(false);
+
fUrl->SetText(NULL);
fUrl->SetEnabled(false);
+
fStationUrl->SetText(NULL);
fStationUrl->SetEnabled(false);
+
fVisitStation->SetEnabled(false);
+
fLogo->ClearViewBitmap();
+
fVolume->SetValue(0);
fVolume->SetEnabled(false);
+
fStationItem = NULL;
} else {
- if (stationItem->Player()
+ if (stationItem->Player() != NULL
&& stationItem->Player()->State() == StreamPlayer::Playing) {
fVolume->SetEnabled(true);
fVolume->SetValue(stationItem->Player()->Volume() * 100);
} else
fVolume->SetEnabled(false);
+
fStationItem = stationItem;
+
Station* station = stationItem->GetStation();
- if (station->Logo())
+ if (station->Logo()) {
fLogo->SetViewBitmap(station->Logo(), station->Logo()->Bounds(),
fLogo->Bounds(), 0, B_FILTER_BITMAP_BILINEAR);
- else
+ } else
fLogo->ClearViewBitmap();
+
fName->SetEnabled(true);
fName->SetText(station->Name()->String());
+
fGenre->SetEnabled(true);
fGenre->SetText(station->Genre().String());
+
fUrl->SetEnabled(true);
fUrl->SetText(station->StreamUrl().UrlString());
+
fStationUrl->SetEnabled(true);
fStationUrl->SetText(station->StationUrl().UrlString());
+
fVisitStation->SetEnabled(true);
}
}
@@ -144,7 +163,7 @@ StationPanel::SetStation(StationListViewItem* stationItem)
void
StationPanel::StateChanged(StreamPlayer::PlayState newState)
{
- if (fStationItem && fStationItem->Player()
+ if (fStationItem != NULL && fStationItem->Player() != NULL
&& fStationItem->Player()->State() == StreamPlayer::Playing) {
fVolume->SetEnabled(true);
fVolume->SetValue(fStationItem->Player()->Volume() * 100);
@@ -160,49 +179,62 @@ StationPanel::MessageReceived(BMessage* msg)
{
Station* station
= (fStationItem != NULL) ? fStationItem->GetStation() : NULL;
- if (station) {
+ if (station != NULL) {
entry_ref ref;
- BBitmap* bm;
if (msg->WasDropped() && msg->IsSourceRemote()
- && msg->FindRef("refs", &ref) == B_OK
- && (bm = BTranslationUtils::GetBitmap(&ref))) {
- station->SetLogo(bm);
- fLogo->SetViewBitmap(station->Logo(), station->Logo()->Bounds(),
- fLogo->Bounds(), 0, B_FILTER_BITMAP_BILINEAR);
+ && msg->FindRef("refs", &ref) == B_OK) {
+ BBitmap* bm = BTranslationUtils::GetBitmap(&ref);
+ if (bm != NULL) {
+ station->SetLogo(bm);
+ fLogo->SetViewBitmap(station->Logo(), station->Logo()->Bounds(),
+ fLogo->Bounds(), 0, B_FILTER_BITMAP_BILINEAR);
+ }
+
return;
}
+
switch (msg->what) {
case MSG_CHG_VOLUME:
{
StreamPlayer* player = fStationItem->Player();
- if (player)
+ if (player != NULL)
player->SetVolume(fVolume->Value() / 100.0);
+
break;
}
+
case MSG_CHG_NAME:
station->SetName(fName->Text());
break;
+
case MSG_CHG_STREAMURL:
station->SetStreamUrl(fUrl->Text());
break;
+
case MSG_CHG_GENRE:
station->SetGenre(fGenre->Text());
break;
+
case MSG_CHG_STATIONURL:
station->SetStation(fStationUrl->Text());
break;
+
case MSG_VISIT_STATION:
+ {
MSG("Trying to launch url %s\n",
station->StationUrl().UrlString().String());
+
if (station->StationUrl().UrlString().IsEmpty()) {
BString search;
- search.SetToFormat("http://google.com/search?q=%s",
+ search.SetToFormat("https://google.com/search?q=%s",
BUrl::UrlEncode(*station->Name()).String());
BUrl searchUrl(search);
searchUrl.OpenWithPreferredApplication(false);
} else
station->StationUrl().OpenWithPreferredApplication(false);
+
break;
+ }
default:
BView::MessageReceived(msg);
diff --git a/StationPanel.h b/StationPanel.h
index 10244c6..7d89361 100644
--- a/StationPanel.h
+++ b/StationPanel.h
@@ -12,26 +12,21 @@
* 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 .
+ * along with this program. If not, see .
*/
+#ifndef _STATION_PANEL_H
+#define _STATION_PANEL_H
-/*
- * File: StationPanel.h
- * Author: Kai Niessen
- *
- * Created on April 13, 2017, 1:25 PM
- */
-
-#ifndef STATIONPANEL_H
-#define STATIONPANEL_H
-#include "Station.h"
-#include "StationListView.h"
#include
#include
#include
#include
+#include "Station.h"
+#include "StationListView.h"
+
+
#define MSG_CHG_NAME 'cNAM'
#define MSG_CHG_VOLUME 'cVOL'
#define MSG_CHG_GENRE 'cGNR'
@@ -39,28 +34,34 @@
#define MSG_CHG_STATIONURL 'cSUR'
#define MSG_VISIT_STATION 'vSUR'
+
class MainWindow;
-class StationPanel : public BView
-{
+
+class StationPanel : public BView {
public:
- StationPanel(MainWindow* mainWindow, bool expanded = false);
- virtual ~StationPanel();
- virtual void AttachedToWindow();
- virtual void MessageReceived(BMessage* msg);
- void SetStation(StationListViewItem* stationItem);
- void StateChanged(StreamPlayer::PlayState newState);
+ StationPanel(MainWindow* mainWindow,
+ bool expanded = false);
+ virtual ~StationPanel();
+
+ virtual void AttachedToWindow();
+ virtual void MessageReceived(BMessage* msg);
+
+ void SetStation(StationListViewItem* stationItem);
+ void StateChanged(StreamPlayer::PlayState newState);
private:
- StationListViewItem* fStationItem;
- MainWindow* fMainWindow;
- BView* fLogo;
- BTextControl* fName;
- BTextControl* fUrl;
- BTextControl* fGenre;
- BTextControl* fStationUrl;
- BButton* fVisitStation;
- BSlider* fVolume;
+ StationListViewItem* fStationItem;
+ MainWindow* fMainWindow;
+
+ BView* fLogo;
+ BTextControl* fName;
+ BTextControl* fUrl;
+ BTextControl* fGenre;
+ BTextControl* fStationUrl;
+ BButton* fVisitStation;
+ BSlider* fVolume;
};
-#endif /* STATIONPANEL_H */
+
+#endif // _STATION_PANEL_H
diff --git a/StreamIO.cpp b/StreamIO.cpp
index c220cf9..3921fa0 100644
--- a/StreamIO.cpp
+++ b/StreamIO.cpp
@@ -12,33 +12,34 @@
* 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 .
+ * along with this program. If not, see .
*/
-/*
- * File: StreamIO.cpp
- * Author: Kai Niessen
- *
- * Created on April 11, 2017, 10:21 PM
- */
#include "StreamIO.h"
-#include "Debug.h"
-#include "HttpUtils.h"
-#include "MediaIO.h"
-#include "Station.h"
+
#define __USE_GNU
+#include
+
#include
#include
-#include
+
+#include "Debug.h"
+#include "HttpUtils.h"
+#include "Station.h"
+
+
+const char kMpegHeader1 = '\xff';
+const char kMpegHeader2 = '\xe0';
#define HTTP_TIMEOUT 30000000
+
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "StreamIO"
-StreamIO::StreamIO(Station* station, BLooper* MetaListener)
+StreamIO::StreamIO(Station* station, BLooper* metaListener)
:
BAdapterIO(B_MEDIA_STREAMING | B_MEDIA_SEEKABLE, HTTP_TIMEOUT),
fStation(station),
@@ -50,11 +51,10 @@ StreamIO::StreamIO(Station* station, BLooper* MetaListener)
fMetaSize(0),
fUntilMetaStart(0),
fUntilMetaEnd(0),
- fMetaListener(MetaListener),
+ fMetaListener(metaListener),
fFrameSync(none),
fLimit(0),
fBuffered(0)
-
{
BUrl url = station->StreamUrl();
@@ -76,33 +76,41 @@ StreamIO::StreamIO(Station* station, BLooper* MetaListener)
// of streams using HTTPS and load balancing between two or more different
// IP's should be small, anyway.
- if (url.Protocol() == "https")
+ if (url.Protocol() == "https") {
fReq = dynamic_cast(
BUrlProtocolRoster::MakeRequest(url.UrlString().String(), this));
- else {
+ } else {
BUrl* newUrl = new BUrl();
+ if (newUrl == NULL)
+ return;
+
status_t portStatus = HttpUtils::CheckPort(url, newUrl);
if (portStatus != B_OK)
return;
+
fReq = dynamic_cast(BUrlProtocolRoster::MakeRequest(
newUrl->UrlString().String(), this));
delete newUrl;
}
BHttpHeaders* headers = new BHttpHeaders();
+ if (headers == NULL)
+ return;
+
headers->AddHeader("Icy-MetaData", 1);
headers->AddHeader("Icy-Reset", 1);
headers->AddHeader("Accept", "audio/*");
+
fReq->AdoptHeaders(headers);
fReq->SetFollowLocation(true);
fReq->SetMaxRedirections(3);
+
fInputAdapter = BuildInputAdapter();
const char* mime = fStation->Mime()->Type();
if (!strcmp(mime, "audio/mpeg") || !strcmp(mime, "audio/aacp"))
fDataFuncs.Add(&StreamIO::DataUnsyncedReceived);
-
fDataFuncs.Add(&StreamIO::DataSyncedReceived);
}
@@ -114,6 +122,7 @@ StreamIO::~StreamIO()
status_t status;
wait_for_thread(fReqThread, &status);
}
+
delete fReq;
}
@@ -143,16 +152,18 @@ StreamIO::ReadAt(off_t position, void* buffer, size_t size)
" remaining\n",
read, size, position, Buffered());
fBuffered -= read;
- } else
+ } else {
TRACE("Reading %" B_PRIuSIZE " bytes from position %" B_PRIdOFF
" failed - %s\n",
size, position, strerror(read));
+ }
return read;
} else {
- TRACE("Position %" B_PRIuSIZE " has reached limit of %" B_PRIuSIZE
+ TRACE("Position %" B_PRIdOFF " has reached limit of %" B_PRIuSIZE
", blocking...\n",
position, fLimit);
+
return 0;
}
}
@@ -165,20 +176,6 @@ StreamIO::SetSize(off_t size)
}
-size_t
-StreamIO::Buffered()
-{
- return fBuffered;
-}
-
-
-void
-StreamIO::SetLimiter(size_t limit)
-{
- fLimit = limit;
-}
-
-
status_t
StreamIO::Open()
{
@@ -187,6 +184,7 @@ StreamIO::Open()
return B_ERROR;
fReqStartTime = system_time() + HTTP_TIMEOUT;
+
return BAdapterIO::Open();
}
@@ -198,6 +196,20 @@ StreamIO::IsRunning() const
}
+void
+StreamIO::SetLimiter(size_t limit)
+{
+ fLimit = limit;
+}
+
+
+size_t
+StreamIO::Buffered()
+{
+ return fBuffered;
+}
+
+
status_t
StreamIO::SeekRequested(off_t position)
{
@@ -227,6 +239,7 @@ StreamIO::HeadersReceived(BUrlRequest* request, const BUrlResult& result)
httpResult->Headers()["location"]);
} else
TRACE("Redirected to %s\n", httpResult->Headers()["location"]);
+
return;
}
@@ -240,8 +253,8 @@ StreamIO::HeadersReceived(BUrlRequest* request, const BUrlResult& result)
fIsMutable = true;
const char* sMetaInt = httpResult->Headers()["icy-metaint"];
- icyName = httpResult->Headers()["icy-name"];
- if (sMetaInt) {
+ fIcyName = httpResult->Headers()["icy-name"];
+ if (sMetaInt != NULL) {
fMetaInt = atoi(sMetaInt);
fUntilMetaStart = fMetaInt;
fDataFuncs.Add(&StreamIO::DataWithMetaReceived, 0);
@@ -270,10 +283,11 @@ void
StreamIO::DataWithMetaReceived(BUrlRequest* request, const char* data,
off_t position, ssize_t size, int next)
{
- while (size)
- if (fUntilMetaEnd != 0)
+ while (size > 0) {
+ if (fUntilMetaEnd != 0) {
if (fUntilMetaEnd <= size) {
- memcpy(fMetaBuffer + fMetaSize, (void*) data, fUntilMetaEnd);
+ memcpy(fMetaBuffer + fMetaSize, (void*)data, fUntilMetaEnd);
+
data += fUntilMetaEnd;
size -= fUntilMetaEnd;
fMetaSize += fUntilMetaEnd;
@@ -292,7 +306,7 @@ StreamIO::DataWithMetaReceived(BUrlRequest* request, const char* data,
fUntilMetaEnd -= size;
size = 0;
}
- else {
+ } else {
DataFunc nextFunc = fDataFuncs.Item(next);
if (size <= fUntilMetaStart) {
(*this.*nextFunc)(request, data, position, size, next + 1);
@@ -304,6 +318,7 @@ StreamIO::DataWithMetaReceived(BUrlRequest* request, const char* data,
size -= fUntilMetaStart;
position += fUntilMetaStart;
data += fUntilMetaStart;
+
fUntilMetaStart = 0;
fUntilMetaEnd = *data * 16;
if (fUntilMetaEnd == 0) {
@@ -312,52 +327,54 @@ StreamIO::DataWithMetaReceived(BUrlRequest* request, const char* data,
} else if (fUntilMetaEnd > 512) {
TRACE("Meta: Size of %" B_PRIdOFF " too large\n",
fUntilMetaEnd);
+
fUntilMetaStart = fMetaInt;
fUntilMetaEnd = 0;
data--;
size++;
}
+
data++;
size--;
}
}
+ }
}
-const char mpegHeader1 = '\xff';
-const char mpegHeader2 = '\xe0';
-
void
StreamIO::DataUnsyncedReceived(BUrlRequest* request, const char* data,
off_t position, ssize_t size, int next)
{
off_t frameStart;
- for (frameStart = 0; frameStart < size - 1; frameStart++)
+ for (frameStart = 0; frameStart < size - 1; frameStart++) {
if (fFrameSync == none) {
- if (data[frameStart] == mpegHeader1) {
+ if (data[frameStart] == kMpegHeader1) {
fFrameSync = first;
continue;
}
- } else if ((data[frameStart] & mpegHeader2) == mpegHeader2) {
+ } else if ((data[frameStart] & kMpegHeader2) == kMpegHeader2) {
next--;
fDataFuncs.Remove(next);
DataFunc nextFunc = fDataFuncs.Item(next);
(*this.*nextFunc)(
- request, &mpegHeader1, position + frameStart - 1, 1, next + 1);
+ request, &kMpegHeader1, position + frameStart - 1, 1, next + 1);
(*this.*nextFunc)(request, data + frameStart, position + frameStart,
size - frameStart, next + 1);
return;
} else
fFrameSync = none;
+ }
if (position + frameStart > 8192) {
- MSG("No mp3 frame header encountered in first %" B_PRIuSIZE
+ MSG("No mp3 frame header encountered in first %" B_PRIiOFF
" bytes, giving up...",
position + frameStart);
+
next--;
fDataFuncs.Remove(next);
- DataFunc nextFunc = fDataFuncs.Item(next);
+ // DataFunc nextFunc = fDataFuncs.Item(next);
}
}
@@ -378,17 +395,21 @@ StreamIO::RequestCompleted(BUrlRequest* request, bool success)
fReqThread = -1;
}
-// void
-// StreamIO::DebugMessage(BUrlRequest* caller, BUrlProtocolDebugMessage type,
-// const char* text) { MSG("Debug: %s\n", text);
-//}
+
+void
+StreamIO::DebugMessage(BUrlRequest* caller, BUrlProtocolDebugMessage type,
+ const char* text)
+{
+ DEBUG("Debug Message: %s\n", text);
+}
+
void
StreamIO::ProcessMeta()
{
TRACE("Meta: %s\n", fMetaBuffer);
- if (!fMetaListener)
+ if (fMetaListener == NULL)
return;
regmatch_t matches[4];
@@ -396,19 +417,24 @@ StreamIO::ProcessMeta()
BMessage* msg = new BMessage(MSG_META_CHANGE);
msg->AddString("station", fStation->Name()->String());
+
int res = regcomp(®ex, "([^=]*)='(([^']|'[^;])*)';",
RE_ICASE | RE_DOT_NEWLINE | RE_DOT_NOT_NULL | RE_NO_BK_PARENS
| RE_NO_BK_VBAR | RE_BACKSLASH_ESCAPE_IN_LISTS);
+
char* text = fMetaBuffer;
while ((res = regexec(®ex, text, 3, matches, 0)) == 0) {
text[matches[1].rm_eo] = 0;
text[matches[2].rm_eo] = 0;
+
if (text + matches[2].rm_so && !(text + matches[2].rm_so)[0])
- msg->AddString(strlwr(text + matches[1].rm_so), icyName);
+ msg->AddString(strlwr(text + matches[1].rm_so), fIcyName);
else
msg->AddString(
strlwr(text + matches[1].rm_so), text + matches[2].rm_so);
+
text += matches[0].rm_eo;
}
+
fMetaListener->PostMessage(msg);
}
diff --git a/StreamIO.h b/StreamIO.h
index c1ee6e8..7b2cb7e 100644
--- a/StreamIO.h
+++ b/StreamIO.h
@@ -12,125 +12,160 @@
* 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 .
+ * along with this program. If not, see .
*/
+#ifndef _STREAM_IO_H
+#define _STREAM_IO_H
-/*
- * File: StreamIO.h
- * Author: Kai Niessen
- *
- * Created on April 11, 2017, 10:21 PM
- */
-#ifndef STREAMIO_H
-#define STREAMIO_H
-
-#include
#include
#include
#include
-#include
#include
#include
#include
+#include
+#include
+
+
#define MSG_META_CHANGE 'META'
+
class Station;
class StreamIO;
+
typedef void (StreamIO::*DataFunc)(BUrlRequest* request, const char* data,
off_t position, ssize_t size, int next);
-class DataFuncs
-{
+
+class DataFuncs {
public:
- DataFuncs() : fSize(10), fLast(-1)
+ DataFuncs()
+ :
+ fSize(10),
+ fLast(-1)
{
for (int i = 0; i < fSize; i++)
fFuncs[i] = NULL;
};
- void Add(DataFunc f) { fFuncs[++fLast] = f; }
- void Add(DataFunc f, int before)
+
+
+ void
+ Add(DataFunc f)
+ {
+ fFuncs[++fLast] = f;
+ }
+
+
+ void
+ Add(DataFunc f, int before)
{
for (int i = fLast; i >= before; i--)
fFuncs[i + 1] = fFuncs[i];
fFuncs[before] = f;
fLast++;
};
- void Remove(int index)
+
+
+ void
+ Remove(int index)
{
- DataFunc result = fFuncs[index];
for (int i = index; i < fLast; i++)
fFuncs[i] = fFuncs[i + 1];
fFuncs[fLast--] = NULL;
};
- DataFunc Item(int index) { return fFuncs[index]; };
- DataFunc First() { return fFuncs[0]; };
+
+
+ DataFunc Item(int index) { return fFuncs[index]; };
+ DataFunc First() { return fFuncs[0]; };
private:
- DataFunc fFuncs[10];
- int fSize;
- int fLast;
+ DataFunc fFuncs[10];
+ int fSize;
+ int fLast;
};
-class StreamIO : public BAdapterIO, protected BUrlProtocolListener
-{
+
+class StreamIO : public BAdapterIO, protected BUrlProtocolListener {
public:
- StreamIO(Station* station, BLooper* MetaListener = NULL);
- virtual ~StreamIO();
- virtual void GetFlags(int32* flags) const;
- virtual ssize_t WriteAt(off_t position, const void* buffer, size_t size);
- virtual ssize_t ReadAt(off_t position, void* buffer, size_t size);
- virtual status_t SetSize(off_t size);
- virtual status_t Open();
- virtual bool IsRunning() const;
- void SetLimiter(size_t limit = 0);
- size_t Buffered();
+ StreamIO(Station* station,
+ BLooper* metaListener = NULL);
+ virtual ~StreamIO();
+
+ virtual void GetFlags(int32* flags) const;
+
+ virtual ssize_t WriteAt(off_t position, const void* buffer,
+ size_t size);
+ virtual ssize_t ReadAt(off_t position, void* buffer,
+ size_t size);
+
+ virtual status_t SetSize(off_t size);
+
+ virtual status_t Open();
+ virtual bool IsRunning() const;
+
+ void SetLimiter(size_t limit = 0);
+ size_t Buffered();
protected:
- virtual status_t SeekRequested(off_t position);
- virtual void HeadersReceived(
- BUrlRequest* request, const BUrlResult& result);
- virtual void DataRedirectReceived(BUrlRequest* request, const char* data,
- off_t position, ssize_t size, int next);
- virtual void DataWithMetaReceived(BUrlRequest* request, const char* data,
- off_t position, ssize_t size, int next);
- virtual void DataUnsyncedReceived(BUrlRequest* request, const char* data,
- off_t position, ssize_t size, int next);
- virtual void DataSyncedReceived(BUrlRequest* request, const char* data,
- off_t position, ssize_t size, int next);
- virtual void DataReceived(
- BUrlRequest* request, const char* data, off_t position, ssize_t size);
- virtual void RequestCompleted(BUrlRequest* request, bool success);
- // virtual void DebugMessage(BUrlRequest* caller,
- // BUrlProtocolDebugMessage type,
- // const char* text);
- void UpdateSize();
- void ProcessMeta();
+ virtual status_t SeekRequested(off_t position);
+ virtual void HeadersReceived(
+ BUrlRequest* request,
+ const BUrlResult& result);
+ virtual void DataRedirectReceived(BUrlRequest* request,
+ const char* data, off_t position,
+ ssize_t size, int next);
+ virtual void DataWithMetaReceived(BUrlRequest* request,
+ const char* data, off_t position,
+ ssize_t size, int next);
+ virtual void DataUnsyncedReceived(BUrlRequest* request,
+ const char* data, off_t position,
+ ssize_t size, int next);
+ virtual void DataSyncedReceived(BUrlRequest* request,
+ const char* data, off_t position,
+ ssize_t size, int next);
+
+ virtual void DataReceived(BUrlRequest* request,
+ const char* data, off_t position,
+ ssize_t size);
+ virtual void RequestCompleted(BUrlRequest* request,
+ bool success);
+ virtual void DebugMessage(BUrlRequest* caller,
+ BUrlProtocolDebugMessage type,
+ const char* text);
+
+ void UpdateSize();
+ void ProcessMeta();
private:
- DataFuncs fDataFuncs;
- Station* fStation;
- BInputAdapter* fInputAdapter;
- BHttpRequest* fReq;
- thread_id fReqThread;
- off_t fPosition;
- off_t fTotalSize;
- bool fIsMutable;
- size_t fMetaInt;
- char fMetaBuffer[512];
- size_t fMetaSize;
- off_t fUntilMetaStart;
- off_t fUntilMetaEnd;
- bigtime_t fReqStartTime;
- BLooper* fMetaListener;
- BString fStreamTitle;
- enum FrameSync { none, first, done };
- FrameSync fFrameSync;
- size_t fLimit;
- size_t fBuffered;
- const char* icyName;
+ enum FrameSync {none, first, done};
+
+ Station* fStation;
+ BHttpRequest* fReq;
+ thread_id fReqThread;
+ off_t fPosition;
+ off_t fTotalSize;
+ size_t fMetaInt;
+ size_t fMetaSize;
+ off_t fUntilMetaStart;
+ off_t fUntilMetaEnd;
+ BLooper* fMetaListener;
+ FrameSync fFrameSync;
+ size_t fLimit;
+ size_t fBuffered;
+
+ DataFuncs fDataFuncs;
+ BInputAdapter* fInputAdapter;
+ BString fStreamTitle;
+
+ const char* fIcyName;
+ bool fIsMutable;
+ char fMetaBuffer[512];
+ bigtime_t fReqStartTime;
+
};
-#endif /* STREAMIO_H */
+
+#endif // _STREAM_IO_H
diff --git a/StreamPlayer.cpp b/StreamPlayer.cpp
index c3a50dc..68ad66e 100644
--- a/StreamPlayer.cpp
+++ b/StreamPlayer.cpp
@@ -1,10 +1,21 @@
/*
- * File: StreamPlayer.cpp
- * Author: Kai Niessen
+ * Copyright (C) 2017 Kai Niessen
*
- * Created on January 25, 2016, 6:49 PM
+ * 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 .
*/
+
#include
#include
#include
@@ -14,27 +25,24 @@
#include "StreamIO.h"
#include "StreamPlayer.h"
-#define milliseconds *1000
-#define seconds *1000 milliseconds
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "StreamPlayer"
-StreamPlayer::StreamPlayer(Station* station, BLooper* Notify)
+StreamPlayer::StreamPlayer(Station* station, BLooper* notify)
:
- BLocker(),
+ BLocker("StreamPlayer"),
fStation(station),
- fNotify(Notify),
- fNoNotifyCount(0),
+ fNotify(notify),
fMediaFile(NULL),
fPlayer(NULL),
- fState(Stopped)
+ fState(StreamPlayer::Stopped)
{
TRACE("Trying to set player for stream %s\n",
station->StreamUrl().UrlString().String());
- fStream = new (std::nothrow) StreamIO(station, Notify);
+ fStream = new(std::nothrow) StreamIO(station, notify);
fInitStatus = fStream->Open();
if (fInitStatus != B_OK) {
MSG("Error retrieving stream from %s - %s\n",
@@ -46,133 +54,215 @@ StreamPlayer::StreamPlayer(Station* station, BLooper* Notify)
StreamPlayer::~StreamPlayer()
{
- setState(Stopped);
- if (fInitStatus == B_OK && fPlayer)
+ _SetState(StreamPlayer::Stopped);
+ if (fInitStatus == B_OK && fPlayer != NULL)
fPlayer->Stop(true, false);
+
delete fPlayer;
delete fStream;
delete fMediaFile;
}
-void
-StreamPlayer::GetDecodedChunk(void* cookie, void* buffer, size_t size,
- const media_raw_audio_format& format)
-{
- StreamPlayer* player = (StreamPlayer*) (cookie);
- BMediaFile* fMediaFile = player->fMediaFile;
- int64 reqFrames = size / format.channel_count
- / (format.format & media_raw_audio_format::B_AUDIO_SIZE_MASK);
- fMediaFile->TrackAt(0)->ReadFrames(
- buffer, &reqFrames, &player->fHeader, &player->fInfo);
-}
-
-
status_t
StreamPlayer::Play()
{
switch (fState) {
- case Playing:
- case Buffering:
+ case StreamPlayer::Playing:
+ case StreamPlayer::Buffering:
+ case StreamPlayer::InActive:
break;
- case Stopped:
+
+ case StreamPlayer::Stopped:
+ {
thread_id playThreadId
- = spawn_thread((thread_func) StreamPlayer::StartPlayThreadFunc,
+ = spawn_thread((thread_func)StreamPlayer::_StartPlayThreadFunc,
fStation->Name()->String(), B_NORMAL_PRIORITY, this);
resume_thread(playThreadId);
+
break;
+ }
}
+
return B_OK;
}
-#ifdef DEBUG
+
+status_t
+StreamPlayer::Stop()
+{
+ switch (fState) {
+ case StreamPlayer::Buffering:
+ fStopRequested = true;
+ break;
+
+ case StreamPlayer::Playing:
+ {
+ Lock();
+
+ if (fPlayer) {
+ fPlayer->Stop(false, true);
+ delete fPlayer;
+ fPlayer = NULL;
+ }
+
+ if (fMediaFile) {
+ fMediaFile->CloseFile();
+ delete fMediaFile;
+ fMediaFile = NULL;
+ }
+
+ Unlock();
+ _SetState(StreamPlayer::Stopped);
+
+ break;
+ }
+
+ case StreamPlayer::Stopped:
+ case StreamPlayer::InActive:
+ break;
+ }
+ return B_OK;
+}
+
+
+float
+StreamPlayer::Volume()
+{
+ if (fPlayer != NULL) {
+ media_node node;
+ int32 paramID;
+ float minDB, maxDB;
+ fPlayer->GetVolumeInfo(&node, ¶mID, &minDB, &maxDB);
+
+ return (fPlayer->VolumeDB(false) - minDB) / (maxDB - minDB);
+ } else
+ return 0;
+}
void
-dumpMessage(BMessage* msg)
+StreamPlayer::SetVolume(float volume)
{
- int n = msg->CountNames(B_ANY_TYPE);
- type_code typeCode;
- int32 arraySize;
- char* name;
- for (long int i = 0; i < n; i++) {
- msg->GetInfo(
- (long unsigned int) B_ANY_TYPE, i, &name, &typeCode, &arraySize);
- MSG("Meta data %s = %s\n", name, name);
+ if (fPlayer != NULL) {
+ media_node node;
+ int32 paramID;
+ float minDB, maxDB;
+ fPlayer->GetVolumeInfo(&node, ¶mID, &minDB, &maxDB);
+ fPlayer->SetVolumeDB(minDB + volume * (maxDB - minDB));
}
}
-#else
-void inline dumpMessage(BMessage* msg)
+void
+StreamPlayer::_SetState(StreamPlayer::PlayState state)
{
+ if (fState != state)
+ fState = state;
+
+ if (fNotify != NULL) {
+ BMessage* notification = new BMessage(MSG_PLAYER_STATE_CHANGED);
+ BMessenger messenger(fNotify);
+ notification->AddPointer("player", this);
+ notification->AddInt32("state", fState);
+ messenger.SendMessage(notification, fNotify);
+ }
+}
+
+
+void
+StreamPlayer::_GetDecodedChunk(void* cookie, void* buffer, size_t size,
+ const media_raw_audio_format& format)
+{
+ StreamPlayer* player = (StreamPlayer*)cookie;
+ BMediaFile* fMediaFile = player->fMediaFile;
+
+ int64 reqFrames = size / format.channel_count
+ / (format.format & media_raw_audio_format::B_AUDIO_SIZE_MASK);
+ fMediaFile->TrackAt(0)->ReadFrames(
+ buffer, &reqFrames, &player->fHeader, &player->fInfo);
}
-#endif
status_t
-StreamPlayer::StartPlayThreadFunc(StreamPlayer* _this)
+StreamPlayer::_StartPlayThreadFunc(StreamPlayer* _this)
{
_this->Lock();
- _this->setState(Buffering);
+
+ _this->_SetState(StreamPlayer::Buffering);
_this->fStopRequested = false;
_this->fStream->SetLimiter(0x40000);
- _this->fMediaFile = new (std::nothrow) BMediaFile(_this->fStream);
+ _this->fMediaFile = new(std::nothrow) BMediaFile(_this->fStream);
+
_this->fInitStatus = _this->fMediaFile->InitCheck();
- if (_this->fInitStatus != B_OK)
+ if (_this->fInitStatus != B_OK) {
MSG("Error creating media extractor for %s - %s\n",
_this->fStation->StreamUrl().UrlString().String(),
strerror(_this->fInitStatus));
+ }
if (_this->fInitStatus != B_OK || _this->fStopRequested) {
delete _this->fStream;
_this->fStream = NULL;
delete _this->fMediaFile;
_this->fMediaFile = NULL;
+
_this->Unlock();
- _this->setState(Stopped);
+ _this->_SetState(StreamPlayer::Stopped);
+
return _this->fInitStatus;
}
+
_this->fStream->SetLimiter(0);
- if (_this->fMediaFile->CountTracks() == 0)
+
+ if (_this->fMediaFile->CountTracks() == 0) {
MSG("No track found inside stream %s - %s\n",
_this->fStation->StreamUrl().UrlString().String(),
strerror(_this->fInitStatus));
+ }
- if (_this->fInitStatus != B_OK || _this->fStopRequested) {
+ if (_this->fStopRequested) {
delete _this->fMediaFile;
_this->fMediaFile = NULL;
+
_this->Unlock();
- _this->setState(Stopped);
+ _this->_SetState(StreamPlayer::Stopped);
+
return _this->fInitStatus;
}
_this->fInitStatus
= _this->fMediaFile->TrackAt(0)->GetCodecInfo(&_this->fCodecInfo);
- if (_this->fInitStatus != B_OK)
+ if (_this->fInitStatus != B_OK) {
MSG("Could not create decoder for %s - %s\n",
_this->fStation->StreamUrl().UrlString().String(),
strerror(_this->fInitStatus));
+ }
if (_this->fInitStatus != B_OK || _this->fStopRequested) {
delete _this->fMediaFile;
_this->fMediaFile = NULL;
+
_this->Unlock();
- _this->setState(Stopped);
+ _this->_SetState(StreamPlayer::Stopped);
+
return _this->fInitStatus;
}
_this->fInitStatus
= _this->fMediaFile->TrackAt(0)->DecodedFormat(&_this->fDecodedFormat);
- if (_this->fInitStatus != B_OK)
+ if (_this->fInitStatus != B_OK) {
MSG("Could not negotiate output format - %s\n",
strerror(_this->fInitStatus));
+ }
if (_this->fInitStatus != B_OK || _this->fStopRequested) {
delete _this->fMediaFile;
_this->fMediaFile = NULL;
+
_this->Unlock();
- _this->setState(Stopped);
+ _this->_SetState(StreamPlayer::Stopped);
+
return _this->fInitStatus;
}
@@ -181,110 +271,46 @@ StreamPlayer::StartPlayThreadFunc(StreamPlayer* _this)
_this->fDecodedFormat.u.raw_audio.frame_rate);
_this->fPlayer = new BSoundPlayer(&_this->fDecodedFormat.u.raw_audio,
- _this->fStation->Name()->String(), &StreamPlayer::GetDecodedChunk, NULL,
- _this);
+ _this->fStation->Name()->String(), &StreamPlayer::_GetDecodedChunk,
+ NULL, _this);
- _this->fStatus = _this->fPlayer->InitCheck();
- if (_this->fStatus != B_OK)
+ _this->fInitStatus = _this->fPlayer->InitCheck();
+ if (_this->fInitStatus != B_OK) {
MSG("Sound Player failed to initialize (%s)\r\n",
- strerror(_this->fStatus));
+ strerror(_this->fInitStatus));
+ }
if (_this->fInitStatus != B_OK || _this->fStopRequested) {
_this->fPlayer->Stop(true, true);
delete _this->fPlayer;
_this->fPlayer = NULL;
+
_this->Unlock();
- _this->setState(Stopped);
- return _this->fStatus;
+ _this->_SetState(StreamPlayer::Stopped);
+
+ return _this->fInitStatus;
}
_this->fPlayer->Preroll();
_this->fInitStatus = _this->fPlayer->Start();
- if (_this->fInitStatus != B_OK)
- MSG("Sound Player failed to start (%s)\r\n", strerror(_this->fStatus));
+ if (_this->fInitStatus != B_OK) {
+ MSG("Sound Player failed to start (%s)\r\n",
+ strerror(_this->fInitStatus));
+ }
if (_this->fInitStatus != B_OK || _this->fStopRequested) {
delete _this->fPlayer;
_this->fPlayer = NULL;
+
_this->Unlock();
- _this->setState(Stopped);
+ _this->_SetState(StreamPlayer::Stopped);
+
return _this->fInitStatus;
}
- _this->setState(Playing);
+ _this->_SetState(StreamPlayer::Playing);
_this->Unlock();
- return _this->fStatus;
-}
-
-
-status_t
-StreamPlayer::Stop()
-{
- switch (fState) {
- case Buffering:
- fStopRequested = true;
- break;
- case Playing:
- Lock();
- if (fPlayer) {
- fPlayer->Stop(false, true);
- delete fPlayer;
- fPlayer = NULL;
- }
- if (fMediaFile) {
- fMediaFile->CloseFile();
- delete fMediaFile;
- fMediaFile = NULL;
- }
- Unlock();
- setState(StreamPlayer::Stopped);
- break;
- case Stopped:
- case StreamPlayer::InActive:
- break;
- }
- return B_OK;
-}
-
-
-void
-StreamPlayer::setState(StreamPlayer::PlayState state)
-{
- if (fState != state)
- fState = state;
- if (fNotify) {
- BMessage* notification = new BMessage(MSG_PLAYER_STATE_CHANGED);
- BMessenger messenger(fNotify);
- notification->AddPointer("player", this);
- notification->AddInt32("state", fState);
- messenger.SendMessage(notification, fNotify);
- }
-}
-
-float
-StreamPlayer::Volume()
-{
- if (fPlayer) {
- media_node node;
- int32 paramID;
- float minDB, maxDB;
- fPlayer->GetVolumeInfo(&node, ¶mID, &minDB, &maxDB);
- return (fPlayer->VolumeDB(false) - minDB) / (maxDB - minDB);
- } else
- return 0;
-}
-
-
-void
-StreamPlayer::SetVolume(float volume)
-{
- if (fPlayer) {
- media_node node;
- int32 paramID;
- float minDB, maxDB;
- fPlayer->GetVolumeInfo(&node, ¶mID, &minDB, &maxDB);
- fPlayer->SetVolumeDB(minDB + volume * (maxDB - minDB));
- }
+ return _this->fInitStatus;
}
diff --git a/StreamPlayer.h b/StreamPlayer.h
index 8abd3c9..f6db508 100644
--- a/StreamPlayer.h
+++ b/StreamPlayer.h
@@ -1,21 +1,31 @@
/*
- * File: HttpPlayer.h
- * Author: Kai Niessen
+ * Copyright (C) 2017 Kai Niessen
*
- * Created on January 25, 2016, 6:49 PM
+ * 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 _STREAM_PLAYER_H
+#define _STREAM_PLAYER_H
+
-#ifndef STREAMPLAYER_H
-#define STREAMPLAYER_H
-//#include
-//#include
+#include
+#include
+#include
#include "Station.h"
#include "StreamIO.h"
-#include
-#include
-#include
+
// Notification Messages
#define MSG_PLAYER_STATE_CHANGED \
@@ -23,41 +33,50 @@
#define MSG_PLAYER_BUFFER_LEVEL \
'mPBL' // "player" = StreamPlayer*, "level" = float percent buffer filled
+
class Station;
-class StreamPlayer : BLocker
-{
+
+class StreamPlayer : private BLocker {
public:
- StreamPlayer(Station* station, BLooper* Notify = NULL);
- virtual ~StreamPlayer();
- inline status_t InitCheck() { return this->fInitStatus; }
- inline Station* GetStation() { return this->fStation; }
- status_t Play();
- status_t Stop();
- float Volume();
- void SetVolume(float volume);
- enum PlayState { InActive = -1, Stopped, Playing, Buffering };
- inline PlayState State() { return fState; }
+ StreamPlayer(Station* station,
+ BLooper* notify = NULL);
+ virtual ~StreamPlayer();
+
+ inline status_t InitCheck() { return fInitStatus; }
+ inline Station* GetStation() { return fStation; }
+ status_t Play();
+ status_t Stop();
+ float Volume();
+ void SetVolume(float volume);
+
+ enum PlayState { InActive = -1, Stopped, Playing, Buffering };
+ inline PlayState State() { return fState; }
+
+private:
+ void _SetState(PlayState state);
+
+ static status_t _StartPlayThreadFunc(StreamPlayer* _this);
+ static void _GetDecodedChunk(void* cookie, void* buffer,
+ size_t size,
+ const media_raw_audio_format& format);
private:
- PlayState fState;
- void setState(PlayState state);
- status_t fStatus, fInitStatus;
- BLooper* fNotify;
- int fNoNotifyCount;
- Station* fStation;
- StreamIO* fStream;
- BMediaFile* fMediaFile;
- BSoundPlayer* fPlayer;
- media_codec_info fCodecInfo;
- media_format fDecodedFormat;
- media_header fHeader;
- media_decode_info fInfo;
- BLocker fLock;
- bool fStopRequested;
- static status_t StartPlayThreadFunc(StreamPlayer* _this);
- static void GetDecodedChunk(void* cookie, void* buffer, size_t size,
- const media_raw_audio_format& format);
+ Station* fStation;
+ BLooper* fNotify;
+ BMediaFile* fMediaFile;
+ StreamIO* fStream;
+ BSoundPlayer* fPlayer;
+ PlayState fState;
+
+ status_t fInitStatus;
+ bool fStopRequested;
+
+ media_codec_info fCodecInfo;
+ media_format fDecodedFormat;
+ media_header fHeader;
+ media_decode_info fInfo;
};
-#endif /* STREAMPLAYER_H */
+
+#endif // _STREAM_PLAYER_H
diff --git a/StreamRadio-version.rdef b/StreamRadio-version.rdef
deleted file mode 100644
index 6158981..0000000
--- a/StreamRadio-version.rdef
+++ /dev/null
@@ -1,7 +0,0 @@
-resource app_signature "application/x-vnd.Fishpond-Radio";
-resource app_version {
- major = 0, middle = 0, minor = 4,
- variety = B_APPV_DEVELOPMENT, internal = 1,
- short_info="A player for online radio",
- long_info="Find and stream online radio stations"
-};
diff --git a/StreamRadio.rdef b/StreamRadio.rdef
index edd454d..8d0fb46 100644
--- a/StreamRadio.rdef
+++ b/StreamRadio.rdef
@@ -1,5 +1,5 @@
-resource app_signature "application/x-vnd.Fishpond-Radio";
+resource app_signature "application/x-vnd.Fishpond-StreamRadio";
resource file_types message {
"types" = "audio/x-mpegurl",
diff --git a/Utils.cpp b/Utils.cpp
index 5a0c891..4664f5a 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -12,17 +12,12 @@
* 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 .
+ * along with this program. If not, see .
*/
-/*
- * File: Utils.cpp
- * Author: Kai Niessen
- *
- * Created on April 16, 2017, 1:15 PM
- */
#include "Utils.h"
+
#include
#include
#include
@@ -33,11 +28,12 @@ Utils::ResourceBitmap(int32 id)
{
size_t size;
const char* data
- = (const char*) be_app->AppResources()->FindResource('BBMP', id, &size);
- if (size && data) {
+ = (const char*)be_app->AppResources()->FindResource('BBMP', id, &size);
+ if (size != 0 && data != NULL) {
BMessage msg;
- status_t status = msg.Unflatten(data);
- return (BBitmap*) BBitmap::Instantiate(&msg);
+ if (msg.Unflatten(data) == B_OK)
+ return (BBitmap*)BBitmap::Instantiate(&msg);
}
+
return NULL;
}
diff --git a/Utils.h b/Utils.h
index 3f428c9..a4a6512 100644
--- a/Utils.h
+++ b/Utils.h
@@ -12,34 +12,30 @@
* 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 .
+ * along with this program. If not, see .
*/
+#ifndef _UTILS_H
+#define _UTILS_H
-/*
- * File: Utils.h
- * Author: Kai Niessen
- *
- * Created on April 16, 2017, 1:15 PM
- */
-
-#ifndef UTILS_H
-#define UTILS_H
#include
#include
+
#define RES_BANNER 100
#define RES_BN_SEARCH 10
#define RES_BN_STOPPED 1
#define RES_BN_SEARCH 10
#define RES_BN_WEB 11
-class Utils
-{
+
+class Utils {
public:
- Utils(){};
- virtual ~Utils(){};
- static BBitmap* ResourceBitmap(int32 id);
+ Utils() {};
+ virtual ~Utils() {};
+
+ static BBitmap* ResourceBitmap(int32 id);
};
-#endif /* UTILS_H */
+
+#endif // _UTILS_H
diff --git a/nbproject/configurations.xml b/nbproject/configurations.xml
deleted file mode 100644
index 01cfb81..0000000
--- a/nbproject/configurations.xml
+++ /dev/null
@@ -1,427 +0,0 @@
-
-
-
-
- About.cpp
- About.h
- Buffering.h
- Debug.h
- Expander.cpp
- Expander.h
- HttpUtils.cpp
- HttpUtils.h
- MainWindow.cpp
- MainWindow.h
- RadioApp.cpp
- RadioApp.h
- RadioSettings.cpp
- RadioSettings.h
- Station.cpp
- Station.h
- StationFinder.cpp
- StationFinder.h
- StationFinderListenLive.cpp
- StationFinderListenLive.h
- StationFinderRadioNetwork.cpp
- StationFinderRadioNetwork.h
- StationListView.cpp
- StationListView.h
- StationPanel.cpp
- StationPanel.h
- StreamIO.cpp
- StreamIO.h
- StreamPlayer.cpp
- StreamPlayer.h
- Utils.cpp
- Utils.h
-
-
- /boot/home/projects/Haiku-Radio/Makefile
- /boot/home/projects/Radio/nbproject/private/launcher.properties
-
-
- ^(nbproject)$
-
- /boot/home/projects/Haiku-Radio
-
- /boot/home/projects/Radio/Makefile
-
-
-
- default
- false
- false
-
-
-
-
-
- /boot/home/projects/Haiku-Radio
- ${MAKE} -f Makefile
- ${MAKE} -f Makefile clean
- dist/Radio
-
-
- /boot/system/develop/headers/private/media/experimental
- /boot/system/develop/headers/private/shared
-
-
-
-
- .
-
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
-
- default
- false
- false
-
-
-
-
-
- /boot/home/projects/Haiku-Radio
- ${MAKE} -f Makefile "DEBUGGER=TRUE"
- ${MAKE} -f Makefile clean
- dist/Radio
-
-
- /boot/system/develop/headers/private/media/experimental
- /boot/system/develop/headers/private/shared
-
-
-
-
- .
-
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
-
diff --git a/nbproject/private/CodeAssistancePathMapper.properties b/nbproject/private/CodeAssistancePathMapper.properties
deleted file mode 100644
index 7f5ded8..0000000
--- a/nbproject/private/CodeAssistancePathMapper.properties
+++ /dev/null
@@ -1 +0,0 @@
-# Automatic path mapper. CRC = 1
diff --git a/nbproject/private/Default-build.log b/nbproject/private/Default-build.log
deleted file mode 100644
index 894a1b1..0000000
--- a/nbproject/private/Default-build.log
+++ /dev/null
@@ -1,56 +0,0 @@
-mkdir -p objects.x86-cc2-release; \
-mkdepend -I./ -Iobjects.x86-cc2-release/ -p .cpp:objects.x86-cc2-release/%n.o -m -f "objects.x86-cc2-release/Utils.d" Utils.cpp
-mkdir -p objects.x86-cc2-release; \
-mkdepend -I./ -Iobjects.x86-cc2-release/ -p .cpp:objects.x86-cc2-release/%n.o -m -f "objects.x86-cc2-release/StreamPlayer.d" StreamPlayer.cpp
-mkdir -p objects.x86-cc2-release; \
-mkdepend -I./ -Iobjects.x86-cc2-release/ -p .cpp:objects.x86-cc2-release/%n.o -m -f "objects.x86-cc2-release/StreamIO.d" StreamIO.cpp
-mkdir -p objects.x86-cc2-release; \
-mkdepend -I./ -Iobjects.x86-cc2-release/ -p .cpp:objects.x86-cc2-release/%n.o -m -f "objects.x86-cc2-release/StationPanel.d" StationPanel.cpp
-mkdir -p objects.x86-cc2-release; \
-mkdepend -I./ -Iobjects.x86-cc2-release/ -p .cpp:objects.x86-cc2-release/%n.o -m -f "objects.x86-cc2-release/StationListView.d" StationListView.cpp
-mkdir -p objects.x86-cc2-release; \
-mkdepend -I./ -Iobjects.x86-cc2-release/ -p .cpp:objects.x86-cc2-release/%n.o -m -f "objects.x86-cc2-release/StationFinderRadioNetwork.d" StationFinderRadioNetwork.cpp
-mkdir -p objects.x86-cc2-release; \
-mkdepend -I./ -Iobjects.x86-cc2-release/ -p .cpp:objects.x86-cc2-release/%n.o -m -f "objects.x86-cc2-release/StationFinderListenLive.d" StationFinderListenLive.cpp
-mkdir -p objects.x86-cc2-release; \
-mkdepend -I./ -Iobjects.x86-cc2-release/ -p .cpp:objects.x86-cc2-release/%n.o -m -f "objects.x86-cc2-release/StationFinder.d" StationFinder.cpp
-mkdir -p objects.x86-cc2-release; \
-mkdepend -I./ -Iobjects.x86-cc2-release/ -p .cpp:objects.x86-cc2-release/%n.o -m -f "objects.x86-cc2-release/Station.d" Station.cpp
-mkdir -p objects.x86-cc2-release; \
-mkdepend -I./ -Iobjects.x86-cc2-release/ -p .cpp:objects.x86-cc2-release/%n.o -m -f "objects.x86-cc2-release/RadioSettings.d" RadioSettings.cpp
-mkdir -p objects.x86-cc2-release; \
-mkdepend -I./ -Iobjects.x86-cc2-release/ -p .cpp:objects.x86-cc2-release/%n.o -m -f "objects.x86-cc2-release/RadioApp.d" RadioApp.cpp
-mkdir -p objects.x86-cc2-release; \
-mkdepend -I./ -Iobjects.x86-cc2-release/ -p .cpp:objects.x86-cc2-release/%n.o -m -f "objects.x86-cc2-release/MainWindow.d" MainWindow.cpp
-mkdir -p objects.x86-cc2-release; \
-mkdepend -I./ -Iobjects.x86-cc2-release/ -p .cpp:objects.x86-cc2-release/%n.o -m -f "objects.x86-cc2-release/HttpUtils.d" HttpUtils.cpp
-mkdir -p objects.x86-cc2-release; \
-mkdepend -I./ -Iobjects.x86-cc2-release/ -p .cpp:objects.x86-cc2-release/%n.o -m -f "objects.x86-cc2-release/Expander.d" Expander.cpp
-mkdir -p objects.x86-cc2-release; \
-mkdepend -I./ -Iobjects.x86-cc2-release/ -p .cpp:objects.x86-cc2-release/%n.o -m -f "objects.x86-cc2-release/About.d" About.cpp
-g++ -c About.cpp -I./ -Iobjects.x86-cc2-release/ -I- -I/boot/system/develop/headers/private/media -I/boot/system/develop/headers/private/media/experimental -I/boot/system/develop/headers/private/shared -I/boot/system/develop/headers/libxml2 -O3 -DHAIKU_TARGET_PLATFORM_HAIKU -o "objects.x86-cc2-release/About.o"
-g++ -c Expander.cpp -I./ -Iobjects.x86-cc2-release/ -I- -I/boot/system/develop/headers/private/media -I/boot/system/develop/headers/private/media/experimental -I/boot/system/develop/headers/private/shared -I/boot/system/develop/headers/libxml2 -O3 -DHAIKU_TARGET_PLATFORM_HAIKU -o "objects.x86-cc2-release/Expander.o"
-g++ -c HttpUtils.cpp -I./ -Iobjects.x86-cc2-release/ -I- -I/boot/system/develop/headers/private/media -I/boot/system/develop/headers/private/media/experimental -I/boot/system/develop/headers/private/shared -I/boot/system/develop/headers/libxml2 -O3 -DHAIKU_TARGET_PLATFORM_HAIKU -o "objects.x86-cc2-release/HttpUtils.o"
-g++ -c MainWindow.cpp -I./ -Iobjects.x86-cc2-release/ -I- -I/boot/system/develop/headers/private/media -I/boot/system/develop/headers/private/media/experimental -I/boot/system/develop/headers/private/shared -I/boot/system/develop/headers/libxml2 -O3 -DHAIKU_TARGET_PLATFORM_HAIKU -o "objects.x86-cc2-release/MainWindow.o"
-g++ -c RadioApp.cpp -I./ -Iobjects.x86-cc2-release/ -I- -I/boot/system/develop/headers/private/media -I/boot/system/develop/headers/private/media/experimental -I/boot/system/develop/headers/private/shared -I/boot/system/develop/headers/libxml2 -O3 -DHAIKU_TARGET_PLATFORM_HAIKU -o "objects.x86-cc2-release/RadioApp.o"
-g++ -c RadioSettings.cpp -I./ -Iobjects.x86-cc2-release/ -I- -I/boot/system/develop/headers/private/media -I/boot/system/develop/headers/private/media/experimental -I/boot/system/develop/headers/private/shared -I/boot/system/develop/headers/libxml2 -O3 -DHAIKU_TARGET_PLATFORM_HAIKU -o "objects.x86-cc2-release/RadioSettings.o"
-g++ -c Station.cpp -I./ -Iobjects.x86-cc2-release/ -I- -I/boot/system/develop/headers/private/media -I/boot/system/develop/headers/private/media/experimental -I/boot/system/develop/headers/private/shared -I/boot/system/develop/headers/libxml2 -O3 -DHAIKU_TARGET_PLATFORM_HAIKU -o "objects.x86-cc2-release/Station.o"
-g++ -c StationFinder.cpp -I./ -Iobjects.x86-cc2-release/ -I- -I/boot/system/develop/headers/private/media -I/boot/system/develop/headers/private/media/experimental -I/boot/system/develop/headers/private/shared -I/boot/system/develop/headers/libxml2 -O3 -DHAIKU_TARGET_PLATFORM_HAIKU -o "objects.x86-cc2-release/StationFinder.o"
-g++ -c StationFinderListenLive.cpp -I./ -Iobjects.x86-cc2-release/ -I- -I/boot/system/develop/headers/private/media -I/boot/system/develop/headers/private/media/experimental -I/boot/system/develop/headers/private/shared -I/boot/system/develop/headers/libxml2 -O3 -DHAIKU_TARGET_PLATFORM_HAIKU -o "objects.x86-cc2-release/StationFinderListenLive.o"
-g++ -c StationFinderRadioNetwork.cpp -I./ -Iobjects.x86-cc2-release/ -I- -I/boot/system/develop/headers/private/media -I/boot/system/develop/headers/private/media/experimental -I/boot/system/develop/headers/private/shared -I/boot/system/develop/headers/libxml2 -O3 -DHAIKU_TARGET_PLATFORM_HAIKU -o "objects.x86-cc2-release/StationFinderRadioNetwork.o"
-g++ -c StationListView.cpp -I./ -Iobjects.x86-cc2-release/ -I- -I/boot/system/develop/headers/private/media -I/boot/system/develop/headers/private/media/experimental -I/boot/system/develop/headers/private/shared -I/boot/system/develop/headers/libxml2 -O3 -DHAIKU_TARGET_PLATFORM_HAIKU -o "objects.x86-cc2-release/StationListView.o"
-g++ -c StationPanel.cpp -I./ -Iobjects.x86-cc2-release/ -I- -I/boot/system/develop/headers/private/media -I/boot/system/develop/headers/private/media/experimental -I/boot/system/develop/headers/private/shared -I/boot/system/develop/headers/libxml2 -O3 -DHAIKU_TARGET_PLATFORM_HAIKU -o "objects.x86-cc2-release/StationPanel.o"
-g++ -c StreamIO.cpp -I./ -Iobjects.x86-cc2-release/ -I- -I/boot/system/develop/headers/private/media -I/boot/system/develop/headers/private/media/experimental -I/boot/system/develop/headers/private/shared -I/boot/system/develop/headers/libxml2 -O3 -DHAIKU_TARGET_PLATFORM_HAIKU -o "objects.x86-cc2-release/StreamIO.o"
-g++ -c StreamPlayer.cpp -I./ -Iobjects.x86-cc2-release/ -I- -I/boot/system/develop/headers/private/media -I/boot/system/develop/headers/private/media/experimental -I/boot/system/develop/headers/private/shared -I/boot/system/develop/headers/libxml2 -O3 -DHAIKU_TARGET_PLATFORM_HAIKU -o "objects.x86-cc2-release/StreamPlayer.o"
-g++ -c Utils.cpp -I./ -Iobjects.x86-cc2-release/ -I- -I/boot/system/develop/headers/private/media -I/boot/system/develop/headers/private/media/experimental -I/boot/system/develop/headers/private/shared -I/boot/system/develop/headers/libxml2 -O3 -DHAIKU_TARGET_PLATFORM_HAIKU -o "objects.x86-cc2-release/Utils.o"
-echo "resource app_signature \"application/x-vnd.Fishpond-Radio\";" > Radio-version.rdef
-echo "resource app_version {" >> Radio-version.rdef
-echo " major = 0, middle = 0, minor = 3," >> Radio-version.rdef
-echo " variety = B_APPV_ALPHA, internal = 9," >> Radio-version.rdef
-echo " short_info=\"Radio\"," >> Radio-version.rdef
-echo " long_info=\"Radio v0.0.3-9, ©Fishpond 2017\"" >> Radio-version.rdef
-echo "};" >> Radio-version.rdef
-cat Radio-version.rdef | cc -E -I./ -Iobjects.x86-cc2-release/ -I- -I/boot/system/develop/headers/private/media -I/boot/system/develop/headers/private/media/experimental -I/boot/system/develop/headers/private/shared -I/boot/system/develop/headers/libxml2 -O3 -DHAIKU_TARGET_PLATFORM_HAIKU - | grep -av '^#' | rc -I ./ -o "objects.x86-cc2-release/Radio-version.rsrc" -
-cc -o "dist/Radio" objects.x86-cc2-release/About.o objects.x86-cc2-release/Expander.o objects.x86-cc2-release/HttpUtils.o objects.x86-cc2-release/MainWindow.o objects.x86-cc2-release/RadioApp.o objects.x86-cc2-release/RadioSettings.o objects.x86-cc2-release/Station.o objects.x86-cc2-release/StationFinder.o objects.x86-cc2-release/StationFinderListenLive.o objects.x86-cc2-release/StationFinderRadioNetwork.o objects.x86-cc2-release/StationListView.o objects.x86-cc2-release/StationPanel.o objects.x86-cc2-release/StreamIO.o objects.x86-cc2-release/StreamPlayer.o objects.x86-cc2-release/Utils.o -Xlinker -soname=_APP_ -L./ -Lobjects.x86-cc2-release/ -lstdc++.r4 -lbe -ltranslation -lbnetapi -lmedia -lxml2
-xres -o ./dist/Radio Radio.rsrc objects.x86-cc2-release/Radio-version.rsrc
-mimeset -f "dist/Radio"
diff --git a/nbproject/private/Release.properties b/nbproject/private/Release.properties
deleted file mode 100644
index e69de29..0000000
diff --git a/nbproject/private/configurations.xml b/nbproject/private/configurations.xml
deleted file mode 100644
index 4489b4d..0000000
--- a/nbproject/private/configurations.xml
+++ /dev/null
@@ -1,148 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- About.cpp
- About.h
- Buffering.h
- Debug.h
- Expander.cpp
- Expander.h
- HttpUtils.cpp
- HttpUtils.h
- MainWindow.cpp
- MainWindow.h
- RadioApp.cpp
- RadioApp.h
- RadioSettings.cpp
- RadioSettings.h
- Station.cpp
- Station.h
- StationFinder.cpp
- StationFinder.h
- StationFinderListenLive.cpp
- StationFinderListenLive.h
- StationFinderRadioNetwork.cpp
- StationFinderRadioNetwork.h
- StationListView.cpp
- StationListView.h
- StationPanel.cpp
- StationPanel.h
- StreamIO.cpp
- StreamIO.h
- StreamPlayer.cpp
- StreamPlayer.h
- Utils.cpp
- Utils.h
-
-
- /boot/home/projects/Radio/Makefile
-
-
-
- localhost
- 5
-
-
-
- .
- ${AUTO_FOLDER}
-
- ${AUTO_FOLDER}
-
- ${MAKE} ${ITEM_NAME}.o
- ${AUTO_COMPILE}
-
- ${AUTO_COMPILE}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- gdb
-
-
-
- "${OUTPUT_PATH}"
- dist/Radio
- Radio
-
- Radio
- dist
- false
- 0
- 0
-
-
-
-
-
-
- localhost
- 5
-
-
-
- .
- ${AUTO_FOLDER}
-
- ${AUTO_FOLDER}
-
- ${MAKE} ${ITEM_NAME}.o
- ${AUTO_COMPILE}
-
- ${AUTO_COMPILE}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- gdb
-
-
-
- "${OUTPUT_PATH}"
- dist/Radio
- Radio
-
- Radio
- dist
- false
- 0
- 0
-
-
-
-
-
-
diff --git a/nbproject/private/launcher.properties b/nbproject/private/launcher.properties
deleted file mode 100644
index 6cc2127..0000000
--- a/nbproject/private/launcher.properties
+++ /dev/null
@@ -1,40 +0,0 @@
-# Launchers File syntax:
-#
-# [Must-have property line]
-# launcher1.runCommand=
-# [Optional extra properties]
-# launcher1.displayName=
-# launcher1.buildCommand=
-# launcher1.runDir=
-# launcher1.symbolFiles=
-# launcher1.env.=
-# (If this value is quoted with ` it is handled as a native command which execution result will become the value)
-# [Common launcher properties]
-# common.runDir=
-# (This value is overwritten by a launcher specific runDir value if the latter exists)
-# common.env.=
-# (Environment variables from common launcher are merged with launcher specific variables)
-# common.symbolFiles=
-# (This value is overwritten by a launcher specific symbolFiles value if the latter exists)
-#
-# In runDir, symbolFiles and env fields you can use these macroses:
-# ${PROJECT_DIR} - project directory absolute path
-# ${OUTPUT_PATH} - linker output path (relative to project directory path)
-# ${OUTPUT_BASENAME}- linker output filename
-# ${TESTDIR} - test files directory (relative to project directory path)
-# ${OBJECTDIR} - object files directory (relative to project directory path)
-# ${CND_DISTDIR} - distribution directory (relative to project directory path)
-# ${CND_BUILDDIR} - build directory (relative to project directory path)
-# ${CND_PLATFORM} - platform name
-# ${CND_CONF} - configuration name
-# ${CND_DLIB_EXT} - dynamic library extension
-#
-# All the project launchers must be listed in the file!
-#
-# launcher1.runCommand=...
-# launcher2.runCommand=...
-# ...
-# common.runDir=...
-# common.env.KEY=VALUE
-
-# launcher1.runCommand=
\ No newline at end of file
diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml
deleted file mode 100644
index 5caf8ac..0000000
--- a/nbproject/private/private.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
- true
-
-
- 0
- 1
-
-
-
-
- file:/boot/home/projects/Haiku-Radio/Makefile
- file:/boot/home/projects/Haiku-Radio/Station.cpp
- file:/boot/home/projects/Haiku-Radio/StationFinder.cpp
- file:/boot/home/projects/Haiku-Radio/PackageInfo
-
-
-
diff --git a/nbproject/project.xml b/nbproject/project.xml
deleted file mode 100644
index 2302750..0000000
--- a/nbproject/project.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
- org.netbeans.modules.cnd.makeproject
-
-
- Radio
-
- cpp
- h
- UTF-8
-
-
- /boot/home/projects/Haiku-Radio
-
-
-
- Release
- 0
-
-
- Debug
- 0
-
-
-
- false
-
-
-
-