From 42b02082538f2aea2ba481b16ec890744e7c85a0 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Sat, 16 Dec 2006 20:19:58 +0000 Subject: [PATCH] Commit the kinds of changes that queue_send is mean for. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11778 a1c6a512-1295-4272-9138-f99709370657 --- apps/playback.c | 131 ++++++++++++++++++++++-------------------- firmware/pcm_record.c | 91 +++++++++++------------------ 2 files changed, 101 insertions(+), 121 deletions(-) diff --git a/apps/playback.c b/apps/playback.c index 63382c7a42..23d68f4be9 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -141,7 +141,9 @@ enum { Q_AUDIO_LOAD_ENCODER, #endif +#if 0 Q_CODEC_REQUEST_PENDING, +#endif Q_CODEC_REQUEST_COMPLETE, Q_CODEC_REQUEST_FAILED, @@ -195,7 +197,6 @@ static bool audio_is_initialized = false; /* TBD: Split out "audio" and "playback" (ie. calling) threads */ /* Main state control */ -static struct event_queue codec_callback_queue; /* Queue for codec callback responses */ static volatile bool audio_codec_loaded; /* Is codec loaded? (C/A-) */ static volatile bool playing; /* Is audio playing? (A) */ static volatile bool paused; /* Is audio paused? (A/C-) */ @@ -251,13 +252,17 @@ static size_t conf_filechunk; /* Largest chunk the codec accep static size_t conf_preseek; /* Codec pre-seek margin (A/C) FIXME */ static size_t buffer_margin; /* Buffer margin aka anti-skip buffer (A/C-) */ static bool v1first = false; /* ID3 data control, true if V1 then V2 (A) */ +#if MEM > 8 +static size_t high_watermark; /* High watermark for rebuffer (A/V/other) */ +#endif /* Multiple threads */ static const char *get_codec_filename(int enc_spec); /* Returns codec filename (A-/C-/V-) */ static void set_filebuf_watermark(int seconds); /* Set low watermark (A/C) FIXME */ /* Audio thread */ -static struct event_queue audio_queue; +static struct event_queue audio_queue; +static struct queue_sender_list audio_queue_sender_list; static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)]; static const char audio_thread_name[] = "audio"; @@ -832,9 +837,8 @@ void audio_preinit(void) #endif queue_init(&audio_queue, true); + queue_enable_queue_send(&audio_queue, &audio_queue_sender_list); queue_init(&codec_queue, true); - /* create a private queue */ - queue_init(&codec_callback_queue, false); create_thread(audio_thread, audio_stack, sizeof(audio_stack), audio_thread_name IF_PRIO(, PRIORITY_BUFFERING)); @@ -1569,26 +1573,25 @@ static void codec_advance_buffer_callback(size_t amount) if (amount > CUR_TI->available) { - struct event ev; + int result; + LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK"); - LOGFQUEUE("codec > audio Q_AUDIO_REBUFFER_SEEK"); - queue_post(&audio_queue, - Q_AUDIO_REBUFFER_SEEK, (void *)(ci.curpos + amount)); - - queue_wait(&codec_callback_queue, &ev); - switch (ev.id) + result = (int)queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK, + (void *)(ci.curpos + amount)); + + switch (result) { case Q_CODEC_REQUEST_FAILED: - LOGFQUEUE("codec < Q_CODEC_REQUEST_FAILED"); + LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED"); ci.stop_codec = true; return; case Q_CODEC_REQUEST_COMPLETE: - LOGFQUEUE("codec < Q_CODEC_REQUEST_COMPLETE"); + LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE"); return; default: - LOGFQUEUE("codec < default"); + LOGFQUEUE("codec |< default"); ci.stop_codec = true; return; } @@ -1713,25 +1716,25 @@ static bool codec_seek_buffer_callback(size_t newpos) /* We need to reload the song. */ if (newpos < CUR_TI->start_pos) { - struct event ev; + int result; - LOGFQUEUE("codec > audio Q_AUDIO_REBUFFER_SEEK"); - queue_post(&audio_queue, Q_AUDIO_REBUFFER_SEEK, (void *)newpos); + LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK"); + result = (int)queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK, + (void *)newpos); - queue_wait(&codec_callback_queue, &ev); - switch (ev.id) + switch (result) { case Q_CODEC_REQUEST_COMPLETE: - LOGFQUEUE("codec < Q_CODEC_REQUEST_COMPLETE"); + LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE"); return true; case Q_CODEC_REQUEST_FAILED: - LOGFQUEUE("codec < Q_CODEC_REQUEST_FAILED"); + LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED"); ci.stop_codec = true; return false; default: - LOGFQUEUE("codec < default"); + LOGFQUEUE("codec |< default"); return false; } } @@ -1831,7 +1834,7 @@ static void codec_track_skip_done(bool was_manual) static bool codec_load_next_track(void) { - struct event ev; + int result; prev_track_elapsed = CUR_TI->id3.elapsed; @@ -1851,8 +1854,10 @@ static bool codec_load_next_track(void) } trigger_cpu_boost(); - LOGFQUEUE("codec > audio Q_AUDIO_CHECK_NEW_TRACK"); - queue_post(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0); + LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK"); + result = (int)queue_send(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, NULL); + +#if 0 /* Q_CODEC_REQUEST_PENDING never posted anyway */ while (1) { queue_wait(&codec_callback_queue, &ev); @@ -1864,22 +1869,23 @@ static bool codec_load_next_track(void) else break; } +#endif - switch (ev.id) + switch (result) { case Q_CODEC_REQUEST_COMPLETE: - LOGFQUEUE("codec < Q_CODEC_REQUEST_COMPLETE"); + LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE"); codec_track_skip_done(!automatic_skip); return true; case Q_CODEC_REQUEST_FAILED: - LOGFQUEUE("codec < Q_CODEC_REQUEST_FAILED"); + LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED"); ci.new_track = 0; ci.stop_codec = true; return false; default: - LOGFQUEUE("codec < default"); + LOGFQUEUE("codec |< default"); ci.stop_codec = true; return false; } @@ -2945,7 +2951,8 @@ static void audio_fill_file_buffer( static void audio_rebuffer(void) { logf("Forcing rebuffer"); - + +#if 0 /* Notify the codec that this will take a while */ /* Currently this can cause some problems (logf in reverse order): * Codec load error:-1 @@ -2962,8 +2969,9 @@ static void audio_rebuffer(void) * Clearing tracks:5/5, 1 * Re-buffering song w/seek */ - //if (!filling) - // queue_post(&codec_callback_queue, Q_CODEC_REQUEST_PENDING, 0); + if (!filling) + queue_post(&codec_callback_queue, Q_CODEC_REQUEST_PENDING, 0); +#endif /* Stop in progress fill, and clear open file descriptor */ if (current_fd >= 0) @@ -2991,7 +2999,7 @@ static void audio_rebuffer(void) audio_fill_file_buffer(false, true, 0); } -static void audio_check_new_track(void) +static int audio_check_new_track(void) { int track_count = audio_track_count(); int old_track_ridx = track_ridx; @@ -3009,9 +3017,8 @@ static void audio_check_new_track(void) } else { - LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED"); - queue_post(&codec_callback_queue, Q_CODEC_REQUEST_FAILED, 0); - return; + LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED"); + return Q_CODEC_REQUEST_FAILED; } } @@ -3023,17 +3030,15 @@ static void audio_check_new_track(void) { if (ci.new_track >= 0) { - LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED"); - queue_post(&codec_callback_queue, Q_CODEC_REQUEST_FAILED, 0); - return; + LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED"); + return Q_CODEC_REQUEST_FAILED; } /* Find the beginning backward if the user over-skips it */ while (!playlist_check(++ci.new_track)) if (ci.new_track >= 0) { - LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED"); - queue_post(&codec_callback_queue, Q_CODEC_REQUEST_FAILED, 0); - return; + LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED"); + return Q_CODEC_REQUEST_FAILED; } } /* Update the playlist */ @@ -3041,9 +3046,8 @@ static void audio_check_new_track(void) if (playlist_next(ci.new_track) < 0) { - LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED"); - queue_post(&codec_callback_queue, Q_CODEC_REQUEST_FAILED, 0); - return; + LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED"); + return Q_CODEC_REQUEST_FAILED; } if (new_playlist) @@ -3127,11 +3131,11 @@ static void audio_check_new_track(void) skip_done: audio_update_trackinfo(); - LOGFQUEUE("audio > codec Q_CODEC_REQUEST_COMPLETE"); - queue_post(&codec_callback_queue, Q_CODEC_REQUEST_COMPLETE, 0); + LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE"); + return Q_CODEC_REQUEST_COMPLETE; } -static void audio_rebuffer_and_seek(size_t newpos) +static int audio_rebuffer_and_seek(size_t newpos) { size_t real_preseek; int fd; @@ -3142,9 +3146,8 @@ static void audio_rebuffer_and_seek(size_t newpos) fd = open(trackname, O_RDONLY); if (fd < 0) { - LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED"); - queue_post(&codec_callback_queue, Q_CODEC_REQUEST_FAILED, 0); - return; + LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED"); + return Q_CODEC_REQUEST_FAILED; } if (current_fd >= 0) @@ -3188,8 +3191,8 @@ static void audio_rebuffer_and_seek(size_t newpos) buf_ridx = RINGBUF_ADD(buf_ridx, real_preseek); - LOGFQUEUE("audio > codec Q_CODEC_REQUEST_COMPLETE"); - queue_post(&codec_callback_queue, Q_CODEC_REQUEST_COMPLETE, 0); + LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE"); + return Q_CODEC_REQUEST_COMPLETE; } void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3, @@ -3424,6 +3427,10 @@ static void audio_reset_buffer(size_t pcmbufsize) filebuflen -= offset; filebuflen &= ~3; +#if MEM > 8 + high_watermark = (3*filebuflen)/4; +#endif + /* Clear any references to the file buffer */ buffer_state = BUFFER_STATE_NORMAL; } @@ -3539,17 +3546,13 @@ bool ata_fillbuffer_callback(void) static void audio_thread(void) { struct event ev; -#if MEM > 8 - size_t high_watermark; -#endif /* At first initialize audio system in background. */ audio_playback_init(); -#if MEM > 8 - high_watermark = (3*filebuflen)/4; -#endif while (1) { + void *result = NULL; + if (filling) { queue_wait_w_tmo(&audio_queue, &ev, 0); @@ -3622,12 +3625,12 @@ static void audio_thread(void) case Q_AUDIO_REBUFFER_SEEK: LOGFQUEUE("audio < Q_AUDIO_REBUFFER_SEEK"); - audio_rebuffer_and_seek((size_t)ev.data); + result = (void *)audio_rebuffer_and_seek((size_t)ev.data); break; case Q_AUDIO_CHECK_NEW_TRACK: LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK"); - audio_check_new_track(); + result = (void *)audio_check_new_track(); break; case Q_AUDIO_DIR_SKIP: @@ -3677,7 +3680,9 @@ static void audio_thread(void) default: LOGFQUEUE("audio < default"); - } - } + } /* end switch */ + + queue_reply(&audio_queue, result); + } /* end while */ } diff --git a/firmware/pcm_record.c b/firmware/pcm_record.c index 34b104d29a..4ec5fc3256 100644 --- a/firmware/pcm_record.c +++ b/firmware/pcm_record.c @@ -222,50 +222,30 @@ static int enc_wr_index_last; /* previsou encoder read position */ /***************************************************************************/ -static struct event_queue pcmrec_queue; +static struct event_queue pcmrec_queue; +static struct queue_sender_list pcmrec_queue_send; static long pcmrec_stack[3*DEFAULT_STACK_SIZE/sizeof(long)]; static const char pcmrec_thread_name[] = "pcmrec"; static void pcmrec_thread(void); -/* Event values which are also single-bit flags */ -#define PCMREC_INIT 0x00000001 /* enable recording */ -#define PCMREC_CLOSE 0x00000002 /* close recording */ -#define PCMREC_OPTIONS 0x00000004 /* set recording options */ -#define PCMREC_START 0x00000008 /* start recording */ -#define PCMREC_STOP 0x00000010 /* stop the current recording */ -#define PCMREC_PAUSE 0x00000020 /* pause the current recording */ -#define PCMREC_RESUME 0x00000040 /* resume the current recording */ -#define PCMREC_NEW_FILE 0x00000080 /* start new file */ -#define PCMREC_FLUSH_NUM 0x00000100 /* flush a number of files out */ -#define PCMREC_FINISH_STOP 0x00000200 /* finish the stopping recording */ - -/* mask for signaling events */ -static volatile long pcm_thread_event_mask = PCMREC_CLOSE; - -static void pcm_thread_sync_post(long event, void *data) +enum { - pcm_thread_event_mask &= ~event; - queue_post(&pcmrec_queue, event, data); - while(!(event & pcm_thread_event_mask)) - yield(); -} /* pcm_thread_sync_post */ + PCMREC_NULL = 0, + PCMREC_INIT, /* enable recording */ + PCMREC_CLOSE, /* close recording */ + PCMREC_OPTIONS, /* set recording options */ + PCMREC_START, /* start recording */ + PCMREC_STOP, /* stop the current recording */ + PCMREC_FINISH_STOP, /* finish the stopping recording */ + PCMREC_PAUSE, /* pause the current recording */ + PCMREC_RESUME, /* resume the current recording */ + PCMREC_NEW_FILE, /* start new file */ +#if 0 + PCMREC_FLUSH_NUM, /* flush a number of files out */ +#endif +}; -static inline void pcm_thread_signal_event(long event) -{ - pcm_thread_event_mask |= event; -} /* pcm_thread_signal_event */ - -static inline void pcm_thread_unsignal_event(long event) -{ - pcm_thread_event_mask &= ~event; -} /* pcm_thread_unsignal_event */ - -static inline bool pcm_thread_event_state(long signaled, long unsignaled) -{ - return ((signaled | unsignaled) & pcm_thread_event_mask) == signaled; -} /* pcm_thread_event_state */ - /*******************************************************************/ /* Functions that are not executing in the pcmrec_thread first */ /*******************************************************************/ @@ -401,6 +381,7 @@ unsigned long pcm_rec_sample_rate(void) void pcm_rec_init(void) { queue_init(&pcmrec_queue, true); + queue_enable_queue_send(&pcmrec_queue, &pcmrec_queue_send); create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack), pcmrec_thread_name, PRIORITY_RECORDING); } /* pcm_rec_init */ @@ -417,7 +398,7 @@ void pcm_rec_init(void) void audio_init_recording(unsigned int buffer_offset) { logf("audio_init_recording"); - pcm_thread_sync_post(PCMREC_INIT, NULL); + queue_send(&pcmrec_queue, PCMREC_INIT, NULL); logf("audio_init_recording done"); (void)buffer_offset; } /* audio_init_recording */ @@ -428,7 +409,7 @@ void audio_init_recording(unsigned int buffer_offset) void audio_close_recording(void) { logf("audio_close_recording"); - pcm_thread_sync_post(PCMREC_CLOSE, NULL); + queue_send(&pcmrec_queue, PCMREC_CLOSE, NULL); logf("audio_close_recording done"); } /* audio_close_recording */ @@ -438,7 +419,7 @@ void audio_close_recording(void) void audio_set_recording_options(struct audio_recording_options *options) { logf("audio_set_recording_options"); - pcm_thread_sync_post(PCMREC_OPTIONS, (void *)options); + queue_send(&pcmrec_queue, PCMREC_OPTIONS, (void *)options); logf("audio_set_recording_options done"); } /* audio_set_recording_options */ @@ -448,7 +429,7 @@ void audio_set_recording_options(struct audio_recording_options *options) void audio_record(const char *filename) { logf("audio_record: %s", filename); - pcm_thread_sync_post(PCMREC_START, (void *)filename); + queue_send(&pcmrec_queue, PCMREC_START, (void *)filename); logf("audio_record_done"); } /* audio_record */ @@ -458,7 +439,7 @@ void audio_record(const char *filename) void audio_new_file(const char *filename) { logf("audio_new_file: %s", filename); - pcm_thread_sync_post(PCMREC_NEW_FILE, (void *)filename); + queue_send(&pcmrec_queue, PCMREC_NEW_FILE, (void *)filename); logf("audio_new_file done"); } /* audio_new_file */ @@ -468,7 +449,7 @@ void audio_new_file(const char *filename) void audio_stop_recording(void) { logf("audio_stop_recording"); - pcm_thread_sync_post(PCMREC_STOP, NULL); + queue_send(&pcmrec_queue, PCMREC_STOP, NULL); logf("audio_stop_recording done"); } /* audio_stop_recording */ @@ -478,7 +459,7 @@ void audio_stop_recording(void) void audio_pause_recording(void) { logf("audio_pause_recording"); - pcm_thread_sync_post(PCMREC_PAUSE, NULL); + queue_send(&pcmrec_queue, PCMREC_PAUSE, NULL); logf("audio_pause_recording done"); } /* audio_pause_recording */ @@ -488,7 +469,7 @@ void audio_pause_recording(void) void audio_resume_recording(void) { logf("audio_resume_recording"); - pcm_thread_sync_post(PCMREC_RESUME, NULL); + queue_send(&pcmrec_queue, PCMREC_RESUME, NULL); logf("audio_resume_recording done"); } /* audio_resume_recording */ @@ -1137,6 +1118,7 @@ static void pcmrec_init(void) is_stopping = false; buffer = audio_get_recording_buffer(&rec_buffer_size); + /* Line align pcm_buffer 2^4=16 bytes */ pcm_buffer = (unsigned char *)ALIGN_UP_P2((unsigned long)buffer, 4); enc_buffer = pcm_buffer + ALIGN_UP_P2(PCM_NUM_CHUNKS*PCM_CHUNK_SIZE + @@ -1145,8 +1127,6 @@ static void pcmrec_init(void) rec_buffer_size -= pcm_buffer - buffer; pcm_init_recording(); - pcm_thread_unsignal_event(PCMREC_CLOSE); - pcm_thread_signal_event(PCMREC_INIT); } /* pcmrec_init */ /* PCMREC_CLOSE */ @@ -1158,8 +1138,6 @@ static void pcmrec_close(void) pcm_close_recording(); reset_hardware(); audio_remove_encoder(); - pcm_thread_unsignal_event(PCMREC_INIT); - pcm_thread_signal_event(PCMREC_CLOSE); } /* pcmrec_close */ /* PCMREC_OPTIONS */ @@ -1218,12 +1196,11 @@ static void pcmrec_set_recording_options(struct audio_recording_options *options errors |= PCMREC_E_LOAD_ENCODER; } - pcm_thread_signal_event(PCMREC_OPTIONS); } /* pcmrec_set_recording_options */ /* PCMREC_START/PCMREC_NEW_FILE - start recording (not gapless) or split stream (gapless) */ -static void pcmrec_start(int event, const char *filename) +static void pcmrec_start(const char *filename) { unsigned long pre_sample_ticks; int rd_start; @@ -1318,7 +1295,6 @@ static void pcmrec_start(int event, const char *filename) enc_rd_index); start_done: - pcm_thread_signal_event(event); logf("pcmrec_start done"); } /* pcmrec_start */ @@ -1343,7 +1319,6 @@ static void pcmrec_stop(void) queue_post(&pcmrec_queue, PCMREC_FINISH_STOP, NULL); not_recording_or_stopping: - pcm_thread_signal_event(PCMREC_STOP); logf("pcmrec_stop done"); } /* pcmrec_stop */ @@ -1419,7 +1394,6 @@ static void pcmrec_pause(void) is_paused = true; not_recording_or_paused: - pcm_thread_signal_event(PCMREC_PAUSE); logf("pcmrec_pause done"); } /* pcmrec_pause */ @@ -1444,7 +1418,6 @@ static void pcmrec_resume(void) dma_lock = false; not_recording_or_not_paused: - pcm_thread_signal_event(PCMREC_RESUME); logf("pcmrec_resume done"); } /* pcmrec_resume */ @@ -1491,7 +1464,7 @@ static void pcmrec_thread(void) case PCMREC_START: case PCMREC_NEW_FILE: - pcmrec_start(ev.id, (const char *)ev.data); + pcmrec_start((const char *)ev.data); break; case PCMREC_STOP: @@ -1509,11 +1482,11 @@ static void pcmrec_thread(void) case PCMREC_RESUME: pcmrec_resume(); break; - +#if 0 case PCMREC_FLUSH_NUM: pcmrec_flush((unsigned)ev.data); break; - +#endif case SYS_USB_CONNECTED: if (is_recording) break; @@ -1523,6 +1496,8 @@ static void pcmrec_thread(void) usb_wait_for_disconnect(&pcmrec_queue); break; } /* end switch */ + + queue_reply(&pcmrec_queue, NULL); } /* end while */ } /* pcmrec_thread */