summaryrefslogtreecommitdiff
authorharlekin <harlekin>2002-04-22 21:47:09 (UTC)
committer harlekin <harlekin>2002-04-22 21:47:09 (UTC)
commitf77f012023dbe7582a4b4297f61c6521ad8a3aa5 (patch) (unidiff)
tree3d41a0320169e8b2749e7cee98f14e0435fe05e3
parentcca7f8ae4f60ae9b6c704d200ab015233abdd4d7 (diff)
downloadopie-f77f012023dbe7582a4b4297f61c6521ad8a3aa5.zip
opie-f77f012023dbe7582a4b4297f61c6521ad8a3aa5.tar.gz
opie-f77f012023dbe7582a4b4297f61c6521ad8a3aa5.tar.bz2
get shoutcast support better, now all stream information are shown in the mediaplayer
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--core/multimedia/opieplayer/libmad/libmadplugin.cpp159
1 files changed, 83 insertions, 76 deletions
diff --git a/core/multimedia/opieplayer/libmad/libmadplugin.cpp b/core/multimedia/opieplayer/libmad/libmadplugin.cpp
index 7de4282..0f952f4 100644
--- a/core/multimedia/opieplayer/libmad/libmadplugin.cpp
+++ b/core/multimedia/opieplayer/libmad/libmadplugin.cpp
@@ -17,6 +17,8 @@
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20// largly modified by Maximilian Reiss <max.reiss@gmx.de>
21
20#include <stdio.h> 22#include <stdio.h>
21#include <stdarg.h> 23#include <stdarg.h>
22#include <stdlib.h> 24#include <stdlib.h>
@@ -31,7 +33,10 @@
31#include <locale.h> 33#include <locale.h>
32#include <math.h> 34#include <math.h>
33#include <assert.h> 35#include <assert.h>
36
34#include <qapplication.h> 37#include <qapplication.h>
38#include <qmessagebox.h>
39
35#include <qpe/config.h> 40#include <qpe/config.h>
36 41
37// for network handling 42// for network handling
@@ -198,45 +203,47 @@ int LibMadPlugin::udp_open(char *address, int port) {
198 stAddr.sin_family = AF_INET; 203 stAddr.sin_family = AF_INET;
199 stAddr.sin_port = htons(port); 204 stAddr.sin_port = htons(port);
200 205
201 if ((host = gethostbyname(address)) == NULL) 206 if ((host = gethostbyname(address)) == NULL) {
202 return (0); 207 return (0);
208 }
203 209
204 stAddr.sin_addr = *((struct in_addr *)host->h_addr_list[0]); 210 stAddr.sin_addr = *((struct in_addr *)host->h_addr_list[0]);
205 211
206 /* Create a UDP socket */ 212 /* Create a UDP socket */
207 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 213 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
208 return (0); 214 return (0);
215 }
209 216
210 /* Allow multiple instance of the client to share the same address and port */ 217 /* Allow multiple instance of the client to share the same address and port */
211 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&enable, sizeof(unsigned long int)) < 0) 218 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&enable, sizeof(unsigned long int)) < 0) {
212 return (0); 219 return (0);
220 }
213 221
214 /* If the address is multicast, register to the multicast group */ 222 /* If the address is multicast, register to the multicast group */
215 if (is_address_multicast(stAddr.sin_addr.s_addr)) 223 if (is_address_multicast(stAddr.sin_addr.s_addr)) {
216 {
217 /* Bind the socket to port */ 224 /* Bind the socket to port */
218 stLclAddr.sin_family = AF_INET; 225 stLclAddr.sin_family = AF_INET;
219 stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY); 226 stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
220 stLclAddr.sin_port = stAddr.sin_port; 227 stLclAddr.sin_port = stAddr.sin_port;
221 if (bind(sock, (struct sockaddr *)&stLclAddr, sizeof(stLclAddr)) < 0) 228 if (bind(sock, (struct sockaddr *)&stLclAddr, sizeof(stLclAddr)) < 0) {
222 return (0); 229 return (0);
230 }
223 231
224 /* Register to a multicast address */ 232 /* Register to a multicast address */
225 stMreq.imr_multiaddr.s_addr = stAddr.sin_addr.s_addr; 233 stMreq.imr_multiaddr.s_addr = stAddr.sin_addr.s_addr;
226 stMreq.imr_interface.s_addr = INADDR_ANY; 234 stMreq.imr_interface.s_addr = INADDR_ANY;
227 if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&stMreq, sizeof(stMreq)) < 0) 235 if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&stMreq, sizeof(stMreq)) < 0) {
228 return (0); 236 return (0);
229 } 237 }
230 else 238 } else {
231 {
232 /* Bind the socket to port */ 239 /* Bind the socket to port */
233 stLclAddr.sin_family = AF_INET; 240 stLclAddr.sin_family = AF_INET;
234 stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY); 241 stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
235 stLclAddr.sin_port = htons(0); 242 stLclAddr.sin_port = htons(0);
236 if (bind(sock, (struct sockaddr *)&stLclAddr, sizeof(stLclAddr)) < 0) 243 if (bind(sock, (struct sockaddr *)&stLclAddr, sizeof(stLclAddr)) < 0) {
237 return (0); 244 return (0);
238 } 245 }
239 246 }
240 return (sock); 247 return (sock);
241} 248}
242 249
@@ -250,21 +257,25 @@ int LibMadPlugin::tcp_open(char *address, int port) {
250 stAddr.sin_family = AF_INET; 257 stAddr.sin_family = AF_INET;
251 stAddr.sin_port = htons(port); 258 stAddr.sin_port = htons(port);
252 259
253 if ((host = gethostbyname(address)) == NULL) 260 if ((host = gethostbyname(address)) == NULL) {
254 return (0); 261 return (0);
262 }
255 263
256 stAddr.sin_addr = *((struct in_addr *)host->h_addr_list[0]); 264 stAddr.sin_addr = *((struct in_addr *)host->h_addr_list[0]);
257 265
258 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) 266 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
259 return (0); 267 return (0);
268 }
260 269
261 l.l_onoff = 1; 270 l.l_onoff = 1;
262 l.l_linger = 5; 271 l.l_linger = 5;
263 if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l)) < 0) 272 if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l)) < 0) {
264 return (0); 273 return (0);
274 }
265 275
266 if (connect(sock, (struct sockaddr *)&stAddr, sizeof(stAddr)) < 0) 276 if (connect(sock, (struct sockaddr *)&stAddr, sizeof(stAddr)) < 0) {
267 return (0); 277 return (0);
278 }
268 279
269 return (sock); 280 return (sock);
270} 281}
@@ -281,14 +292,12 @@ int LibMadPlugin::tcp_open(char *address, int port) {
281int LibMadPlugin::http_read_line(int tcp_sock, char *buf, int size) { 292int LibMadPlugin::http_read_line(int tcp_sock, char *buf, int size) {
282 int offset = 0; 293 int offset = 0;
283 294
284 do 295 do {
285 {
286 if (std::read(tcp_sock, buf + offset, 1) < 0) 296 if (std::read(tcp_sock, buf + offset, 1) < 0)
287 return -1; 297 return -1;
288 if (buf[offset] != '\r') /* Strip \r from answer */ 298 if (buf[offset] != '\r') /* Strip \r from answer */
289 offset++; 299 offset++;
290 } 300 } while (offset < size - 1 && buf[offset - 1] != '\n');
291 while (offset < size - 1 && buf[offset - 1] != '\n');
292 301
293 buf[offset] = 0; 302 buf[offset] = 0;
294 return offset; 303 return offset;
@@ -305,25 +314,26 @@ int LibMadPlugin::http_open(const QString& path ) {
305 char *arg =strdup(path.latin1()); 314 char *arg =strdup(path.latin1());
306 315
307 /* Check for URL syntax */ 316 /* Check for URL syntax */
308 if (strncmp(arg, "http://", strlen("http://"))) 317 if (strncmp(arg, "http://", strlen("http://"))) {
309 return (0); 318 return (0);
319 }
310 320
311 /* Parse URL */ 321 /* Parse URL */
312 port = 80; 322 port = 80;
313 host = arg + strlen("http://"); 323 host = arg + strlen("http://");
314 if ((request = strchr(host, '/')) == NULL) 324 if ((request = strchr(host, '/')) == NULL) {
315 return (0); 325 return (0);
326 }
327
316 *request++ = 0; 328 *request++ = 0;
317 329
318 if (strchr(host, ':') != NULL) /* port is specified */ 330 if (strchr(host, ':') != NULL) { /* port is specified */
319 {
320 port = atoi(strchr(host, ':') + 1); 331 port = atoi(strchr(host, ':') + 1);
321 *strchr(host, ':') = 0; 332 *strchr(host, ':') = 0;
322 } 333 }
323 334
324 /* Open a TCP socket */ 335 /* Open a TCP socket */
325 if (!(tcp_sock = tcp_open(host, port))) 336 if (!(tcp_sock = tcp_open(host, port))) {
326 {
327 perror("http_open"); 337 perror("http_open");
328 return (0); 338 return (0);
329 } 339 }
@@ -346,34 +356,35 @@ int LibMadPlugin::http_open(const QString& path ) {
346 while (c != ' '); 356 while (c != ' ');
347 read(tcp_sock, http_request, 4 * sizeof(char)); 357 read(tcp_sock, http_request, 4 * sizeof(char));
348 http_request[4] = 0; 358 http_request[4] = 0;
349 if (strcmp(http_request, "200 ")) 359 if (strcmp(http_request, "200 ")) {
350 {
351 fprintf(stderr, "http_open: "); 360 fprintf(stderr, "http_open: ");
352 do 361 do {
353 {
354 read(tcp_sock, &c, sizeof(char)); 362 read(tcp_sock, &c, sizeof(char));
355 fprintf(stderr, "%c", c); 363 fprintf(stderr, "%c", c);
356 } 364 } while (c != '\r');
357 while (c != '\r');
358 fprintf(stderr, "\n"); 365 fprintf(stderr, "\n");
359 return (0); 366 return (0);
360 } 367 }
361#endif 368#endif
362 369
363 do 370 QString name;
364 { 371 QString genre;
372 QString bitrate;
373 QString url;
374 QString message = tr("Info: ");
375
376 do {
377
365 int len; 378 int len;
366 379
367 len = http_read_line(tcp_sock, http_request, sizeof(http_request)); 380 len = http_read_line(tcp_sock, http_request, sizeof(http_request));
368 381
369 if (len == -1) 382 if (len == -1) {
370 {
371 fprintf(stderr, "http_open: %s\n", strerror(errno)); 383 fprintf(stderr, "http_open: %s\n", strerror(errno));
372 return 0; 384 return 0;
373 } 385 }
374 386
375 if (strncmp(http_request, "Location:", 9) == 0) 387 if (strncmp(http_request, "Location:", 9) == 0) {
376 {
377 /* redirect */ 388 /* redirect */
378 std::close(tcp_sock); 389 std::close(tcp_sock);
379 390
@@ -382,28 +393,37 @@ int LibMadPlugin::http_open(const QString& path ) {
382 return http_open(&http_request[10]); 393 return http_open(&http_request[10]);
383 } 394 }
384 395
385 if (strncmp(http_request, "ICY ", 4) == 0) 396 if (strncmp(http_request, "ICY ", 4) == 0) {
386 {
387 /* This is icecast streaming */ 397 /* This is icecast streaming */
388 if (strncmp(http_request + 4, "200 ", 4)) 398 if (strncmp(http_request + 4, "200 ", 4)) {
389 {
390 fprintf(stderr, "http_open: %s\n", http_request); 399 fprintf(stderr, "http_open: %s\n", http_request);
391 return 0; 400 return 0;
392 } 401 }
393 } 402 } else if (strncmp(http_request, "icy-", 4) == 0) {
394 else if (strncmp(http_request, "icy-", 4) == 0)
395 {
396 /* we can have: icy-noticeX, icy-name, icy-genre, icy-url, icy-pub, icy-metaint, icy-br */ 403 /* we can have: icy-noticeX, icy-name, icy-genre, icy-url, icy-pub, icy-metaint, icy-br */
397 /* Don't print these - mpg123 doesn't */ 404 if ( QString( http_request ).left( 8 ) == "icy-name" ) {
398 /* fprintf(stderr,"%s\n",http_request); */ 405 name = tr("Name: ") + QString(http_request).mid(9, (QString(http_request).length())- 9 );
406 } else if ( QString( http_request ).left( 9 ) == "icy-genre" ) {
407 genre = tr("Genre: ") + QString(http_request).mid(10, (QString(http_request).length())-10 );
408 } else if ( QString( http_request ).left( 6 ) == "icy-br" ) {
409 bitrate = tr("Bitrate: ") + QString(http_request).mid(7, (QString(http_request).length())- 7 );
410 } else if ( QString( http_request ).left( 7 ) == "icy-url" ) {
411 url = tr("URL: ") + QString(http_request).mid(8, (QString(http_request).length())- 8 );
412 } else if ( QString( http_request ).left( 10 ) == "icy-notice" ) {
413 message += QString(http_request).mid(11, QString(http_request).length()-11 ) ;
399 } 414 }
400 } 415 }
401 while (strcmp(http_request, "\n") != 0); 416 } while (strcmp(http_request, "\n") != 0);
417
418 info = QString(name + genre + url + bitrate + message).replace( QRegExp("\n"), " : " );
419
420 qDebug("Stream info: " + info);
402 421
403 return (tcp_sock); 422 return (tcp_sock);
404} 423}
405 424
406 425
426
407bool LibMadPlugin::open( const QString& path ) { 427bool LibMadPlugin::open( const QString& path ) {
408 debugMsg( "LibMadPlugin::open" ); 428 debugMsg( "LibMadPlugin::open" );
409 Config cfg("MediaPlayer"); 429 Config cfg("MediaPlayer");
@@ -418,23 +438,27 @@ bool LibMadPlugin::open( const QString& path ) {
418 438
419 439
420 if (path.left( 4 ) == "http" ) { 440 if (path.left( 4 ) == "http" ) {
441 // in case of any error we get 0 here
442 if ( !(http_open(path)==0) ) {
421 d->input.fd = http_open(path); 443 d->input.fd = http_open(path);
422 444 }
423 } else { 445 } else {
424 d->input.path = path.latin1(); 446 d->input.path = path.latin1();
425 d->input.fd = ::open( d->input.path, O_RDONLY ); 447 d->input.fd = ::open( d->input.path, O_RDONLY );
448 // thats a better place, since it should only seek for ID3 tags on mp3 files, not streams
449 printID3Tags();
426 } 450 }
427 if (d->input.fd == -1) { 451 if (d->input.fd == -1) {
428 qDebug("error opening %s", d->input.path ); 452// qDebug("error opening %s", d->input.path );
429 return FALSE; 453 return FALSE;
430 } 454 }
431 455
432 printID3Tags(); 456// printID3Tags();
433 457
434#if defined(HAVE_MMAP) 458#if defined(HAVE_MMAP)
435 struct stat stat; 459 struct stat stat;
436 if (fstat(d->input.fd, &stat) == -1) { 460 if (fstat(d->input.fd, &stat) == -1) {
437 qDebug("error calling fstat"); return FALSE; 461 //qDebug("error calling fstat"); return FALSE;
438 } 462 }
439 if (S_ISREG(stat.st_mode) && stat.st_size > 0) { 463 if (S_ISREG(stat.st_mode) && stat.st_size > 0) {
440 d->input.length = stat.st_size; 464 d->input.length = stat.st_size;
@@ -648,8 +672,7 @@ static const int bits = 16;
648static const int shift = MAD_F_FRACBITS + 1 - bits; 672static const int shift = MAD_F_FRACBITS + 1 - bits;
649 673
650 674
651inline long audio_linear_dither( mad_fixed_t sample, mad_fixed_t& error ) 675inline long audio_linear_dither( mad_fixed_t sample, mad_fixed_t& error ) {
652{
653 sample += error; 676 sample += error;
654 mad_fixed_t quantized = (sample >= MAD_F_ONE) ? MAD_F_ONE - 1 : ( (sample < -MAD_F_ONE) ? -MAD_F_ONE : sample ); 677 mad_fixed_t quantized = (sample >= MAD_F_ONE) ? MAD_F_ONE - 1 : ( (sample < -MAD_F_ONE) ? -MAD_F_ONE : sample );
655 quantized &= ~((1L << shift) - 1); 678 quantized &= ~((1L << shift) - 1);
@@ -658,8 +681,7 @@ inline long audio_linear_dither( mad_fixed_t sample, mad_fixed_t& error )
658} 681}
659 682
660 683
661inline void audio_pcm( short *data, unsigned int nsamples, mad_fixed_t *left, mad_fixed_t *right ) 684inline void audio_pcm( short *data, unsigned int nsamples, mad_fixed_t *left, mad_fixed_t *right ) {
662{
663 if ( right ) { 685 if ( right ) {
664 while (nsamples--) { 686 while (nsamples--) {
665 data[0] = audio_linear_dither( *left++, left_err ); 687 data[0] = audio_linear_dither( *left++, left_err );
@@ -685,8 +707,9 @@ bool LibMadPlugin::decode( short *output, long samples, long& samplesMade ) {
685 707
686 static int maxBuffered = 8000; // 65536; 708 static int maxBuffered = 8000; // 65536;
687 709
688 if ( samples > maxBuffered ) 710 if ( samples > maxBuffered ) {
689 samples = maxBuffered; 711 samples = maxBuffered;
712 }
690 713
691 if ( d->flush ) { 714 if ( d->flush ) {
692 buffered = 0; 715 buffered = 0;
@@ -715,27 +738,22 @@ bool LibMadPlugin::decode( short *output, long samples, long& samplesMade ) {
715 offset += decodedSamples; 738 offset += decodedSamples;
716 buffered += decodedSamples; 739 buffered += decodedSamples;
717 } 740 }
741
718//qApp->processEvents(); 742//qApp->processEvents();
719 audio_pcm( output, samples, buffer[0], (d->synth.pcm.channels == 2) ? buffer[1] : 0 ); 743 audio_pcm( output, samples, buffer[0], (d->synth.pcm.channels == 2) ? buffer[1] : 0 );
720// audio_pcm( output, samples, buffer[1], buffer[0] ); 744// audio_pcm( output, samples, buffer[1], buffer[0] );
721// audio_pcm( output, samples, buffer[0], buffer[1] ); 745// audio_pcm( output, samples, buffer[0], buffer[1] );
722 samplesMade = samples; 746 samplesMade = samples;
723 memmove( buffer[0], &(buffer[0][samples]), (buffered - samples) * sizeof(mad_fixed_t) ); 747 memmove( buffer[0], &(buffer[0][samples]), (buffered - samples) * sizeof(mad_fixed_t) );
724 if ( d->synth.pcm.channels == 2 ) 748 if ( d->synth.pcm.channels == 2 ) {
725 memmove( buffer[1], &(buffer[1][samples]), (buffered - samples) * sizeof(mad_fixed_t) ); 749 memmove( buffer[1], &(buffer[1][samples]), (buffered - samples) * sizeof(mad_fixed_t) );
750 }
726 buffered -= samples; 751 buffered -= samples;
727 752
728 return TRUE; 753 return TRUE;
729} 754}
730 755
731/* 756/*bool LibMadPlugin::audioReadStereoSamples( short *output, long samples, long& samplesMade, int ) {
732bool LibMadPlugin::audioReadMonoSamples( short *, long, long&, int ) {
733 debugMsg( "LibMadPlugin::audioReadMonoSamples" );
734 return FALSE;
735}
736
737
738bool LibMadPlugin::audioReadStereoSamples( short *output, long samples, long& samplesMade, int ) {
739*/ 757*/
740bool LibMadPlugin::audioReadSamples( short *output, int /*channels*/, long samples, long& samplesMade, int ) { 758bool LibMadPlugin::audioReadSamples( short *output, int /*channels*/, long samples, long& samplesMade, int ) {
741 debugMsg( "LibMadPlugin::audioReadStereoSamples" ); 759 debugMsg( "LibMadPlugin::audioReadStereoSamples" );
@@ -748,9 +766,6 @@ bool LibMadPlugin::audioReadSamples( short *output, int /*channels*/, long sampl
748 do { 766 do {
749 if ( needInput ) 767 if ( needInput )
750 if ( !read() ) { 768 if ( !read() ) {
751// if ( d->input.eof )
752// needInput = FALSE;
753// else
754 return FALSE; 769 return FALSE;
755 } 770 }
756 771
@@ -762,15 +777,7 @@ bool LibMadPlugin::audioReadSamples( short *output, int /*channels*/, long sampl
762 needInput = TRUE; 777 needInput = TRUE;
763 } 778 }
764 while ( ( samplesMade < samples ) && ( !d->input.eof ) ); 779 while ( ( samplesMade < samples ) && ( !d->input.eof ) );
765/*
766 static bool firstTimeThru = TRUE;
767 780
768 if ( firstTimeThru ) {
769 firstTimeThru = FALSE;
770 decode( output, samples, samplesMade );
771 return FALSE;
772 } else
773*/
774 return FALSE; 781 return FALSE;
775} 782}
776 783