Diffstat (limited to 'core/multimedia/opieplayer/libmad/libmadplugin.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/libmad/libmadplugin.cpp | 302 |
1 files changed, 151 insertions, 151 deletions
diff --git a/core/multimedia/opieplayer/libmad/libmadplugin.cpp b/core/multimedia/opieplayer/libmad/libmadplugin.cpp index 9d04f7e..9f8ba65 100644 --- a/core/multimedia/opieplayer/libmad/libmadplugin.cpp +++ b/core/multimedia/opieplayer/libmad/libmadplugin.cpp | |||
@@ -46,9 +46,9 @@ extern "C" { | |||
46 | } | 46 | } |
47 | 47 | ||
48 | 48 | ||
49 | #define MPEG_BUFFER_SIZE 65536 | 49 | #define MPEG_BUFFER_SIZE 65536 |
50 | //#define debugMsg(a) qDebug(a) | 50 | //#define debugMsg(a) qDebug(a) |
51 | #define debugMsg(a) | 51 | #define debugMsg(a) |
52 | 52 | ||
53 | 53 | ||
54 | class Input { | 54 | class Input { |
@@ -144,20 +144,20 @@ LibMadPlugin::~LibMadPlugin() { | |||
144 | bool LibMadPlugin::isFileSupported( const QString& path ) { | 144 | bool LibMadPlugin::isFileSupported( const QString& path ) { |
145 | debugMsg( "LibMadPlugin::isFileSupported" ); | 145 | debugMsg( "LibMadPlugin::isFileSupported" ); |
146 | 146 | ||
147 | // Mpeg file extensions | 147 | // Mpeg file extensions |
148 | //"mp2","mp3","m1v","m2v","m2s","mpg","vob","mpeg","ac3" | 148 | // "mp2","mp3","m1v","m2v","m2s","mpg","vob","mpeg","ac3" |
149 | // Other media extensions | 149 | // Other media extensions |
150 | // "wav","mid","mod","s3m","ogg","avi","mov","sid" | 150 | // "wav","mid","mod","s3m","ogg","avi","mov","sid" |
151 | 151 | ||
152 | char *ext = strrchr( path.latin1(), '.' ); | 152 | char *ext = strrchr( path.latin1(), '.' ); |
153 | 153 | ||
154 | // Test file extension | 154 | // Test file extension |
155 | if ( ext ) { | 155 | if ( ext ) { |
156 | if ( strncasecmp(ext, ".mp2", 4) == 0 ) | 156 | if ( strncasecmp(ext, ".mp2", 4) == 0 ) |
157 | return TRUE; | 157 | return TRUE; |
158 | if ( strncasecmp(ext, ".mp3", 4) == 0 ) | 158 | if ( strncasecmp(ext, ".mp3", 4) == 0 ) |
159 | return TRUE; | 159 | return TRUE; |
160 | } | 160 | } |
161 | 161 | ||
162 | return FALSE; | 162 | return FALSE; |
163 | } | 163 | } |
@@ -175,35 +175,35 @@ bool LibMadPlugin::open( const QString& path ) { | |||
175 | d->input.path = path.latin1(); | 175 | d->input.path = path.latin1(); |
176 | d->input.fd = ::open( d->input.path, O_RDONLY ); | 176 | d->input.fd = ::open( d->input.path, O_RDONLY ); |
177 | if (d->input.fd == -1) { | 177 | if (d->input.fd == -1) { |
178 | qDebug("error opening %s", d->input.path ); | 178 | qDebug("error opening %s", d->input.path ); |
179 | return FALSE; | 179 | return FALSE; |
180 | } | 180 | } |
181 | 181 | ||
182 | printID3Tags(); | 182 | printID3Tags(); |
183 | 183 | ||
184 | #if defined(HAVE_MMAP) | 184 | #if defined(HAVE_MMAP) |
185 | struct stat stat; | 185 | struct stat stat; |
186 | if (fstat(d->input.fd, &stat) == -1) { | 186 | if (fstat(d->input.fd, &stat) == -1) { |
187 | qDebug("error calling fstat"); return FALSE; | 187 | qDebug("error calling fstat"); return FALSE; |
188 | } | 188 | } |
189 | if (S_ISREG(stat.st_mode) && stat.st_size > 0) { | 189 | if (S_ISREG(stat.st_mode) && stat.st_size > 0) { |
190 | d->input.length = stat.st_size; | 190 | d->input.length = stat.st_size; |
191 | d->input.fdm = map_file(d->input.fd, &d->input.length); | 191 | d->input.fdm = map_file(d->input.fd, &d->input.length); |
192 | if (d->input.fdm == 0) { | 192 | if (d->input.fdm == 0) { |
193 | qDebug("error mmapping file"); return FALSE; | 193 | qDebug("error mmapping file"); return FALSE; |
194 | } | 194 | } |
195 | d->input.data = (unsigned char *)d->input.fdm; | 195 | d->input.data = (unsigned char *)d->input.fdm; |
196 | } | 196 | } |
197 | #endif | 197 | #endif |
198 | 198 | ||
199 | if (d->input.data == 0) { | 199 | if (d->input.data == 0) { |
200 | d->input.data = (unsigned char *)malloc(MPEG_BUFFER_SIZE); | 200 | d->input.data = (unsigned char *)malloc(MPEG_BUFFER_SIZE); |
201 | if (d->input.data == 0) { | 201 | if (d->input.data == 0) { |
202 | qDebug("error allocating input buffer"); | 202 | qDebug("error allocating input buffer"); |
203 | return FALSE; | 203 | return FALSE; |
204 | } | 204 | } |
205 | d->input.length = 0; | 205 | d->input.length = 0; |
206 | } | 206 | } |
207 | 207 | ||
208 | d->input.eof = 0; | 208 | d->input.eof = 0; |
209 | 209 | ||
@@ -225,25 +225,25 @@ bool LibMadPlugin::close() { | |||
225 | mad_stream_finish(&d->stream); | 225 | mad_stream_finish(&d->stream); |
226 | 226 | ||
227 | #if defined(HAVE_MMAP) | 227 | #if defined(HAVE_MMAP) |
228 | if (d->input.fdm) { | 228 | if (d->input.fdm) { |
229 | if (unmap_file(d->input.fdm, d->input.length) == -1) { | 229 | if (unmap_file(d->input.fdm, d->input.length) == -1) { |
230 | qDebug("error munmapping file"); | 230 | qDebug("error munmapping file"); |
231 | result = FALSE; | 231 | result = FALSE; |
232 | } | 232 | } |
233 | d->input.fdm = 0; | 233 | d->input.fdm = 0; |
234 | d->input.data = 0; | 234 | d->input.data = 0; |
235 | } | 235 | } |
236 | #endif | 236 | #endif |
237 | 237 | ||
238 | if (d->input.data) { | 238 | if (d->input.data) { |
239 | free(d->input.data); | 239 | free(d->input.data); |
240 | d->input.data = 0; | 240 | d->input.data = 0; |
241 | } | 241 | } |
242 | 242 | ||
243 | if (::close(d->input.fd) == -1) { | 243 | if (::close(d->input.fd) == -1) { |
244 | qDebug("error closing file %s", d->input.path); | 244 | qDebug("error closing file %s", d->input.path); |
245 | result = FALSE; | 245 | result = FALSE; |
246 | } | 246 | } |
247 | 247 | ||
248 | d->input.fd = 0; | 248 | d->input.fd = 0; |
249 | 249 | ||
@@ -322,72 +322,72 @@ bool LibMadPlugin::read() { | |||
322 | debugMsg( "LibMadPlugin::read" ); | 322 | debugMsg( "LibMadPlugin::read" ); |
323 | int len; | 323 | int len; |
324 | 324 | ||
325 | if (d->input.eof) | 325 | if (d->input.eof) |
326 | return FALSE; | 326 | return FALSE; |
327 | 327 | ||
328 | #if defined(HAVE_MMAP) | 328 | #if defined(HAVE_MMAP) |
329 | if (d->input.fdm) { | 329 | if (d->input.fdm) { |
330 | unsigned long skip = 0; | 330 | unsigned long skip = 0; |
331 | 331 | ||
332 | if (d->stream.next_frame) { | 332 | if (d->stream.next_frame) { |
333 | struct stat stat; | 333 | struct stat stat; |
334 | 334 | ||
335 | if (fstat(d->input.fd, &stat) == -1) | 335 | if (fstat(d->input.fd, &stat) == -1) |
336 | return FALSE; | 336 | return FALSE; |
337 | 337 | ||
338 | if (stat.st_size + MAD_BUFFER_GUARD <= (signed)d->input.length) | 338 | if (stat.st_size + MAD_BUFFER_GUARD <= (signed)d->input.length) |
339 | return FALSE; | 339 | return FALSE; |
340 | 340 | ||
341 | // file size changed; update memory map | 341 | // file size changed; update memory map |
342 | skip = d->stream.next_frame - d->input.data; | 342 | skip = d->stream.next_frame - d->input.data; |
343 | 343 | ||
344 | if (unmap_file(d->input.fdm, d->input.length) == -1) { | 344 | if (unmap_file(d->input.fdm, d->input.length) == -1) { |
345 | d->input.fdm = 0; | 345 | d->input.fdm = 0; |
346 | d->input.data = 0; | 346 | d->input.data = 0; |
347 | return FALSE; | 347 | return FALSE; |
348 | } | 348 | } |
349 | 349 | ||
350 | d->input.length = stat.st_size; | 350 | d->input.length = stat.st_size; |
351 | 351 | ||
352 | d->input.fdm = map_file(d->input.fd, &d->input.length); | 352 | d->input.fdm = map_file(d->input.fd, &d->input.length); |
353 | if (d->input.fdm == 0) { | 353 | if (d->input.fdm == 0) { |
354 | d->input.data = 0; | 354 | d->input.data = 0; |
355 | return FALSE; | 355 | return FALSE; |
356 | } | 356 | } |
357 | 357 | ||
358 | d->input.data = (unsigned char *)d->input.fdm; | 358 | d->input.data = (unsigned char *)d->input.fdm; |
359 | } | 359 | } |
360 | 360 | ||
361 | mad_stream_buffer(&d->stream, d->input.data + skip, d->input.length - skip); | 361 | mad_stream_buffer(&d->stream, d->input.data + skip, d->input.length - skip); |
362 | 362 | ||
363 | } else | 363 | } else |
364 | #endif | 364 | #endif |
365 | { | 365 | { |
366 | if (d->stream.next_frame) { | 366 | if (d->stream.next_frame) { |
367 | memmove(d->input.data, d->stream.next_frame, | 367 | memmove(d->input.data, d->stream.next_frame, |
368 | d->input.length = &d->input.data[d->input.length] - d->stream.next_frame); | 368 | d->input.length = &d->input.data[d->input.length] - d->stream.next_frame); |
369 | } | 369 | } |
370 | 370 | ||
371 | do { | 371 | do { |
372 | len = ::read(d->input.fd, d->input.data + d->input.length, MPEG_BUFFER_SIZE - d->input.length); | 372 | len = ::read(d->input.fd, d->input.data + d->input.length, MPEG_BUFFER_SIZE - d->input.length); |
373 | } | 373 | } |
374 | while (len == -1 && errno == EINTR); | 374 | while (len == -1 && errno == EINTR); |
375 | 375 | ||
376 | if (len == -1) { | 376 | if (len == -1) { |
377 | qDebug("error reading audio"); | 377 | qDebug("error reading audio"); |
378 | return FALSE; | 378 | return FALSE; |
379 | } | 379 | } |
380 | else if (len == 0) { | 380 | else if (len == 0) { |
381 | d->input.eof = 1; | 381 | d->input.eof = 1; |
382 | 382 | ||
383 | assert(MPEG_BUFFER_SIZE - d->input.length >= MAD_BUFFER_GUARD); | 383 | assert(MPEG_BUFFER_SIZE - d->input.length >= MAD_BUFFER_GUARD); |
384 | 384 | ||
385 | while (len < MAD_BUFFER_GUARD) | 385 | while (len < MAD_BUFFER_GUARD) |
386 | d->input.data[d->input.length + len++] = 0; | 386 | d->input.data[d->input.length + len++] = 0; |
387 | } | 387 | } |
388 | 388 | ||
389 | mad_stream_buffer(&d->stream, d->input.data, d->input.length += len); | 389 | mad_stream_buffer(&d->stream, d->input.data, d->input.length += len); |
390 | } | 390 | } |
391 | 391 | ||
392 | return TRUE; | 392 | return TRUE; |
393 | } | 393 | } |
@@ -410,18 +410,18 @@ inline long audio_linear_dither( mad_fixed_t sample, mad_fixed_t& error ) | |||
410 | 410 | ||
411 | inline void audio_pcm( short *data, unsigned int nsamples, mad_fixed_t *left, mad_fixed_t *right ) | 411 | inline void audio_pcm( short *data, unsigned int nsamples, mad_fixed_t *left, mad_fixed_t *right ) |
412 | { | 412 | { |
413 | if ( right ) { | 413 | if ( right ) { |
414 | while (nsamples--) { | 414 | while (nsamples--) { |
415 | data[0] = audio_linear_dither( *left++, left_err ); | 415 | data[0] = audio_linear_dither( *left++, left_err ); |
416 | data[1] = audio_linear_dither( *right++, right_err ); | 416 | data[1] = audio_linear_dither( *right++, right_err ); |
417 | data += 2; | 417 | data += 2; |
418 | } | 418 | } |
419 | } else { | 419 | } else { |
420 | while (nsamples--) { | 420 | while (nsamples--) { |
421 | data[0] = data[1] = audio_linear_dither( *left++, left_err ); | 421 | data[0] = data[1] = audio_linear_dither( *left++, left_err ); |
422 | data += 2; | 422 | data += 2; |
423 | } | 423 | } |
424 | } | 424 | } |
425 | } | 425 | } |
426 | 426 | ||
427 | 427 | ||
@@ -435,38 +435,38 @@ bool LibMadPlugin::decode( short *output, long samples, long& samplesMade ) { | |||
435 | 435 | ||
436 | static int maxBuffered = 8000; // 65536; | 436 | static int maxBuffered = 8000; // 65536; |
437 | 437 | ||
438 | if ( samples > maxBuffered ) | 438 | if ( samples > maxBuffered ) |
439 | samples = maxBuffered; | 439 | samples = maxBuffered; |
440 | 440 | ||
441 | if ( d->flush ) { | 441 | if ( d->flush ) { |
442 | buffered = 0; | 442 | buffered = 0; |
443 | offset = 0; | 443 | offset = 0; |
444 | d->flush = FALSE; | 444 | d->flush = FALSE; |
445 | } | 445 | } |
446 | 446 | ||
447 | while ( buffered < maxBuffered ) { | 447 | while ( buffered < maxBuffered ) { |
448 | 448 | ||
449 | while (mad_frame_decode(&d->frame, &d->stream) == -1) { | 449 | while (mad_frame_decode(&d->frame, &d->stream) == -1) { |
450 | if (!MAD_RECOVERABLE(d->stream.error)) { | 450 | if (!MAD_RECOVERABLE(d->stream.error)) { |
451 | debugMsg( "feed me" ); | 451 | debugMsg( "feed me" ); |
452 | return FALSE; // Feed me | 452 | return FALSE; // Feed me |
453 | } | 453 | } |
454 | if ( d->stream.error == MAD_ERROR_BADCRC ) { | 454 | if ( d->stream.error == MAD_ERROR_BADCRC ) { |
455 | mad_frame_mute(&d->frame); | 455 | mad_frame_mute(&d->frame); |
456 | qDebug( "error decoding, bad crc" ); | 456 | qDebug( "error decoding, bad crc" ); |
457 | } | 457 | } |
458 | } | 458 | } |
459 | 459 | ||
460 | mad_synth_frame(&d->synth, &d->frame); | 460 | mad_synth_frame(&d->synth, &d->frame); |
461 | int decodedSamples = d->synth.pcm.length; | 461 | int decodedSamples = d->synth.pcm.length; |
462 | memcpy( &(buffer[0][offset]), d->synth.pcm.samples[0], decodedSamples * sizeof(mad_fixed_t) ); | 462 | memcpy( &(buffer[0][offset]), d->synth.pcm.samples[0], decodedSamples * sizeof(mad_fixed_t) ); |
463 | if ( d->synth.pcm.channels == 2 ) | 463 | if ( d->synth.pcm.channels == 2 ) |
464 | memcpy( &(buffer[1][offset]), d->synth.pcm.samples[1], decodedSamples * sizeof(mad_fixed_t) ); | 464 | memcpy( &(buffer[1][offset]), d->synth.pcm.samples[1], decodedSamples * sizeof(mad_fixed_t) ); |
465 | offset += decodedSamples; | 465 | offset += decodedSamples; |
466 | buffered += decodedSamples; | 466 | buffered += decodedSamples; |
467 | } | 467 | } |
468 | 468 | //qApp->processEvents(); | |
469 | audio_pcm( output, samples, buffer[0], (d->synth.pcm.channels == 2) ? buffer[1] : 0 ); | 469 | audio_pcm( output, samples, buffer[0], (d->synth.pcm.channels == 2) ? buffer[1] : 0 ); |
470 | // audio_pcm( output, samples, buffer[1], buffer[0] ); | 470 | // audio_pcm( output, samples, buffer[1], buffer[0] ); |
471 | // audio_pcm( output, samples, buffer[0], buffer[1] ); | 471 | // audio_pcm( output, samples, buffer[0], buffer[1] ); |
472 | samplesMade = samples; | 472 | samplesMade = samples; |
@@ -492,34 +492,34 @@ bool LibMadPlugin::audioReadSamples( short *output, int /*channels*/, long sampl | |||
492 | 492 | ||
493 | static bool needInput = TRUE; | 493 | static bool needInput = TRUE; |
494 | 494 | ||
495 | if ( samples == 0 ) | 495 | if ( samples == 0 ) |
496 | return FALSE; | 496 | return FALSE; |
497 | 497 | ||
498 | do { | 498 | do { |
499 | if ( needInput ) | 499 | if ( needInput ) |
500 | if ( !read() ) { | 500 | if ( !read() ) { |
501 | // if ( d->input.eof ) | 501 | // if ( d->input.eof ) |
502 | // needInput = FALSE; | 502 | // needInput = FALSE; |
503 | // else | 503 | // else |
504 | return FALSE; | 504 | return FALSE; |
505 | } | 505 | } |
506 | 506 | ||
507 | needInput = FALSE; | 507 | needInput = FALSE; |
508 | 508 | ||
509 | if ( decode( output, samples, samplesMade ) ) | 509 | if ( decode( output, samples, samplesMade ) ) |
510 | return TRUE; | 510 | return TRUE; |
511 | else | 511 | else |
512 | needInput = TRUE; | 512 | needInput = TRUE; |
513 | } | 513 | } |
514 | while ( ( samplesMade < samples ) && ( !d->input.eof ) ); | 514 | while ( ( samplesMade < samples ) && ( !d->input.eof ) ); |
515 | /* | 515 | /* |
516 | static bool firstTimeThru = TRUE; | 516 | static bool firstTimeThru = TRUE; |
517 | 517 | ||
518 | if ( firstTimeThru ) { | 518 | if ( firstTimeThru ) { |
519 | firstTimeThru = FALSE; | 519 | firstTimeThru = FALSE; |
520 | decode( output, samples, samplesMade ); | 520 | decode( output, samples, samplesMade ); |
521 | return FALSE; | 521 | return FALSE; |
522 | } else | 522 | } else |
523 | */ | 523 | */ |
524 | return FALSE; | 524 | return FALSE; |
525 | } | 525 | } |
@@ -536,43 +536,43 @@ void LibMadPlugin::printID3Tags() { | |||
536 | 536 | ||
537 | char id3v1[128 + 1]; | 537 | char id3v1[128 + 1]; |
538 | 538 | ||
539 | if ( ::lseek( d->input.fd, -128, SEEK_END ) == -1 ) { | 539 | if ( ::lseek( d->input.fd, -128, SEEK_END ) == -1 ) { |
540 | qDebug( "error seeking to id3 tags" ); | 540 | qDebug( "error seeking to id3 tags" ); |
541 | return; | 541 | return; |
542 | } | 542 | } |
543 | 543 | ||
544 | if ( ::read( d->input.fd, id3v1, 128 ) != 128 ) { | 544 | if ( ::read( d->input.fd, id3v1, 128 ) != 128 ) { |
545 | qDebug( "error reading in id3 tags" ); | 545 | qDebug( "error reading in id3 tags" ); |
546 | return; | 546 | return; |
547 | } | 547 | } |
548 | 548 | ||
549 | if ( ::strncmp( (const char *)id3v1, "TAG", 3 ) != 0 ) { | 549 | if ( ::strncmp( (const char *)id3v1, "TAG", 3 ) != 0 ) { |
550 | debugMsg( "sorry, no id3 tags" ); | 550 | debugMsg( "sorry, no id3 tags" ); |
551 | } else { | 551 | } else { |
552 | int len[5] = { 30, 30, 30, 4, 30 }; | 552 | int len[5] = { 30, 30, 30, 4, 30 }; |
553 | QString label[5] = { tr( "Title" ), tr( "Artist" ), tr( "Album" ), tr( "Year" ), tr( "Comment" ) }; | 553 | QString label[5] = { tr( "Title" ), tr( "Artist" ), tr( "Album" ), tr( "Year" ), tr( "Comment" ) }; |
554 | char *ptr = id3v1 + 3, *ptr2 = ptr + len[0]; | 554 | char *ptr = id3v1 + 3, *ptr2 = ptr + len[0]; |
555 | qDebug( "ID3 tags in file:" ); | 555 | qDebug( "ID3 tags in file:" ); |
556 | info = ""; | 556 | info = ""; |
557 | for ( int i = 0; i < 5; ptr += len[i], i++, ptr2 += len[i] ) { | 557 | for ( int i = 0; i < 5; ptr += len[i], i++, ptr2 += len[i] ) { |
558 | char push = *ptr2; | 558 | char push = *ptr2; |
559 | *ptr2 = '\0'; | 559 | *ptr2 = '\0'; |
560 | char *ptr3 = ptr2; | 560 | char *ptr3 = ptr2; |
561 | while ( ptr3-1 >= ptr && isspace(ptr3[-1]) ) ptr3--; | 561 | while ( ptr3-1 >= ptr && isspace(ptr3[-1]) ) ptr3--; |
562 | char push2 = *ptr3; *ptr3 = '\0'; | 562 | char push2 = *ptr3; *ptr3 = '\0'; |
563 | if ( strcmp( ptr, "" ) ) | 563 | if ( strcmp( ptr, "" ) ) |
564 | info += ( i != 0 ? ", " : "" ) + label[i] + ": " + ptr; | 564 | info += ( i != 0 ? ", " : "" ) + label[i] + ": " + ptr; |
565 | //qDebug( info.latin1() ); | 565 | //qDebug( info.latin1() ); |
566 | *ptr3 = push2; | 566 | *ptr3 = push2; |
567 | *ptr2 = push; | 567 | *ptr2 = push; |
568 | } | 568 | } |
569 | if (id3v1[126] == 0 && id3v1[127] != 0) | 569 | if (id3v1[126] == 0 && id3v1[127] != 0) |
570 | info += tr( ", Track: " ) + id3v1[127]; | 570 | info += tr( ", Track: " ) + id3v1[127]; |
571 | } | 571 | } |
572 | 572 | ||
573 | if ( ::lseek(d->input.fd, 0, SEEK_SET) == -1 ) { | 573 | if ( ::lseek(d->input.fd, 0, SEEK_SET) == -1 ) { |
574 | qDebug( "error seeking back to beginning" ); | 574 | qDebug( "error seeking back to beginning" ); |
575 | return; | 575 | return; |
576 | } | 576 | } |
577 | } | 577 | } |
578 | 578 | ||