Merge lp:~pwhelan/mixxx/shoutcast into lp:mixxx/1.7
- shoutcast
- Merge into release-1.6.2
Status: | Merged |
---|---|
Approved by: | Albert Santoni |
Approved revision: | 2453 |
Merge reported by: | Albert Santoni |
Merged at revision: | not available |
Proposed branch: | lp:~pwhelan/mixxx/shoutcast |
Merge into: | lp:mixxx/1.7 |
Diff against target: | None lines |
To merge this branch: | bzr merge lp:~pwhelan/mixxx/shoutcast |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Albert Santoni | Approve | ||
Review via email: mp+8518@code.launchpad.net |
Commit message
Description of the change
Phillip Whelan (pwhelan) wrote : | # |
- 2452. By Phillip Whelan <madjester@voidwalker>
-
More stability changes for Shoutcast, as well as reseting the metadata lifetime
back to a sane value.* Check metadata every 32 invocations, as before.
* Reconnect on server connect error
* Reconnect on shout_send error - 2453. By Phillip Whelan <madjester@voidwalker>
-
Comments for EngineShoutcast.
Albert Santoni (gamegod) wrote : | # |
This looks like it includes your recent shoutcast-
On lines 295-297 of the merge proposal, you convert QStrings to latin1-encoded char* strings. Does libshout support utf8? If so, use toUtf8() instead of toLatin1(). If not, leave it the way it is.
Just a heads up - In my sqlite branch, I have a real "Player" class which should probably deprecate the PlayerInfo class. It'll probably be my job to modify your code to use that since your code will be in trunk before mine. :)
Anyways, looks good otherwise. For sanity, I also think this should go in the 1.7 branch A) because that's where the latest shoutcast code is otherwise (it might save us some merging headaches later) and B) all of your changes only apply when Mixxx is built with shoutcast=1.
Thanks!
Phillip Whelan (pwhelan) wrote : | # |
> Review: Needs Information
> This looks like it includes your recent shoutcast-
and
> shoutcast-
More for the most part, yes you are correct. I did extensive testing on the
metadata update code and fixed it to actually work. I was doing the
crossfader conditional totally wrong. I also changed the code to use
properly instantiated ControlObjectThread objects which are instantiated
once, instead of for each pass of the code which detects which is the
active track.
>
> On lines 295-297 of the merge proposal, you convert QStrings to
> latin1-encoded char* strings. Does libshout support utf8? If so, use
> toUtf8() instead of toLatin1(). If not, leave it the way it is.
I'll check into that, but I seriously doubt that libshout supports UTF-8,
and if so, Shoutcast might not support metadata in UTF-8.
> Just a heads up - In my sqlite branch, I have a real "Player" class which
> should probably deprecate the PlayerInfo class. It'll probably be my job
to
> modify your code to use that since your code will be in trunk before
mine.
> :)
That'd be great, on both accounts.
> Anyways, looks good otherwise. For sanity, I also think this should go in
> the 1.7 branch A) because that's where the latest shoutcast code is
> otherwise (it might save us some merging headaches later) and B) all of
> your changes only apply when Mixxx is built with shoutcast=1.
I also thought the same.
> Thanks!
Your welcome!
Albert Santoni (gamegod) : | # |
Sean M. Pappalardo (pegasus-renegadetech) wrote : | # |
> For sanity, I also think this should go in the
> 1.7 branch A) because that's where the latest shoutcast code is otherwise (it
> might save us some merging headaches later) and B) all of your changes only
> apply when Mixxx is built with shoutcast=1.
Does that mean we should offer it as a new feature in 1.7.1? Or are we going to reserve point releases strictly for bug fixes?
Albert Santoni (gamegod) wrote : | # |
For the time being, point releases are going to be strictly bug fix
releases. If you're doing feature development, it should stay in a
branch until it's ready to be merged into the 1.8 branch. The case of
madjesta's shoutcast code is special because we're transitioning to
this new development cycle still.
On Mon, Jul 13, 2009 at 7:59 PM, Pegasus<email address hidden> wrote:
>> For sanity, I also think this should go in the
>> 1.7 branch A) because that's where the latest shoutcast code is otherwise (it
>> might save us some merging headaches later) and B) all of your changes only
>> apply when Mixxx is built with shoutcast=1.
>
> Does that mean we should offer it as a new feature in 1.7.1? Or are we going to reserve point releases strictly for bug fixes?
> --
> https:/
> You are reviewing the proposed merge of lp:~pwhelan/mixxx/shoutcast into lp:mixxx/1.7.
>
Preview Diff
1 | === modified file 'mixxx/src/SConscript' | |||
2 | --- mixxx/src/SConscript 2009-07-07 21:55:55 +0000 | |||
3 | +++ mixxx/src/SConscript 2009-07-08 03:00:57 +0000 | |||
4 | @@ -872,16 +872,42 @@ | |||
5 | 872 | 872 | ||
6 | 873 | #Experimental Shoutcast | 873 | #Experimental Shoutcast |
7 | 874 | flags_shoutcast = getFlags(env, 'shoutcast', 0) | 874 | flags_shoutcast = getFlags(env, 'shoutcast', 0) |
8 | 875 | |||
9 | 875 | if int(flags_shoutcast): | 876 | if int(flags_shoutcast): |
14 | 876 | #TODO: check for libshout | 877 | shoutmp3 = 0 |
15 | 877 | env.Append(LIBS = 'shout'); | 878 | shoutogg = 0 |
16 | 878 | env.Append(LIBS = 'vorbisenc'); | 879 | |
17 | 879 | env.Append(LIBS = 'mp3lame'); | 880 | conf = Configure(env, custom_tests = { 'CheckForPKGConfig' : CheckForPKGConfig, 'CheckForPKG' : CheckForPKG }) |
18 | 881 | conf.CheckLib('shout') | ||
19 | 882 | |||
20 | 880 | env.Append(CPPDEFINES = '__SHOUTCAST__') | 883 | env.Append(CPPDEFINES = '__SHOUTCAST__') |
22 | 881 | sources += Split(""" dlgprefshoutcast.cpp engine/engineshoutcast.cpp encoder.cpp encodervorbis.cpp encodermp3.cpp""" ) | 884 | |
23 | 885 | sources += Split(""" dlgprefshoutcast.cpp engine/engineshoutcast.cpp encoder.cpp """ ) | ||
24 | 886 | build_flags += 'shoutcast ' | ||
25 | 887 | |||
26 | 888 | |||
27 | 889 | if conf.CheckLib('mp3lame'): | ||
28 | 890 | env.Append(CPPDEFINES = '__SHOUTCAST_LAME__') | ||
29 | 891 | sources += Split(""" encodermp3.cpp """) | ||
30 | 892 | shoutmp3 = 1 | ||
31 | 893 | |||
32 | 894 | if conf.CheckLib('vorbisenc'): | ||
33 | 895 | env.Append(CPPDEFINES = '__SHOUTCAST_VORBIS__') | ||
34 | 896 | sources += Split(""" encodervorbis.cpp """) | ||
35 | 897 | shoutogg = 1 | ||
36 | 898 | |||
37 | 899 | |||
38 | 900 | if shoutmp3 and shoutogg: | ||
39 | 901 | print "Shoutcast support (OGG/MP3)... enabled" | ||
40 | 902 | elif shoutmp3: | ||
41 | 903 | print "Shoutcast support (MP3)... enabled" | ||
42 | 904 | elif shoutogg: | ||
43 | 905 | print "Shoutcast support (OGG)... enabled" | ||
44 | 906 | else: | ||
45 | 907 | print "Shoutcast support... enabled" | ||
46 | 908 | |||
47 | 882 | env.Uic4('dlgprefshoutcastdlg.ui') | 909 | env.Uic4('dlgprefshoutcastdlg.ui') |
50 | 883 | print "Shoutcast support... enabled" | 910 | |
49 | 884 | build_flags += 'shoutcast ' | ||
51 | 885 | else: | 911 | else: |
52 | 886 | print "Shoutcast support... disabled" | 912 | print "Shoutcast support... disabled" |
53 | 887 | 913 | ||
54 | 888 | 914 | ||
55 | === modified file 'mixxx/src/engine/engineshoutcast.cpp' | |||
56 | --- mixxx/src/engine/engineshoutcast.cpp 2009-02-18 06:27:27 +0000 | |||
57 | +++ mixxx/src/engine/engineshoutcast.cpp 2009-07-08 17:47:11 +0000 | |||
58 | @@ -19,8 +19,13 @@ | |||
59 | 19 | #include "configobject.h" | 19 | #include "configobject.h" |
60 | 20 | #include "dlgprefshoutcast.h" | 20 | #include "dlgprefshoutcast.h" |
61 | 21 | 21 | ||
62 | 22 | #ifdef __SHOUTCAST_VORBIS__ | ||
63 | 22 | #include "encodervorbis.h" | 23 | #include "encodervorbis.h" |
64 | 24 | #endif // __SHOUTCAST_VORBIS__ | ||
65 | 25 | #ifdef __SHOUTCAST_LAME__ | ||
66 | 23 | #include "encodermp3.h" | 26 | #include "encodermp3.h" |
67 | 27 | #endif // __SHOUTCAST_LAME__ | ||
68 | 28 | |||
69 | 24 | #include "playerinfo.h" | 29 | #include "playerinfo.h" |
70 | 25 | #include "trackinfoobject.h" | 30 | #include "trackinfoobject.h" |
71 | 26 | 31 | ||
72 | @@ -45,6 +50,10 @@ | |||
73 | 45 | m_pConfig = _config; | 50 | m_pConfig = _config; |
74 | 46 | m_pUpdateShoutcastFromPrefs = new ControlObjectThreadMain(ControlObject::getControl(ConfigKey(SHOUTCAST_PREF_KEY, "update_from_prefs"))); | 51 | m_pUpdateShoutcastFromPrefs = new ControlObjectThreadMain(ControlObject::getControl(ConfigKey(SHOUTCAST_PREF_KEY, "update_from_prefs"))); |
75 | 47 | 52 | ||
76 | 53 | m_pCrossfader = new ControlObjectThread(ControlObject::getControl(ConfigKey("[Master]","crossfader"))); | ||
77 | 54 | m_pVolume1 = new ControlObjectThread(ControlObject::getControl(ConfigKey("[Channel1]","volume"))); | ||
78 | 55 | m_pVolume2 = new ControlObjectThread(ControlObject::getControl(ConfigKey("[Channel2]","volume"))); | ||
79 | 56 | |||
80 | 48 | QByteArray baBitrate = m_pConfig->getValueString(ConfigKey(SHOUTCAST_PREF_KEY,"bitrate")).toLatin1(); | 57 | QByteArray baBitrate = m_pConfig->getValueString(ConfigKey(SHOUTCAST_PREF_KEY,"bitrate")).toLatin1(); |
81 | 49 | QByteArray baFormat = m_pConfig->getValueString(ConfigKey(SHOUTCAST_PREF_KEY,"format")).toLatin1(); | 58 | QByteArray baFormat = m_pConfig->getValueString(ConfigKey(SHOUTCAST_PREF_KEY,"format")).toLatin1(); |
82 | 50 | int len; | 59 | int len; |
83 | @@ -58,6 +67,15 @@ | |||
84 | 58 | return; | 67 | return; |
85 | 59 | } | 68 | } |
86 | 60 | 69 | ||
87 | 70 | if (!(m_pShoutMetaData = shout_metadata_new())) { | ||
88 | 71 | qDebug() << "Cound not allocate shout_metadata_t"; | ||
89 | 72 | return; | ||
90 | 73 | } | ||
91 | 74 | |||
92 | 75 | // set to a high number to automatically update the metadata | ||
93 | 76 | // on the first change | ||
94 | 77 | m_pMetaDataLife = 31337; | ||
95 | 78 | |||
96 | 61 | //Initialize the m_pShout structure with the info from Mixxx's shoutcast preferences. | 79 | //Initialize the m_pShout structure with the info from Mixxx's shoutcast preferences. |
97 | 62 | updateFromPreferences(); | 80 | updateFromPreferences(); |
98 | 63 | 81 | ||
99 | @@ -67,7 +85,8 @@ | |||
100 | 67 | } | 85 | } |
101 | 68 | 86 | ||
102 | 69 | qDebug("********START SERVERCONNECT*******"); | 87 | qDebug("********START SERVERCONNECT*******"); |
104 | 70 | serverConnect(); | 88 | if ( !serverConnect()) |
105 | 89 | return; | ||
106 | 71 | 90 | ||
107 | 72 | if (( len = baBitrate.indexOf(' ')) != -1) { | 91 | if (( len = baBitrate.indexOf(' ')) != -1) { |
108 | 73 | baBitrate.resize(len); | 92 | baBitrate.resize(len); |
109 | @@ -75,10 +94,20 @@ | |||
110 | 75 | 94 | ||
111 | 76 | // Initialize encoder | 95 | // Initialize encoder |
112 | 77 | if ( ! qstrcmp(baFormat, "MP3")) { | 96 | if ( ! qstrcmp(baFormat, "MP3")) { |
113 | 97 | #ifdef __SHOUTCAST_LAME__ | ||
114 | 78 | encoder = new EncoderMp3(m_pConfig, this); | 98 | encoder = new EncoderMp3(m_pConfig, this); |
115 | 99 | #else | ||
116 | 100 | qDebug() << "*** Missing MP3 Encoder Support"; | ||
117 | 101 | return; | ||
118 | 102 | #endif // __SHOUTCAST_LAME__ | ||
119 | 79 | } | 103 | } |
120 | 80 | else if ( ! qstrcmp(baFormat, "Ogg Vorbis")) { | 104 | else if ( ! qstrcmp(baFormat, "Ogg Vorbis")) { |
121 | 105 | #ifdef __SHOUTCAST_VORBIS__ | ||
122 | 81 | encoder = new EncoderVorbis(m_pConfig, this); | 106 | encoder = new EncoderVorbis(m_pConfig, this); |
123 | 107 | #else | ||
124 | 108 | qDebug() << "*** Missing OGG Vorbis Encoder Support"; | ||
125 | 109 | return; | ||
126 | 110 | #endif // __SHOUTCAST_VORBIS__ | ||
127 | 82 | } | 111 | } |
128 | 83 | else { | 112 | else { |
129 | 84 | qDebug() << "**** Unknown Encoder Format"; | 113 | qDebug() << "**** Unknown Encoder Format"; |
130 | @@ -95,7 +124,12 @@ | |||
131 | 95 | { | 124 | { |
132 | 96 | delete encoder; | 125 | delete encoder; |
133 | 97 | delete m_pUpdateShoutcastFromPrefs; | 126 | delete m_pUpdateShoutcastFromPrefs; |
134 | 127 | delete m_pCrossfader; | ||
135 | 128 | delete m_pVolume1; | ||
136 | 129 | delete m_pVolume2; | ||
137 | 98 | 130 | ||
138 | 131 | if (m_pShoutMetaData) | ||
139 | 132 | shout_metadata_free(m_pShoutMetaData); | ||
140 | 99 | if (m_pShout) | 133 | if (m_pShout) |
141 | 100 | shout_close(m_pShout); | 134 | shout_close(m_pShout); |
142 | 101 | shout_shutdown(); | 135 | shout_shutdown(); |
143 | @@ -205,7 +239,7 @@ | |||
144 | 205 | 239 | ||
145 | 206 | } | 240 | } |
146 | 207 | 241 | ||
148 | 208 | void EngineShoutcast::serverConnect() | 242 | bool EngineShoutcast::serverConnect() |
149 | 209 | { | 243 | { |
150 | 210 | qDebug("in serverConnect();"); | 244 | qDebug("in serverConnect();"); |
151 | 211 | if (m_pShout) | 245 | if (m_pShout) |
152 | @@ -223,7 +257,10 @@ | |||
153 | 223 | } | 257 | } |
154 | 224 | if (m_iShoutStatus == SHOUTERR_CONNECTED) { | 258 | if (m_iShoutStatus == SHOUTERR_CONNECTED) { |
155 | 225 | qDebug() << "***********Connected to Shoutcast server..."; | 259 | qDebug() << "***********Connected to Shoutcast server..."; |
156 | 260 | return true; | ||
157 | 226 | } | 261 | } |
158 | 262 | |||
159 | 263 | return false; | ||
160 | 227 | } | 264 | } |
161 | 228 | 265 | ||
162 | 229 | void EngineShoutcast::writePage(unsigned char *header, unsigned char *body, | 266 | void EngineShoutcast::writePage(unsigned char *header, unsigned char *body, |
163 | @@ -259,15 +296,128 @@ | |||
164 | 259 | } | 296 | } |
165 | 260 | } | 297 | } |
166 | 261 | 298 | ||
177 | 262 | /*void EngineShoutcast::wrapper2writePage(void *pObj, unsigned char *header, unsigned char *body, | 299 | void EngineShoutcast::process(const CSAMPLE *, const CSAMPLE *pOut, const int iBufferSize) |
178 | 263 | int headerLen, int bodyLen) | 300 | { |
179 | 264 | { | 301 | if (m_iShoutStatus != SHOUTERR_CONNECTED) |
180 | 265 | EngineShoutcast* mySelf = (EngineShoutcast*)pObj; | 302 | return; |
181 | 266 | pObj->writePage(header, body, headerLen, bodyLen); | 303 | |
172 | 267 | }*/ | ||
173 | 268 | |||
174 | 269 | void EngineShoutcast::process(const CSAMPLE *pIn, const CSAMPLE *pOut, const int iBufferSize) | ||
175 | 270 | { | ||
176 | 271 | // encoder->encodeBuffer((void*) &objA, EngineShoutcast::wrapper2writePage, pOut, iBufferSize); | ||
182 | 272 | if (iBufferSize > 0) encoder->encodeBuffer(pOut, iBufferSize); | 304 | if (iBufferSize > 0) encoder->encodeBuffer(pOut, iBufferSize); |
183 | 305 | |||
184 | 306 | if ( metaDataHasChanged()) | ||
185 | 307 | updateMetaData(); | ||
186 | 308 | } | ||
187 | 309 | |||
188 | 310 | /* Algorithm which simply flips the lowest and/or second lowest bits, | ||
189 | 311 | * bits 1 and 2, to represent which track is active and returns the result. | ||
190 | 312 | */ | ||
191 | 313 | |||
192 | 314 | int EngineShoutcast::getActiveTracks() | ||
193 | 315 | { | ||
194 | 316 | int tracks = 0; | ||
195 | 317 | |||
196 | 318 | |||
197 | 319 | if (ControlObject::getControl(ConfigKey("[Channel1]","play"))->get()==1.) tracks |= 1; | ||
198 | 320 | if (ControlObject::getControl(ConfigKey("[Channel2]","play"))->get()==1.) tracks |= 2; | ||
199 | 321 | |||
200 | 322 | if (tracks == 0) | ||
201 | 323 | return 0; | ||
202 | 324 | |||
203 | 325 | // Detect the dominant track by checking the crossfader and volume levels | ||
204 | 326 | if ((tracks & 1) && (tracks & 2)) { | ||
205 | 327 | |||
206 | 328 | if ((m_pVolume1->get() == 0) && (m_pVolume2->get() == 0)) | ||
207 | 329 | return 0; | ||
208 | 330 | |||
209 | 331 | if (m_pVolume2->get() == 0) { | ||
210 | 332 | tracks = 1; | ||
211 | 333 | } | ||
212 | 334 | else if ( m_pVolume1->get() == 0) { | ||
213 | 335 | tracks = 2; | ||
214 | 336 | } | ||
215 | 337 | // allow a bit of leeway with the crossfader | ||
216 | 338 | else if ((m_pCrossfader->get() < 0.05) && (m_pCrossfader->get() > -0.05)) { | ||
217 | 339 | |||
218 | 340 | if (m_pVolume1->get() > m_pVolume2->get()) { | ||
219 | 341 | tracks = 1; | ||
220 | 342 | } | ||
221 | 343 | else if (m_pVolume1->get() < m_pVolume2->get()) { | ||
222 | 344 | tracks = 2; | ||
223 | 345 | } | ||
224 | 346 | |||
225 | 347 | } | ||
226 | 348 | else if ( m_pCrossfader->get() < -0.05 ) { | ||
227 | 349 | tracks = 1; | ||
228 | 350 | } | ||
229 | 351 | else if ( m_pCrossfader->get() > 0.05 ) { | ||
230 | 352 | tracks = 2; | ||
231 | 353 | } | ||
232 | 354 | |||
233 | 355 | } | ||
234 | 356 | |||
235 | 357 | return tracks; | ||
236 | 358 | } | ||
237 | 359 | |||
238 | 360 | bool EngineShoutcast::metaDataHasChanged() | ||
239 | 361 | { | ||
240 | 362 | int tracks; | ||
241 | 363 | TrackInfoObject *newMetaData; | ||
242 | 364 | bool changed = false; | ||
243 | 365 | |||
244 | 366 | |||
245 | 367 | if ( m_pMetaDataLife < 1 ) { | ||
246 | 368 | m_pMetaDataLife++; | ||
247 | 369 | return false; | ||
248 | 370 | } | ||
249 | 371 | |||
250 | 372 | m_pMetaDataLife = 0; | ||
251 | 373 | |||
252 | 374 | |||
253 | 375 | tracks = getActiveTracks(); | ||
254 | 376 | |||
255 | 377 | |||
256 | 378 | switch (tracks) | ||
257 | 379 | { | ||
258 | 380 | case 0: | ||
259 | 381 | // no tracks are playing | ||
260 | 382 | // we should set the metadata to nothing | ||
261 | 383 | break; | ||
262 | 384 | case 1: | ||
263 | 385 | // track 1 is active | ||
264 | 386 | |||
265 | 387 | newMetaData = PlayerInfo::Instance().getTrackInfo(1); | ||
266 | 388 | if (newMetaData != m_pMetaData) | ||
267 | 389 | { | ||
268 | 390 | m_pMetaData = newMetaData; | ||
269 | 391 | changed = true; | ||
270 | 392 | } | ||
271 | 393 | break; | ||
272 | 394 | case 2: | ||
273 | 395 | // track 2 is active | ||
274 | 396 | newMetaData = PlayerInfo::Instance().getTrackInfo(2); | ||
275 | 397 | if (newMetaData != m_pMetaData) | ||
276 | 398 | { | ||
277 | 399 | m_pMetaData = newMetaData; | ||
278 | 400 | changed = true; | ||
279 | 401 | } | ||
280 | 402 | break; | ||
281 | 403 | case 3: | ||
282 | 404 | // both tracks are active, just stick with it for now | ||
283 | 405 | break; | ||
284 | 406 | } | ||
285 | 407 | |||
286 | 408 | qDebug() << "tracks = " << tracks << " changed = " << changed; | ||
287 | 409 | |||
288 | 410 | |||
289 | 411 | return changed; | ||
290 | 412 | } | ||
291 | 413 | |||
292 | 414 | void EngineShoutcast::updateMetaData() | ||
293 | 415 | { | ||
294 | 416 | // convert QStrings to char*s | ||
295 | 417 | QByteArray baArtist = m_pMetaData->getArtist().toLatin1(); | ||
296 | 418 | QByteArray baTitle = m_pMetaData->getTitle().toLatin1(); | ||
297 | 419 | QByteArray baSong = baArtist + " - " + baTitle; | ||
298 | 420 | |||
299 | 421 | shout_metadata_add(m_pShoutMetaData, "song", baSong.data()); | ||
300 | 422 | shout_set_metadata(m_pShout, m_pShoutMetaData); | ||
301 | 273 | } | 423 | } |
302 | 274 | 424 | ||
303 | === modified file 'mixxx/src/engine/engineshoutcast.h' | |||
304 | --- mixxx/src/engine/engineshoutcast.h 2009-02-18 04:28:21 +0000 | |||
305 | +++ mixxx/src/engine/engineshoutcast.h 2009-07-08 03:01:35 +0000 | |||
306 | @@ -51,14 +51,23 @@ | |||
307 | 51 | // void writePage(unsigned char *header, unsigned char *body, | 51 | // void writePage(unsigned char *header, unsigned char *body, |
308 | 52 | // int headerLen, int bodyLen, int count); | 52 | // int headerLen, int bodyLen, int count); |
309 | 53 | private: | 53 | private: |
311 | 54 | void serverConnect(); | 54 | bool serverConnect(); |
312 | 55 | int getActiveTracks(); | ||
313 | 56 | bool metaDataHasChanged(); | ||
314 | 57 | void updateMetaData(); | ||
315 | 58 | TrackInfoObject *m_pMetaData; | ||
316 | 55 | shout_t *m_pShout; | 59 | shout_t *m_pShout; |
317 | 60 | shout_metadata_t *m_pShoutMetaData; | ||
318 | 61 | int m_pMetaDataLife; | ||
319 | 56 | long m_iShoutStatus; | 62 | long m_iShoutStatus; |
320 | 57 | ConfigObject<ConfigValue> *m_pConfig; | 63 | ConfigObject<ConfigValue> *m_pConfig; |
321 | 58 | ControlObject* recReady; | 64 | ControlObject* recReady; |
322 | 59 | Encoder *encoder; | 65 | Encoder *encoder; |
323 | 60 | ControlObjectThreadMain* m_pUpdateShoutcastFromPrefs; | 66 | ControlObjectThreadMain* m_pUpdateShoutcastFromPrefs; |
324 | 61 | // void (*writeFn)(unsigned char *, unsigned char *, int, int); | 67 | // void (*writeFn)(unsigned char *, unsigned char *, int, int); |
325 | 68 | ControlObjectThread* m_pCrossfader; | ||
326 | 69 | ControlObjectThread* m_pVolume1; | ||
327 | 70 | ControlObjectThread* m_pVolume2; | ||
328 | 62 | }; | 71 | }; |
329 | 63 | 72 | ||
330 | 64 | #endif | 73 | #endif |
Several changes and bugfixes to Shoutcast, including:
* Check in EngineShoutcast ::writePage for the connection status
* Better Tracking of the Active track for Metadata
* Metadata Updates for Shoutcast support
I know 1.7 is feature frozen, but my previous changes were also accepted, as well, none of the binaries are rolled out with shoutcast support.
If there was a trunk branch I'd be proposing it to be merged there... but oh well...