diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index 2d75185f62..d1835fb197 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c @@ -83,12 +83,14 @@ struct pcmbufdesc void (*callback)(void); } pcmbuffers[NUM_PCM_BUFFERS] IDATA_ATTR; -volatile int pcmbuf_read_index; -volatile int pcmbuf_write_index; -int pcmbuf_unplayed_bytes IDATA_ATTR; -int pcmbuf_mix_used_bytes; -int pcmbuf_watermark; -void (*pcmbuf_watermark_event)(int bytes_left); +static int pcmbuf_read_index; +static int pcmbuf_write_index; +static int pcmbuf_unplayed_bytes IDATA_ATTR; +static int pcmbuf_mix_used_bytes; +static int pcmbuf_watermark; +static void pcmbuf_under_watermark(int bytes_left); +static int pcmbuf_num_used_buffers(void); +static void (*position_callback)(int size); static int last_chunksize; static long mixpos = 0; @@ -116,7 +118,7 @@ void pcmbuf_set_boost_mode(bool state) } #endif -int pcmbuf_num_used_buffers(void) +static int pcmbuf_num_used_buffers(void) { return (pcmbuf_write_index - pcmbuf_read_index) & NUM_PCM_BUFFERS_MASK; } @@ -125,6 +127,10 @@ static void pcmbuf_callback(unsigned char** start, long* size) ICODE_ATTR; static void pcmbuf_callback(unsigned char** start, long* size) { struct pcmbufdesc *desc = &pcmbuffers[pcmbuf_read_index]; + + if (position_callback) { + position_callback(last_chunksize); + } pcmbuf_unplayed_bytes -= last_chunksize; audiobuffer_free += last_chunksize; @@ -159,19 +165,20 @@ static void pcmbuf_callback(unsigned char** start, long* size) } last_chunksize = *size; + if(pcmbuf_unplayed_bytes <= pcmbuf_watermark) { - if(pcmbuf_watermark_event) - { - pcmbuf_watermark_event(pcmbuf_unplayed_bytes); - } + pcmbuf_under_watermark(pcmbuf_unplayed_bytes); } } -void pcmbuf_set_watermark(int numbytes, void (*callback)(int bytes_left)) +void pcmbuf_set_position_callback(void (*callback)(int size)) { + position_callback = callback; +} + +static void pcmbuf_set_watermark_bytes(int numbytes) { pcmbuf_watermark = numbytes; - pcmbuf_watermark_event = callback; } bool pcmbuf_add_chunk(void *addr, int size, void (*callback)(void)) @@ -192,7 +199,7 @@ bool pcmbuf_add_chunk(void *addr, int size, void (*callback)(void)) return false; } -void pcmbuf_watermark_callback(int bytes_left) +static void pcmbuf_under_watermark(int bytes_left) { /* Fill audio buffer by boosting cpu */ pcmbuf_boost(true); @@ -802,9 +809,9 @@ void pcmbuf_crossfade_enable(bool on_off) crossfade_enabled = on_off; if (crossfade_enabled) { - pcmbuf_set_watermark(pcmbuf_size - (CHUNK_SIZE*6), pcmbuf_watermark_callback); + pcmbuf_set_watermark_bytes(pcmbuf_size - (CHUNK_SIZE*6)); } else { - pcmbuf_set_watermark(PCMBUF_WATERMARK, pcmbuf_watermark_callback); + pcmbuf_set_watermark_bytes(PCMBUF_WATERMARK); } } diff --git a/apps/pcmbuf.h b/apps/pcmbuf.h index 9031db60b1..7e7ecf1d75 100644 --- a/apps/pcmbuf.h +++ b/apps/pcmbuf.h @@ -30,8 +30,6 @@ bool pcmbuf_is_crossfade_active(void); /* These functions are for playing chained buffers of PCM data */ bool pcmbuf_add_chunk(void *addr, int size, void (*callback)(void)); -int pcmbuf_num_used_buffers(void); -void pcmbuf_set_watermark(int numbytes, void (*callback)(int bytes_left)); #ifdef HAVE_ADJUSTABLE_CPU_FREQ void pcmbuf_boost(bool state); @@ -45,6 +43,7 @@ void pcmbuf_flush_audio(void); void pcmbuf_play_start(void); bool pcmbuf_crossfade_init(void); void pcmbuf_add_event(void (*event_handler)(void)); +void pcmbuf_set_position_callback(void (*callback)(int size)); unsigned int pcmbuf_get_latency(void); bool pcmbuf_insert_buffer(char *buf, long length); void pcmbuf_flush_buffer(long length); diff --git a/apps/playback.c b/apps/playback.c index 3da4b6fbdb..48b993474b 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -179,6 +179,7 @@ static struct track_info tracks[MAX_TRACK]; /* Pointer to track info structure about current song playing. */ static struct track_info *cur_ti; +static struct track_info *prev_ti; /* Have we reached end of the current playlist. */ static bool playlist_end = false; @@ -395,6 +396,17 @@ void* get_codec_memory_callback(long *size) return &audiobuf[0]; } +static void pcmbuf_position_callback(int size) ICODE_ATTR; +static void pcmbuf_position_callback(int size) { + unsigned int time = size * 1000 / 4 / 44100 + prev_ti->id3.elapsed; + if (time >= prev_ti->id3.length) { + pcmbuf_set_position_callback(NULL); + prev_ti->id3.elapsed = cur_ti->id3.length; + } else { + prev_ti->id3.elapsed = time; + } +} + void codec_set_elapsed_callback(unsigned int value) { unsigned int latency; @@ -1640,8 +1652,8 @@ static void audio_change_track(void) bool codec_request_next_track_callback(void) { - struct track_info *prev_ti = cur_ti; - + prev_ti = cur_ti; + if (current_codec == CODEC_IDX_VOICE) { voice_remaining = 0; /* Terminate the codec if there are messages waiting on the queue or @@ -1649,6 +1661,8 @@ bool codec_request_next_track_callback(void) return !ci_voice.stop_codec && queue_empty(&voice_codec_queue); } + pcmbuf_set_position_callback(pcmbuf_position_callback); + if (ci.stop_codec || !playing) return false; @@ -1878,6 +1892,7 @@ void audio_thread(void) if (track_changed_callback) track_changed_callback(&cur_ti->id3); playlist_update_resume_info(audio_current_track()); + pcmbuf_set_position_callback(NULL); break ; case AUDIO_CODEC_DONE: