summaryrefslogtreecommitdiff
path: root/apps/pcmbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/pcmbuf.c')
-rw-r--r--apps/pcmbuf.c55
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.*/
87static size_t pcmbuffer_fillpos IDATA_ATTR; 87static size_t pcmbuffer_fillpos IDATA_ATTR;
88 88
89static struct chunkdesc *first_desc;
90
89/* Gapless playback */ 91/* Gapless playback */
90static bool track_transition IDATA_ATTR; 92static bool track_transition IDATA_ATTR;
91 93
@@ -144,6 +146,11 @@ static void write_to_crossfade(size_t length);
144static void pcmbuf_finish_crossfade_enable(void); 146static void pcmbuf_finish_crossfade_enable(void);
145#endif 147#endif
146 148
149/* Callbacks into playback.c */
150extern void audio_pcmbuf_position_callback(unsigned int time);
151extern void audio_pcmbuf_track_change(bool pcmbuf);
152extern 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
157static struct chunkdesc *first_desc;
158static 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
422static inline void init_pcmbuffers(void) 436static 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
509void pcmbuf_start_track_change(bool auto_skip) 529bool 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;