From 19c6e66c1353993659ee007a6c1792a6b0b7ba13 Mon Sep 17 00:00:00 2001 From: Miika Pekkarinen Date: Sun, 16 Mar 2008 13:55:16 +0000 Subject: [PATCH] Implement the playback event handling as a system-wide multi-purpose event system. Unified mpeg.c and playback.c audio event handling. Converted ata_idle_notify to use the new event handling system also. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16682 a1c6a512-1295-4272-9138-f99709370657 --- apps/lang/english.lang | 16 +++--- apps/main.c | 2 - apps/playback.c | 58 ++------------------ apps/playback.h | 14 +---- apps/scrobbler.c | 17 +++--- apps/settings.c | 20 +------ apps/tagtree.c | 11 ++-- firmware/SOURCES | 1 + firmware/ata_idle_notify.c | 61 ++++----------------- firmware/events.c | 88 +++++++++++++++++++++++++++++++ firmware/export/ata_idle_notify.h | 10 ++-- firmware/export/events.h | 51 ++++++++++++++++++ firmware/export/mpeg.h | 1 + firmware/mpeg.c | 41 ++------------ 14 files changed, 182 insertions(+), 209 deletions(-) create mode 100644 firmware/events.c create mode 100644 firmware/export/events.h diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 3911223d2d..e5df04a460 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -8191,29 +8191,27 @@ id: LANG_SETTINGS_SAVE_FAILED - desc: displayed if save settings has failed + desc: DEPRECATED user: - *: "Save Failed" + *: "" - *: "Save Failed" + *: "" - *: "Save Failed" + *: "" id: LANG_SETTINGS_PARTITION - desc: if save settings has failed + desc: DEPRECATED user: - *: "No partition?" - player: "Partition?" + *: "" - *: "No partition?" - player: "Partition?" + *: "" *: "" diff --git a/apps/main.c b/apps/main.c index 598597520f..5dd92e5e02 100644 --- a/apps/main.c +++ b/apps/main.c @@ -19,7 +19,6 @@ #include "config.h" #include "ata.h" -#include "ata_idle_notify.h" #include "disk.h" #include "fat.h" #include "lcd.h" @@ -428,7 +427,6 @@ static void init(void) } #endif - ata_idle_notify_init(); rc = ata_init(); if(rc) { diff --git a/apps/playback.c b/apps/playback.c index b36f68f135..ee1787e612 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -245,13 +245,6 @@ static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer */ static bool codec_requested_stop = false; -struct playback_event { - enum PLAYBACK_EVENT_TYPE type; - void (*callback)(void *data); -}; - -struct playback_event events[PLAYBACK_MAX_EVENTS]; - static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */ /* Multiple threads */ @@ -1447,51 +1440,6 @@ static void codec_thread(void) /* --- Audio thread --- */ -void playback_add_event(enum PLAYBACK_EVENT_TYPE type, void (*handler)) -{ - int i; - - /* Try to find a free slot. */ - for (i = 0; i < PLAYBACK_MAX_EVENTS; i++) - { - if (events[i].callback == NULL) - { - events[i].type = type; - events[i].callback = handler; - return; - } - } - - panicf("playback event line full"); -} - -void playback_remove_event(enum PLAYBACK_EVENT_TYPE type, void (*handler)) -{ - int i; - - for (i = 0; i < PLAYBACK_MAX_EVENTS; i++) - { - if (events[i].type == type && events[i].callback == handler) - { - events[i].callback = NULL; - return; - } - } - - panicf("playback event not found"); -} - -static void send_event(enum PLAYBACK_EVENT_TYPE type, void *data) -{ - int i; - - for (i = 0; i < PLAYBACK_MAX_EVENTS; i++) - { - if (events[i].type == type && events[i].callback != NULL) - events[i].callback(data); - } -} - static bool audio_have_tracks(void) { return (audio_track_count() != 0); @@ -1783,7 +1731,7 @@ static bool audio_load_track(int offset, bool start_play) { if (get_metadata(&id3, fd, trackname)) { - send_event(PLAYBACK_EVENT_TRACK_BUFFER, &id3); + send_event(PLAYBACK_EVENT_TRACK_BUFFER, false, &id3); tracks[track_widx].id3_hid = bufalloc(&id3, sizeof(struct mp3entry), TYPE_ID3); @@ -2020,7 +1968,7 @@ static int audio_check_new_track(void) bool end_of_playlist; /* Temporary flag, not the same as playlist_end */ /* Now it's good time to send track unbuffer events. */ - send_event(PLAYBACK_EVENT_TRACK_FINISH, &curtrack_id3); + send_event(PLAYBACK_EVENT_TRACK_FINISH, false, &curtrack_id3); if (dir_skip) { @@ -2391,7 +2339,7 @@ static void audio_finalise_track_change(void) bufgetid3(prev_ti->id3_hid)->elapsed = 0; } - send_event(PLAYBACK_EVENT_TRACK_CHANGE, &curtrack_id3); + send_event(PLAYBACK_EVENT_TRACK_CHANGE, false, &curtrack_id3); track_changed = true; playlist_update_resume_info(audio_current_track()); diff --git a/apps/playback.h b/apps/playback.h index 14ba35cea4..0b78eb3bcb 100644 --- a/apps/playback.h +++ b/apps/playback.h @@ -24,6 +24,7 @@ #include "id3.h" #include "mp3data.h" +#include "events.h" #define CODEC_IDX_AUDIO 0 #define CODEC_IDX_VOICE 1 @@ -39,13 +40,6 @@ #define MAX_TRACK_MASK (MAX_TRACK-1) -#define PLAYBACK_MAX_EVENTS 4 -enum PLAYBACK_EVENT_TYPE { - PLAYBACK_EVENT_TRACK_BUFFER, - PLAYBACK_EVENT_TRACK_FINISH, - PLAYBACK_EVENT_TRACK_CHANGE, -}; - /* Functions */ const char * get_codec_filename(int cod_spec); void voice_wait(void); @@ -53,13 +47,7 @@ void voice_wait(void); #if CONFIG_CODEC == SWCODEC /* This #ifdef is better here than gui/gwps.c */ extern void audio_next_dir(void); extern void audio_prev_dir(void); -void playback_add_event(enum PLAYBACK_EVENT_TYPE type, void (*handler)); -void playback_remove_event(enum PLAYBACK_EVENT_TYPE type, void (*handler)); #else -/* Really, should get rid of these HWCODEC api definitions here. */ -void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3)); -void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3)); -void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3)); # define audio_next_dir() #define audio_prev_dir() #endif diff --git a/apps/scrobbler.c b/apps/scrobbler.c index 16869bf18f..2f60e858e1 100644 --- a/apps/scrobbler.c +++ b/apps/scrobbler.c @@ -183,7 +183,10 @@ static void add_to_cache(unsigned long play_length) } else { cache_pos++; if (!scrobbler_ata_callback) - scrobbler_ata_callback = register_ata_idle_func(scrobbler_flush_callback); + { + register_ata_idle_func(scrobbler_flush_callback); + scrobbler_ata_callback = true; + } } } @@ -224,11 +227,7 @@ int scrobbler_init(void) scrobbler_cache = buffer_alloc(SCROBBLER_MAX_CACHE*SCROBBLER_CACHE_LEN); -#if CONFIG_CODEC == SWCODEC - playback_add_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event); -#else - audio_set_track_changed_event(&scrobbler_change_event); -#endif + add_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event); cache_pos = 0; pending = false; scrobbler_initialised = true; @@ -263,11 +262,7 @@ void scrobbler_shutdown(void) if (scrobbler_initialised) { -#if CONFIG_CODEC == SWCODEC - playback_remove_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event); -#else - audio_set_track_changed_event(NULL); -#endif + remove_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event); scrobbler_initialised = false; } } diff --git a/apps/settings.c b/apps/settings.c index 27832b427f..7eec15baf3 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -601,25 +601,7 @@ int settings_save( void ) target doesnt have rtc ram */ write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE); #endif - if(!register_ata_idle_func(flush_config_block_callback)) - { - int i; - FOR_NB_SCREENS(i) - { - screens[i].clear_display(); -#ifdef HAVE_LCD_CHARCELLS - screens[i].puts(0, 0, str(LANG_SETTINGS_SAVE_FAILED)); - screens[i].puts(0, 1, str(LANG_SETTINGS_PARTITION)); -#else - screens[i].puts(4, 2, str(LANG_SETTINGS_SAVE_FAILED)); - screens[i].puts(2, 4, str(LANG_SETTINGS_PARTITION)); - screens[i].update(); -#endif - } - cond_talk_ids_fq(LANG_SETTINGS_SAVE_FAILED); - sleep(HZ*2); - return -1; - } + register_ata_idle_func(flush_config_block_callback); return 0; } bool settings_save_config(int options) diff --git a/apps/tagtree.c b/apps/tagtree.c index c5e3ebff1e..4572204ae5 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c @@ -924,14 +924,9 @@ void tagtree_init(void) root_menu = 0; uniqbuf = buffer_alloc(UNIQBUF_SIZE); -#if CONFIG_CODEC == SWCODEC - playback_add_event(PLAYBACK_EVENT_TRACK_BUFFER, tagtree_buffer_event); - playback_add_event(PLAYBACK_EVENT_TRACK_FINISH, tagtree_track_finish_event); -#else - audio_set_track_buffer_event(tagtree_buffer_event); - audio_set_track_unbuffer_event(tagtree_track_finish_event); -#endif - + + add_event(PLAYBACK_EVENT_TRACK_BUFFER, tagtree_buffer_event); + add_event(PLAYBACK_EVENT_TRACK_FINISH, tagtree_track_finish_event); } static bool show_search_progress(bool init, int count) diff --git a/firmware/SOURCES b/firmware/SOURCES index b5906d4648..ea8ce46cca 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -1,4 +1,5 @@ ata_idle_notify.c +events.c backlight.c buffer.c id3.c diff --git a/firmware/ata_idle_notify.c b/firmware/ata_idle_notify.c index 1fc6605ac6..a97c3538da 100644 --- a/firmware/ata_idle_notify.c +++ b/firmware/ata_idle_notify.c @@ -23,60 +23,31 @@ #include "kernel.h" #include "string.h" -#if USING_ATA_CALLBACK -static ata_idle_notify ata_idle_notify_funcs[MAX_ATA_CALLBACKS]; -static int ata_callback_count = 0; -#endif - - -bool register_ata_idle_func(ata_idle_notify function) +void register_ata_idle_func(ata_idle_notify function) { #if USING_ATA_CALLBACK - int i; - if (ata_callback_count >= MAX_ATA_CALLBACKS) - return false; - for (i=0; i ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2008 by Miika Pekkarinen + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include "events.h" +#include "panic.h" + +struct sysevent { + unsigned short id; + void (*callback)(void *data); +}; + +struct sysevent events[MAX_SYS_EVENTS]; + +bool add_event(unsigned short id, void (*handler)) +{ + int i; + + /* Chcek if the event already exists. */ + for (i = 0; i < MAX_SYS_EVENTS; i++) + { + if (events[i].callback == handler && events[i].id == id) + return false; + } + + /* Try to find a free slot. */ + for (i = 0; i < MAX_SYS_EVENTS; i++) + { + if (events[i].callback == NULL) + { + events[i].id = id; + events[i].callback = handler; + return true; + } + } + + panicf("event line full"); + return false; +} + +void remove_event(unsigned short id, void (*handler)) +{ + int i; + + for (i = 0; i < MAX_SYS_EVENTS; i++) + { + if (events[i].id == id && events[i].callback == handler) + { + events[i].callback = NULL; + return; + } + } + + panicf("event not found"); +} + +void send_event(unsigned short id, bool oneshot, void *data) +{ + int i; + + for (i = 0; i < MAX_SYS_EVENTS; i++) + { + if (events[i].id == id && events[i].callback != NULL) + { + events[i].callback(data); + + if (oneshot) + events[i].callback = NULL; + } + } +} + diff --git a/firmware/export/ata_idle_notify.h b/firmware/export/ata_idle_notify.h index ee825c967e..1dda3e196a 100644 --- a/firmware/export/ata_idle_notify.h +++ b/firmware/export/ata_idle_notify.h @@ -19,7 +19,9 @@ #ifndef __ATACALLBACK_H__ #define __ATACALLBACK_H__ + #include +#include "events.h" #if 0 NOTE: ata_idle_nofity usage notes.. @@ -34,15 +36,17 @@ 5) Dont Panic! #endif +enum { + DISK_EVENT_SPINUP = (EVENT_CLASS_DISK|1), +}; + #define USING_ATA_CALLBACK !defined(SIMULATOR) \ && !defined(HAVE_FLASH_DISK) -#define MAX_ATA_CALLBACKS 5 typedef bool (*ata_idle_notify)(void); -extern bool register_ata_idle_func(ata_idle_notify function); +extern void register_ata_idle_func(ata_idle_notify function); #if USING_ATA_CALLBACK -extern void ata_idle_notify_init(void); extern void unregister_ata_idle_func(ata_idle_notify function, bool run); extern bool call_ata_idle_notifys(bool force); #else diff --git a/firmware/export/events.h b/firmware/export/events.h new file mode 100644 index 0000000000..b27b5dee4c --- /dev/null +++ b/firmware/export/events.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2008 by Miika Pekkarinen + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef _EVENTS_H +#define _EVENTS_H + +#include + +#define MAX_SYS_EVENTS 10 + +/** + * High nibble = Event class definition + * Low nibble = Event ID + */ + +#define EVENT_CLASS_DISK 0x0100 +#define EVENT_CLASS_PLAYBACK 0x0200 + +/** + * Because same playback events are used in mpeg.c and playback.c, define + * them here to prevent cluttering and ifdefs. + */ +enum { + PLAYBACK_EVENT_TRACK_BUFFER = (EVENT_CLASS_PLAYBACK|1), + PLAYBACK_EVENT_TRACK_FINISH, + PLAYBACK_EVENT_TRACK_CHANGE, +}; + + +bool add_event(unsigned short id, void (*handler)); +void remove_event(unsigned short id, void (*handler)); +void send_event(unsigned short id, bool oneshot, void *data); + +#endif + diff --git a/firmware/export/mpeg.h b/firmware/export/mpeg.h index 3e36c44ac5..0a9d62cdf0 100644 --- a/firmware/export/mpeg.h +++ b/firmware/export/mpeg.h @@ -21,6 +21,7 @@ #include #include "id3.h" +#include "events.h" #define MPEG_SWAP_CHUNKSIZE 0x2000 #define MPEG_HIGH_WATER 2 /* We leave 2 bytes empty because otherwise we diff --git a/firmware/mpeg.c b/firmware/mpeg.c index 693e2df480..9023c304d2 100644 --- a/firmware/mpeg.c +++ b/firmware/mpeg.c @@ -100,7 +100,6 @@ struct trackdata struct mp3entry id3; int mempos; int load_ahead_index; - bool event_sent; }; static struct trackdata trackdata[MAX_TRACK_ENTRIES]; @@ -116,11 +115,6 @@ static int track_read_idx = 0; static int track_write_idx = 0; #endif /* !SIMULATOR */ -/* Callback function to call when current track has really changed. */ -void (*track_changed_callback)(struct mp3entry *id3) = NULL; -void (*track_buffer_callback)(struct mp3entry *id3) = NULL; -void (*track_unbuffer_callback)(struct mp3entry *id3) = NULL; - /* Cuesheet callback */ static bool (*cuesheet_callback)(const char *filename) = NULL; @@ -475,21 +469,6 @@ unsigned long mpeg_get_last_header(void) #endif /* !SIMULATOR */ } -void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3)) -{ - track_buffer_callback = handler; -} - -void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3)) -{ - track_unbuffer_callback = handler; -} - -void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3)) -{ - track_changed_callback = handler; -} - void audio_set_cuesheet_callback(bool (*handler)(const char *filename)) { cuesheet_callback = handler; @@ -506,12 +485,7 @@ static void generate_unbuffer_events(void) for (i = 0; i < numentries; i++) { /* Send an event to notify that track has finished. */ - if (trackdata[cur_idx].event_sent) - { - if (track_unbuffer_callback) - track_unbuffer_callback(&trackdata[cur_idx].id3); - trackdata[cur_idx].event_sent = false; - } + send_event(PLAYBACK_EVENT_TRACK_FINISH, false, &trackdata[cur_idx].id3); cur_idx = (cur_idx + 1) & MAX_TRACK_ENTRIES_MASK; } } @@ -525,12 +499,7 @@ static void generate_postbuffer_events(void) for (i = 0; i < numentries; i++) { - if (!trackdata[cur_idx].event_sent) - { - if (track_buffer_callback) - track_buffer_callback(&trackdata[cur_idx].id3); - trackdata[cur_idx].event_sent = true; - } + send_event(PLAYBACK_EVENT_TRACK_BUFFER, false, &trackdata[cur_idx].id3); cur_idx = (cur_idx + 1) & MAX_TRACK_ENTRIES_MASK; } } @@ -1080,8 +1049,7 @@ static void track_change(void) if (num_tracks_in_memory() > 0) { remove_current_tag(); - if (track_changed_callback) - track_changed_callback(audio_current_track()); + send_event(PLAYBACK_EVENT_TRACK_CHANGE, false, audio_current_track()); update_playlist(); } @@ -1134,8 +1102,7 @@ static void start_playback_if_ready(void) if (play_pending_track_change) { play_pending_track_change = false; - if(track_changed_callback) - track_changed_callback(audio_current_track()); + send_event(PLAYBACK_EVENT_TRACK_CHANGE, false, audio_current_track()); } play_pending = false; }