summaryrefslogtreecommitdiff
path: root/apps/playback.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/playback.c')
-rw-r--r--apps/playback.c215
1 files changed, 126 insertions, 89 deletions
diff --git a/apps/playback.c b/apps/playback.c
index a37e0ad679..d4f3626f99 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -74,29 +74,18 @@
74#include "misc.h" 74#include "misc.h"
75#include "sound.h" 75#include "sound.h"
76#include "metadata.h" 76#include "metadata.h"
77#include "splash.h"
77#include "talk.h" 78#include "talk.h"
78#ifdef CONFIG_TUNER 79
79#include "radio.h" 80#ifdef HAVE_RECORDING
81#include "recording.h"
80#endif 82#endif
81#include "splash.h"
82 83
83static volatile bool audio_codec_loaded; 84static volatile bool audio_codec_loaded;
84static volatile bool voice_codec_loaded; 85static volatile bool voice_codec_loaded;
85static volatile bool playing; 86static volatile bool playing;
86static volatile bool paused; 87static volatile bool paused;
87 88
88#define CODEC_VORBIS "/.rockbox/codecs/vorbis.codec"
89#define CODEC_MPA_L3 "/.rockbox/codecs/mpa.codec"
90#define CODEC_FLAC "/.rockbox/codecs/flac.codec"
91#define CODEC_WAV "/.rockbox/codecs/wav.codec"
92#define CODEC_A52 "/.rockbox/codecs/a52.codec"
93#define CODEC_MPC "/.rockbox/codecs/mpc.codec"
94#define CODEC_WAVPACK "/.rockbox/codecs/wavpack.codec"
95#define CODEC_ALAC "/.rockbox/codecs/alac.codec"
96#define CODEC_AAC "/.rockbox/codecs/aac.codec"
97#define CODEC_SHN "/.rockbox/codecs/shorten.codec"
98#define CODEC_AIFF "/.rockbox/codecs/aiff.codec"
99#define CODEC_SID "/.rockbox/codecs/sid.codec"
100 89
101/* default point to start buffer refill */ 90/* default point to start buffer refill */
102#define AUDIO_DEFAULT_WATERMARK (1024*512) 91#define AUDIO_DEFAULT_WATERMARK (1024*512)
@@ -133,6 +122,11 @@ enum {
133 122
134 Q_CODEC_LOAD, 123 Q_CODEC_LOAD,
135 Q_CODEC_LOAD_DISK, 124 Q_CODEC_LOAD_DISK,
125
126#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
127 Q_ENCODER_LOAD_DISK,
128 Q_ENCODER_RECORD,
129#endif
136}; 130};
137 131
138/* As defined in plugins/lib/xxx2wav.h */ 132/* As defined in plugins/lib/xxx2wav.h */
@@ -382,7 +376,7 @@ static bool voice_pcmbuf_insert_split_callback(
382 } 376 }
383 377
384 return true; 378 return true;
385} 379} /* voice_pcmbuf_insert_split_callback */
386 380
387static bool codec_pcmbuf_insert_split_callback( 381static bool codec_pcmbuf_insert_split_callback(
388 const void *ch1, const void *ch2, size_t length) 382 const void *ch1, const void *ch2, size_t length)
@@ -444,7 +438,7 @@ static bool codec_pcmbuf_insert_split_callback(
444 } 438 }
445 439
446 return true; 440 return true;
447} 441} /* codec_pcmbuf_insert_split_callback */
448 442
449static bool voice_pcmbuf_insert_callback(const char *buf, size_t length) 443static bool voice_pcmbuf_insert_callback(const char *buf, size_t length)
450{ 444{
@@ -649,7 +643,7 @@ static size_t codec_filebuf_callback(void *ptr, size_t size)
649 643
650 /* Return the actual amount of data copied to the buffer */ 644 /* Return the actual amount of data copied to the buffer */
651 return copy_n; 645 return copy_n;
652} 646} /* codec_filebuf_callback */
653 647
654static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize) 648static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
655{ 649{
@@ -664,7 +658,9 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
664 while (1) 658 while (1)
665 { 659 {
666 if (voice_is_playing) 660 if (voice_is_playing)
661 {
667 queue_wait_w_tmo(&voice_codec_queue, &ev, 0); 662 queue_wait_w_tmo(&voice_codec_queue, &ev, 0);
663 }
668 else if (playing) 664 else if (playing)
669 { 665 {
670 queue_wait_w_tmo(&voice_codec_queue, &ev, 0); 666 queue_wait_w_tmo(&voice_codec_queue, &ev, 0);
@@ -679,7 +675,11 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
679 if (playing) 675 if (playing)
680 swap_codec(); 676 swap_codec();
681 break; 677 break;
682 678#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
679 case Q_ENCODER_RECORD:
680 swap_codec();
681 break;
682#endif
683 case Q_VOICE_STOP: 683 case Q_VOICE_STOP:
684 if (voice_is_playing) 684 if (voice_is_playing)
685 { 685 {
@@ -743,7 +743,7 @@ voice_play_clip:
743 return NULL; 743 return NULL;
744 744
745 return voicebuf; 745 return voicebuf;
746} 746} /* voice_request_buffer_callback */
747 747
748static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize) 748static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
749{ 749{
@@ -794,7 +794,7 @@ static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
794 *realsize = copy_n; 794 *realsize = copy_n;
795 795
796 return (char *)&filebuf[buf_ridx]; 796 return (char *)&filebuf[buf_ridx];
797} 797} /* codec_request_buffer_callback */
798 798
799static int get_codec_base_type(int type) 799static int get_codec_base_type(int type)
800{ 800{
@@ -1531,52 +1531,24 @@ static void codec_discard_codec_callback(void)
1531#endif 1531#endif
1532} 1532}
1533 1533
1534static const char *get_codec_path(int codectype) 1534static const char * get_codec_filename(int enc_spec)
1535{ 1535{
1536 switch (codectype) { 1536 const char *fname;
1537 case AFMT_OGG_VORBIS: 1537 int type = enc_spec & CODEC_TYPE_MASK;
1538 logf("Codec: Vorbis"); 1538 int afmt = enc_spec & CODEC_AFMT_MASK;
1539 return CODEC_VORBIS; 1539
1540 case AFMT_MPA_L1: 1540 if ((unsigned)afmt >= AFMT_NUM_CODECS)
1541 case AFMT_MPA_L2: 1541 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
1542 case AFMT_MPA_L3: 1542
1543 logf("Codec: MPA L1/L2/L3"); 1543 fname = (type == CODEC_TYPE_DECODER) ?
1544 return CODEC_MPA_L3; 1544 audio_formats[afmt].codec_fn : audio_formats[afmt].codec_enc_fn;
1545 case AFMT_PCM_WAV: 1545
1546 logf("Codec: PCM WAV"); 1546 logf("%s: %d - %s",
1547 return CODEC_WAV; 1547 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
1548 case AFMT_FLAC: 1548 afmt, fname ? fname : "<unknown>");
1549 logf("Codec: FLAC"); 1549
1550 return CODEC_FLAC; 1550 return fname;
1551 case AFMT_A52: 1551} /* get_codec_filename */
1552 logf("Codec: A52");
1553 return CODEC_A52;
1554 case AFMT_MPC:
1555 logf("Codec: Musepack");
1556 return CODEC_MPC;
1557 case AFMT_WAVPACK:
1558 logf("Codec: WAVPACK");
1559 return CODEC_WAVPACK;
1560 case AFMT_ALAC:
1561 logf("Codec: ALAC");
1562 return CODEC_ALAC;
1563 case AFMT_AAC:
1564 logf("Codec: AAC");
1565 return CODEC_AAC;
1566 case AFMT_SHN:
1567 logf("Codec: SHN");
1568 return CODEC_SHN;
1569 case AFMT_AIFF:
1570 logf("Codec: PCM AIFF");
1571 return CODEC_AIFF;
1572 case AFMT_SID:
1573 logf("Codec: SID");
1574 return CODEC_SID;
1575 default:
1576 logf("Codec: Unsupported");
1577 return NULL;
1578 }
1579}
1580 1552
1581static bool loadcodec(bool start_play) 1553static bool loadcodec(bool start_play)
1582{ 1554{
@@ -1585,9 +1557,10 @@ static bool loadcodec(bool start_play)
1585 int rc; 1557 int rc;
1586 size_t copy_n; 1558 size_t copy_n;
1587 int prev_track; 1559 int prev_track;
1560 char codec_path[MAX_PATH]; /* Full path to codec */
1588 1561
1589 const char *codec_path = get_codec_path(tracks[track_widx].id3.codectype); 1562 const char * codec_fn = get_codec_filename(tracks[track_widx].id3.codectype);
1590 if (codec_path == NULL) 1563 if (codec_fn == NULL)
1591 return false; 1564 return false;
1592 1565
1593 tracks[track_widx].has_codec = false; 1566 tracks[track_widx].has_codec = false;
@@ -1603,7 +1576,7 @@ static bool loadcodec(bool start_play)
1603 ci.taginfo_ready = &cur_ti->taginfo_ready; 1576 ci.taginfo_ready = &cur_ti->taginfo_ready;
1604 ci.curpos = 0; 1577 ci.curpos = 0;
1605 playing = true; 1578 playing = true;
1606 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_path); 1579 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_fn);
1607 return true; 1580 return true;
1608 } 1581 }
1609 else 1582 else
@@ -1625,6 +1598,8 @@ static bool loadcodec(bool start_play)
1625 } 1598 }
1626 } 1599 }
1627 1600
1601 codec_get_full_path(codec_path, codec_fn);
1602
1628 fd = open(codec_path, O_RDONLY); 1603 fd = open(codec_path, O_RDONLY);
1629 if (fd < 0) 1604 if (fd < 0)
1630 { 1605 {
@@ -1973,11 +1948,8 @@ static void audio_stop_playback(void)
1973 (playlist_end && ci.stop_codec)?NULL:audio_current_track()); 1948 (playlist_end && ci.stop_codec)?NULL:audio_current_track());
1974 } 1949 }
1975 1950
1976 if (voice_is_playing) 1951 while (voice_is_playing && !queue_empty(&voice_codec_queue))
1977 { 1952 yield();
1978 while (voice_is_playing && !queue_empty(&voice_codec_queue))
1979 yield();
1980 }
1981 1953
1982 filebufused = 0; 1954 filebufused = 0;
1983 playing = false; 1955 playing = false;
@@ -1998,10 +1970,8 @@ static void audio_stop_playback(void)
1998 1970
1999static void audio_play_start(size_t offset) 1971static void audio_play_start(size_t offset)
2000{ 1972{
2001#ifdef CONFIG_TUNER 1973#if defined(HAVE_RECORDING) || defined(CONFIG_TUNER)
2002 /* check if radio is playing */ 1974 rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
2003 if (get_radio_status() != FMRADIO_OFF)
2004 radio_stop();
2005#endif 1975#endif
2006 1976
2007 /* Wait for any previously playing audio to flush - TODO: Not necessary? */ 1977 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
@@ -2483,6 +2453,20 @@ static void codec_thread(void)
2483 mutex_unlock(&mutex_codecthread); 2453 mutex_unlock(&mutex_codecthread);
2484 break ; 2454 break ;
2485 2455
2456#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
2457 case Q_ENCODER_LOAD_DISK:
2458 logf("Encoder load disk");
2459 audio_codec_loaded = false;
2460 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2461 queue_post(&voice_codec_queue, Q_ENCODER_RECORD, NULL);
2462 mutex_lock(&mutex_codecthread);
2463 current_codec = CODEC_IDX_AUDIO;
2464 ci.stop_codec = false;
2465 status = codec_load_file((const char *)ev.data, &ci);
2466 mutex_unlock(&mutex_codecthread);
2467 break;
2468#endif
2469
2486#ifndef SIMULATOR 2470#ifndef SIMULATOR
2487 case SYS_USB_CONNECTED: 2471 case SYS_USB_CONNECTED:
2488 queue_clear(&codec_queue); 2472 queue_clear(&codec_queue);
@@ -2511,8 +2495,6 @@ static void codec_thread(void)
2511 case Q_CODEC_LOAD: 2495 case Q_CODEC_LOAD:
2512 if (playing) 2496 if (playing)
2513 { 2497 {
2514 const char *codec_path;
2515
2516 if (ci.new_track || status != CODEC_OK) 2498 if (ci.new_track || status != CODEC_OK)
2517 { 2499 {
2518 if (!ci.new_track) 2500 if (!ci.new_track)
@@ -2523,7 +2505,8 @@ static void codec_thread(void)
2523 2505
2524 if (!load_next_track()) 2506 if (!load_next_track())
2525 { 2507 {
2526 queue_post(&codec_queue, Q_AUDIO_STOP, 0); 2508 // queue_post(&codec_queue, Q_AUDIO_STOP, 0);
2509 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2527 break; 2510 break;
2528 } 2511 }
2529 } 2512 }
@@ -2545,12 +2528,12 @@ static void codec_thread(void)
2545 queue_post(&codec_queue, Q_CODEC_LOAD, 0); 2528 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
2546 else 2529 else
2547 { 2530 {
2548 codec_path = get_codec_path(cur_ti->id3.codectype); 2531 const char *codec_fn = get_codec_filename(cur_ti->id3.codectype);
2549 queue_post(&codec_queue, 2532 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
2550 Q_CODEC_LOAD_DISK, (void *)codec_path); 2533 (void *)codec_fn);
2551 } 2534 }
2552 } 2535 }
2553 } 2536 } /* end switch */
2554 } 2537 }
2555} 2538}
2556 2539
@@ -2596,6 +2579,37 @@ static void reset_buffer(void)
2596 filebuflen &= ~3; 2579 filebuflen &= ~3;
2597} 2580}
2598 2581
2582void audio_load_encoder(int enc_id)
2583{
2584#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
2585 const char *enc_fn = get_codec_filename(enc_id | CODEC_TYPE_ENCODER);
2586 if (!enc_fn)
2587 return;
2588
2589 audio_remove_encoder();
2590
2591 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (void *)enc_fn);
2592
2593 while (!ci.enc_codec_loaded)
2594 yield();
2595#endif
2596 return;
2597 (void)enc_id;
2598} /* audio_load_encoder */
2599
2600void audio_remove_encoder(void)
2601{
2602#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
2603 /* force encoder codec unload (if previously loaded) */
2604 if (!ci.enc_codec_loaded)
2605 return;
2606
2607 ci.stop_codec = true;
2608 while (ci.enc_codec_loaded)
2609 yield();
2610#endif
2611} /* audio_remove_encoder */
2612
2599static void voice_codec_thread(void) 2613static void voice_codec_thread(void)
2600{ 2614{
2601 while (1) 2615 while (1)
@@ -2608,13 +2622,13 @@ static void voice_codec_thread(void)
2608 voice_remaining = 0; 2622 voice_remaining = 0;
2609 voice_getmore = NULL; 2623 voice_getmore = NULL;
2610 2624
2611 codec_load_file(CODEC_MPA_L3, &ci_voice); 2625 codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
2612 2626
2613 logf("Voice codec finished"); 2627 logf("Voice codec finished");
2614 mutex_unlock(&mutex_codecthread);
2615 voice_codec_loaded = false; 2628 voice_codec_loaded = false;
2629 mutex_unlock(&mutex_codecthread);
2616 } 2630 }
2617} 2631} /* voice_codec_thread */
2618 2632
2619void voice_init(void) 2633void voice_init(void)
2620{ 2634{
@@ -2642,7 +2656,20 @@ void voice_init(void)
2642 2656
2643 while (!voice_codec_loaded) 2657 while (!voice_codec_loaded)
2644 yield(); 2658 yield();
2645} 2659} /* voice_init */
2660
2661void voice_stop(void)
2662{
2663 /* Messages should not be posted to voice codec queue unless it is the
2664 current codec or deadlocks happen. This will be addressed globally soon.
2665 -- jhMikeS */
2666 if (current_codec != CODEC_IDX_VOICE)
2667 return;
2668
2669 mp3_play_stop();
2670 while (voice_is_playing && !queue_empty(&voice_codec_queue))
2671 yield();
2672} /* voice_stop */
2646 2673
2647struct mp3entry* audio_current_track(void) 2674struct mp3entry* audio_current_track(void)
2648{ 2675{
@@ -2803,9 +2830,19 @@ int audio_status(void)
2803 if (paused) 2830 if (paused)
2804 ret |= AUDIO_STATUS_PAUSE; 2831 ret |= AUDIO_STATUS_PAUSE;
2805 2832
2833#ifdef HAVE_RECORDING
2834 /* Do this here for constitency with mpeg.c version */
2835 ret |= pcm_rec_status();
2836#endif
2837
2806 return ret; 2838 return ret;
2807} 2839}
2808 2840
2841bool audio_query_poweroff(void)
2842{
2843 return !(playing && paused);
2844}
2845
2809int audio_get_file_pos(void) 2846int audio_get_file_pos(void)
2810{ 2847{
2811 return 0; 2848 return 0;