--- a/src/sc2mpd.cpp
+++ b/src/sc2mpd.cpp
@@ -51,7 +51,7 @@
using namespace std;
-WorkQueue<AudioMessage*> audioqueue("audioqueue", 2);
+WorkQueue<AudioMessage*> audioqueue("audioqueue", 4);
#ifdef _WIN32
@@ -95,7 +95,7 @@
class OhmReceiverDriver : public IOhmReceiverDriver, public IOhmMsgProcessor {
public:
- OhmReceiverDriver(int port);
+ OhmReceiverDriver(AudioEater* eater, int port);
private:
// IOhmReceiverDriver
@@ -137,13 +137,15 @@
void process(OhmMsgAudio& aMsg);
};
- Observer obs;
+ Observer m_obs;
+ AudioEater *m_eater;
};
-OhmReceiverDriver::OhmReceiverDriver(int port)
-{
- AudioEaterContext *ctxt = new AudioEaterContext(port);
- audioqueue.start(1, &audioEater, ctxt);
+OhmReceiverDriver::OhmReceiverDriver(AudioEater *eater, int port)
+ : m_eater(eater)
+{
+ AudioEater::Context *ctxt = new AudioEater::Context(&audioqueue, port);
+ audioqueue.start(1, m_eater->worker, ctxt);
}
void OhmReceiverDriver::Add(OhmMsg& aMsg)
@@ -163,7 +165,7 @@
void OhmReceiverDriver::Connected()
{
- obs.reset();
+ m_obs.reset();
LOGDEB("=== CONNECTED ====\n");
}
@@ -184,6 +186,7 @@
LOGDEB("=== STOPPED ====\n");
}
+// Debug and stats only, not needed for main function
void OhmReceiverDriver::Observer::process(OhmMsgAudio& aMsg)
{
if (++iCount == 400 || aMsg.Halt()) {
@@ -254,11 +257,12 @@
void OhmReceiverDriver::Process(OhmMsgAudio& aMsg)
{
-
if (aMsg.Audio().Bytes() == 0) {
LOGDEB("OhmReceiverDriver::Process: empty message\n");
return;
}
+
+ m_obs.process(aMsg);
unsigned int bytes = aMsg.Audio().Bytes();
char *buf = (char *)malloc(bytes);
@@ -268,35 +272,48 @@
return;
}
+ // Songcast data is always msb-first. Convert to desired order:
+ // depends on what downstream wants, and just as well we do it
+ // here because we copy the buf anyway.
+ bool needswap = false;
+ switch (m_eater->input_border) {
+ case AudioEater::BO_MSB: break;
+ case AudioEater::BO_LSB: needswap = true; break;
+ case AudioEater::BO_HOST:
#ifdef WORDS_BIGENDIAN
- memcpy(buf, aMsg.Audio().Ptr(), bytes);
+ needswap = false;
#else
- if (aMsg.BitDepth() == 16) {
- swab(aMsg.Audio().Ptr(), buf, bytes);
- } else if (aMsg.BitDepth() == 24) {
+ needswap = true;
+#endif
+ }
+
+ if (needswap) {
unsigned char *ocp = (unsigned char *)buf;
- const unsigned char *icp = (const unsigned char *)aMsg.Audio().Ptr();
+ const unsigned char *icp =
+ (const unsigned char *)aMsg.Audio().Ptr();
const unsigned char *icp0 = icp;
- while (icp - icp0 <= int(bytes) - 3) {
- *ocp++ = icp[2];
- *ocp++ = icp[1];
- *ocp++ = *icp;
- icp += 3;
- }
- } else if (aMsg.BitDepth() == 32) {
- // Never seen this but whatever...
- unsigned char *ocp = (unsigned char *)buf;
- const unsigned char *icp = (const unsigned char *)aMsg.Audio().Ptr();
- const unsigned char *icp0 = icp;
- while (icp - icp0 <= int(bytes) - 4) {
- *ocp++ = icp[3];
- *ocp++ = icp[2];
- *ocp++ = icp[1];
- *ocp++ = *icp;
- icp += 4;
- }
- }
-#endif
+ if (aMsg.BitDepth() == 16) {
+ swab(aMsg.Audio().Ptr(), buf, bytes);
+ } else if (aMsg.BitDepth() == 24) {
+ while (icp - icp0 <= int(bytes) - 3) {
+ *ocp++ = icp[2];
+ *ocp++ = icp[1];
+ *ocp++ = *icp;
+ icp += 3;
+ }
+ } else if (aMsg.BitDepth() == 32) {
+ // Never seen this but whatever...
+ while (icp - icp0 <= int(bytes) - 4) {
+ *ocp++ = icp[3];
+ *ocp++ = icp[2];
+ *ocp++ = icp[1];
+ *ocp++ = *icp;
+ icp += 4;
+ }
+ }
+ } else {
+ memcpy(buf, aMsg.Audio().Ptr(), bytes);
+ }
AudioMessage *ap = new
AudioMessage(aMsg.BitDepth(), aMsg.Channels(), aMsg.Samples(),
@@ -304,7 +321,7 @@
// There is nothing special we can do if put fails: no way to
// return status. Should we just exit ?
- if (!audioqueue.put(ap, true)) {
+ if (!audioqueue.put(ap, false)) {
}
}
@@ -351,6 +368,11 @@
"[config] upmpdcli configuration file path");
parser.AddOption(&optionConfig);
+ OptionBool optionDevice("-d", "--direct-alsa",
+ "[stream] Use alsa directly instead of producing "
+ "http stream");
+ parser.AddOption(&optionDevice);
+
if (!parser.Parse(aArgc, aArgv)) {
return (1);
}
@@ -400,7 +422,8 @@
((subnet >> 8) & 0xff) << "." << ((subnet >> 16) & 0xff) << "." <<
((subnet >> 24) & 0xff) << endl);
- OhmReceiverDriver* driver = new OhmReceiverDriver(port);
+ OhmReceiverDriver* driver = new OhmReceiverDriver(
+ optionDevice.Value() ? &alsaAudioEater : &httpAudioEater, port);
OhmReceiver* receiver = new OhmReceiver(lib->Env(), adapter, ttl, *driver);