diff options
Diffstat (limited to 'apps/pcmbuf.c')
-rw-r--r-- | apps/pcmbuf.c | 55 |
1 files changed, 37 insertions, 18 deletions
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index f548b156b3..c7baad08e4 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c | |||
@@ -86,6 +86,8 @@ static size_t pcmbuffer_pos IDATA_ATTR; | |||
86 | /* Amount pcmbuffer_pos will be increased.*/ | 86 | /* Amount pcmbuffer_pos will be increased.*/ |
87 | static size_t pcmbuffer_fillpos IDATA_ATTR; | 87 | static size_t pcmbuffer_fillpos IDATA_ATTR; |
88 | 88 | ||
89 | static struct chunkdesc *first_desc; | ||
90 | |||
89 | /* Gapless playback */ | 91 | /* Gapless playback */ |
90 | static bool track_transition IDATA_ATTR; | 92 | static bool track_transition IDATA_ATTR; |
91 | 93 | ||
@@ -144,6 +146,11 @@ static void write_to_crossfade(size_t length); | |||
144 | static void pcmbuf_finish_crossfade_enable(void); | 146 | static void pcmbuf_finish_crossfade_enable(void); |
145 | #endif | 147 | #endif |
146 | 148 | ||
149 | /* Callbacks into playback.c */ | ||
150 | extern void audio_pcmbuf_position_callback(unsigned int time); | ||
151 | extern void audio_pcmbuf_track_change(bool pcmbuf); | ||
152 | extern bool audio_pcmbuf_may_play(void); | ||
153 | |||
147 | 154 | ||
148 | /**************************************/ | 155 | /**************************************/ |
149 | 156 | ||
@@ -153,9 +160,8 @@ static void pcmbuf_finish_crossfade_enable(void); | |||
153 | #ifndef SIMULATOR | 160 | #ifndef SIMULATOR |
154 | #undef DESC_DEBUG | 161 | #undef DESC_DEBUG |
155 | #endif | 162 | #endif |
163 | |||
156 | #ifdef DESC_DEBUG | 164 | #ifdef DESC_DEBUG |
157 | static struct chunkdesc *first_desc; | ||
158 | static bool show_desc_in_use = false; | ||
159 | #define DISPLAY_DESC(caller) while(!show_desc(caller)) | 165 | #define DISPLAY_DESC(caller) while(!show_desc(caller)) |
160 | #define DESC_IDX(desc) (desc ? desc - first_desc : -1) | 166 | #define DESC_IDX(desc) (desc ? desc - first_desc : -1) |
161 | #define SHOW_DESC(desc) if(DESC_IDX(desc)==-1) DEBUGF("--"); \ | 167 | #define SHOW_DESC(desc) if(DESC_IDX(desc)==-1) DEBUGF("--"); \ |
@@ -231,6 +237,7 @@ static void commit_chunk(bool flush_next_time) | |||
231 | /* Flush! Discard all data after the currently playing chunk, | 237 | /* Flush! Discard all data after the currently playing chunk, |
232 | and make the current chunk play next */ | 238 | and make the current chunk play next */ |
233 | logf("commit_chunk: flush"); | 239 | logf("commit_chunk: flush"); |
240 | pcm_play_lock(); | ||
234 | write_end_chunk->link = read_chunk->link; | 241 | write_end_chunk->link = read_chunk->link; |
235 | read_chunk->link = pcmbuf_current; | 242 | read_chunk->link = pcmbuf_current; |
236 | while (write_end_chunk->link) | 243 | while (write_end_chunk->link) |
@@ -238,6 +245,9 @@ static void commit_chunk(bool flush_next_time) | |||
238 | write_end_chunk = write_end_chunk->link; | 245 | write_end_chunk = write_end_chunk->link; |
239 | pcmbuf_unplayed_bytes -= write_end_chunk->size; | 246 | pcmbuf_unplayed_bytes -= write_end_chunk->size; |
240 | } | 247 | } |
248 | |||
249 | read_chunk->end_of_track = track_transition; | ||
250 | pcm_play_unlock(); | ||
241 | } | 251 | } |
242 | /* If there is already a read buffer setup, add to it */ | 252 | /* If there is already a read buffer setup, add to it */ |
243 | else | 253 | else |
@@ -248,7 +258,7 @@ static void commit_chunk(bool flush_next_time) | |||
248 | /* Otherwise create the buffer */ | 258 | /* Otherwise create the buffer */ |
249 | read_chunk = pcmbuf_current; | 259 | read_chunk = pcmbuf_current; |
250 | } | 260 | } |
251 | 261 | ||
252 | /* If flush_next_time is true, then the current chunk will be thrown out | 262 | /* If flush_next_time is true, then the current chunk will be thrown out |
253 | * and the next chunk to be committed will be the next to be played. | 263 | * and the next chunk to be committed will be the next to be played. |
254 | * This is used to empty the PCM buffer for a track change. */ | 264 | * This is used to empty the PCM buffer for a track change. */ |
@@ -354,7 +364,7 @@ static bool prepare_insert(size_t length) | |||
354 | #endif | 364 | #endif |
355 | { | 365 | { |
356 | logf("pcm starting"); | 366 | logf("pcm starting"); |
357 | if (!(audio_status() & AUDIO_STATUS_PAUSE)) | 367 | if (audio_pcmbuf_may_play()) |
358 | pcmbuf_play_start(); | 368 | pcmbuf_play_start(); |
359 | } | 369 | } |
360 | } | 370 | } |
@@ -373,8 +383,12 @@ void *pcmbuf_request_buffer(int *count) | |||
373 | /* crossfade has begun, put the new track samples in fadebuf */ | 383 | /* crossfade has begun, put the new track samples in fadebuf */ |
374 | if (crossfade_active) | 384 | if (crossfade_active) |
375 | { | 385 | { |
376 | *count = MIN(*count, CROSSFADE_BUFSIZE/4); | 386 | int cnt = MIN(*count, CROSSFADE_BUFSIZE/4); |
377 | return fadebuf; | 387 | if (prepare_insert(cnt << 2)) |
388 | { | ||
389 | *count = cnt; | ||
390 | return fadebuf; | ||
391 | } | ||
378 | } | 392 | } |
379 | else | 393 | else |
380 | #endif | 394 | #endif |
@@ -421,9 +435,7 @@ void pcmbuf_write_complete(int count) | |||
421 | 435 | ||
422 | static inline void init_pcmbuffers(void) | 436 | static inline void init_pcmbuffers(void) |
423 | { | 437 | { |
424 | #ifdef DESC_DEBUG | ||
425 | first_desc = write_chunk; | 438 | first_desc = write_chunk; |
426 | #endif | ||
427 | struct chunkdesc *next = write_chunk; | 439 | struct chunkdesc *next = write_chunk; |
428 | next++; | 440 | next++; |
429 | write_end_chunk = write_chunk; | 441 | write_end_chunk = write_chunk; |
@@ -494,19 +506,27 @@ void pcmbuf_monitor_track_change(bool monitor) | |||
494 | currently playing chunk. If not, cancel notification. */ | 506 | currently playing chunk. If not, cancel notification. */ |
495 | track_transition = monitor; | 507 | track_transition = monitor; |
496 | read_end_chunk->end_of_track = monitor; | 508 | read_end_chunk->end_of_track = monitor; |
509 | if (!monitor) | ||
510 | { | ||
511 | /* Clear all notifications */ | ||
512 | struct chunkdesc *desc = first_desc; | ||
513 | struct chunkdesc *end = desc + pcmbuf_descs(); | ||
514 | while (desc < end) | ||
515 | desc++->end_of_track = false; | ||
516 | } | ||
497 | } | 517 | } |
498 | else | 518 | else |
499 | { | 519 | { |
500 | /* Post now if PCM stopped and last buffer was sent. */ | 520 | /* Post now if PCM stopped and last buffer was sent. */ |
501 | track_transition = false; | 521 | track_transition = false; |
502 | if (monitor) | 522 | if (monitor) |
503 | audio_post_track_change(false); | 523 | audio_pcmbuf_track_change(false); |
504 | } | 524 | } |
505 | 525 | ||
506 | pcm_play_unlock(); | 526 | pcm_play_unlock(); |
507 | } | 527 | } |
508 | 528 | ||
509 | void pcmbuf_start_track_change(bool auto_skip) | 529 | bool pcmbuf_start_track_change(bool auto_skip) |
510 | { | 530 | { |
511 | bool crossfade = false; | 531 | bool crossfade = false; |
512 | #ifdef HAVE_CROSSFADE | 532 | #ifdef HAVE_CROSSFADE |
@@ -546,9 +566,6 @@ void pcmbuf_start_track_change(bool auto_skip) | |||
546 | 566 | ||
547 | /* Cancel any pending automatic gapless transition */ | 567 | /* Cancel any pending automatic gapless transition */ |
548 | pcmbuf_monitor_track_change(false); | 568 | pcmbuf_monitor_track_change(false); |
549 | |||
550 | /* Notify the wps that the track change starts now */ | ||
551 | audio_post_track_change(false); | ||
552 | 569 | ||
553 | /* Can't do two crossfades at once and, no fade if pcm is off now */ | 570 | /* Can't do two crossfades at once and, no fade if pcm is off now */ |
554 | if ( | 571 | if ( |
@@ -559,7 +576,8 @@ void pcmbuf_start_track_change(bool auto_skip) | |||
559 | { | 576 | { |
560 | pcmbuf_play_stop(); | 577 | pcmbuf_play_stop(); |
561 | pcm_play_unlock(); | 578 | pcm_play_unlock(); |
562 | return; | 579 | /* Notify playback that the track change starts now */ |
580 | return true; | ||
563 | } | 581 | } |
564 | 582 | ||
565 | /* Not enough data, or not crossfading, flush the old data instead */ | 583 | /* Not enough data, or not crossfading, flush the old data instead */ |
@@ -584,6 +602,9 @@ void pcmbuf_start_track_change(bool auto_skip) | |||
584 | /* Keep trigger outside the play lock or HW FIFO underruns can happen | 602 | /* Keep trigger outside the play lock or HW FIFO underruns can happen |
585 | since frequency scaling is *not* always fast */ | 603 | since frequency scaling is *not* always fast */ |
586 | trigger_cpu_boost(); | 604 | trigger_cpu_boost(); |
605 | |||
606 | /* Notify playback that the track change starts now */ | ||
607 | return true; | ||
587 | } | 608 | } |
588 | else /* automatic and not crossfading, so do gapless track change */ | 609 | else /* automatic and not crossfading, so do gapless track change */ |
589 | { | 610 | { |
@@ -593,6 +614,7 @@ void pcmbuf_start_track_change(bool auto_skip) | |||
593 | * as the last one in the track. */ | 614 | * as the last one in the track. */ |
594 | logf(" gapless track change"); | 615 | logf(" gapless track change"); |
595 | pcmbuf_monitor_track_change(true); | 616 | pcmbuf_monitor_track_change(true); |
617 | return false; | ||
596 | } | 618 | } |
597 | } | 619 | } |
598 | 620 | ||
@@ -623,7 +645,7 @@ static void pcmbuf_pcm_callback(unsigned char** start, size_t* size) | |||
623 | if (pcmbuf_current->end_of_track) | 645 | if (pcmbuf_current->end_of_track) |
624 | { | 646 | { |
625 | track_transition = false; | 647 | track_transition = false; |
626 | audio_post_track_change(true); | 648 | audio_pcmbuf_track_change(true); |
627 | } | 649 | } |
628 | 650 | ||
629 | /* Put the finished chunk back into circulation */ | 651 | /* Put the finished chunk back into circulation */ |
@@ -955,9 +977,6 @@ static void write_to_crossfade(size_t length) | |||
955 | return; | 977 | return; |
956 | } | 978 | } |
957 | 979 | ||
958 | /* Commit samples to the buffer */ | ||
959 | while (!prepare_insert(length)) | ||
960 | sleep(1); | ||
961 | while (length > 0) | 980 | while (length > 0) |
962 | { | 981 | { |
963 | COMMIT_IF_NEEDED; | 982 | COMMIT_IF_NEEDED; |