summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/libmad/libmadplugin.cpp4
1 files changed, 2 insertions, 2 deletions
diff --git a/core/multimedia/opieplayer/libmad/libmadplugin.cpp b/core/multimedia/opieplayer/libmad/libmadplugin.cpp
index 428fc28..7438a45 100644
--- a/core/multimedia/opieplayer/libmad/libmadplugin.cpp
+++ b/core/multimedia/opieplayer/libmad/libmadplugin.cpp
@@ -197,677 +197,677 @@ int LibMadPlugin::is_address_multicast(unsigned long address) {
197 return (1); 197 return (1);
198 return (0); 198 return (0);
199} 199}
200 200
201 201
202int LibMadPlugin::udp_open(char *address, int port) { 202int LibMadPlugin::udp_open(char *address, int port) {
203 203
204 int enable = 1L; 204 int enable = 1L;
205 struct sockaddr_in stAddr; 205 struct sockaddr_in stAddr;
206 struct sockaddr_in stLclAddr; 206 struct sockaddr_in stLclAddr;
207 struct ip_mreq stMreq; 207 struct ip_mreq stMreq;
208 struct hostent *host; 208 struct hostent *host;
209 int sock; 209 int sock;
210 210
211 stAddr.sin_family = AF_INET; 211 stAddr.sin_family = AF_INET;
212 stAddr.sin_port = htons(port); 212 stAddr.sin_port = htons(port);
213 213
214 if ((host = gethostbyname(address)) == NULL) { 214 if ((host = gethostbyname(address)) == NULL) {
215 return (0); 215 return (0);
216 } 216 }
217 217
218 stAddr.sin_addr = *((struct in_addr *)host->h_addr_list[0]); 218 stAddr.sin_addr = *((struct in_addr *)host->h_addr_list[0]);
219 219
220 /* Create a UDP socket */ 220 /* Create a UDP socket */
221 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 221 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
222 return (0); 222 return (0);
223 } 223 }
224 224
225 /* Allow multiple instance of the client to share the same address and port */ 225 /* Allow multiple instance of the client to share the same address and port */
226 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&enable, sizeof(unsigned long int)) < 0) { 226 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&enable, sizeof(unsigned long int)) < 0) {
227 return (0); 227 return (0);
228 } 228 }
229 229
230 /* If the address is multicast, register to the multicast group */ 230 /* If the address is multicast, register to the multicast group */
231 if (is_address_multicast(stAddr.sin_addr.s_addr)) { 231 if (is_address_multicast(stAddr.sin_addr.s_addr)) {
232 /* Bind the socket to port */ 232 /* Bind the socket to port */
233 stLclAddr.sin_family = AF_INET; 233 stLclAddr.sin_family = AF_INET;
234 stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY); 234 stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
235 stLclAddr.sin_port = stAddr.sin_port; 235 stLclAddr.sin_port = stAddr.sin_port;
236 if (bind(sock, (struct sockaddr *)&stLclAddr, sizeof(stLclAddr)) < 0) { 236 if (bind(sock, (struct sockaddr *)&stLclAddr, sizeof(stLclAddr)) < 0) {
237 return (0); 237 return (0);
238 } 238 }
239 239
240 /* Register to a multicast address */ 240 /* Register to a multicast address */
241 stMreq.imr_multiaddr.s_addr = stAddr.sin_addr.s_addr; 241 stMreq.imr_multiaddr.s_addr = stAddr.sin_addr.s_addr;
242 stMreq.imr_interface.s_addr = INADDR_ANY; 242 stMreq.imr_interface.s_addr = INADDR_ANY;
243 if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&stMreq, sizeof(stMreq)) < 0) { 243 if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&stMreq, sizeof(stMreq)) < 0) {
244 return (0); 244 return (0);
245 } 245 }
246 } else { 246 } else {
247 /* Bind the socket to port */ 247 /* Bind the socket to port */
248 stLclAddr.sin_family = AF_INET; 248 stLclAddr.sin_family = AF_INET;
249 stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY); 249 stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
250 stLclAddr.sin_port = htons(0); 250 stLclAddr.sin_port = htons(0);
251 if (bind(sock, (struct sockaddr *)&stLclAddr, sizeof(stLclAddr)) < 0) { 251 if (bind(sock, (struct sockaddr *)&stLclAddr, sizeof(stLclAddr)) < 0) {
252 return (0); 252 return (0);
253 } 253 }
254 } 254 }
255 return (sock); 255 return (sock);
256} 256}
257 257
258int LibMadPlugin::tcp_open(char *address, int port) { 258int LibMadPlugin::tcp_open(char *address, int port) {
259 struct sockaddr_in stAddr; 259 struct sockaddr_in stAddr;
260 struct hostent *host; 260 struct hostent *host;
261 int sock; 261 int sock;
262 struct linger l; 262 struct linger l;
263 263
264 memset(&stAddr, 0, sizeof(stAddr)); 264 memset(&stAddr, 0, sizeof(stAddr));
265 stAddr.sin_family = AF_INET; 265 stAddr.sin_family = AF_INET;
266 stAddr.sin_port = htons(port); 266 stAddr.sin_port = htons(port);
267 267
268 if ((host = gethostbyname(address)) == NULL) { 268 if ((host = gethostbyname(address)) == NULL) {
269 return (0); 269 return (0);
270 } 270 }
271 271
272 stAddr.sin_addr = *((struct in_addr *)host->h_addr_list[0]); 272 stAddr.sin_addr = *((struct in_addr *)host->h_addr_list[0]);
273 273
274 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 274 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
275 return (0); 275 return (0);
276 } 276 }
277 277
278 l.l_onoff = 1; 278 l.l_onoff = 1;
279 l.l_linger = 5; 279 l.l_linger = 5;
280 if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l)) < 0) { 280 if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l)) < 0) {
281 return (0); 281 return (0);
282 } 282 }
283 283
284 if (connect(sock, (struct sockaddr *)&stAddr, sizeof(stAddr)) < 0) { 284 if (connect(sock, (struct sockaddr *)&stAddr, sizeof(stAddr)) < 0) {
285 return (0); 285 return (0);
286 } 286 }
287 287
288 return (sock); 288 return (sock);
289} 289}
290 290
291 291
292/** 292/**
293 * Read a http line header. 293 * Read a http line header.
294 * This function read character by character. 294 * This function read character by character.
295 * @param tcp_sock the socket use to read the stream 295 * @param tcp_sock the socket use to read the stream
296 * @param buf a buffer to receive the data 296 * @param buf a buffer to receive the data
297 * @param size size of the buffer 297 * @param size size of the buffer
298 * @return the size of the stream read or -1 if an error occured 298 * @return the size of the stream read or -1 if an error occured
299 */ 299 */
300int LibMadPlugin::http_read_line(int tcp_sock, char *buf, int size) { 300int LibMadPlugin::http_read_line(int tcp_sock, char *buf, int size) {
301 int offset = 0; 301 int offset = 0;
302 302
303 do { 303 do {
304 if (::read(tcp_sock, buf + offset, 1) < 0) 304 if (::read(tcp_sock, buf + offset, 1) < 0)
305 return -1; 305 return -1;
306 if (buf[offset] != '\r') /* Strip \r from answer */ 306 if (buf[offset] != '\r') /* Strip \r from answer */
307 offset++; 307 offset++;
308 } while (offset < size - 1 && buf[offset - 1] != '\n'); 308 } while (offset < size - 1 && buf[offset - 1] != '\n');
309 309
310 buf[offset] = 0; 310 buf[offset] = 0;
311 return offset; 311 return offset;
312} 312}
313 313
314int LibMadPlugin::http_open(const QString& path ) { 314int LibMadPlugin::http_open(const QString& path ) {
315 char *host; 315 char *host;
316 int port; 316 int port;
317 char *request; 317 char *request;
318 int tcp_sock; 318 int tcp_sock;
319 char http_request[PATH_MAX]; 319 char http_request[PATH_MAX];
320 char filename[PATH_MAX]; 320 char filename[PATH_MAX];
321 //char c; 321 //char c;
322 char *arg =strdup(path.latin1()); 322 char *arg =strdup(path.latin1());
323 323
324 /* Check for URL syntax */ 324 /* Check for URL syntax */
325 if (strncmp(arg, "http://", strlen("http://"))) { 325 if (strncmp(arg, "http://", strlen("http://"))) {
326 return (0); 326 return (0);
327 } 327 }
328 328
329 /* Parse URL */ 329 /* Parse URL */
330 port = 80; 330 port = 80;
331 host = arg + strlen("http://"); 331 host = arg + strlen("http://");
332 if ((request = strchr(host, '/')) == NULL) { 332 if ((request = strchr(host, '/')) == NULL) {
333 return (0); 333 return (0);
334 } 334 }
335 335
336 *request++ = 0; 336 *request++ = 0;
337 337
338 if (strchr(host, ':') != NULL) { /* port is specified */ 338 if (strchr(host, ':') != NULL) { /* port is specified */
339 port = atoi(strchr(host, ':') + 1); 339 port = atoi(strchr(host, ':') + 1);
340 *strchr(host, ':') = 0; 340 *strchr(host, ':') = 0;
341 } 341 }
342 342
343 /* Open a TCP socket */ 343 /* Open a TCP socket */
344 if (!(tcp_sock = tcp_open(host, port))) { 344 if (!(tcp_sock = tcp_open(host, port))) {
345 perror("http_open"); 345 perror("http_open");
346 return (0); 346 return (0);
347 } 347 }
348 348
349 snprintf(filename, sizeof(filename) - strlen(host) - 75, "%s", request); 349 snprintf(filename, sizeof(filename) - strlen(host) - 75, "%s", request);
350 350
351 /* Send HTTP GET request */ 351 /* Send HTTP GET request */
352 /* Please don't use a Agent know by shoutcast (Lynx, Mozilla) seems to be reconized and print 352 /* Please don't use a Agent know by shoutcast (Lynx, Mozilla) seems to be reconized and print
353 * a html page and not the stream */ 353 * a html page and not the stream */
354 snprintf(http_request, sizeof(http_request), "GET /%s HTTP/1.0\r\n" 354 snprintf(http_request, sizeof(http_request), "GET /%s HTTP/1.0\r\n"
355 /* "User-Agent: Mozilla/2.0 (Win95; I)\r\n" */ 355 /* "User-Agent: Mozilla/2.0 (Win95; I)\r\n" */
356 "Pragma: no-cache\r\n" "Host: %s\r\n" "Accept: */*\r\n" "\r\n", filename, host); 356 "Pragma: no-cache\r\n" "Host: %s\r\n" "Accept: */*\r\n" "\r\n", filename, host);
357 357
358 send(tcp_sock, http_request, strlen(http_request), 0); 358 send(tcp_sock, http_request, strlen(http_request), 0);
359 359
360 /* Parse server reply */ 360 /* Parse server reply */
361#if 0 361#if 0
362 do 362 do
363 read(tcp_sock, &c, sizeof(char)); 363 read(tcp_sock, &c, sizeof(char));
364 while (c != ' '); 364 while (c != ' ');
365 read(tcp_sock, http_request, 4 * sizeof(char)); 365 read(tcp_sock, http_request, 4 * sizeof(char));
366 http_request[4] = 0; 366 http_request[4] = 0;
367 if (strcmp(http_request, "200 ")) { 367 if (strcmp(http_request, "200 ")) {
368 fprintf(stderr, "http_open: "); 368 fprintf(stderr, "http_open: ");
369 do { 369 do {
370 read(tcp_sock, &c, sizeof(char)); 370 read(tcp_sock, &c, sizeof(char));
371 fprintf(stderr, "%c", c); 371 fprintf(stderr, "%c", c);
372 } while (c != '\r'); 372 } while (c != '\r');
373 fprintf(stderr, "\n"); 373 fprintf(stderr, "\n");
374 return (0); 374 return (0);
375 } 375 }
376#endif 376#endif
377 377
378 QString name; 378 QString name;
379 QString genre; 379 QString genre;
380 QString bitrate; 380 QString bitrate;
381 QString url; 381 QString url;
382 QString message = tr("Info: "); 382 QString message = tr("Info: ");
383 do { 383 do {
384 384
385 int len; 385 int len;
386 386
387 len = http_read_line(tcp_sock, http_request, sizeof(http_request)); 387 len = http_read_line(tcp_sock, http_request, sizeof(http_request));
388 388
389 if (len == -1) { 389 if (len == -1) {
390 // odebug << "http_open: "+ QString(strerror(errno)) +"\n" << oendl; 390 // odebug << "http_open: "+ QString(strerror(errno)) +"\n" << oendl;
391 return 0; 391 return 0;
392 } 392 }
393 393
394 if (QString(http_request).left(9) == "Location:") { 394 if (QString(http_request).left(9) == "Location:") {
395 /* redirect */ 395 /* redirect */
396 ::close(tcp_sock); 396 ::close(tcp_sock);
397 http_request[strlen(http_request) - 1] = '\0'; 397 http_request[strlen(http_request) - 1] = '\0';
398 return http_open(&http_request[10]); 398 return http_open(&http_request[10]);
399 } 399 }
400 400
401 if (QString(http_request).left(4) == "ICY ") { 401 if (QString(http_request).left(4) == "ICY ") {
402 /* This is shoutcast/icecast streaming */ 402 /* This is shoutcast/icecast streaming */
403 if (strncmp(http_request + 4, "200 ", 4)) { 403 if (strncmp(http_request + 4, "200 ", 4)) {
404 // odebug << "http_open: " + QString(http_request) + "\n" << oendl; 404 // odebug << "http_open: " + QString(http_request) + "\n" << oendl;
405 return 0; 405 return 0;
406 } 406 }
407 } else if (QString(http_request).left(4) == "icy-") { 407 } else if (QString(http_request).left(4) == "icy-") {
408 /* we can have: icy-noticeX, icy-name, icy-genre, icy-url, icy-pub, icy-metaint, icy-br */ 408 /* we can have: icy-noticeX, icy-name, icy-genre, icy-url, icy-pub, icy-metaint, icy-br */
409 if ( QString( http_request ).left( 8 ) == "icy-name" ) { 409 if ( QString( http_request ).left( 8 ) == "icy-name" ) {
410 name = tr("Name: ") + QString(http_request).mid(9, (QString(http_request).length())- 9 ); 410 name = tr("Name: ") + QString(http_request).mid(9, (QString(http_request).length())- 9 );
411 } else if ( QString( http_request ).left( 9 ) == "icy-genre" ) { 411 } else if ( QString( http_request ).left( 9 ) == "icy-genre" ) {
412 genre = tr("Genre: ") + QString(http_request).mid(10, (QString(http_request).length())-10 ); 412 genre = tr("Genre: ") + QString(http_request).mid(10, (QString(http_request).length())-10 );
413 } else if ( QString( http_request ).left( 6 ) == "icy-br" ) { 413 } else if ( QString( http_request ).left( 6 ) == "icy-br" ) {
414 bitrate = tr("Bitrate: ") + QString(http_request).mid(7, (QString(http_request).length())- 7 ); 414 bitrate = tr("Bitrate: ") + QString(http_request).mid(7, (QString(http_request).length())- 7 );
415 } else if ( QString( http_request ).left( 7 ) == "icy-url" ) { 415 } else if ( QString( http_request ).left( 7 ) == "icy-url" ) {
416 url = tr("URL: ") + QString(http_request).mid(8, (QString(http_request).length())- 8 ); 416 url = tr("URL: ") + QString(http_request).mid(8, (QString(http_request).length())- 8 );
417 } else if ( QString( http_request ).left( 10 ) == "icy-notice" ) { 417 } else if ( QString( http_request ).left( 10 ) == "icy-notice" ) {
418 message += QString(http_request).mid(11, QString(http_request).length()-11 ) ; 418 message += QString(http_request).mid(11, QString(http_request).length()-11 ) ;
419 } 419 }
420 } 420 }
421 } while (strcmp(http_request, "\n") != 0); 421 } while (strcmp(http_request, "\n") != 0);
422 422
423 info = QString(name + genre + url + bitrate + message).replace( QRegExp("\n"), " : " ); 423 info = QString(name + genre + url + bitrate + message).replace( QRegExp("\n"), " : " );
424 424
425 // odebug << "Stream info: " + info << oendl; 425 // odebug << "Stream info: " + info << oendl;
426 426
427 return (tcp_sock); 427 return (tcp_sock);
428} 428}
429 429
430 430
431 431
432bool LibMadPlugin::open( const QString& path ) { 432bool LibMadPlugin::open( const QString& path ) {
433 debugMsg( "LibMadPlugin::open" ); 433 debugMsg( "LibMadPlugin::open" );
434 Config cfg("OpiePlayer"); 434 Config cfg("OpiePlayer");
435 cfg.setGroup("Options"); 435 cfg.setGroup("Options");
436 bufferSize = cfg.readNumEntry("MPeg_BufferSize",MPEG_BUFFER_SIZE); 436 bufferSize = cfg.readNumEntry("MPeg_BufferSize",MPEG_BUFFER_SIZE);
437 // odebug << "buffer size is " << bufferSize << "" << oendl; 437 // odebug << "buffer size is " << bufferSize << "" << oendl;
438 d->bad_last_frame = 0; 438 d->bad_last_frame = 0;
439 d->flush = TRUE; 439 d->flush = TRUE;
440 info = QString( "" ); 440 info = QString( "" );
441 441
442 //odebug << "Opening " << path << "" << oendl; 442 //odebug << "Opening " << path << "" << oendl;
443 443
444 if (path.left( 4 ) == "http" ) { 444 if (path.left( 4 ) == "http" ) {
445 // in case of any error we get 0 here 445 // in case of any error we get 0 here
446 if ( !(http_open(path) == 0) ) { 446 if ( !(http_open(path) == 0) ) {
447 d->input.fd = http_open(path); 447 d->input.fd = http_open(path);
448 } else { 448 } else {
449 return FALSE; 449 return FALSE;
450 } 450 }
451 } else { 451 } else {
452 d->input.path = path.latin1(); 452 d->input.path = path.latin1();
453 d->input.fd = ::open( d->input.path, O_RDONLY ); 453 d->input.fd = ::open( d->input.path, O_RDONLY );
454 // thats a better place, since it should only seek for ID3 tags on mp3 files, not streams 454 // thats a better place, since it should only seek for ID3 tags on mp3 files, not streams
455 printID3Tags(); 455 printID3Tags();
456 } 456 }
457 if (d->input.fd == -1) { 457 if (d->input.fd == -1) {
458 // odebug << "error opening " << d->input.path << "" << oendl; 458 // odebug << "error opening " << d->input.path << "" << oendl;
459 return FALSE; 459 return FALSE;
460 } 460 }
461 461
462 struct stat stat; 462 struct stat stat;
463 if (fstat(d->input.fd, &stat) == -1) { 463 if (fstat(d->input.fd, &stat) == -1) {
464 // odebug << "error calling fstat" << oendl; return FALSE; 464 // odebug << "error calling fstat" << oendl; return FALSE;
465 } 465 }
466 if (S_ISREG(stat.st_mode) && stat.st_size > 0) 466 if (S_ISREG(stat.st_mode) && stat.st_size > 0)
467 d->input.fileLength = stat.st_size; 467 d->input.fileLength = stat.st_size;
468 else 468 else
469 d->input.fileLength = 0; 469 d->input.fileLength = 0;
470 470
471#if defined(HAVE_MMAP) 471#if defined(HAVE_MMAP)
472 if (S_ISREG(stat.st_mode) && stat.st_size > 0) { 472 if (S_ISREG(stat.st_mode) && stat.st_size > 0) {
473 d->input.length = stat.st_size; 473 d->input.length = stat.st_size;
474 d->input.fdm = map_file(d->input.fd, &d->input.length); 474 d->input.fdm = map_file(d->input.fd, &d->input.length);
475 if (d->input.fdm == 0) { 475 if (d->input.fdm == 0) {
476 // odebug << "error mmapping file" << oendl; return FALSE; 476 // odebug << "error mmapping file" << oendl; return FALSE;
477 } 477 }
478 d->input.data = (unsigned char *)d->input.fdm; 478 d->input.data = (unsigned char *)d->input.fdm;
479 } 479 }
480#endif 480#endif
481 481
482 if (d->input.data == 0) { 482 if (d->input.data == 0) {
483 d->input.data = (unsigned char *)malloc( bufferSize /*MPEG_BUFFER_SIZE*/); 483 d->input.data = (unsigned char *)malloc( bufferSize /*MPEG_BUFFER_SIZE*/);
484 if (d->input.data == 0) { 484 if (d->input.data == 0) {
485 // odebug << "error allocating input buffer" << oendl; 485 // odebug << "error allocating input buffer" << oendl;
486 return FALSE; 486 return FALSE;
487 } 487 }
488 d->input.length = 0; 488 d->input.length = 0;
489 } 489 }
490 490
491 d->input.eof = 0; 491 d->input.eof = 0;
492 492
493 mad_stream_init(&d->stream); 493 mad_stream_init(&d->stream);
494 mad_frame_init(&d->frame); 494 mad_frame_init(&d->frame);
495 mad_synth_init(&d->synth); 495 mad_synth_init(&d->synth);
496 496
497 return TRUE; 497 return TRUE;
498} 498}
499 499
500 500
501bool LibMadPlugin::close() { 501bool LibMadPlugin::close() {
502 debugMsg( "LibMadPlugin::close" ); 502 debugMsg( "LibMadPlugin::close" );
503 503
504 int result = TRUE; 504 int result = TRUE;
505 505
506 mad_synth_finish(&d->synth); 506 mad_synth_finish(&d->synth);
507 mad_frame_finish(&d->frame); 507 mad_frame_finish(&d->frame);
508 mad_stream_finish(&d->stream); 508 mad_stream_finish(&d->stream);
509 509
510#if defined(HAVE_MMAP) 510#if defined(HAVE_MMAP)
511 if (d->input.fdm) { 511 if (d->input.fdm) {
512 if (unmap_file(d->input.fdm, d->input.length) == -1) { 512 if (unmap_file(d->input.fdm, d->input.length) == -1) {
513 // odebug << "error munmapping file" << oendl; 513 // odebug << "error munmapping file" << oendl;
514 result = FALSE; 514 result = FALSE;
515 } 515 }
516 d->input.fdm = 0; 516 d->input.fdm = 0;
517 d->input.data = 0; 517 d->input.data = 0;
518 } 518 }
519#endif 519#endif
520 520
521 if (d->input.data) { 521 if (d->input.data) {
522 free(d->input.data); 522 free(d->input.data);
523 d->input.data = 0; 523 d->input.data = 0;
524 } 524 }
525 525
526 if (::close(d->input.fd) == -1) { 526 if (::close(d->input.fd) == -1) {
527 // odebug << "error closing file " << d->input.path << "" << oendl; 527 // odebug << "error closing file " << d->input.path << "" << oendl;
528 result = FALSE; 528 result = FALSE;
529 } 529 }
530 530
531 d->input.fd = 0; 531 d->input.fd = 0;
532 532
533 return result; 533 return result;
534} 534}
535 535
536 536
537bool LibMadPlugin::isOpen() { 537bool LibMadPlugin::isOpen() {
538 debugMsg( "LibMadPlugin::isOpen" ); 538 debugMsg( "LibMadPlugin::isOpen" );
539 return ( d->input.fd != 0 ); 539 return ( d->input.fd != 0 );
540} 540}
541 541
542 542
543int LibMadPlugin::audioStreams() { 543int LibMadPlugin::audioStreams() {
544 debugMsg( "LibMadPlugin::audioStreams" ); 544 debugMsg( "LibMadPlugin::audioStreams" );
545 return 1; 545 return 1;
546} 546}
547 547
548 548
549int LibMadPlugin::audioChannels( int ) { 549int LibMadPlugin::audioChannels( int ) {
550 debugMsg( "LibMadPlugin::audioChannels" ); 550 debugMsg( "LibMadPlugin::audioChannels" );
551/* 551/*
552 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 ); 552 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 );
553 odebug << "LibMadPlugin::audioChannels: " << d->frame.header.mode > 0 ? 2 : 1 << "" << oendl; 553 odebug << "LibMadPlugin::audioChannels: " << d->frame.header.mode > 0 ? 2 : 1 << "" << oendl;
554 return d->frame.header.mode > 0 ? 2 : 1; 554 return d->frame.header.mode > 0 ? 2 : 1;
555*/ 555*/
556 return 2; 556 return 2;
557} 557}
558 558
559 559
560int LibMadPlugin::audioFrequency( int ) { 560int LibMadPlugin::audioFrequency( int ) {
561 debugMsg( "LibMadPlugin::audioFrequency" ); 561 debugMsg( "LibMadPlugin::audioFrequency" );
562 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 ); 562 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 );
563 // odebug << "LibMadPlugin::audioFrequency: " << d->frame.header.samplerate << "" << oendl; 563 // odebug << "LibMadPlugin::audioFrequency: " << d->frame.header.samplerate << "" << oendl;
564 return d->frame.header.samplerate; 564 return d->frame.header.samplerate;
565} 565}
566 566
567 567
568int LibMadPlugin::audioSamples( int ) { 568int LibMadPlugin::audioSamples( int ) {
569 debugMsg( "LibMadPlugin::audioSamples" ); 569 debugMsg( "LibMadPlugin::audioSamples" );
570 570
571 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 ); 571 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 );
572 mad_header_decode( (struct mad_header *)&d->frame.header, &d->stream ); 572 mad_header_decode( (struct mad_header *)&d->frame.header, &d->stream );
573/* 573/*
574 odebug << "LibMadPlugin::audioSamples: " << d->frame.header.duration.seconds << "*" << d->frame.header.samplerate << oendl; 574 odebug << "LibMadPlugin::audioSamples: " << d->frame.header.duration.seconds << "*" << d->frame.header.samplerate << oendl;
575 return d->frame.header.duration.seconds * d->frame.header.samplerate; 575 return d->frame.header.duration.seconds * d->frame.header.samplerate;
576*/ 576*/
577 if ( d->frame.header.bitrate == 0 ) 577 if ( d->frame.header.bitrate == 0 )
578 return 0; 578 return 0;
579 int samples = (d->input.fileLength / (d->frame.header.bitrate/8)) * d->frame.header.samplerate; 579 int samples = (d->input.fileLength / (d->frame.header.bitrate/8)) * d->frame.header.samplerate;
580 580
581 // qDebug( "LibMadPlugin::audioSamples: %i * %i * 8 / %i", (int)d->input.fileLength, 581 // odebug << "LibMadPlugin::audioSamples: " << (int)d->input.fileLength
582 // (int)d->frame.header.samplerate, (int)d->frame.header.bitrate ); 582 // << " * " << (int)d->frame.header.samplerate << " * 8 / " << (int)d->frame.header.bitrate << oendl;
583 // odebug << "LibMadPlugin::audioSamples: " << samples << "" << oendl; 583 // odebug << "LibMadPlugin::audioSamples: " << samples << "" << oendl;
584 584
585 return samples; 585 return samples;
586 586
587// return 10000000; 587// return 10000000;
588} 588}
589 589
590 590
591bool LibMadPlugin::audioSetSample( long, int ) { 591bool LibMadPlugin::audioSetSample( long, int ) {
592 debugMsg( "LibMadPlugin::audioSetSample" ); 592 debugMsg( "LibMadPlugin::audioSetSample" );
593 593
594// long totalSamples = audioSamples(0); 594// long totalSamples = audioSamples(0);
595// if ( totalSamples <= 1 ) 595// if ( totalSamples <= 1 )
596// return FALSE; 596// return FALSE;
597 597
598// // Seek to requested position 598// // Seek to requested position
599// odebug << "seek pos: " << (int)((double)pos * d->input.fileLength / totalSamples) << "" << oendl; 599// odebug << "seek pos: " << (int)((double)pos * d->input.fileLength / totalSamples) << "" << oendl;
600// ::lseek( d->input.fd, (long)((double)pos * d->input.fileLength / totalSamples), SEEK_SET ); 600// ::lseek( d->input.fd, (long)((double)pos * d->input.fileLength / totalSamples), SEEK_SET );
601// mad_stream_sync(&d->stream); 601// mad_stream_sync(&d->stream);
602 602
603// mad_stream_init(&d->stream); 603// mad_stream_init(&d->stream);
604// mad_frame_init(&d->frame); 604// mad_frame_init(&d->frame);
605// mad_synth_init(&d->synth); 605// mad_synth_init(&d->synth);
606 606
607// return TRUE; 607// return TRUE;
608 debugMsg( "LibMadPlugin::audioSetSample" ); 608 debugMsg( "LibMadPlugin::audioSetSample" );
609 return FALSE; 609 return FALSE;
610} 610}
611 611
612 612
613long LibMadPlugin::audioGetSample( int ) { 613long LibMadPlugin::audioGetSample( int ) {
614 debugMsg( "LibMadPlugin::audioGetSample" ); 614 debugMsg( "LibMadPlugin::audioGetSample" );
615 return 0; 615 return 0;
616} 616}
617 617
618/* 618/*
619bool LibMadPlugin::audioReadSamples( short *, int, long, int ) { 619bool LibMadPlugin::audioReadSamples( short *, int, long, int ) {
620debugMsg( "LibMadPlugin::audioReadSamples" ); 620debugMsg( "LibMadPlugin::audioReadSamples" );
621return FALSE; 621return FALSE;
622} 622}
623 623
624 624
625bool LibMadPlugin::audioReReadSamples( short *, int, long, int ) { 625bool LibMadPlugin::audioReReadSamples( short *, int, long, int ) {
626debugMsg( "LibMadPlugin::audioReReadSamples" ); 626debugMsg( "LibMadPlugin::audioReReadSamples" );
627 return FALSE; 627 return FALSE;
628 } 628 }
629*/ 629*/
630 630
631bool LibMadPlugin::read() { 631bool LibMadPlugin::read() {
632 debugMsg( "LibMadPlugin::read" ); 632 debugMsg( "LibMadPlugin::read" );
633 int len; 633 int len;
634 634
635 if (d->input.eof) 635 if (d->input.eof)
636 return FALSE; 636 return FALSE;
637 637
638#if defined(HAVE_MMAP) 638#if defined(HAVE_MMAP)
639 if (d->input.fdm) { 639 if (d->input.fdm) {
640 unsigned long skip = 0; 640 unsigned long skip = 0;
641 641
642 if (d->stream.next_frame) { 642 if (d->stream.next_frame) {
643 struct stat stat; 643 struct stat stat;
644 644
645 if (fstat(d->input.fd, &stat) == -1) 645 if (fstat(d->input.fd, &stat) == -1)
646 return FALSE; 646 return FALSE;
647 647
648 if (stat.st_size + MAD_BUFFER_GUARD <= (signed)d->input.length) 648 if (stat.st_size + MAD_BUFFER_GUARD <= (signed)d->input.length)
649 return FALSE; 649 return FALSE;
650 650
651 // file size changed; update memory map 651 // file size changed; update memory map
652 skip = d->stream.next_frame - d->input.data; 652 skip = d->stream.next_frame - d->input.data;
653 653
654 if (unmap_file(d->input.fdm, d->input.length) == -1) { 654 if (unmap_file(d->input.fdm, d->input.length) == -1) {
655 d->input.fdm = 0; 655 d->input.fdm = 0;
656 d->input.data = 0; 656 d->input.data = 0;
657 return FALSE; 657 return FALSE;
658 } 658 }
659 659
660 d->input.length = stat.st_size; 660 d->input.length = stat.st_size;
661 661
662 d->input.fdm = map_file(d->input.fd, &d->input.length); 662 d->input.fdm = map_file(d->input.fd, &d->input.length);
663 if (d->input.fdm == 0) { 663 if (d->input.fdm == 0) {
664 d->input.data = 0; 664 d->input.data = 0;
665 return FALSE; 665 return FALSE;
666 } 666 }
667 667
668 d->input.data = (unsigned char *)d->input.fdm; 668 d->input.data = (unsigned char *)d->input.fdm;
669 } 669 }
670 670
671 mad_stream_buffer(&d->stream, d->input.data + skip, d->input.length - skip); 671 mad_stream_buffer(&d->stream, d->input.data + skip, d->input.length - skip);
672 672
673 } else 673 } else
674#endif 674#endif
675 { 675 {
676 if (d->stream.next_frame) { 676 if (d->stream.next_frame) {
677 memmove(d->input.data, d->stream.next_frame, 677 memmove(d->input.data, d->stream.next_frame,
678 d->input.length = &d->input.data[d->input.length] - d->stream.next_frame); 678 d->input.length = &d->input.data[d->input.length] - d->stream.next_frame);
679 } 679 }
680 680
681 do { 681 do {
682 len = ::read(d->input.fd, d->input.data + d->input.length, bufferSize /* MPEG_BUFFER_SIZE*/ - d->input.length); 682 len = ::read(d->input.fd, d->input.data + d->input.length, bufferSize /* MPEG_BUFFER_SIZE*/ - d->input.length);
683 } 683 }
684 while (len == -1 && errno == EINTR); 684 while (len == -1 && errno == EINTR);
685 685
686 if (len == -1) { 686 if (len == -1) {
687 // odebug << "error reading audio" << oendl; 687 // odebug << "error reading audio" << oendl;
688 return FALSE; 688 return FALSE;
689 } 689 }
690 else if (len == 0) { 690 else if (len == 0) {
691 d->input.eof = 1; 691 d->input.eof = 1;
692 692
693 assert(bufferSize /*MPEG_BUFFER_SIZE*/ - d->input.length >= MAD_BUFFER_GUARD); 693 assert(bufferSize /*MPEG_BUFFER_SIZE*/ - d->input.length >= MAD_BUFFER_GUARD);
694 694
695 while (len < MAD_BUFFER_GUARD) 695 while (len < MAD_BUFFER_GUARD)
696 d->input.data[d->input.length + len++] = 0; 696 d->input.data[d->input.length + len++] = 0;
697 } 697 }
698 698
699 mad_stream_buffer(&d->stream, d->input.data, d->input.length += len); 699 mad_stream_buffer(&d->stream, d->input.data, d->input.length += len);
700 } 700 }
701 701
702 return TRUE; 702 return TRUE;
703} 703}
704 704
705 705
706static mad_fixed_t left_err, right_err; 706static mad_fixed_t left_err, right_err;
707static const int bits = 16; 707static const int bits = 16;
708static const int shift = MAD_F_FRACBITS + 1 - bits; 708static const int shift = MAD_F_FRACBITS + 1 - bits;
709 709
710 710
711inline long audio_linear_dither( mad_fixed_t sample, mad_fixed_t& error ) { 711inline long audio_linear_dither( mad_fixed_t sample, mad_fixed_t& error ) {
712 sample += error; 712 sample += error;
713 mad_fixed_t quantized = (sample >= MAD_F_ONE) ? MAD_F_ONE - 1 : ( (sample < -MAD_F_ONE) ? -MAD_F_ONE : sample ); 713 mad_fixed_t quantized = (sample >= MAD_F_ONE) ? MAD_F_ONE - 1 : ( (sample < -MAD_F_ONE) ? -MAD_F_ONE : sample );
714 quantized &= ~((1L << shift) - 1); 714 quantized &= ~((1L << shift) - 1);
715 error = sample - quantized; 715 error = sample - quantized;
716 return quantized >> shift; 716 return quantized >> shift;
717} 717}
718 718
719 719
720inline void audio_pcm( short *data, unsigned int nsamples, mad_fixed_t *left, mad_fixed_t *right ) { 720inline void audio_pcm( short *data, unsigned int nsamples, mad_fixed_t *left, mad_fixed_t *right ) {
721 if ( right ) { 721 if ( right ) {
722 while (nsamples--) { 722 while (nsamples--) {
723 data[0] = audio_linear_dither( *left++, left_err ); 723 data[0] = audio_linear_dither( *left++, left_err );
724 data[1] = audio_linear_dither( *right++, right_err ); 724 data[1] = audio_linear_dither( *right++, right_err );
725 data += 2; 725 data += 2;
726 } 726 }
727 } else { 727 } else {
728 while (nsamples--) { 728 while (nsamples--) {
729 data[0] = data[1] = audio_linear_dither( *left++, left_err ); 729 data[0] = data[1] = audio_linear_dither( *left++, left_err );
730 data += 2; 730 data += 2;
731 } 731 }
732 } 732 }
733} 733}
734 734
735 735
736bool LibMadPlugin::decode( short *output, long samples, long& samplesMade ) { 736bool LibMadPlugin::decode( short *output, long samples, long& samplesMade ) {
737 debugMsg( "LibMadPlugin::decode" ); 737 debugMsg( "LibMadPlugin::decode" );
738 738
739 static int buffered = 0; 739 static int buffered = 0;
740 static mad_fixed_t buffer[2][65536 * 2]; 740 static mad_fixed_t buffer[2][65536 * 2];
741 int offset = buffered; 741 int offset = buffered;
742 samplesMade = 0; 742 samplesMade = 0;
743 743
744 static int maxBuffered = 8000; // 65536; 744 static int maxBuffered = 8000; // 65536;
745 745
746 if ( samples > maxBuffered ) { 746 if ( samples > maxBuffered ) {
747 samples = maxBuffered; 747 samples = maxBuffered;
748 } 748 }
749 749
750 if ( d->flush ) { 750 if ( d->flush ) {
751 buffered = 0; 751 buffered = 0;
752 offset = 0; 752 offset = 0;
753 d->flush = FALSE; 753 d->flush = FALSE;
754 } 754 }
755 755
756 while ( buffered < maxBuffered ) { 756 while ( buffered < maxBuffered ) {
757 757
758 while (mad_frame_decode(&d->frame, &d->stream) == -1) { 758 while (mad_frame_decode(&d->frame, &d->stream) == -1) {
759 if (!MAD_RECOVERABLE(d->stream.error)) { 759 if (!MAD_RECOVERABLE(d->stream.error)) {
760 debugMsg( "feed me" ); 760 debugMsg( "feed me" );
761 return FALSE; // Feed me 761 return FALSE; // Feed me
762 } 762 }
763 if ( d->stream.error == MAD_ERROR_BADCRC ) { 763 if ( d->stream.error == MAD_ERROR_BADCRC ) {
764 mad_frame_mute(&d->frame); 764 mad_frame_mute(&d->frame);
765 // odebug << "error decoding, bad crc" << oendl; 765 // odebug << "error decoding, bad crc" << oendl;
766 } 766 }
767 } 767 }
768 768
769 mad_synth_frame(&d->synth, &d->frame); 769 mad_synth_frame(&d->synth, &d->frame);
770 int decodedSamples = d->synth.pcm.length; 770 int decodedSamples = d->synth.pcm.length;
771 memcpy( &(buffer[0][offset]), d->synth.pcm.samples[0], decodedSamples * sizeof(mad_fixed_t) ); 771 memcpy( &(buffer[0][offset]), d->synth.pcm.samples[0], decodedSamples * sizeof(mad_fixed_t) );
772 if ( d->synth.pcm.channels == 2 ) 772 if ( d->synth.pcm.channels == 2 )
773 memcpy( &(buffer[1][offset]), d->synth.pcm.samples[1], decodedSamples * sizeof(mad_fixed_t) ); 773 memcpy( &(buffer[1][offset]), d->synth.pcm.samples[1], decodedSamples * sizeof(mad_fixed_t) );
774 offset += decodedSamples; 774 offset += decodedSamples;
775 buffered += decodedSamples; 775 buffered += decodedSamples;
776 } 776 }
777 777
778//qApp->processEvents(); 778//qApp->processEvents();
779 audio_pcm( output, samples, buffer[0], (d->synth.pcm.channels == 2) ? buffer[1] : 0 ); 779 audio_pcm( output, samples, buffer[0], (d->synth.pcm.channels == 2) ? buffer[1] : 0 );
780// audio_pcm( output, samples, buffer[1], buffer[0] ); 780// audio_pcm( output, samples, buffer[1], buffer[0] );
781// audio_pcm( output, samples, buffer[0], buffer[1] ); 781// audio_pcm( output, samples, buffer[0], buffer[1] );
782 samplesMade = samples; 782 samplesMade = samples;
783 memmove( buffer[0], &(buffer[0][samples]), (buffered - samples) * sizeof(mad_fixed_t) ); 783 memmove( buffer[0], &(buffer[0][samples]), (buffered - samples) * sizeof(mad_fixed_t) );
784 if ( d->synth.pcm.channels == 2 ) { 784 if ( d->synth.pcm.channels == 2 ) {
785 memmove( buffer[1], &(buffer[1][samples]), (buffered - samples) * sizeof(mad_fixed_t) ); 785 memmove( buffer[1], &(buffer[1][samples]), (buffered - samples) * sizeof(mad_fixed_t) );
786 } 786 }
787 buffered -= samples; 787 buffered -= samples;
788 788
789 return TRUE; 789 return TRUE;
790} 790}
791 791
792/*bool LibMadPlugin::audioReadStereoSamples( short *output, long samples, long& samplesMade, int ) { 792/*bool LibMadPlugin::audioReadStereoSamples( short *output, long samples, long& samplesMade, int ) {
793*/ 793*/
794bool LibMadPlugin::audioReadSamples( short *output, int /*channels*/, long samples, long& samplesMade, int ) { 794bool LibMadPlugin::audioReadSamples( short *output, int /*channels*/, long samples, long& samplesMade, int ) {
795 debugMsg( "LibMadPlugin::audioReadStereoSamples" ); 795 debugMsg( "LibMadPlugin::audioReadStereoSamples" );
796 796
797 static bool needInput = TRUE; 797 static bool needInput = TRUE;
798 798
799 if ( samples == 0 ) 799 if ( samples == 0 )
800 return FALSE; 800 return FALSE;
801 801
802 do { 802 do {
803 if ( needInput ) 803 if ( needInput )
804 if ( !read() ) { 804 if ( !read() ) {
805 return FALSE; 805 return FALSE;
806 } 806 }
807 807
808 needInput = FALSE; 808 needInput = FALSE;
809 809
810 if ( decode( output, samples, samplesMade ) ) 810 if ( decode( output, samples, samplesMade ) )
811 return TRUE; 811 return TRUE;
812 else 812 else
813 needInput = TRUE; 813 needInput = TRUE;
814 } 814 }
815 while ( ( samplesMade < samples ) && ( !d->input.eof ) ); 815 while ( ( samplesMade < samples ) && ( !d->input.eof ) );
816 816
817 return FALSE; 817 return FALSE;
818} 818}
819 819
820 820
821double LibMadPlugin::getTime() { 821double LibMadPlugin::getTime() {
822 debugMsg( "LibMadPlugin::getTime" ); 822 debugMsg( "LibMadPlugin::getTime" );
823 return 0.0; 823 return 0.0;
824} 824}
825 825
826 826
827void LibMadPlugin::printID3Tags() { 827void LibMadPlugin::printID3Tags() {
828 // odebug << "LibMadPlugin::printID3Tags" << oendl; 828 // odebug << "LibMadPlugin::printID3Tags" << oendl;
829 829
830 char id3v1[128 + 1]; 830 char id3v1[128 + 1];
831 831
832 if ( ::lseek( d->input.fd, -128, SEEK_END ) == -1 ) { 832 if ( ::lseek( d->input.fd, -128, SEEK_END ) == -1 ) {
833 // odebug << "error seeking to id3 tags" << oendl; 833 // odebug << "error seeking to id3 tags" << oendl;
834 return; 834 return;
835 } 835 }
836 836
837 if ( ::read( d->input.fd, id3v1, 128 ) != 128 ) { 837 if ( ::read( d->input.fd, id3v1, 128 ) != 128 ) {
838 // odebug << "error reading in id3 tags" << oendl; 838 // odebug << "error reading in id3 tags" << oendl;
839 return; 839 return;
840 } 840 }
841 841
842 if ( ::strncmp( (const char *)id3v1, "TAG", 3 ) != 0 ) { 842 if ( ::strncmp( (const char *)id3v1, "TAG", 3 ) != 0 ) {
843 debugMsg( "sorry, no id3 tags" ); 843 debugMsg( "sorry, no id3 tags" );
844 } else { 844 } else {
845 int len[5] = { 30, 30, 30, 4, 30 }; 845 int len[5] = { 30, 30, 30, 4, 30 };
846 QString label[5] = { tr( "Title" ), tr( "Artist" ), tr( "Album" ), tr( "Year" ), tr( "Comment" ) }; 846 QString label[5] = { tr( "Title" ), tr( "Artist" ), tr( "Album" ), tr( "Year" ), tr( "Comment" ) };
847 char *ptr = id3v1 + 3, *ptr2 = ptr + len[0]; 847 char *ptr = id3v1 + 3, *ptr2 = ptr + len[0];
848 // odebug << "ID3 tags in file:" << oendl; 848 // odebug << "ID3 tags in file:" << oendl;
849 info = ""; 849 info = "";
850 for ( int i = 0; i < 5; ptr += len[i], i++, ptr2 += len[i] ) { 850 for ( int i = 0; i < 5; ptr += len[i], i++, ptr2 += len[i] ) {
851 char push = *ptr2; 851 char push = *ptr2;
852 *ptr2 = '\0'; 852 *ptr2 = '\0';
853 char *ptr3 = ptr2; 853 char *ptr3 = ptr2;
854 while ( ptr3-1 >= ptr && isspace(ptr3[-1]) ) ptr3--; 854 while ( ptr3-1 >= ptr && isspace(ptr3[-1]) ) ptr3--;
855 char push2 = *ptr3; *ptr3 = '\0'; 855 char push2 = *ptr3; *ptr3 = '\0';
856 if ( strcmp( ptr, "" ) ) { 856 if ( strcmp( ptr, "" ) ) {
857 if( ((QString)ptr).find(" ") == -1) // don't add anything that has blanks 857 if( ((QString)ptr).find(" ") == -1) // don't add anything that has blanks
858 info += ( i != 0 ? ", " : "" ) + label[i] + ": " + ptr; 858 info += ( i != 0 ? ", " : "" ) + label[i] + ": " + ptr;
859 } 859 }
860// odebug << info.latin1() << oendl; 860// odebug << info.latin1() << oendl;
861 *ptr3 = push2; 861 *ptr3 = push2;
862 *ptr2 = push; 862 *ptr2 = push;
863 } 863 }
864 if (id3v1[126] == 0 && id3v1[127] != 0) 864 if (id3v1[126] == 0 && id3v1[127] != 0)
865 info += tr( ", Track: " ) + id3v1[127]; 865 info += tr( ", Track: " ) + id3v1[127];
866 } 866 }
867 867
868 if ( ::lseek(d->input.fd, 0, SEEK_SET) == -1 ) { 868 if ( ::lseek(d->input.fd, 0, SEEK_SET) == -1 ) {
869 // odebug << "error seeking back to beginning" << oendl; 869 // odebug << "error seeking back to beginning" << oendl;
870 return; 870 return;
871 } 871 }
872} 872}
873 873