events: Rework event subsystem (add_event, send_event) to be more versatile.

add_event_ex is added that takes an extra user_data pointer. This pointer is
passed to the callback (add_event and add_event_ex have slightly different
callbacks types). All callbacks also get the event id passed. Events added
with add_event_ex must be removed with remove_event_ex because the user_data
pointer must match in addition to the callback pointer.

On the other add_event is simplified to omit the oneshort parameter which
was almost always false (still there with add_event_ex).

As a side effect the ata_idle_notify callbacks are changed as well, they
do not take a data parameter anymore which was always NULL anyway.

This commit also adds some documentation to events.h

Change-Id: I13e29a0f88ef908f175b376d83550f9e0231f772
This commit is contained in:
Thomas Martitz 2014-03-14 23:15:16 +01:00
parent 50f0dd80d6
commit 470989bd70
25 changed files with 247 additions and 149 deletions

View file

@ -66,16 +66,17 @@ static bool list_is_dirty(struct gui_synclist *list)
return TIME_BEFORE(list->dirty_tick, last_dirty_tick); return TIME_BEFORE(list->dirty_tick, last_dirty_tick);
} }
static void list_force_reinit(void *param) static void list_force_reinit(unsigned short id, void *param, void *last_dirty_tick)
{ {
(void)id;
(void)param; (void)param;
last_dirty_tick = current_tick; *(int *)last_dirty_tick = current_tick;
} }
void list_init(void) void list_init(void)
{ {
last_dirty_tick = current_tick; last_dirty_tick = current_tick;
add_event(GUI_EVENT_THEME_CHANGED, false, list_force_reinit); add_event_ex(GUI_EVENT_THEME_CHANGED, false, list_force_reinit, &last_dirty_tick);
} }
static void list_init_viewports(struct gui_synclist *list) static void list_init_viewports(struct gui_synclist *list)
@ -611,8 +612,9 @@ bool gui_synclist_keyclick_callback(int action, void* data)
*/ */
static struct gui_synclist *current_lists; static struct gui_synclist *current_lists;
static bool ui_update_event_registered = false; static bool ui_update_event_registered = false;
static void _lists_uiviewport_update_callback(void *data) static void _lists_uiviewport_update_callback(unsigned short id, void *data)
{ {
(void)id;
(void)data; (void)data;
if (current_lists) if (current_lists)
gui_synclist_draw(current_lists); gui_synclist_draw(current_lists);
@ -801,8 +803,7 @@ int list_do_action_timeout(struct gui_synclist *lists, int timeout)
{ {
if (!ui_update_event_registered) if (!ui_update_event_registered)
ui_update_event_registered = ui_update_event_registered =
add_event(GUI_EVENT_NEED_UI_UPDATE, false, add_event(GUI_EVENT_NEED_UI_UPDATE, _lists_uiviewport_update_callback);
_lists_uiviewport_update_callback);
current_lists = lists; current_lists = lists;
} }
if(lists->scheduled_talk_tick) if(lists->scheduled_talk_tick)

View file

@ -178,8 +178,9 @@ void sb_skin_update(enum screen_type screen, bool force)
} }
} }
void do_sbs_update_callback(void *param) void do_sbs_update_callback(unsigned short id, void *param)
{ {
(void)id;
(void)param; (void)param;
/* the WPS handles changing the actual id3 data in the id3 pointers /* the WPS handles changing the actual id3 data in the id3 pointers
* we imported, we just want a full update */ * we imported, we just want a full update */

View file

@ -66,5 +66,5 @@ int sb_postproccess(enum screen_type screen, struct wps_data *data);
#define sb_preproccess NULL #define sb_preproccess NULL
#define sb_postproccess NULL #define sb_postproccess NULL
#endif #endif
void do_sbs_update_callback(void *param); void do_sbs_update_callback(unsigned short id, void *param);
#endif /* __STATUSBAR_SKINNED_H__ */ #endif /* __STATUSBAR_SKINNED_H__ */

View file

@ -69,7 +69,7 @@ struct viewport_stack_item
}; };
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
static void viewportmanager_redraw(void* data); static void viewportmanager_redraw(unsigned short id, void* data);
static int theme_stack_top[NB_SCREENS]; /* the last item added */ static int theme_stack_top[NB_SCREENS]; /* the last item added */
static struct viewport_stack_item theme_stack[NB_SCREENS][VPSTACK_DEPTH]; static struct viewport_stack_item theme_stack[NB_SCREENS][VPSTACK_DEPTH];
@ -80,14 +80,12 @@ static void toggle_events(bool enable)
{ {
if (enable) if (enable)
{ {
add_event(GUI_EVENT_ACTIONUPDATE, false, viewportmanager_redraw); add_event(GUI_EVENT_ACTIONUPDATE, viewportmanager_redraw);
#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
add_event(LCD_EVENT_ACTIVATION, false, do_sbs_update_callback); add_event(LCD_EVENT_ACTIVATION, do_sbs_update_callback);
#endif #endif
add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, add_event(PLAYBACK_EVENT_TRACK_CHANGE, do_sbs_update_callback);
do_sbs_update_callback); add_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, do_sbs_update_callback);
add_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, false,
do_sbs_update_callback);
} }
else else
{ {
@ -232,8 +230,9 @@ int viewport_get_nb_lines(const struct viewport *vp)
#endif #endif
} }
static void viewportmanager_redraw(void* data) static void viewportmanager_redraw(unsigned short id, void* data)
{ {
(void)id;
FOR_NB_SCREENS(i) FOR_NB_SCREENS(i)
{ {
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
@ -256,7 +255,7 @@ void viewportmanager_init()
viewportmanager_theme_enable(i, true, NULL); viewportmanager_theme_enable(i, true, NULL);
} }
#else #else
add_event(GUI_EVENT_ACTIONUPDATE, false, viewportmanager_redraw); add_event(GUI_EVENT_ACTIONUPDATE, viewportmanager_redraw);
#endif #endif
} }

View file

@ -74,8 +74,7 @@
/* initial setup of wps_data */ /* initial setup of wps_data */
static void wps_state_init(void); static void wps_state_init(void);
static void track_changed_callback(void *param); static void track_info_callback(unsigned short id, void *param);
static void nextid3available_callback(void* param);
#define WPS_DEFAULTCFG WPS_DIR "/rockbox_default.wps" #define WPS_DEFAULTCFG WPS_DIR "/rockbox_default.wps"
#ifdef HAVE_REMOTE_LCD #ifdef HAVE_REMOTE_LCD
@ -626,8 +625,9 @@ static void play_hop(int direction)
* we suppress updates until the wps is activated again (the lcd driver will * we suppress updates until the wps is activated again (the lcd driver will
* call this hook to issue an instant update) * call this hook to issue an instant update)
* */ * */
static void wps_lcd_activation_hook(void *param) static void wps_lcd_activation_hook(unsigned short id, void *param)
{ {
(void)id;
(void)param; (void)param;
skin_request_full_update(WPS); skin_request_full_update(WPS);
/* force timeout in wps main loop, so that the update is instantly */ /* force timeout in wps main loop, so that the update is instantly */
@ -1119,7 +1119,7 @@ long gui_wps_show(void)
restore = false; restore = false;
restoretimer = RESTORE_WPS_INSTANTLY; restoretimer = RESTORE_WPS_INSTANTLY;
#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
add_event(LCD_EVENT_ACTIVATION, false, wps_lcd_activation_hook); add_event(LCD_EVENT_ACTIVATION, wps_lcd_activation_hook);
#endif #endif
/* we remove the update delay since it's not very usable in the wps, /* we remove the update delay since it's not very usable in the wps,
* e.g. during volume changing or ffwd/rewind */ * e.g. during volume changing or ffwd/rewind */
@ -1187,36 +1187,28 @@ long gui_wps_show(void)
} }
/* this is called from the playback thread so NO DRAWING! */ /* this is called from the playback thread so NO DRAWING! */
static void track_changed_callback(void *param) static void track_info_callback(unsigned short id, void *param)
{ {
struct wps_state *state = skin_get_global_state(); struct wps_state *state = skin_get_global_state();
state->id3 = ((struct track_event *)param)->id3;
state->nid3 = audio_next_track(); if (id == PLAYBACK_EVENT_TRACK_CHANGE || id == PLAYBACK_EVENT_CUR_TRACK_READY)
if (state->id3->cuesheet)
{ {
cue_find_current_track(state->id3->cuesheet, state->id3->elapsed); state->id3 = ((struct track_event *)param)->id3;
if (state->id3->cuesheet)
{
cue_find_current_track(state->id3->cuesheet, state->id3->elapsed);
}
} }
skin_request_full_update(WPS); #ifdef AUDIO_FAST_SKIP_PREVIEW
} else if (id == PLAYBACK_EVENT_TRACK_SKIP)
static void nextid3available_callback(void* param) {
{ state->id3 = audio_current_track();
(void)param; }
#endif
skin_get_global_state()->nid3 = audio_next_track(); skin_get_global_state()->nid3 = audio_next_track();
skin_request_full_update(WPS); skin_request_full_update(WPS);
} }
#ifdef AUDIO_FAST_SKIP_PREVIEW
/* this is called on the audio_skip caller thread */
static void track_skip_callback(void *param)
{
struct wps_state *state = skin_get_global_state();
state->id3 = audio_current_track();
state->nid3 = audio_next_track();
skin_request_full_update(WPS);
(void)param;
}
#endif /* AUDIO_FAST_SKIP_PREVIEW */
static void wps_state_init(void) static void wps_state_init(void)
{ {
struct wps_state *state = skin_get_global_state(); struct wps_state *state = skin_get_global_state();
@ -1235,15 +1227,15 @@ static void wps_state_init(void)
/* We'll be updating due to restore initialized with true */ /* We'll be updating due to restore initialized with true */
skin_request_full_update(WPS); skin_request_full_update(WPS);
/* add the WPS track event callbacks */ /* add the WPS track event callbacks */
add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, track_changed_callback); add_event(PLAYBACK_EVENT_TRACK_CHANGE, track_info_callback);
add_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, false, nextid3available_callback); add_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, track_info_callback);
#if CONFIG_CODEC == SWCODEC #if CONFIG_CODEC == SWCODEC
/* Use the same callback as ..._TRACK_CHANGE for when remaining handles have /* Use the same callback as ..._TRACK_CHANGE for when remaining handles have
finished */ finished */
add_event(PLAYBACK_EVENT_CUR_TRACK_READY, false, track_changed_callback); add_event(PLAYBACK_EVENT_CUR_TRACK_READY, track_info_callback);
#endif #endif
#ifdef AUDIO_FAST_SKIP_PREVIEW #ifdef AUDIO_FAST_SKIP_PREVIEW
add_event(PLAYBACK_EVENT_TRACK_SKIP, false, track_skip_callback); add_event(PLAYBACK_EVENT_TRACK_SKIP, track_info_callback);
#endif #endif
} }

View file

@ -44,8 +44,9 @@ static const struct dim dim = { .width = 200, .height = 200 };
/* /*
* notify about track change, and show track info */ * notify about track change, and show track info */
static void track_changed_callback(void *param) static void track_changed_callback(unsigned short id, void *param)
{ {
(void)id;
struct mp3entry* id3 = ((struct track_event *)param)->id3; struct mp3entry* id3 = ((struct track_event *)param)->id3;
JNIEnv e = *env_ptr; JNIEnv e = *env_ptr;
if (id3) if (id3)
@ -106,8 +107,9 @@ static void track_changed_callback(void *param)
/* /*
* notify about track finishing */ * notify about track finishing */
static void track_finished_callback(void *param) static void track_finished_callback(unsigned short id, void *param)
{ {
(void)id;
if (((struct track_event *)param)->flags & TEF_REWIND) if (((struct track_event *)param)->flags & TEF_REWIND)
return; /* Not a true track end */ return; /* Not a true track end */
@ -144,6 +146,6 @@ void notification_init(void)
finishNotification = e->GetMethodID(env_ptr, class, "finishNotification", finishNotification = e->GetMethodID(env_ptr, class, "finishNotification",
"()V"); "()V");
add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, track_changed_callback); add_event(PLAYBACK_EVENT_TRACK_CHANGE track_changed_callback);
add_event(PLAYBACK_EVENT_TRACK_FINISH, false, track_finished_callback); add_event(PLAYBACK_EVENT_TRACK_FINISH track_finished_callback);
} }

View file

@ -349,8 +349,9 @@ static void iap_thread(void)
} }
/* called by playback when the next track starts */ /* called by playback when the next track starts */
static void iap_track_changed(void *ignored) static void iap_track_changed(unsigned short id, void *ignored)
{ {
(void)id;
(void)ignored; (void)ignored;
if ((interface_state == IST_EXTENDED) && device.do_notify) { if ((interface_state == IST_EXTENDED) && device.do_notify) {
long playlist_pos = playlist_next(0); long playlist_pos = playlist_next(0);
@ -401,7 +402,7 @@ static void iap_start(void)
if (!tid) if (!tid)
panicf("Could not create iap thread"); panicf("Could not create iap thread");
timeout_register(&iap_task_tmo, iap_task, MS_TO_TICKS(100), (intptr_t)NULL); timeout_register(&iap_task_tmo, iap_task, MS_TO_TICKS(100), (intptr_t)NULL);
add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, iap_track_changed); add_event(PLAYBACK_EVENT_TRACK_CHANGE, iap_track_changed);
/* Since we cannot allocate memory while in interrupt context /* Since we cannot allocate memory while in interrupt context
* post a message to our own queue to get that done * post a message to our own queue to get that done

View file

@ -334,17 +334,18 @@ enum audio_start_playback_flags
static void audio_start_playback(const struct audio_resume_info *resume_info, static void audio_start_playback(const struct audio_resume_info *resume_info,
unsigned int flags); unsigned int flags);
static void audio_stop_playback(void); static void audio_stop_playback(void);
static void buffer_event_buffer_low_callback(void *data); static void buffer_event_buffer_low_callback(unsigned short id, void *data, void *user_data);
static void buffer_event_rebuffer_callback(void *data); static void buffer_event_rebuffer_callback(unsigned short id, void *data);
static void buffer_event_finished_callback(void *data); static void buffer_event_finished_callback(unsigned short id, void *data);
void audio_pcmbuf_sync_position(void); void audio_pcmbuf_sync_position(void);
/**************************************/ /**************************************/
/** --- voice event --- **/ /** --- voice event --- **/
void playback_voice_event(void *data) void playback_voice_event(unsigned short id, void *data)
{ {
(void)id;
/* Make audio play softly while voice is speaking */ /* Make audio play softly while voice is speaking */
pcmbuf_soft_mode(*(bool *)data); pcmbuf_soft_mode(*(bool *)data);
} }
@ -1757,7 +1758,7 @@ static int audio_load_track(void)
should have been cleared already */ should have been cleared already */
logf("%s(): finishing load: %d", __func__, info->id3_hid); logf("%s(): finishing load: %d", __func__, info->id3_hid);
filling = STATE_FILLING; filling = STATE_FILLING;
buffer_event_finished_callback(&info->id3_hid); buffer_event_finished_callback(BUFFER_EVENT_FINISHED, &info->id3_hid);
return LOAD_TRACK_OK; return LOAD_TRACK_OK;
} }
} }
@ -2585,8 +2586,8 @@ static void audio_start_playback(const struct audio_resume_info *resume_info,
/* Add these now - finish event for the first id3 will most likely be sent /* Add these now - finish event for the first id3 will most likely be sent
immediately */ immediately */
add_event(BUFFER_EVENT_REBUFFER, false, buffer_event_rebuffer_callback); add_event(BUFFER_EVENT_REBUFFER, buffer_event_rebuffer_callback);
add_event(BUFFER_EVENT_FINISHED, false, buffer_event_finished_callback); add_event(BUFFER_EVENT_FINISHED, buffer_event_finished_callback);
if (old_status == PLAY_STOPPED) if (old_status == PLAY_STOPPED)
{ {
@ -2647,7 +2648,7 @@ static void audio_stop_playback(void)
/* Close all tracks and mark them NULL */ /* Close all tracks and mark them NULL */
remove_event(BUFFER_EVENT_REBUFFER, buffer_event_rebuffer_callback); remove_event(BUFFER_EVENT_REBUFFER, buffer_event_rebuffer_callback);
remove_event(BUFFER_EVENT_FINISHED, buffer_event_finished_callback); remove_event(BUFFER_EVENT_FINISHED, buffer_event_finished_callback);
remove_event(BUFFER_EVENT_BUFFER_LOW, buffer_event_buffer_low_callback); remove_event_ex(BUFFER_EVENT_BUFFER_LOW, buffer_event_buffer_low_callback, NULL);
track_list_clear(TRACK_LIST_CLEAR_ALL); track_list_clear(TRACK_LIST_CLEAR_ALL);
@ -3164,8 +3165,8 @@ void audio_playback_handler(struct queue_event *ev)
/* End of buffering for now, let's calculate the watermark, /* End of buffering for now, let's calculate the watermark,
register for a low buffer event and unboost */ register for a low buffer event and unboost */
audio_update_filebuf_watermark(0); audio_update_filebuf_watermark(0);
add_event(BUFFER_EVENT_BUFFER_LOW, true, add_event_ex(BUFFER_EVENT_BUFFER_LOW, true,
buffer_event_buffer_low_callback); buffer_event_buffer_low_callback, NULL);
} }
/* Fall-through */ /* Fall-through */
case STATE_FINISHED: case STATE_FINISHED:
@ -3200,27 +3201,31 @@ void audio_playback_handler(struct queue_event *ev)
/* --- Buffering callbacks --- */ /* --- Buffering callbacks --- */
/* Called when fullness is below the watermark level */ /* Called when fullness is below the watermark level */
static void buffer_event_buffer_low_callback(void *data) static void buffer_event_buffer_low_callback(unsigned short id, void *ev_data, void *user_data)
{ {
logf("low buffer callback"); logf("low buffer callback");
LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: buffer low"); LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: buffer low");
audio_queue_post(Q_AUDIO_BUFFERING, BUFFER_EVENT_BUFFER_LOW); audio_queue_post(Q_AUDIO_BUFFERING, BUFFER_EVENT_BUFFER_LOW);
(void)data; (void)id;
(void)ev_data;
(void)user_data;
} }
/* Called when handles must be discarded in order to buffer new data */ /* Called when handles must be discarded in order to buffer new data */
static void buffer_event_rebuffer_callback(void *data) static void buffer_event_rebuffer_callback(unsigned short id, void *ev_data)
{ {
logf("rebuffer callback"); logf("rebuffer callback");
LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: rebuffer"); LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: rebuffer");
audio_queue_post(Q_AUDIO_BUFFERING, BUFFER_EVENT_REBUFFER); audio_queue_post(Q_AUDIO_BUFFERING, BUFFER_EVENT_REBUFFER);
(void)data; (void)id;
(void)ev_data;
} }
/* A handle has completed buffering and all required data is available */ /* A handle has completed buffering and all required data is available */
static void buffer_event_finished_callback(void *data) static void buffer_event_finished_callback(unsigned short id, void *ev_data)
{ {
int hid = *(const int *)data; (void)id;
int hid = *(const int *)ev_data;
const enum data_type htype = buf_handle_data_type(hid); const enum data_type htype = buf_handle_data_type(hid);
logf("handle %d finished buffering (type:%u)", hid, (unsigned)htype); logf("handle %d finished buffering (type:%u)", hid, (unsigned)htype);
@ -3717,7 +3722,7 @@ void INIT_ATTR playback_init(void)
track_list_init(); track_list_init();
buffering_init(); buffering_init();
pcmbuf_update_frequency(); pcmbuf_update_frequency();
add_event(PLAYBACK_EVENT_VOICE_PLAYING, false, playback_voice_event); add_event(PLAYBACK_EVENT_VOICE_PLAYING, playback_voice_event);
#ifdef HAVE_CROSSFADE #ifdef HAVE_CROSSFADE
/* Set crossfade setting for next buffer init which should be about... */ /* Set crossfade setting for next buffer init which should be about... */
pcmbuf_request_crossfade_enable(global_settings.crossfade); pcmbuf_request_crossfade_enable(global_settings.crossfade);

View file

@ -1223,9 +1223,8 @@ static int compare(const void* p1, const void* p2)
* without affecting playlist load up performance. This thread also flushes * without affecting playlist load up performance. This thread also flushes
* any pending control commands when the disk spins up. * any pending control commands when the disk spins up.
*/ */
static void playlist_flush_callback(void *param) static void playlist_flush_callback(void)
{ {
(void)param;
struct playlist_info *playlist; struct playlist_info *playlist;
playlist = &current_playlist; playlist = &current_playlist;
if (playlist->control_fd >= 0) if (playlist->control_fd >= 0)

View file

@ -160,12 +160,12 @@ void* plugin_get_buffer(size_t *buffer_size);
#define PLUGIN_MAGIC 0x526F634B /* RocK */ #define PLUGIN_MAGIC 0x526F634B /* RocK */
/* increase this every time the api struct changes */ /* increase this every time the api struct changes */
#define PLUGIN_API_VERSION 227 #define PLUGIN_API_VERSION 228
/* update this to latest version if a change to the api struct breaks /* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any backwards compatibility (and please take the opportunity to sort in any
new function which are "waiting" at the end of the function table) */ new function which are "waiting" at the end of the function table) */
#define PLUGIN_MIN_API_VERSION 227 #define PLUGIN_MIN_API_VERSION 228
/* plugin return codes */ /* plugin return codes */
/* internal returns start at 0x100 to make exit(1..255) work */ /* internal returns start at 0x100 to make exit(1..255) work */
@ -450,8 +450,8 @@ struct plugin_api {
void (*storage_spin)(void); void (*storage_spin)(void);
void (*storage_spindown)(int seconds); void (*storage_spindown)(int seconds);
#if USING_STORAGE_CALLBACK #if USING_STORAGE_CALLBACK
void (*register_storage_idle_func)(void (*function)(void *data)); void (*register_storage_idle_func)(void (*function)(void));
void (*unregister_storage_idle_func)(void (*function)(void *data), bool run); void (*unregister_storage_idle_func)(void (*function)(void), bool run);
#endif /* USING_STORAGE_CALLBACK */ #endif /* USING_STORAGE_CALLBACK */
void (*reload_directory)(void); void (*reload_directory)(void);
char *(*create_numbered_filename)(char *buffer, const char *path, char *(*create_numbered_filename)(char *buffer, const char *path,
@ -569,8 +569,8 @@ struct plugin_api {
void (*profile_func_exit)(void *this_fn, void *call_site); void (*profile_func_exit)(void *this_fn, void *call_site);
#endif #endif
/* event api */ /* event api */
bool (*add_event)(unsigned short id, bool oneshot, void (*handler)(void *data)); bool (*add_event)(unsigned short id, void (*handler)(unsigned short id, void *data));
void (*remove_event)(unsigned short id, void (*handler)(void *data)); void (*remove_event)(unsigned short id, void (*handler)(unsigned short id, void *data));
void (*send_event)(unsigned short id, void *data); void (*send_event)(unsigned short id, void *data);
#if (CONFIG_PLATFORM & PLATFORM_HOSTED) #if (CONFIG_PLATFORM & PLATFORM_HOSTED)

View file

@ -359,9 +359,8 @@ static unsigned int charge_state(void)
#endif #endif
static void flush_buffer(void* data) static void flush_buffer(void)
{ {
(void)data;
int fd; int fd;
unsigned int i; unsigned int i;
@ -445,7 +444,7 @@ static void thread(void)
for this to occur because it requires > 16 hours of no disk activity. for this to occur because it requires > 16 hours of no disk activity.
*/ */
if (buf_idx == BUF_ELEMENTS) { if (buf_idx == BUF_ELEMENTS) {
flush_buffer(NULL); flush_buffer();
} }
/* sleep some time until next measurement */ /* sleep some time until next measurement */
@ -479,7 +478,7 @@ static void thread(void)
/* unregister flush callback and flush to disk */ /* unregister flush callback and flush to disk */
rb->unregister_storage_idle_func(flush_buffer, true); rb->unregister_storage_idle_func(flush_buffer, true);
#else #else
flush_buffer(NULL); flush_buffer();
#endif #endif
/* log end of bench and exit reason */ /* log end of bench and exit reason */

View file

@ -677,8 +677,9 @@ static uint32_t increment_time(uint32_t val, int32_t amount, uint32_t range)
} }
#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
static void get_start_time_lcd_enable_hook(void *param) static void get_start_time_lcd_enable_hook(unsigned short id, void *param)
{ {
(void)id;
(void)param; (void)param;
rb->queue_post(rb->button_queue, LCD_ENABLE_EVENT_0, 0); rb->queue_post(rb->button_queue, LCD_ENABLE_EVENT_0, 0);
} }
@ -698,7 +699,7 @@ static int get_start_time(uint32_t duration)
mylcd_update(); mylcd_update();
#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
rb->add_event(LCD_EVENT_ACTIVATION, false, get_start_time_lcd_enable_hook); rb->add_event(LCD_EVENT_ACTIVATION, get_start_time_lcd_enable_hook);
#endif #endif
draw_slider(0, 100, &rc_bound); draw_slider(0, 100, &rc_bound);

View file

@ -1026,8 +1026,9 @@ static void fps_init(void)
#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
/* So we can refresh the overlay */ /* So we can refresh the overlay */
static void osd_lcd_enable_hook(void* param) static void osd_lcd_enable_hook(unsigned short id, void* param)
{ {
(void)id;
(void)param; (void)param;
rb->queue_post(rb->button_queue, LCD_ENABLE_EVENT_1, 0); rb->queue_post(rb->button_queue, LCD_ENABLE_EVENT_1, 0);
} }
@ -1043,7 +1044,7 @@ static void osd_backlight_on_video_mode(bool video_on)
#endif #endif
} else { } else {
#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
rb->add_event(LCD_EVENT_ACTIVATION, false, osd_lcd_enable_hook); rb->add_event(LCD_EVENT_ACTIVATION, osd_lcd_enable_hook);
#endif #endif
/* Revert to user's backlight settings */ /* Revert to user's backlight settings */
backlight_use_settings(); backlight_use_settings();

View file

@ -145,7 +145,7 @@ int radio_get_art_hid(struct dim *requested_dim)
return -1; return -1;
} }
static void buffer_reset_handler(void *data) static void buffer_reset_handler(unsigned short id, void *data, void *user_data)
{ {
buf = NULL; buf = NULL;
for(int i=0;i<MAX_RADIOART_IMAGES;i++) for(int i=0;i<MAX_RADIOART_IMAGES;i++)
@ -156,7 +156,9 @@ static void buffer_reset_handler(void *data)
radioart[i].name[0] = '\0'; radioart[i].name[0] = '\0';
} }
(void)id;
(void)data; (void)data;
(void)user_data;
} }
static int shrink_callback(int handle, unsigned hints, void* start, size_t old_size) static int shrink_callback(int handle, unsigned hints, void* start, size_t old_size)
@ -183,7 +185,7 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s
buf = start; buf = start;
/* one-shot */ /* one-shot */
add_event(BUFFER_EVENT_BUFFER_RESET, true, buffer_reset_handler); add_event_ex(BUFFER_EVENT_BUFFER_RESET, true, buffer_reset_handler, NULL);
} }
return BUFLIB_CB_OK; return BUFLIB_CB_OK;
@ -203,7 +205,7 @@ void radioart_init(bool entering_screen)
buffering_reset(core_get_data(handle), bufsize); buffering_reset(core_get_data(handle), bufsize);
buf = core_get_data(handle); buf = core_get_data(handle);
/* one-shot */ /* one-shot */
add_event(BUFFER_EVENT_BUFFER_RESET, true, buffer_reset_handler); add_event_ex(BUFFER_EVENT_BUFFER_RESET, true, buffer_reset_handler, NULL);
} }
else /* init at startup */ else /* init at startup */
{ {

View file

@ -88,8 +88,9 @@ static int last_screen = GO_TO_ROOT; /* unfortunatly needed so we can resume
static char current_track_path[MAX_PATH]; static char current_track_path[MAX_PATH];
static void rootmenu_track_changed_callback(void* param) static void rootmenu_track_changed_callback(unsigned short id, void* param)
{ {
(void)id;
struct mp3entry *id3 = ((struct track_event *)param)->id3; struct mp3entry *id3 = ((struct track_event *)param)->id3;
strlcpy(current_track_path, id3->path, MAX_PATH); strlcpy(current_track_path, id3->path, MAX_PATH);
} }
@ -746,7 +747,7 @@ void root_menu(void)
if (global_settings.start_in_screen == 0) if (global_settings.start_in_screen == 0)
next_screen = (int)global_status.last_screen; next_screen = (int)global_status.last_screen;
else next_screen = global_settings.start_in_screen - 2; else next_screen = global_settings.start_in_screen - 2;
add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, rootmenu_track_changed_callback); add_event(PLAYBACK_EVENT_TRACK_CHANGE, rootmenu_track_changed_callback);
#ifdef HAVE_RTC_ALARM #ifdef HAVE_RTC_ALARM
if ( rtc_check_alarm_started(true) ) if ( rtc_check_alarm_started(true) )
{ {

View file

@ -150,9 +150,8 @@ static void write_cache(void)
cache_pos = 0; cache_pos = 0;
} }
static void scrobbler_flush_callback(void *data) static void scrobbler_flush_callback(void)
{ {
(void)data;
if (scrobbler_initialised && cache_pos) if (scrobbler_initialised && cache_pos)
write_cache(); write_cache();
} }
@ -200,16 +199,17 @@ static void add_to_cache(const struct mp3entry *id)
} }
static void scrobbler_change_event(void *data) static void scrobbler_change_event(unsigned short id, void *ev_data)
{ {
struct mp3entry *id = ((struct track_event *)data)->id3; (void)id;
struct mp3entry *id3 = ((struct track_event *)ev_data)->id3;
/* check if track was resumed > %50 played /* check if track was resumed > %50 played
check for blank artist or track name */ check for blank artist or track name */
if (id->elapsed > id->length / 2 || !id->artist || !id->title) if (id3->elapsed > id3->length / 2 || !id3->artist || !id3->title)
{ {
pending = false; pending = false;
logf("SCROBBLER: skipping file %s", id->path); logf("SCROBBLER: skipping file %s", id3->path);
} }
else else
{ {
@ -219,8 +219,9 @@ static void scrobbler_change_event(void *data)
} }
} }
static void scrobbler_finish_event(void *data) static void scrobbler_finish_event(unsigned short id, void *data)
{ {
(void)id;
struct track_event *te = (struct track_event *)data; struct track_event *te = (struct track_event *)data;
/* add entry using the currently ending track */ /* add entry using the currently ending track */
@ -254,8 +255,8 @@ int scrobbler_init(void)
scrobbler_initialised = true; scrobbler_initialised = true;
add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, scrobbler_change_event); add_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
add_event(PLAYBACK_EVENT_TRACK_FINISH, false, scrobbler_finish_event); add_event(PLAYBACK_EVENT_TRACK_FINISH, scrobbler_finish_event);
return 1; return 1;
} }

View file

@ -591,15 +591,13 @@ static bool settings_write_config(const char* filename, int options)
return true; return true;
} }
#ifndef HAVE_RTC_RAM #ifndef HAVE_RTC_RAM
static void flush_global_status_callback(void *data) static void flush_global_status_callback(void)
{ {
(void)data;
write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE); write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
} }
#endif #endif
static void flush_config_block_callback(void *data) static void flush_config_block_callback(void)
{ {
(void)data;
write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE); write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
settings_write_config(CONFIGFILE, SETTINGS_SAVE_CHANGED); settings_write_config(CONFIGFILE, SETTINGS_SAVE_CHANGED);
} }
@ -1307,4 +1305,3 @@ void set_file(const char* filename, char* setting, const int maxlen)
strlcpy(setting, fptr, len); strlcpy(setting, fptr, len);
settings_save(); settings_save();
} }

View file

@ -184,9 +184,8 @@ static void init_shortcut(struct shortcut* sc)
static int first_idx_to_writeback = -1; static int first_idx_to_writeback = -1;
static bool overwrite_shortcuts = false; static bool overwrite_shortcuts = false;
static void shortcuts_ata_idle_callback(void* data) static void shortcuts_ata_idle_callback(void)
{ {
(void)data;
int fd; int fd;
char buf[MAX_PATH]; char buf[MAX_PATH];
int current_idx = first_idx_to_writeback; int current_idx = first_idx_to_writeback;
@ -387,7 +386,7 @@ static int shortcut_menu_get_action(int action, struct gui_synclist *lists)
gui_synclist_select_item(lists, shortcut_count - 1); gui_synclist_select_item(lists, shortcut_count - 1);
first_idx_to_writeback = 0; first_idx_to_writeback = 0;
overwrite_shortcuts = true; overwrite_shortcuts = true;
shortcuts_ata_idle_callback(NULL); shortcuts_ata_idle_callback();
if (shortcut_count == 0) if (shortcut_count == 0)
return ACTION_STD_CANCEL; return ACTION_STD_CANCEL;
return ACTION_REDRAW; return ACTION_REDRAW;

View file

@ -3195,9 +3195,8 @@ static bool command_queue_is_full(void)
return (next == command_queue_ridx); return (next == command_queue_ridx);
} }
static void command_queue_sync_callback(void *data) static void command_queue_sync_callback(void)
{ {
(void)data;
struct master_header myhdr; struct master_header myhdr;
int masterfd; int masterfd;
@ -3246,7 +3245,7 @@ static void run_command_queue(bool force)
return; return;
if (force || command_queue_is_full()) if (force || command_queue_is_full())
command_queue_sync_callback(NULL); command_queue_sync_callback();
else else
register_storage_idle_func(command_queue_sync_callback); register_storage_idle_func(command_queue_sync_callback);
} }
@ -4898,4 +4897,3 @@ int tagcache_get_max_commit_step(void)
{ {
return (int)(SORTED_TAGS_COUNT)+1; return (int)(SORTED_TAGS_COUNT)+1;
} }

View file

@ -804,10 +804,11 @@ static int nat_compare(const void *p1, const void *p2)
return strnatcasecmp(e1->name, e2->name); return strnatcasecmp(e1->name, e2->name);
} }
static void tagtree_buffer_event(void *data) static void tagtree_buffer_event(unsigned short id, void *ev_data)
{ {
(void)id;
struct tagcache_search tcs; struct tagcache_search tcs;
struct mp3entry *id3 = ((struct track_event *)data)->id3; struct mp3entry *id3 = ((struct track_event *)ev_data)->id3;
bool runtimedb = global_settings.runtimedb; bool runtimedb = global_settings.runtimedb;
bool autoresume = global_settings.autoresume_enable; bool autoresume = global_settings.autoresume_enable;
@ -868,9 +869,10 @@ static void tagtree_buffer_event(void *data)
tagcache_search_finish(&tcs); tagcache_search_finish(&tcs);
} }
static void tagtree_track_finish_event(void *data) static void tagtree_track_finish_event(unsigned short id, void *ev_data)
{ {
struct track_event *te = (struct track_event *)data; (void)id;
struct track_event *te = (struct track_event *)ev_data;
struct mp3entry *id3 = te->id3; struct mp3entry *id3 = te->id3;
long tagcache_idx = id3->tagcache_idx; long tagcache_idx = id3->tagcache_idx;
@ -1183,8 +1185,8 @@ void tagtree_init(void)
if (rootmenu < 0) if (rootmenu < 0)
rootmenu = 0; rootmenu = 0;
add_event(PLAYBACK_EVENT_TRACK_BUFFER, false, tagtree_buffer_event); add_event(PLAYBACK_EVENT_TRACK_BUFFER, tagtree_buffer_event);
add_event(PLAYBACK_EVENT_TRACK_FINISH, false, tagtree_track_finish_event); add_event(PLAYBACK_EVENT_TRACK_FINISH, tagtree_track_finish_event);
core_shrink(tagtree_handle, core_get_data(tagtree_handle), tagtree_buf_used); core_shrink(tagtree_handle, core_get_data(tagtree_handle), tagtree_buf_used);
} }

View file

@ -25,12 +25,20 @@
#include "kernel.h" #include "kernel.h"
#include "string.h" #include "string.h"
void register_storage_idle_func(void (*function)(void *data)) static void wrapper(unsigned short id, void *ev_data, void *user_data)
{
(void)id;
(void)ev_data;
void (*func)(void) = user_data;
func();
}
void register_storage_idle_func(void (*function)(void))
{ {
#if USING_STORAGE_CALLBACK #if USING_STORAGE_CALLBACK
add_event(DISK_EVENT_SPINUP, true, function); add_event_ex(DISK_EVENT_SPINUP, true, wrapper, function);
#else #else
function(NULL); /* just call the function now */ function(); /* just call the function now */
/* this _may_ cause problems later if the calling function /* this _may_ cause problems later if the calling function
sets a variable expecting the callback to unset it, because sets a variable expecting the callback to unset it, because
the callback will be run before this function exits, so before the var is set */ the callback will be run before this function exits, so before the var is set */
@ -38,12 +46,12 @@ void register_storage_idle_func(void (*function)(void *data))
} }
#if USING_STORAGE_CALLBACK #if USING_STORAGE_CALLBACK
void unregister_storage_idle_func(void (*func)(void *data), bool run) void unregister_storage_idle_func(void (*func)(void), bool run)
{ {
remove_event(DISK_EVENT_SPINUP, func); remove_event_ex(DISK_EVENT_SPINUP, wrapper, func);
if (run) if (run)
func(NULL); func();
} }
bool call_storage_idle_notifys(bool force) bool call_storage_idle_notifys(bool force)

View file

@ -28,30 +28,41 @@
struct sysevent { struct sysevent {
unsigned short id; unsigned short id;
bool oneshot; bool oneshot;
void (*callback)(void *data); bool has_user_data;
union {
void (*callback)(unsigned short id, void *event_data);
struct {
void (*callback2)(unsigned short id, void *event_data, void *user_data);
void *user_data;
};
} handler;
}; };
static struct sysevent events[MAX_SYS_EVENTS]; static struct sysevent events[MAX_SYS_EVENTS];
bool add_event(unsigned short id, bool oneshot, void (*handler)(void *data)) static bool do_add_event(unsigned short id, bool oneshot, bool user_data_valid,
void *handler, void *user_data)
{ {
int i; int i;
/* Check if the event already exists. */ /* Check if the event already exists. */
for (i = 0; i < MAX_SYS_EVENTS; i++) for (i = 0; i < MAX_SYS_EVENTS; i++)
{ {
if (events[i].callback == handler && events[i].id == id) if (events[i].handler.callback == handler && events[i].id == id
&& (!user_data_valid || (user_data == events[i].handler.callback)))
return false; return false;
} }
/* Try to find a free slot. */ /* Try to find a free slot. */
for (i = 0; i < MAX_SYS_EVENTS; i++) for (i = 0; i < MAX_SYS_EVENTS; i++)
{ {
if (events[i].callback == NULL) if (events[i].handler.callback == NULL)
{ {
events[i].id = id; events[i].id = id;
events[i].oneshot = oneshot; events[i].oneshot = oneshot;
events[i].callback = handler; if ((events[i].has_user_data = user_data_valid))
events[i].handler.user_data = user_data;
events[i].handler.callback = handler;
return true; return true;
} }
} }
@ -60,33 +71,59 @@ bool add_event(unsigned short id, bool oneshot, void (*handler)(void *data))
return false; return false;
} }
void remove_event(unsigned short id, void (*handler)(void *data)) bool add_event(unsigned short id, void (*handler)(unsigned short id, void *data))
{
return do_add_event(id, false, false, handler, NULL);
}
bool add_event_ex(unsigned short id, bool oneshot, void (*handler)(unsigned short id, void *event_data, void *user_data), void *user_data)
{
return do_add_event(id, oneshot, true, handler, user_data);
}
void do_remove_event(unsigned short id, bool user_data_valid,
void *handler, void *user_data)
{ {
int i; int i;
for (i = 0; i < MAX_SYS_EVENTS; i++) for (i = 0; i < MAX_SYS_EVENTS; i++)
{ {
if (events[i].id == id && events[i].callback == handler) if (events[i].id == id && events[i].handler.callback == handler
&& (!user_data_valid || (user_data == events[i].handler.callback)))
{ {
events[i].callback = NULL; events[i].handler.callback = NULL;
return; return;
} }
} }
} }
void remove_event(unsigned short id, void (*handler)(unsigned short id, void *data))
{
do_remove_event(id, false, handler, NULL);
}
void remove_event_ex(unsigned short id,
void (*handler)(unsigned short id, void *event_data, void *user_data),
void *user_data)
{
do_remove_event(id, true, handler, user_data);
}
void send_event(unsigned short id, void *data) void send_event(unsigned short id, void *data)
{ {
int i; int i;
for (i = 0; i < MAX_SYS_EVENTS; i++) for (i = 0; i < MAX_SYS_EVENTS; i++)
{ {
if (events[i].id == id && events[i].callback != NULL) if (events[i].id == id && events[i].handler.callback != NULL)
{ {
events[i].callback(data); if (events[i].has_user_data)
events[i].handler.callback2(id, data, events[i].handler.user_data);
else
events[i].handler.callback(id, data);
if (events[i].oneshot) if (events[i].oneshot)
events[i].callback = NULL; events[i].handler.callback = NULL;
} }
} }
} }

View file

@ -48,9 +48,9 @@ enum {
*/ */
#define USING_STORAGE_CALLBACK !defined(BOOTLOADER) && !defined(APPLICATION) && !defined(__PCTOOL__) #define USING_STORAGE_CALLBACK !defined(BOOTLOADER) && !defined(APPLICATION) && !defined(__PCTOOL__)
extern void register_storage_idle_func(void (*function)(void *data)); extern void register_storage_idle_func(void (*function)(void));
#if USING_STORAGE_CALLBACK #if USING_STORAGE_CALLBACK
extern void unregister_storage_idle_func(void (*function)(void *data), bool run); extern void unregister_storage_idle_func(void (*function)(void), bool run);
extern bool call_storage_idle_notifys(bool force); extern bool call_storage_idle_notifys(bool force);
#else #else
#define unregister_storage_idle_func(f,r) #define unregister_storage_idle_func(f,r)

View file

@ -23,12 +23,24 @@
#define _EVENTS_H #define _EVENTS_H
#include <stdbool.h> #include <stdbool.h>
/** Only CLASS defines and firmware/ level events should be defined here.
* apps/ level events are defined in apps/appevents.h
*/
/** /**
* Synchronouos event system.
*
* Callbacks are subscribed with add_event() or add_event_ex(). events
* are fired using send_event().
*
* Events are always dispatched synchronously: the callbacks are called
* in the thread context of the event sender, without context switch. This
* also means that callbacks should be as simple as possible to avoid
* blocking the sender and other callbacks
*
* Use the kernel-level event_queue for cross-thread event dispatching.
* */
/*
* Only CLASS defines and firmware/ level events should be defined here.
* apps/ level events are defined in apps/appevents.h
*
* High byte = Event class definition * High byte = Event class definition
* Low byte = Event ID * Low byte = Event ID
*/ */
@ -40,9 +52,50 @@
#define EVENT_CLASS_RECORDING 0x1000 #define EVENT_CLASS_RECORDING 0x1000
#define EVENT_CLASS_LCD 0x2000 #define EVENT_CLASS_LCD 0x2000
bool add_event(unsigned short id, bool oneshot, void (*handler)(void *data)); /**
void remove_event(unsigned short id, void (*handler)(void *data)); * Subscribe to an event with a simple callback. The callback will be called
* synchronously everytime the event fires, passing the event id and data to
* the callback.
*
* Must be removed with remove_event().
*/
bool add_event(unsigned short id, void (*handler)(unsigned short id, void *event_data));
/**
* Subscribe to an event with a detailed callback. The callback will be called
* synchronously everytime the event fires, passing the event id and data, as
* well as the user_data pointer passed here, to the callback.
*
* With oneshot == true, the callback is unsubscribed automatically after
* the event fired for the first time. In this case the event need not to be
* removed with remove_event_ex().
*
* Must be removed with remove_event_ex(). remove_event() will never remove
* events added with this function.
*/
bool add_event_ex(unsigned short id, bool oneshot, void (*handler)(unsigned short id, void *event_data, void *user_data), void *user_data);
/**
* Unsubscribe a callback from an event. The handler pointer is matched.
*
* This will only work for subscriptions made with add_event().
*/
void remove_event(unsigned short id, void (*handler)(unsigned short id, void *data));
/**
* Unsubscribe a callback from an event. The handler and user_data pointers
* are matched. That means the same user_data that was passed to add_event_ex()
* must be passed to this too.
*
* This will only work for subscriptions made with add_event_ex().
*/
void remove_event_ex(unsigned short id, void (*handler)(unsigned short id, void *event_data, void *user_data), void *user_data);
/**
* Fire an event, which synchronously calls all subscribed callbacks. The
* event id and data pointer are passed to the callbacks as well, and
* optionally the user_data pointer from add_event_ex().
*/
void send_event(unsigned short id, void *data); void send_event(unsigned short id, void *data);
#endif #endif

View file

@ -322,7 +322,7 @@ static int logdiskf_push(void *userp, unsigned char c)
return true; return true;
} }
static void flush_buffer(void* data); static void flush_buffer(void);
void _logdiskf(const char* file, const char level, const char *fmt, ...) void _logdiskf(const char* file, const char level, const char *fmt, ...)
{ {
@ -350,9 +350,8 @@ void _logdiskf(const char* file, const char level, const char *fmt, ...)
register_storage_idle_func(flush_buffer); register_storage_idle_func(flush_buffer);
} }
static void flush_buffer(void* data) static void flush_buffer(void)
{ {
(void)data;
int fd; int fd;
if(logdiskfindex < 1) if(logdiskfindex < 1)
return; return;