summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2014-03-14 23:15:16 +0100
committerThomas Martitz <kugel@rockbox.org>2014-03-14 23:36:30 +0100
commit470989bd708d9a425dbbf2d83b8fcbd0a8d0f488 (patch)
treef3bef37bc0f8ff7da4beddad9903209ced1bc25a
parent50f0dd80d660b332a1739e07a630c2cef1b678c6 (diff)
downloadrockbox-470989bd708d9a425dbbf2d83b8fcbd0a8d0f488.tar.gz
rockbox-470989bd708d9a425dbbf2d83b8fcbd0a8d0f488.zip
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
-rw-r--r--apps/gui/list.c13
-rw-r--r--apps/gui/statusbar-skinned.c3
-rw-r--r--apps/gui/statusbar-skinned.h2
-rw-r--r--apps/gui/viewport.c17
-rw-r--r--apps/gui/wps.c52
-rw-r--r--apps/hosted/android/notification.c10
-rw-r--r--apps/iap/iap-core.c5
-rw-r--r--apps/playback.c39
-rwxr-xr-xapps/playlist.c3
-rw-r--r--apps/plugin.h12
-rw-r--r--apps/plugins/battery_bench.c7
-rw-r--r--apps/plugins/mpegplayer/mpeg_settings.c5
-rw-r--r--apps/plugins/mpegplayer/mpegplayer.c5
-rw-r--r--apps/radio/radioart.c8
-rw-r--r--apps/root_menu.c5
-rw-r--r--apps/scrobbler.c19
-rw-r--r--apps/settings.c7
-rw-r--r--apps/shortcuts.c5
-rw-r--r--apps/tagcache.c6
-rw-r--r--apps/tagtree.c14
-rw-r--r--firmware/ata_idle_notify.c20
-rw-r--r--firmware/events.c61
-rw-r--r--firmware/export/ata_idle_notify.h4
-rw-r--r--firmware/export/events.h69
-rw-r--r--firmware/logf.c5
25 files changed, 247 insertions, 149 deletions
diff --git a/apps/gui/list.c b/apps/gui/list.c
index c393340c57..8663abe8a0 100644
--- a/apps/gui/list.c
+++ b/apps/gui/list.c
@@ -66,16 +66,17 @@ static bool list_is_dirty(struct gui_synclist *list)
66 return TIME_BEFORE(list->dirty_tick, last_dirty_tick); 66 return TIME_BEFORE(list->dirty_tick, last_dirty_tick);
67} 67}
68 68
69static void list_force_reinit(void *param) 69static void list_force_reinit(unsigned short id, void *param, void *last_dirty_tick)
70{ 70{
71 (void)id;
71 (void)param; 72 (void)param;
72 last_dirty_tick = current_tick; 73 *(int *)last_dirty_tick = current_tick;
73} 74}
74 75
75void list_init(void) 76void list_init(void)
76{ 77{
77 last_dirty_tick = current_tick; 78 last_dirty_tick = current_tick;
78 add_event(GUI_EVENT_THEME_CHANGED, false, list_force_reinit); 79 add_event_ex(GUI_EVENT_THEME_CHANGED, false, list_force_reinit, &last_dirty_tick);
79} 80}
80 81
81static void list_init_viewports(struct gui_synclist *list) 82static void list_init_viewports(struct gui_synclist *list)
@@ -611,8 +612,9 @@ bool gui_synclist_keyclick_callback(int action, void* data)
611 */ 612 */
612static struct gui_synclist *current_lists; 613static struct gui_synclist *current_lists;
613static bool ui_update_event_registered = false; 614static bool ui_update_event_registered = false;
614static void _lists_uiviewport_update_callback(void *data) 615static void _lists_uiviewport_update_callback(unsigned short id, void *data)
615{ 616{
617 (void)id;
616 (void)data; 618 (void)data;
617 if (current_lists) 619 if (current_lists)
618 gui_synclist_draw(current_lists); 620 gui_synclist_draw(current_lists);
@@ -801,8 +803,7 @@ int list_do_action_timeout(struct gui_synclist *lists, int timeout)
801 { 803 {
802 if (!ui_update_event_registered) 804 if (!ui_update_event_registered)
803 ui_update_event_registered = 805 ui_update_event_registered =
804 add_event(GUI_EVENT_NEED_UI_UPDATE, false, 806 add_event(GUI_EVENT_NEED_UI_UPDATE, _lists_uiviewport_update_callback);
805 _lists_uiviewport_update_callback);
806 current_lists = lists; 807 current_lists = lists;
807 } 808 }
808 if(lists->scheduled_talk_tick) 809 if(lists->scheduled_talk_tick)
diff --git a/apps/gui/statusbar-skinned.c b/apps/gui/statusbar-skinned.c
index c991d8ea40..c4cc37d539 100644
--- a/apps/gui/statusbar-skinned.c
+++ b/apps/gui/statusbar-skinned.c
@@ -178,8 +178,9 @@ void sb_skin_update(enum screen_type screen, bool force)
178 } 178 }
179} 179}
180 180
181void do_sbs_update_callback(void *param) 181void do_sbs_update_callback(unsigned short id, void *param)
182{ 182{
183 (void)id;
183 (void)param; 184 (void)param;
184 /* the WPS handles changing the actual id3 data in the id3 pointers 185 /* the WPS handles changing the actual id3 data in the id3 pointers
185 * we imported, we just want a full update */ 186 * we imported, we just want a full update */
diff --git a/apps/gui/statusbar-skinned.h b/apps/gui/statusbar-skinned.h
index ac12dfa1aa..237ec45c82 100644
--- a/apps/gui/statusbar-skinned.h
+++ b/apps/gui/statusbar-skinned.h
@@ -66,5 +66,5 @@ int sb_postproccess(enum screen_type screen, struct wps_data *data);
66#define sb_preproccess NULL 66#define sb_preproccess NULL
67#define sb_postproccess NULL 67#define sb_postproccess NULL
68#endif 68#endif
69void do_sbs_update_callback(void *param); 69void do_sbs_update_callback(unsigned short id, void *param);
70#endif /* __STATUSBAR_SKINNED_H__ */ 70#endif /* __STATUSBAR_SKINNED_H__ */
diff --git a/apps/gui/viewport.c b/apps/gui/viewport.c
index aeb884a95d..194954c1d2 100644
--- a/apps/gui/viewport.c
+++ b/apps/gui/viewport.c
@@ -69,7 +69,7 @@ struct viewport_stack_item
69}; 69};
70 70
71#ifdef HAVE_LCD_BITMAP 71#ifdef HAVE_LCD_BITMAP
72static void viewportmanager_redraw(void* data); 72static void viewportmanager_redraw(unsigned short id, void* data);
73 73
74static int theme_stack_top[NB_SCREENS]; /* the last item added */ 74static int theme_stack_top[NB_SCREENS]; /* the last item added */
75static struct viewport_stack_item theme_stack[NB_SCREENS][VPSTACK_DEPTH]; 75static struct viewport_stack_item theme_stack[NB_SCREENS][VPSTACK_DEPTH];
@@ -80,14 +80,12 @@ static void toggle_events(bool enable)
80{ 80{
81 if (enable) 81 if (enable)
82 { 82 {
83 add_event(GUI_EVENT_ACTIONUPDATE, false, viewportmanager_redraw); 83 add_event(GUI_EVENT_ACTIONUPDATE, viewportmanager_redraw);
84#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) 84#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
85 add_event(LCD_EVENT_ACTIVATION, false, do_sbs_update_callback); 85 add_event(LCD_EVENT_ACTIVATION, do_sbs_update_callback);
86#endif 86#endif
87 add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, 87 add_event(PLAYBACK_EVENT_TRACK_CHANGE, do_sbs_update_callback);
88 do_sbs_update_callback); 88 add_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, do_sbs_update_callback);
89 add_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, false,
90 do_sbs_update_callback);
91 } 89 }
92 else 90 else
93 { 91 {
@@ -232,8 +230,9 @@ int viewport_get_nb_lines(const struct viewport *vp)
232#endif 230#endif
233} 231}
234 232
235static void viewportmanager_redraw(void* data) 233static void viewportmanager_redraw(unsigned short id, void* data)
236{ 234{
235 (void)id;
237 FOR_NB_SCREENS(i) 236 FOR_NB_SCREENS(i)
238 { 237 {
239#ifdef HAVE_LCD_BITMAP 238#ifdef HAVE_LCD_BITMAP
@@ -256,7 +255,7 @@ void viewportmanager_init()
256 viewportmanager_theme_enable(i, true, NULL); 255 viewportmanager_theme_enable(i, true, NULL);
257 } 256 }
258#else 257#else
259 add_event(GUI_EVENT_ACTIONUPDATE, false, viewportmanager_redraw); 258 add_event(GUI_EVENT_ACTIONUPDATE, viewportmanager_redraw);
260#endif 259#endif
261} 260}
262 261
diff --git a/apps/gui/wps.c b/apps/gui/wps.c
index b4c3f40e9f..d1161ea71d 100644
--- a/apps/gui/wps.c
+++ b/apps/gui/wps.c
@@ -74,8 +74,7 @@
74 74
75/* initial setup of wps_data */ 75/* initial setup of wps_data */
76static void wps_state_init(void); 76static void wps_state_init(void);
77static void track_changed_callback(void *param); 77static void track_info_callback(unsigned short id, void *param);
78static void nextid3available_callback(void* param);
79 78
80#define WPS_DEFAULTCFG WPS_DIR "/rockbox_default.wps" 79#define WPS_DEFAULTCFG WPS_DIR "/rockbox_default.wps"
81#ifdef HAVE_REMOTE_LCD 80#ifdef HAVE_REMOTE_LCD
@@ -626,8 +625,9 @@ static void play_hop(int direction)
626 * we suppress updates until the wps is activated again (the lcd driver will 625 * we suppress updates until the wps is activated again (the lcd driver will
627 * call this hook to issue an instant update) 626 * call this hook to issue an instant update)
628 * */ 627 * */
629static void wps_lcd_activation_hook(void *param) 628static void wps_lcd_activation_hook(unsigned short id, void *param)
630{ 629{
630 (void)id;
631 (void)param; 631 (void)param;
632 skin_request_full_update(WPS); 632 skin_request_full_update(WPS);
633 /* force timeout in wps main loop, so that the update is instantly */ 633 /* force timeout in wps main loop, so that the update is instantly */
@@ -1119,7 +1119,7 @@ long gui_wps_show(void)
1119 restore = false; 1119 restore = false;
1120 restoretimer = RESTORE_WPS_INSTANTLY; 1120 restoretimer = RESTORE_WPS_INSTANTLY;
1121#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) 1121#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
1122 add_event(LCD_EVENT_ACTIVATION, false, wps_lcd_activation_hook); 1122 add_event(LCD_EVENT_ACTIVATION, wps_lcd_activation_hook);
1123#endif 1123#endif
1124 /* we remove the update delay since it's not very usable in the wps, 1124 /* we remove the update delay since it's not very usable in the wps,
1125 * e.g. during volume changing or ffwd/rewind */ 1125 * e.g. during volume changing or ffwd/rewind */
@@ -1187,35 +1187,27 @@ long gui_wps_show(void)
1187} 1187}
1188 1188
1189/* this is called from the playback thread so NO DRAWING! */ 1189/* this is called from the playback thread so NO DRAWING! */
1190static void track_changed_callback(void *param) 1190static void track_info_callback(unsigned short id, void *param)
1191{ 1191{
1192 struct wps_state *state = skin_get_global_state(); 1192 struct wps_state *state = skin_get_global_state();
1193 state->id3 = ((struct track_event *)param)->id3; 1193
1194 state->nid3 = audio_next_track(); 1194 if (id == PLAYBACK_EVENT_TRACK_CHANGE || id == PLAYBACK_EVENT_CUR_TRACK_READY)
1195 if (state->id3->cuesheet)
1196 { 1195 {
1197 cue_find_current_track(state->id3->cuesheet, state->id3->elapsed); 1196 state->id3 = ((struct track_event *)param)->id3;
1197 if (state->id3->cuesheet)
1198 {
1199 cue_find_current_track(state->id3->cuesheet, state->id3->elapsed);
1200 }
1198 } 1201 }
1199 skin_request_full_update(WPS);
1200}
1201static void nextid3available_callback(void* param)
1202{
1203 (void)param;
1204 skin_get_global_state()->nid3 = audio_next_track();
1205 skin_request_full_update(WPS);
1206}
1207
1208#ifdef AUDIO_FAST_SKIP_PREVIEW 1202#ifdef AUDIO_FAST_SKIP_PREVIEW
1209/* this is called on the audio_skip caller thread */ 1203 else if (id == PLAYBACK_EVENT_TRACK_SKIP)
1210static void track_skip_callback(void *param) 1204 {
1211{ 1205 state->id3 = audio_current_track();
1212 struct wps_state *state = skin_get_global_state(); 1206 }
1213 state->id3 = audio_current_track(); 1207#endif
1214 state->nid3 = audio_next_track(); 1208 skin_get_global_state()->nid3 = audio_next_track();
1215 skin_request_full_update(WPS); 1209 skin_request_full_update(WPS);
1216 (void)param;
1217} 1210}
1218#endif /* AUDIO_FAST_SKIP_PREVIEW */
1219 1211
1220static void wps_state_init(void) 1212static void wps_state_init(void)
1221{ 1213{
@@ -1235,15 +1227,15 @@ static void wps_state_init(void)
1235 /* We'll be updating due to restore initialized with true */ 1227 /* We'll be updating due to restore initialized with true */
1236 skin_request_full_update(WPS); 1228 skin_request_full_update(WPS);
1237 /* add the WPS track event callbacks */ 1229 /* add the WPS track event callbacks */
1238 add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, track_changed_callback); 1230 add_event(PLAYBACK_EVENT_TRACK_CHANGE, track_info_callback);
1239 add_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, false, nextid3available_callback); 1231 add_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, track_info_callback);
1240#if CONFIG_CODEC == SWCODEC 1232#if CONFIG_CODEC == SWCODEC
1241 /* Use the same callback as ..._TRACK_CHANGE for when remaining handles have 1233 /* Use the same callback as ..._TRACK_CHANGE for when remaining handles have
1242 finished */ 1234 finished */
1243 add_event(PLAYBACK_EVENT_CUR_TRACK_READY, false, track_changed_callback); 1235 add_event(PLAYBACK_EVENT_CUR_TRACK_READY, track_info_callback);
1244#endif 1236#endif
1245#ifdef AUDIO_FAST_SKIP_PREVIEW 1237#ifdef AUDIO_FAST_SKIP_PREVIEW
1246 add_event(PLAYBACK_EVENT_TRACK_SKIP, false, track_skip_callback); 1238 add_event(PLAYBACK_EVENT_TRACK_SKIP, track_info_callback);
1247#endif 1239#endif
1248} 1240}
1249 1241
diff --git a/apps/hosted/android/notification.c b/apps/hosted/android/notification.c
index 874cd3bcef..66715d26f9 100644
--- a/apps/hosted/android/notification.c
+++ b/apps/hosted/android/notification.c
@@ -44,8 +44,9 @@ static const struct dim dim = { .width = 200, .height = 200 };
44 44
45/* 45/*
46 * notify about track change, and show track info */ 46 * notify about track change, and show track info */
47static void track_changed_callback(void *param) 47static void track_changed_callback(unsigned short id, void *param)
48{ 48{
49 (void)id;
49 struct mp3entry* id3 = ((struct track_event *)param)->id3; 50 struct mp3entry* id3 = ((struct track_event *)param)->id3;
50 JNIEnv e = *env_ptr; 51 JNIEnv e = *env_ptr;
51 if (id3) 52 if (id3)
@@ -106,8 +107,9 @@ static void track_changed_callback(void *param)
106 107
107/* 108/*
108 * notify about track finishing */ 109 * notify about track finishing */
109static void track_finished_callback(void *param) 110static void track_finished_callback(unsigned short id, void *param)
110{ 111{
112 (void)id;
111 if (((struct track_event *)param)->flags & TEF_REWIND) 113 if (((struct track_event *)param)->flags & TEF_REWIND)
112 return; /* Not a true track end */ 114 return; /* Not a true track end */
113 115
@@ -144,6 +146,6 @@ void notification_init(void)
144 finishNotification = e->GetMethodID(env_ptr, class, "finishNotification", 146 finishNotification = e->GetMethodID(env_ptr, class, "finishNotification",
145 "()V"); 147 "()V");
146 148
147 add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, track_changed_callback); 149 add_event(PLAYBACK_EVENT_TRACK_CHANGE track_changed_callback);
148 add_event(PLAYBACK_EVENT_TRACK_FINISH, false, track_finished_callback); 150 add_event(PLAYBACK_EVENT_TRACK_FINISH track_finished_callback);
149} 151}
diff --git a/apps/iap/iap-core.c b/apps/iap/iap-core.c
index 7226a908c5..4fa9c09a47 100644
--- a/apps/iap/iap-core.c
+++ b/apps/iap/iap-core.c
@@ -349,8 +349,9 @@ static void iap_thread(void)
349} 349}
350 350
351/* called by playback when the next track starts */ 351/* called by playback when the next track starts */
352static void iap_track_changed(void *ignored) 352static void iap_track_changed(unsigned short id, void *ignored)
353{ 353{
354 (void)id;
354 (void)ignored; 355 (void)ignored;
355 if ((interface_state == IST_EXTENDED) && device.do_notify) { 356 if ((interface_state == IST_EXTENDED) && device.do_notify) {
356 long playlist_pos = playlist_next(0); 357 long playlist_pos = playlist_next(0);
@@ -401,7 +402,7 @@ static void iap_start(void)
401 if (!tid) 402 if (!tid)
402 panicf("Could not create iap thread"); 403 panicf("Could not create iap thread");
403 timeout_register(&iap_task_tmo, iap_task, MS_TO_TICKS(100), (intptr_t)NULL); 404 timeout_register(&iap_task_tmo, iap_task, MS_TO_TICKS(100), (intptr_t)NULL);
404 add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, iap_track_changed); 405 add_event(PLAYBACK_EVENT_TRACK_CHANGE, iap_track_changed);
405 406
406 /* Since we cannot allocate memory while in interrupt context 407 /* Since we cannot allocate memory while in interrupt context
407 * post a message to our own queue to get that done 408 * post a message to our own queue to get that done
diff --git a/apps/playback.c b/apps/playback.c
index 80a0585b17..eba90f9a0a 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -334,17 +334,18 @@ enum audio_start_playback_flags
334static void audio_start_playback(const struct audio_resume_info *resume_info, 334static void audio_start_playback(const struct audio_resume_info *resume_info,
335 unsigned int flags); 335 unsigned int flags);
336static void audio_stop_playback(void); 336static void audio_stop_playback(void);
337static void buffer_event_buffer_low_callback(void *data); 337static void buffer_event_buffer_low_callback(unsigned short id, void *data, void *user_data);
338static void buffer_event_rebuffer_callback(void *data); 338static void buffer_event_rebuffer_callback(unsigned short id, void *data);
339static void buffer_event_finished_callback(void *data); 339static void buffer_event_finished_callback(unsigned short id, void *data);
340void audio_pcmbuf_sync_position(void); 340void audio_pcmbuf_sync_position(void);
341 341
342 342
343/**************************************/ 343/**************************************/
344 344
345/** --- voice event --- **/ 345/** --- voice event --- **/
346void playback_voice_event(void *data) 346void playback_voice_event(unsigned short id, void *data)
347{ 347{
348 (void)id;
348 /* Make audio play softly while voice is speaking */ 349 /* Make audio play softly while voice is speaking */
349 pcmbuf_soft_mode(*(bool *)data); 350 pcmbuf_soft_mode(*(bool *)data);
350} 351}
@@ -1757,7 +1758,7 @@ static int audio_load_track(void)
1757 should have been cleared already */ 1758 should have been cleared already */
1758 logf("%s(): finishing load: %d", __func__, info->id3_hid); 1759 logf("%s(): finishing load: %d", __func__, info->id3_hid);
1759 filling = STATE_FILLING; 1760 filling = STATE_FILLING;
1760 buffer_event_finished_callback(&info->id3_hid); 1761 buffer_event_finished_callback(BUFFER_EVENT_FINISHED, &info->id3_hid);
1761 return LOAD_TRACK_OK; 1762 return LOAD_TRACK_OK;
1762 } 1763 }
1763 } 1764 }
@@ -2585,8 +2586,8 @@ static void audio_start_playback(const struct audio_resume_info *resume_info,
2585 2586
2586 /* Add these now - finish event for the first id3 will most likely be sent 2587 /* Add these now - finish event for the first id3 will most likely be sent
2587 immediately */ 2588 immediately */
2588 add_event(BUFFER_EVENT_REBUFFER, false, buffer_event_rebuffer_callback); 2589 add_event(BUFFER_EVENT_REBUFFER, buffer_event_rebuffer_callback);
2589 add_event(BUFFER_EVENT_FINISHED, false, buffer_event_finished_callback); 2590 add_event(BUFFER_EVENT_FINISHED, buffer_event_finished_callback);
2590 2591
2591 if (old_status == PLAY_STOPPED) 2592 if (old_status == PLAY_STOPPED)
2592 { 2593 {
@@ -2647,7 +2648,7 @@ static void audio_stop_playback(void)
2647 /* Close all tracks and mark them NULL */ 2648 /* Close all tracks and mark them NULL */
2648 remove_event(BUFFER_EVENT_REBUFFER, buffer_event_rebuffer_callback); 2649 remove_event(BUFFER_EVENT_REBUFFER, buffer_event_rebuffer_callback);
2649 remove_event(BUFFER_EVENT_FINISHED, buffer_event_finished_callback); 2650 remove_event(BUFFER_EVENT_FINISHED, buffer_event_finished_callback);
2650 remove_event(BUFFER_EVENT_BUFFER_LOW, buffer_event_buffer_low_callback); 2651 remove_event_ex(BUFFER_EVENT_BUFFER_LOW, buffer_event_buffer_low_callback, NULL);
2651 2652
2652 track_list_clear(TRACK_LIST_CLEAR_ALL); 2653 track_list_clear(TRACK_LIST_CLEAR_ALL);
2653 2654
@@ -3164,8 +3165,8 @@ void audio_playback_handler(struct queue_event *ev)
3164 /* End of buffering for now, let's calculate the watermark, 3165 /* End of buffering for now, let's calculate the watermark,
3165 register for a low buffer event and unboost */ 3166 register for a low buffer event and unboost */
3166 audio_update_filebuf_watermark(0); 3167 audio_update_filebuf_watermark(0);
3167 add_event(BUFFER_EVENT_BUFFER_LOW, true, 3168 add_event_ex(BUFFER_EVENT_BUFFER_LOW, true,
3168 buffer_event_buffer_low_callback); 3169 buffer_event_buffer_low_callback, NULL);
3169 } 3170 }
3170 /* Fall-through */ 3171 /* Fall-through */
3171 case STATE_FINISHED: 3172 case STATE_FINISHED:
@@ -3200,27 +3201,31 @@ void audio_playback_handler(struct queue_event *ev)
3200/* --- Buffering callbacks --- */ 3201/* --- Buffering callbacks --- */
3201 3202
3202/* Called when fullness is below the watermark level */ 3203/* Called when fullness is below the watermark level */
3203static void buffer_event_buffer_low_callback(void *data) 3204static void buffer_event_buffer_low_callback(unsigned short id, void *ev_data, void *user_data)
3204{ 3205{
3205 logf("low buffer callback"); 3206 logf("low buffer callback");
3206 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: buffer low"); 3207 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: buffer low");
3207 audio_queue_post(Q_AUDIO_BUFFERING, BUFFER_EVENT_BUFFER_LOW); 3208 audio_queue_post(Q_AUDIO_BUFFERING, BUFFER_EVENT_BUFFER_LOW);
3208 (void)data; 3209 (void)id;
3210 (void)ev_data;
3211 (void)user_data;
3209} 3212}
3210 3213
3211/* Called when handles must be discarded in order to buffer new data */ 3214/* Called when handles must be discarded in order to buffer new data */
3212static void buffer_event_rebuffer_callback(void *data) 3215static void buffer_event_rebuffer_callback(unsigned short id, void *ev_data)
3213{ 3216{
3214 logf("rebuffer callback"); 3217 logf("rebuffer callback");
3215 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: rebuffer"); 3218 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: rebuffer");
3216 audio_queue_post(Q_AUDIO_BUFFERING, BUFFER_EVENT_REBUFFER); 3219 audio_queue_post(Q_AUDIO_BUFFERING, BUFFER_EVENT_REBUFFER);
3217 (void)data; 3220 (void)id;
3221 (void)ev_data;
3218} 3222}
3219 3223
3220/* A handle has completed buffering and all required data is available */ 3224/* A handle has completed buffering and all required data is available */
3221static void buffer_event_finished_callback(void *data) 3225static void buffer_event_finished_callback(unsigned short id, void *ev_data)
3222{ 3226{
3223 int hid = *(const int *)data; 3227 (void)id;
3228 int hid = *(const int *)ev_data;
3224 const enum data_type htype = buf_handle_data_type(hid); 3229 const enum data_type htype = buf_handle_data_type(hid);
3225 3230
3226 logf("handle %d finished buffering (type:%u)", hid, (unsigned)htype); 3231 logf("handle %d finished buffering (type:%u)", hid, (unsigned)htype);
@@ -3717,7 +3722,7 @@ void INIT_ATTR playback_init(void)
3717 track_list_init(); 3722 track_list_init();
3718 buffering_init(); 3723 buffering_init();
3719 pcmbuf_update_frequency(); 3724 pcmbuf_update_frequency();
3720 add_event(PLAYBACK_EVENT_VOICE_PLAYING, false, playback_voice_event); 3725 add_event(PLAYBACK_EVENT_VOICE_PLAYING, playback_voice_event);
3721#ifdef HAVE_CROSSFADE 3726#ifdef HAVE_CROSSFADE
3722 /* Set crossfade setting for next buffer init which should be about... */ 3727 /* Set crossfade setting for next buffer init which should be about... */
3723 pcmbuf_request_crossfade_enable(global_settings.crossfade); 3728 pcmbuf_request_crossfade_enable(global_settings.crossfade);
diff --git a/apps/playlist.c b/apps/playlist.c
index 0e73781238..a066dd2ea0 100755
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -1223,9 +1223,8 @@ static int compare(const void* p1, const void* p2)
1223 * without affecting playlist load up performance. This thread also flushes 1223 * without affecting playlist load up performance. This thread also flushes
1224 * any pending control commands when the disk spins up. 1224 * any pending control commands when the disk spins up.
1225 */ 1225 */
1226static void playlist_flush_callback(void *param) 1226static void playlist_flush_callback(void)
1227{ 1227{
1228 (void)param;
1229 struct playlist_info *playlist; 1228 struct playlist_info *playlist;
1230 playlist = &current_playlist; 1229 playlist = &current_playlist;
1231 if (playlist->control_fd >= 0) 1230 if (playlist->control_fd >= 0)
diff --git a/apps/plugin.h b/apps/plugin.h
index ffdfa8fb77..874f6e0069 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -160,12 +160,12 @@ void* plugin_get_buffer(size_t *buffer_size);
160#define PLUGIN_MAGIC 0x526F634B /* RocK */ 160#define PLUGIN_MAGIC 0x526F634B /* RocK */
161 161
162/* increase this every time the api struct changes */ 162/* increase this every time the api struct changes */
163#define PLUGIN_API_VERSION 227 163#define PLUGIN_API_VERSION 228
164 164
165/* update this to latest version if a change to the api struct breaks 165/* update this to latest version if a change to the api struct breaks
166 backwards compatibility (and please take the opportunity to sort in any 166 backwards compatibility (and please take the opportunity to sort in any
167 new function which are "waiting" at the end of the function table) */ 167 new function which are "waiting" at the end of the function table) */
168#define PLUGIN_MIN_API_VERSION 227 168#define PLUGIN_MIN_API_VERSION 228
169 169
170/* plugin return codes */ 170/* plugin return codes */
171/* internal returns start at 0x100 to make exit(1..255) work */ 171/* internal returns start at 0x100 to make exit(1..255) work */
@@ -450,8 +450,8 @@ struct plugin_api {
450 void (*storage_spin)(void); 450 void (*storage_spin)(void);
451 void (*storage_spindown)(int seconds); 451 void (*storage_spindown)(int seconds);
452#if USING_STORAGE_CALLBACK 452#if USING_STORAGE_CALLBACK
453 void (*register_storage_idle_func)(void (*function)(void *data)); 453 void (*register_storage_idle_func)(void (*function)(void));
454 void (*unregister_storage_idle_func)(void (*function)(void *data), bool run); 454 void (*unregister_storage_idle_func)(void (*function)(void), bool run);
455#endif /* USING_STORAGE_CALLBACK */ 455#endif /* USING_STORAGE_CALLBACK */
456 void (*reload_directory)(void); 456 void (*reload_directory)(void);
457 char *(*create_numbered_filename)(char *buffer, const char *path, 457 char *(*create_numbered_filename)(char *buffer, const char *path,
@@ -569,8 +569,8 @@ struct plugin_api {
569 void (*profile_func_exit)(void *this_fn, void *call_site); 569 void (*profile_func_exit)(void *this_fn, void *call_site);
570#endif 570#endif
571 /* event api */ 571 /* event api */
572 bool (*add_event)(unsigned short id, bool oneshot, void (*handler)(void *data)); 572 bool (*add_event)(unsigned short id, void (*handler)(unsigned short id, void *data));
573 void (*remove_event)(unsigned short id, void (*handler)(void *data)); 573 void (*remove_event)(unsigned short id, void (*handler)(unsigned short id, void *data));
574 void (*send_event)(unsigned short id, void *data); 574 void (*send_event)(unsigned short id, void *data);
575 575
576#if (CONFIG_PLATFORM & PLATFORM_HOSTED) 576#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
diff --git a/apps/plugins/battery_bench.c b/apps/plugins/battery_bench.c
index 93876d0807..174a589d8f 100644
--- a/apps/plugins/battery_bench.c
+++ b/apps/plugins/battery_bench.c
@@ -359,9 +359,8 @@ static unsigned int charge_state(void)
359#endif 359#endif
360 360
361 361
362static void flush_buffer(void* data) 362static void flush_buffer(void)
363{ 363{
364 (void)data;
365 int fd; 364 int fd;
366 unsigned int i; 365 unsigned int i;
367 366
@@ -445,7 +444,7 @@ static void thread(void)
445 for this to occur because it requires > 16 hours of no disk activity. 444 for this to occur because it requires > 16 hours of no disk activity.
446 */ 445 */
447 if (buf_idx == BUF_ELEMENTS) { 446 if (buf_idx == BUF_ELEMENTS) {
448 flush_buffer(NULL); 447 flush_buffer();
449 } 448 }
450 449
451 /* sleep some time until next measurement */ 450 /* sleep some time until next measurement */
@@ -479,7 +478,7 @@ static void thread(void)
479 /* unregister flush callback and flush to disk */ 478 /* unregister flush callback and flush to disk */
480 rb->unregister_storage_idle_func(flush_buffer, true); 479 rb->unregister_storage_idle_func(flush_buffer, true);
481#else 480#else
482 flush_buffer(NULL); 481 flush_buffer();
483#endif 482#endif
484 483
485 /* log end of bench and exit reason */ 484 /* log end of bench and exit reason */
diff --git a/apps/plugins/mpegplayer/mpeg_settings.c b/apps/plugins/mpegplayer/mpeg_settings.c
index bcef4c66bf..b5c9c6bbc8 100644
--- a/apps/plugins/mpegplayer/mpeg_settings.c
+++ b/apps/plugins/mpegplayer/mpeg_settings.c
@@ -677,8 +677,9 @@ static uint32_t increment_time(uint32_t val, int32_t amount, uint32_t range)
677} 677}
678 678
679#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) 679#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
680static void get_start_time_lcd_enable_hook(void *param) 680static void get_start_time_lcd_enable_hook(unsigned short id, void *param)
681{ 681{
682 (void)id;
682 (void)param; 683 (void)param;
683 rb->queue_post(rb->button_queue, LCD_ENABLE_EVENT_0, 0); 684 rb->queue_post(rb->button_queue, LCD_ENABLE_EVENT_0, 0);
684} 685}
@@ -698,7 +699,7 @@ static int get_start_time(uint32_t duration)
698 mylcd_update(); 699 mylcd_update();
699 700
700#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) 701#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
701 rb->add_event(LCD_EVENT_ACTIVATION, false, get_start_time_lcd_enable_hook); 702 rb->add_event(LCD_EVENT_ACTIVATION, get_start_time_lcd_enable_hook);
702#endif 703#endif
703 704
704 draw_slider(0, 100, &rc_bound); 705 draw_slider(0, 100, &rc_bound);
diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c
index 928c48ab11..467c961912 100644
--- a/apps/plugins/mpegplayer/mpegplayer.c
+++ b/apps/plugins/mpegplayer/mpegplayer.c
@@ -1026,8 +1026,9 @@ static void fps_init(void)
1026 1026
1027#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) 1027#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
1028/* So we can refresh the overlay */ 1028/* So we can refresh the overlay */
1029static void osd_lcd_enable_hook(void* param) 1029static void osd_lcd_enable_hook(unsigned short id, void* param)
1030{ 1030{
1031 (void)id;
1031 (void)param; 1032 (void)param;
1032 rb->queue_post(rb->button_queue, LCD_ENABLE_EVENT_1, 0); 1033 rb->queue_post(rb->button_queue, LCD_ENABLE_EVENT_1, 0);
1033} 1034}
@@ -1043,7 +1044,7 @@ static void osd_backlight_on_video_mode(bool video_on)
1043#endif 1044#endif
1044 } else { 1045 } else {
1045#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) 1046#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
1046 rb->add_event(LCD_EVENT_ACTIVATION, false, osd_lcd_enable_hook); 1047 rb->add_event(LCD_EVENT_ACTIVATION, osd_lcd_enable_hook);
1047#endif 1048#endif
1048 /* Revert to user's backlight settings */ 1049 /* Revert to user's backlight settings */
1049 backlight_use_settings(); 1050 backlight_use_settings();
diff --git a/apps/radio/radioart.c b/apps/radio/radioart.c
index 86a987c14f..283815167a 100644
--- a/apps/radio/radioart.c
+++ b/apps/radio/radioart.c
@@ -145,7 +145,7 @@ int radio_get_art_hid(struct dim *requested_dim)
145 return -1; 145 return -1;
146} 146}
147 147
148static void buffer_reset_handler(void *data) 148static void buffer_reset_handler(unsigned short id, void *data, void *user_data)
149{ 149{
150 buf = NULL; 150 buf = NULL;
151 for(int i=0;i<MAX_RADIOART_IMAGES;i++) 151 for(int i=0;i<MAX_RADIOART_IMAGES;i++)
@@ -156,7 +156,9 @@ static void buffer_reset_handler(void *data)
156 radioart[i].name[0] = '\0'; 156 radioart[i].name[0] = '\0';
157 } 157 }
158 158
159 (void)id;
159 (void)data; 160 (void)data;
161 (void)user_data;
160} 162}
161 163
162static int shrink_callback(int handle, unsigned hints, void* start, size_t old_size) 164static 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
183 buf = start; 185 buf = start;
184 186
185 /* one-shot */ 187 /* one-shot */
186 add_event(BUFFER_EVENT_BUFFER_RESET, true, buffer_reset_handler); 188 add_event_ex(BUFFER_EVENT_BUFFER_RESET, true, buffer_reset_handler, NULL);
187 } 189 }
188 190
189 return BUFLIB_CB_OK; 191 return BUFLIB_CB_OK;
@@ -203,7 +205,7 @@ void radioart_init(bool entering_screen)
203 buffering_reset(core_get_data(handle), bufsize); 205 buffering_reset(core_get_data(handle), bufsize);
204 buf = core_get_data(handle); 206 buf = core_get_data(handle);
205 /* one-shot */ 207 /* one-shot */
206 add_event(BUFFER_EVENT_BUFFER_RESET, true, buffer_reset_handler); 208 add_event_ex(BUFFER_EVENT_BUFFER_RESET, true, buffer_reset_handler, NULL);
207 } 209 }
208 else /* init at startup */ 210 else /* init at startup */
209 { 211 {
diff --git a/apps/root_menu.c b/apps/root_menu.c
index 09c7efad9d..c94a4443e6 100644
--- a/apps/root_menu.c
+++ b/apps/root_menu.c
@@ -88,8 +88,9 @@ static int last_screen = GO_TO_ROOT; /* unfortunatly needed so we can resume
88 88
89 89
90static char current_track_path[MAX_PATH]; 90static char current_track_path[MAX_PATH];
91static void rootmenu_track_changed_callback(void* param) 91static void rootmenu_track_changed_callback(unsigned short id, void* param)
92{ 92{
93 (void)id;
93 struct mp3entry *id3 = ((struct track_event *)param)->id3; 94 struct mp3entry *id3 = ((struct track_event *)param)->id3;
94 strlcpy(current_track_path, id3->path, MAX_PATH); 95 strlcpy(current_track_path, id3->path, MAX_PATH);
95} 96}
@@ -746,7 +747,7 @@ void root_menu(void)
746 if (global_settings.start_in_screen == 0) 747 if (global_settings.start_in_screen == 0)
747 next_screen = (int)global_status.last_screen; 748 next_screen = (int)global_status.last_screen;
748 else next_screen = global_settings.start_in_screen - 2; 749 else next_screen = global_settings.start_in_screen - 2;
749 add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, rootmenu_track_changed_callback); 750 add_event(PLAYBACK_EVENT_TRACK_CHANGE, rootmenu_track_changed_callback);
750#ifdef HAVE_RTC_ALARM 751#ifdef HAVE_RTC_ALARM
751 if ( rtc_check_alarm_started(true) ) 752 if ( rtc_check_alarm_started(true) )
752 { 753 {
diff --git a/apps/scrobbler.c b/apps/scrobbler.c
index efd028327c..b8a95f85cb 100644
--- a/apps/scrobbler.c
+++ b/apps/scrobbler.c
@@ -150,9 +150,8 @@ static void write_cache(void)
150 cache_pos = 0; 150 cache_pos = 0;
151} 151}
152 152
153static void scrobbler_flush_callback(void *data) 153static void scrobbler_flush_callback(void)
154{ 154{
155 (void)data;
156 if (scrobbler_initialised && cache_pos) 155 if (scrobbler_initialised && cache_pos)
157 write_cache(); 156 write_cache();
158} 157}
@@ -200,16 +199,17 @@ static void add_to_cache(const struct mp3entry *id)
200 199
201} 200}
202 201
203static void scrobbler_change_event(void *data) 202static void scrobbler_change_event(unsigned short id, void *ev_data)
204{ 203{
205 struct mp3entry *id = ((struct track_event *)data)->id3; 204 (void)id;
205 struct mp3entry *id3 = ((struct track_event *)ev_data)->id3;
206 206
207 /* check if track was resumed > %50 played 207 /* check if track was resumed > %50 played
208 check for blank artist or track name */ 208 check for blank artist or track name */
209 if (id->elapsed > id->length / 2 || !id->artist || !id->title) 209 if (id3->elapsed > id3->length / 2 || !id3->artist || !id3->title)
210 { 210 {
211 pending = false; 211 pending = false;
212 logf("SCROBBLER: skipping file %s", id->path); 212 logf("SCROBBLER: skipping file %s", id3->path);
213 } 213 }
214 else 214 else
215 { 215 {
@@ -219,8 +219,9 @@ static void scrobbler_change_event(void *data)
219 } 219 }
220} 220}
221 221
222static void scrobbler_finish_event(void *data) 222static void scrobbler_finish_event(unsigned short id, void *data)
223{ 223{
224 (void)id;
224 struct track_event *te = (struct track_event *)data; 225 struct track_event *te = (struct track_event *)data;
225 226
226 /* add entry using the currently ending track */ 227 /* add entry using the currently ending track */
@@ -254,8 +255,8 @@ int scrobbler_init(void)
254 255
255 scrobbler_initialised = true; 256 scrobbler_initialised = true;
256 257
257 add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, scrobbler_change_event); 258 add_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
258 add_event(PLAYBACK_EVENT_TRACK_FINISH, false, scrobbler_finish_event); 259 add_event(PLAYBACK_EVENT_TRACK_FINISH, scrobbler_finish_event);
259 260
260 return 1; 261 return 1;
261} 262}
diff --git a/apps/settings.c b/apps/settings.c
index 58d58788be..f2a923e24d 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -591,15 +591,13 @@ static bool settings_write_config(const char* filename, int options)
591 return true; 591 return true;
592} 592}
593#ifndef HAVE_RTC_RAM 593#ifndef HAVE_RTC_RAM
594static void flush_global_status_callback(void *data) 594static void flush_global_status_callback(void)
595{ 595{
596 (void)data;
597 write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE); 596 write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
598} 597}
599#endif 598#endif
600static void flush_config_block_callback(void *data) 599static void flush_config_block_callback(void)
601{ 600{
602 (void)data;
603 write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE); 601 write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
604 settings_write_config(CONFIGFILE, SETTINGS_SAVE_CHANGED); 602 settings_write_config(CONFIGFILE, SETTINGS_SAVE_CHANGED);
605} 603}
@@ -1307,4 +1305,3 @@ void set_file(const char* filename, char* setting, const int maxlen)
1307 strlcpy(setting, fptr, len); 1305 strlcpy(setting, fptr, len);
1308 settings_save(); 1306 settings_save();
1309} 1307}
1310
diff --git a/apps/shortcuts.c b/apps/shortcuts.c
index ee8454485d..a9ae8248f1 100644
--- a/apps/shortcuts.c
+++ b/apps/shortcuts.c
@@ -184,9 +184,8 @@ static void init_shortcut(struct shortcut* sc)
184 184
185static int first_idx_to_writeback = -1; 185static int first_idx_to_writeback = -1;
186static bool overwrite_shortcuts = false; 186static bool overwrite_shortcuts = false;
187static void shortcuts_ata_idle_callback(void* data) 187static void shortcuts_ata_idle_callback(void)
188{ 188{
189 (void)data;
190 int fd; 189 int fd;
191 char buf[MAX_PATH]; 190 char buf[MAX_PATH];
192 int current_idx = first_idx_to_writeback; 191 int current_idx = first_idx_to_writeback;
@@ -387,7 +386,7 @@ static int shortcut_menu_get_action(int action, struct gui_synclist *lists)
387 gui_synclist_select_item(lists, shortcut_count - 1); 386 gui_synclist_select_item(lists, shortcut_count - 1);
388 first_idx_to_writeback = 0; 387 first_idx_to_writeback = 0;
389 overwrite_shortcuts = true; 388 overwrite_shortcuts = true;
390 shortcuts_ata_idle_callback(NULL); 389 shortcuts_ata_idle_callback();
391 if (shortcut_count == 0) 390 if (shortcut_count == 0)
392 return ACTION_STD_CANCEL; 391 return ACTION_STD_CANCEL;
393 return ACTION_REDRAW; 392 return ACTION_REDRAW;
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 3ce0247188..b7d5516e81 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -3195,9 +3195,8 @@ static bool command_queue_is_full(void)
3195 return (next == command_queue_ridx); 3195 return (next == command_queue_ridx);
3196} 3196}
3197 3197
3198static void command_queue_sync_callback(void *data) 3198static void command_queue_sync_callback(void)
3199{ 3199{
3200 (void)data;
3201 struct master_header myhdr; 3200 struct master_header myhdr;
3202 int masterfd; 3201 int masterfd;
3203 3202
@@ -3246,7 +3245,7 @@ static void run_command_queue(bool force)
3246 return; 3245 return;
3247 3246
3248 if (force || command_queue_is_full()) 3247 if (force || command_queue_is_full())
3249 command_queue_sync_callback(NULL); 3248 command_queue_sync_callback();
3250 else 3249 else
3251 register_storage_idle_func(command_queue_sync_callback); 3250 register_storage_idle_func(command_queue_sync_callback);
3252} 3251}
@@ -4898,4 +4897,3 @@ int tagcache_get_max_commit_step(void)
4898{ 4897{
4899 return (int)(SORTED_TAGS_COUNT)+1; 4898 return (int)(SORTED_TAGS_COUNT)+1;
4900} 4899}
4901
diff --git a/apps/tagtree.c b/apps/tagtree.c
index ff364ec5e4..b3b94a489e 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -804,10 +804,11 @@ static int nat_compare(const void *p1, const void *p2)
804 return strnatcasecmp(e1->name, e2->name); 804 return strnatcasecmp(e1->name, e2->name);
805} 805}
806 806
807static void tagtree_buffer_event(void *data) 807static void tagtree_buffer_event(unsigned short id, void *ev_data)
808{ 808{
809 (void)id;
809 struct tagcache_search tcs; 810 struct tagcache_search tcs;
810 struct mp3entry *id3 = ((struct track_event *)data)->id3; 811 struct mp3entry *id3 = ((struct track_event *)ev_data)->id3;
811 812
812 bool runtimedb = global_settings.runtimedb; 813 bool runtimedb = global_settings.runtimedb;
813 bool autoresume = global_settings.autoresume_enable; 814 bool autoresume = global_settings.autoresume_enable;
@@ -868,9 +869,10 @@ static void tagtree_buffer_event(void *data)
868 tagcache_search_finish(&tcs); 869 tagcache_search_finish(&tcs);
869} 870}
870 871
871static void tagtree_track_finish_event(void *data) 872static void tagtree_track_finish_event(unsigned short id, void *ev_data)
872{ 873{
873 struct track_event *te = (struct track_event *)data; 874 (void)id;
875 struct track_event *te = (struct track_event *)ev_data;
874 struct mp3entry *id3 = te->id3; 876 struct mp3entry *id3 = te->id3;
875 877
876 long tagcache_idx = id3->tagcache_idx; 878 long tagcache_idx = id3->tagcache_idx;
@@ -1183,8 +1185,8 @@ void tagtree_init(void)
1183 if (rootmenu < 0) 1185 if (rootmenu < 0)
1184 rootmenu = 0; 1186 rootmenu = 0;
1185 1187
1186 add_event(PLAYBACK_EVENT_TRACK_BUFFER, false, tagtree_buffer_event); 1188 add_event(PLAYBACK_EVENT_TRACK_BUFFER, tagtree_buffer_event);
1187 add_event(PLAYBACK_EVENT_TRACK_FINISH, false, tagtree_track_finish_event); 1189 add_event(PLAYBACK_EVENT_TRACK_FINISH, tagtree_track_finish_event);
1188 1190
1189 core_shrink(tagtree_handle, core_get_data(tagtree_handle), tagtree_buf_used); 1191 core_shrink(tagtree_handle, core_get_data(tagtree_handle), tagtree_buf_used);
1190} 1192}
diff --git a/firmware/ata_idle_notify.c b/firmware/ata_idle_notify.c
index 35d192bee0..ee9f3c035f 100644
--- a/firmware/ata_idle_notify.c
+++ b/firmware/ata_idle_notify.c
@@ -25,12 +25,20 @@
25#include "kernel.h" 25#include "kernel.h"
26#include "string.h" 26#include "string.h"
27 27
28void register_storage_idle_func(void (*function)(void *data)) 28static void wrapper(unsigned short id, void *ev_data, void *user_data)
29{
30 (void)id;
31 (void)ev_data;
32 void (*func)(void) = user_data;
33 func();
34}
35
36void register_storage_idle_func(void (*function)(void))
29{ 37{
30#if USING_STORAGE_CALLBACK 38#if USING_STORAGE_CALLBACK
31 add_event(DISK_EVENT_SPINUP, true, function); 39 add_event_ex(DISK_EVENT_SPINUP, true, wrapper, function);
32#else 40#else
33 function(NULL); /* just call the function now */ 41 function(); /* just call the function now */
34/* this _may_ cause problems later if the calling function 42/* this _may_ cause problems later if the calling function
35 sets a variable expecting the callback to unset it, because 43 sets a variable expecting the callback to unset it, because
36 the callback will be run before this function exits, so before the var is set */ 44 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))
38} 46}
39 47
40#if USING_STORAGE_CALLBACK 48#if USING_STORAGE_CALLBACK
41void unregister_storage_idle_func(void (*func)(void *data), bool run) 49void unregister_storage_idle_func(void (*func)(void), bool run)
42{ 50{
43 remove_event(DISK_EVENT_SPINUP, func); 51 remove_event_ex(DISK_EVENT_SPINUP, wrapper, func);
44 52
45 if (run) 53 if (run)
46 func(NULL); 54 func();
47} 55}
48 56
49bool call_storage_idle_notifys(bool force) 57bool call_storage_idle_notifys(bool force)
diff --git a/firmware/events.c b/firmware/events.c
index 74172e1fa0..4a51e7ae87 100644
--- a/firmware/events.c
+++ b/firmware/events.c
@@ -28,30 +28,41 @@
28struct sysevent { 28struct sysevent {
29 unsigned short id; 29 unsigned short id;
30 bool oneshot; 30 bool oneshot;
31 void (*callback)(void *data); 31 bool has_user_data;
32 union {
33 void (*callback)(unsigned short id, void *event_data);
34 struct {
35 void (*callback2)(unsigned short id, void *event_data, void *user_data);
36 void *user_data;
37 };
38 } handler;
32}; 39};
33 40
34static struct sysevent events[MAX_SYS_EVENTS]; 41static struct sysevent events[MAX_SYS_EVENTS];
35 42
36bool add_event(unsigned short id, bool oneshot, void (*handler)(void *data)) 43static bool do_add_event(unsigned short id, bool oneshot, bool user_data_valid,
44 void *handler, void *user_data)
37{ 45{
38 int i; 46 int i;
39 47
40 /* Check if the event already exists. */ 48 /* Check if the event already exists. */
41 for (i = 0; i < MAX_SYS_EVENTS; i++) 49 for (i = 0; i < MAX_SYS_EVENTS; i++)
42 { 50 {
43 if (events[i].callback == handler && events[i].id == id) 51 if (events[i].handler.callback == handler && events[i].id == id
52 && (!user_data_valid || (user_data == events[i].handler.callback)))
44 return false; 53 return false;
45 } 54 }
46 55
47 /* Try to find a free slot. */ 56 /* Try to find a free slot. */
48 for (i = 0; i < MAX_SYS_EVENTS; i++) 57 for (i = 0; i < MAX_SYS_EVENTS; i++)
49 { 58 {
50 if (events[i].callback == NULL) 59 if (events[i].handler.callback == NULL)
51 { 60 {
52 events[i].id = id; 61 events[i].id = id;
53 events[i].oneshot = oneshot; 62 events[i].oneshot = oneshot;
54 events[i].callback = handler; 63 if ((events[i].has_user_data = user_data_valid))
64 events[i].handler.user_data = user_data;
65 events[i].handler.callback = handler;
55 return true; 66 return true;
56 } 67 }
57 } 68 }
@@ -60,33 +71,59 @@ bool add_event(unsigned short id, bool oneshot, void (*handler)(void *data))
60 return false; 71 return false;
61} 72}
62 73
63void remove_event(unsigned short id, void (*handler)(void *data)) 74bool add_event(unsigned short id, void (*handler)(unsigned short id, void *data))
75{
76 return do_add_event(id, false, false, handler, NULL);
77}
78
79bool add_event_ex(unsigned short id, bool oneshot, void (*handler)(unsigned short id, void *event_data, void *user_data), void *user_data)
80{
81 return do_add_event(id, oneshot, true, handler, user_data);
82}
83
84void do_remove_event(unsigned short id, bool user_data_valid,
85 void *handler, void *user_data)
64{ 86{
65 int i; 87 int i;
66 88
67 for (i = 0; i < MAX_SYS_EVENTS; i++) 89 for (i = 0; i < MAX_SYS_EVENTS; i++)
68 { 90 {
69 if (events[i].id == id && events[i].callback == handler) 91 if (events[i].id == id && events[i].handler.callback == handler
92 && (!user_data_valid || (user_data == events[i].handler.callback)))
70 { 93 {
71 events[i].callback = NULL; 94 events[i].handler.callback = NULL;
72 return; 95 return;
73 } 96 }
74 } 97 }
75} 98}
76 99
100void remove_event(unsigned short id, void (*handler)(unsigned short id, void *data))
101{
102 do_remove_event(id, false, handler, NULL);
103}
104
105void remove_event_ex(unsigned short id,
106 void (*handler)(unsigned short id, void *event_data, void *user_data),
107 void *user_data)
108{
109 do_remove_event(id, true, handler, user_data);
110}
111
77void send_event(unsigned short id, void *data) 112void send_event(unsigned short id, void *data)
78{ 113{
79 int i; 114 int i;
80 115
81 for (i = 0; i < MAX_SYS_EVENTS; i++) 116 for (i = 0; i < MAX_SYS_EVENTS; i++)
82 { 117 {
83 if (events[i].id == id && events[i].callback != NULL) 118 if (events[i].id == id && events[i].handler.callback != NULL)
84 { 119 {
85 events[i].callback(data); 120 if (events[i].has_user_data)
121 events[i].handler.callback2(id, data, events[i].handler.user_data);
122 else
123 events[i].handler.callback(id, data);
86 124
87 if (events[i].oneshot) 125 if (events[i].oneshot)
88 events[i].callback = NULL; 126 events[i].handler.callback = NULL;
89 } 127 }
90 } 128 }
91} 129}
92
diff --git a/firmware/export/ata_idle_notify.h b/firmware/export/ata_idle_notify.h
index 93a53eee34..0443f8e516 100644
--- a/firmware/export/ata_idle_notify.h
+++ b/firmware/export/ata_idle_notify.h
@@ -48,9 +48,9 @@ enum {
48 */ 48 */
49#define USING_STORAGE_CALLBACK !defined(BOOTLOADER) && !defined(APPLICATION) && !defined(__PCTOOL__) 49#define USING_STORAGE_CALLBACK !defined(BOOTLOADER) && !defined(APPLICATION) && !defined(__PCTOOL__)
50 50
51extern void register_storage_idle_func(void (*function)(void *data)); 51extern void register_storage_idle_func(void (*function)(void));
52#if USING_STORAGE_CALLBACK 52#if USING_STORAGE_CALLBACK
53extern void unregister_storage_idle_func(void (*function)(void *data), bool run); 53extern void unregister_storage_idle_func(void (*function)(void), bool run);
54extern bool call_storage_idle_notifys(bool force); 54extern bool call_storage_idle_notifys(bool force);
55#else 55#else
56#define unregister_storage_idle_func(f,r) 56#define unregister_storage_idle_func(f,r)
diff --git a/firmware/export/events.h b/firmware/export/events.h
index 859901c0b4..fd7f9df42e 100644
--- a/firmware/export/events.h
+++ b/firmware/export/events.h
@@ -23,12 +23,24 @@
23#define _EVENTS_H 23#define _EVENTS_H
24 24
25#include <stdbool.h> 25#include <stdbool.h>
26
27/** Only CLASS defines and firmware/ level events should be defined here.
28 * apps/ level events are defined in apps/appevents.h
29 */
30
31/** 26/**
27 * Synchronouos event system.
28 *
29 * Callbacks are subscribed with add_event() or add_event_ex(). events
30 * are fired using send_event().
31 *
32 * Events are always dispatched synchronously: the callbacks are called
33 * in the thread context of the event sender, without context switch. This
34 * also means that callbacks should be as simple as possible to avoid
35 * blocking the sender and other callbacks
36 *
37 * Use the kernel-level event_queue for cross-thread event dispatching.
38 * */
39
40/*
41 * Only CLASS defines and firmware/ level events should be defined here.
42 * apps/ level events are defined in apps/appevents.h
43 *
32 * High byte = Event class definition 44 * High byte = Event class definition
33 * Low byte = Event ID 45 * Low byte = Event ID
34 */ 46 */
@@ -40,9 +52,50 @@
40#define EVENT_CLASS_RECORDING 0x1000 52#define EVENT_CLASS_RECORDING 0x1000
41#define EVENT_CLASS_LCD 0x2000 53#define EVENT_CLASS_LCD 0x2000
42 54
43bool add_event(unsigned short id, bool oneshot, void (*handler)(void *data)); 55/**
44void remove_event(unsigned short id, void (*handler)(void *data)); 56 * Subscribe to an event with a simple callback. The callback will be called
57 * synchronously everytime the event fires, passing the event id and data to
58 * the callback.
59 *
60 * Must be removed with remove_event().
61 */
62bool add_event(unsigned short id, void (*handler)(unsigned short id, void *event_data));
63
64/**
65 * Subscribe to an event with a detailed callback. The callback will be called
66 * synchronously everytime the event fires, passing the event id and data, as
67 * well as the user_data pointer passed here, to the callback.
68 *
69 * With oneshot == true, the callback is unsubscribed automatically after
70 * the event fired for the first time. In this case the event need not to be
71 * removed with remove_event_ex().
72 *
73 * Must be removed with remove_event_ex(). remove_event() will never remove
74 * events added with this function.
75 */
76bool add_event_ex(unsigned short id, bool oneshot, void (*handler)(unsigned short id, void *event_data, void *user_data), void *user_data);
77
78/**
79 * Unsubscribe a callback from an event. The handler pointer is matched.
80 *
81 * This will only work for subscriptions made with add_event().
82 */
83void remove_event(unsigned short id, void (*handler)(unsigned short id, void *data));
84
85/**
86 * Unsubscribe a callback from an event. The handler and user_data pointers
87 * are matched. That means the same user_data that was passed to add_event_ex()
88 * must be passed to this too.
89 *
90 * This will only work for subscriptions made with add_event_ex().
91 */
92void remove_event_ex(unsigned short id, void (*handler)(unsigned short id, void *event_data, void *user_data), void *user_data);
93
94/**
95 * Fire an event, which synchronously calls all subscribed callbacks. The
96 * event id and data pointer are passed to the callbacks as well, and
97 * optionally the user_data pointer from add_event_ex().
98 */
45void send_event(unsigned short id, void *data); 99void send_event(unsigned short id, void *data);
46 100
47#endif 101#endif
48
diff --git a/firmware/logf.c b/firmware/logf.c
index a24a635570..ade5458ca9 100644
--- a/firmware/logf.c
+++ b/firmware/logf.c
@@ -322,7 +322,7 @@ static int logdiskf_push(void *userp, unsigned char c)
322 return true; 322 return true;
323} 323}
324 324
325static void flush_buffer(void* data); 325static void flush_buffer(void);
326 326
327void _logdiskf(const char* file, const char level, const char *fmt, ...) 327void _logdiskf(const char* file, const char level, const char *fmt, ...)
328{ 328{
@@ -350,9 +350,8 @@ void _logdiskf(const char* file, const char level, const char *fmt, ...)
350 register_storage_idle_func(flush_buffer); 350 register_storage_idle_func(flush_buffer);
351} 351}
352 352
353static void flush_buffer(void* data) 353static void flush_buffer(void)
354{ 354{
355 (void)data;
356 int fd; 355 int fd;
357 if(logdiskfindex < 1) 356 if(logdiskfindex < 1)
358 return; 357 return;