I have several updates for Shoutcast, including:
* Rewrote the buffer code in EncoderMp3 to initialize and grow them
with the same function. This makes for less redundant code and also
makes sure that it doesn't use uninitialized values.
* Moved all the encoder code to updateFromPreferences. It will now
reinitialize the encoder if the format or bitrate changes.
* Renaming encoder to m_pEncoder
Should I revive features_shoutcast, wait for swift approval or just
commit straight to trunk? Any comments or questions are also welcome.
Have Fun!
Madjester
--
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS d--@>+ s(+):(-) a- C++(++++)$ ULC+++(++++) P+ L+++ E-() W++ N o? K
w-- O? !M V PS+(+++) PE(-) Y+ !PGP !t !5 X(+) !R tv+ b++ DI+ D+ G e>++
h r y+
------END GEEK CODE BLOCK------
=== modified file 'mixxx/src/encodermp3.cpp'
--- mixxx/src/encodermp3.cpp 2009-02-18 04:28:21 +0000
+++ mixxx/src/encodermp3.cpp 2009-10-15 06:09:01 +0000
@@ -32,6 +32,14 @@
if (engine) pEngine = engine;
metaDataTitle = metaDataArtist = "";
m_pConfig = _config;
+
+ // Set the buffers to NULL values. The First buffer growth allocates them.
+ m_bufferOutSize = 0;
+ m_bufferOut = NULL;
+
+ m_bufferInSize = 0;
+ m_bufferIn[0] = (float *)NULL;
+ m_bufferIn[1] = (float *)NULL;
}
// Destructor
@@ -50,7 +58,7 @@
if ( m_bufferOutSize >= size )
return 0;
- m_bufferOut = (unsigned char *)realloc(m_bufferOut, size);
+ m_bufferOut = (unsigned char *)realloc(m_bufferOut, size * sizeof(short));
if ( m_bufferOut == NULL )
return -1;
@@ -93,8 +101,8 @@
outsize = (int)((1.25 * size + 7200) + 1);
+
bufferOutGrow(outsize);
-
bufferInGrow(size);
// Deinterleave samples
@@ -114,11 +122,11 @@
void EncoderMp3::initStream()
{
- m_bufferOutSize = (int)((1.25 * 20000 + 7200) + 1);
- m_bufferOut = (unsigned char *)malloc(m_bufferOutSize);
+ // Assume a buffer of 20000 samples as the first default
+ int size = (int)((1.25 * 20000 + 7200) + 1);
- m_bufferIn[0] = (float *)malloc(m_bufferOutSize * sizeof(float));
- m_bufferIn[1] = (float *)malloc(m_bufferOutSize * sizeof(float));
+ bufferOutGrow(size);
+ bufferInGrow(size);
return;
}
=== modified file 'mixxx/src/engine/engineshoutcast.cpp'
--- mixxx/src/engine/engineshoutcast.cpp 2009-10-15 00:39:09 +0000
+++ mixxx/src/engine/engineshoutcast.cpp 2009-10-15 21:06:02 +0000
@@ -43,15 +43,13 @@
m_iShoutStatus = 0;
m_pConfig = _config;
m_pUpdateShoutcastFromPrefs = new ControlObjectThreadMain(ControlObject::getControl(ConfigKey(SHOUTCAST_PREF_KEY, "update_from_prefs")));
+ m_pEncoder = NULL;
+
m_pCrossfader = new ControlObjectThread(ControlObject::getControl(ConfigKey("[Master]","crossfader")));
m_pVolume1 = new ControlObjectThread(ControlObject::getControl(ConfigKey("[Channel1]","volume")));
m_pVolume2 = new ControlObjectThread(ControlObject::getControl(ConfigKey("[Channel2]","volume")));
- QByteArray baBitrate = m_pConfig->getValueString(ConfigKey(SHOUTCAST_PREF_KEY,"bitrate")).toLatin1();
- QByteArray baFormat = m_pConfig->getValueString(ConfigKey(SHOUTCAST_PREF_KEY,"format")).toLatin1();
- int len;
-
// Initialize libshout
shout_init();
@@ -77,40 +75,7 @@
if ( !serverConnect())
return;
-
qDebug("********SERVERCONNECTED********");
-
-
- if (( len = baBitrate.indexOf(' ')) != -1) {
- baBitrate.resize(len);
- }
-
- // Initialize encoder
- if ( ! qstrcmp(baFormat, "MP3")) {
-#ifdef __SHOUTCAST_LAME__
- encoder = new EncoderMp3(m_pConfig, this);
-#else
- qDebug() << "*** Missing MP3 Encoder Support";
- return;
-#endif // __SHOUTCAST_LAME__
- }
- else if ( ! qstrcmp(baFormat, "Ogg Vorbis")) {
-#ifdef __SHOUTCAST_VORBIS__
- encoder = new EncoderVorbis(m_pConfig, this);
-#else
- qDebug() << "*** Missing OGG Vorbis Encoder Support";
- return;
-#endif // __SHOUTCAST_VORBIS__
- }
- else {
- qDebug() << "**** Unknown Encoder Format";
- return;
- }
-
-
- if (encoder->initEncoder(baBitrate.toInt()) < 0) {
- qDebug() << "**** Vorbis init failed";
- }
}
/*
@@ -118,7 +83,9 @@
*/
EngineShoutcast::~EngineShoutcast()
{
- delete encoder;
+ if ( m_pEncoder )
+ delete m_pEncoder;
+
delete m_pUpdateShoutcastFromPrefs;
delete m_pCrossfader;
delete m_pVolume1;
@@ -160,16 +127,46 @@
int protocol;
+ if ( ! qstricmp(baServerType.data(), "Icecast 2")) {
+ protocol = SHOUT_PROTOCOL_HTTP;
+ } else if ( ! qstricmp(baServerType.data(), "Shoutcast")) {
+ protocol = SHOUT_PROTOCOL_ICY;
+ } else if ( ! qstricmp(baServerType.data(), "Icecast 1")) {
+ protocol = SHOUT_PROTOCOL_XAUDIOCAST;
+ } else {
+ qDebug() << "Error: unknown server protocol:" << baServerType.data();
+ return;
+ }
+
+
+ if ( !qstrcmp(baFormat.data(), "MP3")) {
+ format = SHOUT_FORMAT_MP3;
+ }
+ else if ( !qstrcmp(baFormat.data(), "Ogg Vorbis")) {
+ format = SHOUT_FORMAT_OGG;
+ }
+ else {
+ qDebug() << "Error: unknown format:" << baFormat.data();
+ return;
+ }
+
+
+ if (( protocol == SHOUT_PROTOCOL_ICY ) && ( format != SHOUT_FORMAT_MP3)) {
+ qDebug() << "Error: libshout only supports Shoutcast With MP3 format";
+ return;
+ }
+
+
+ if ( shout_set_protocol(m_pShout, protocol) != SHOUTERR_SUCCESS) {
+ qDebug() << "Error setting protocol: " << shout_get_error(m_pShout);
+ return;
+ }
+
if (shout_set_host(m_pShout, baHost.data()) != SHOUTERR_SUCCESS) {
qDebug() << "Error setting hostname:" << shout_get_error(m_pShout);
return;
}
-
- if (shout_set_protocol(m_pShout, SHOUT_PROTOCOL_HTTP) != SHOUTERR_SUCCESS) {
- qDebug() << "Error setting protocol:" << shout_get_error(m_pShout);
- return;
- }
-
+
if (shout_set_port(m_pShout, baPort.toUInt()) != SHOUTERR_SUCCESS) {
qDebug() << "Error setting port:" << shout_get_error(m_pShout);
return;
@@ -190,51 +187,59 @@
}
- if ( !qstrcmp(baFormat.data(), "MP3")) {
- format = SHOUT_FORMAT_MP3;
- }
- else if ( !qstrcmp(baFormat.data(), "Ogg Vorbis")) {
- format = SHOUT_FORMAT_OGG;
- }
- else {
- qDebug() << "Error: unknown format:" << baFormat.data();
- return;
- }
-
+ if ((len = baBitrate.indexOf(' ')) != -1) {
+ baBitrate.resize(len);
+ }
+
+ const char * sbrate = shout_get_audio_info(m_pShout, SHOUT_AI_BITRATE);
+ int brate = (sbrate != NULL ? atoi(sbrate) : 0);
+
+
+ if ((shout_get_format(m_pShout) != format) || (brate != baBitrate.toInt())) {
+
+ if ( m_pEncoder )
+ delete m_pEncoder;
+
+ switch(format)
+ {
+ case SHOUT_FORMAT_MP3:
+#ifdef __SHOUTCAST_LAME__
+ m_pEncoder = new EncoderMp3(m_pConfig, this);
+ break;
+#else
+ qDebug() << "*** Missing MP3 Encoder Support";
+ return;
+#endif // __SHOUTCAST_LAME__
+ case SHOUT_FORMAT_OGG:
+#ifdef __SHOUTCAST_VORBIS__
+ m_pEncoder = new EncoderVorbis(m_pConfig, this);
+ break;
+#else
+ qDebug() << "*** Missing OGG Vorbis Encoder Support";
+ return;
+#endif // __SHOUTCAST_VORBIS__
+ default:
+ qDebug() << "*** UKNOWN FORMAT:" << format;
+ return;
+ }
+
+ if (m_pEncoder->initEncoder(baBitrate.toInt()) < 0) {
+ qDebug() << "**** Encoder init failed";
+ return;
+ }
+ }
+
+
if (shout_set_format(m_pShout, format) != SHOUTERR_SUCCESS) {
qDebug() << "Error setting format:" << shout_get_error(m_pShout);
return;
}
-
- if ((len = baBitrate.indexOf(' ')) != -1) {
- baBitrate.resize(len);
- }
-
if (shout_set_audio_info(m_pShout, SHOUT_AI_BITRATE, baBitrate.data()) != SHOUTERR_SUCCESS) {
qDebug() << "Error setting bitrate:" << shout_get_error(m_pShout);
return;
}
- if ( ! qstricmp(baServerType.data(), "Icecast 2")) {
- protocol = SHOUT_PROTOCOL_HTTP;
- } else if ( ! qstricmp(baServerType.data(), "Shoutcast")) {
- protocol = SHOUT_PROTOCOL_ICY;
- } else if ( ! qstricmp(baServerType.data(), "Icecast 1")) {
- protocol = SHOUT_PROTOCOL_XAUDIOCAST;
- } else {
- qDebug() << "Error: unknown server protocol:" << baServerType.data();
- return;
- }
-
- if (( protocol == SHOUT_PROTOCOL_ICY ) && ( format != SHOUT_FORMAT_MP3)) {
- qDebug() << "Error: libshout only supports Shoutcast With MP3 format";
- }
-
- if ( shout_set_protocol(m_pShout, protocol) != SHOUTERR_SUCCESS) {
- qDebug() << "Error setting protocol: " << shout_get_error(m_pShout);
- return;
- }
}
@@ -268,14 +273,14 @@
break;
m_iShoutFailures++;
- sleep(30);
+ sleep(5);
}
m_iShoutFailures = 0;
while (m_iShoutStatus == SHOUTERR_BUSY) {
- qDebug() << "Connection pending. Sleeping...";
+ qDebug() << "Connection pending. Sleeping... " << m_iShoutStatus;
sleep(1);
m_iShoutStatus = shout_get_connected(m_pShout);
}
@@ -283,6 +288,9 @@
qDebug() << "***********Connected to Shoutcast server...";
return true;
}
+ else {
+ qDebug() << "Error connecting to Shoutcast server:" << shout_get_error(m_pShout);
+ }
return false;
}
@@ -342,7 +350,7 @@
if (m_iShoutStatus != SHOUTERR_CONNECTED)
return;
- if (iBufferSize > 0) encoder->encodeBuffer(pOut, iBufferSize);
+ if (iBufferSize > 0) m_pEncoder->encodeBuffer(pOut, iBufferSize);
if (metaDataHasChanged())
updateMetaData();
=== modified file 'mixxx/src/engine/engineshoutcast.h'
--- mixxx/src/engine/engineshoutcast.h 2009-07-10 22:30:31 +0000
+++ mixxx/src/engine/engineshoutcast.h 2009-10-15 20:43:42 +0000
@@ -63,7 +63,7 @@
long m_iShoutFailures;
ConfigObject<ConfigValue> *m_pConfig;
ControlObject* recReady;
- Encoder *encoder;
+ Encoder *m_pEncoder;
ControlObjectThreadMain* m_pUpdateShoutcastFromPrefs;
// void (*writeFn)(unsigned char *, unsigned char *, int, int);
ControlObjectThread* m_pCrossfader;
------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Mixxx-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mixxx-devel