From 29e259a29190a5ec67dbffc85389a1cb71a9fe26 Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Tue, 31 Oct 2006 11:17:00 +0000 Subject: [PATCH] * give tsr plugins the choice to quit or not * bumps plugin api version git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11405 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugin.c | 31 +++++++++++++++++++++---------- apps/plugin.h | 25 +++++++++++++++---------- apps/plugins/alpine_cdc.c | 5 ++++- apps/plugins/battery_bench.c | 28 +++++++++++++++++++++------- 4 files changed, 61 insertions(+), 28 deletions(-) diff --git a/apps/plugin.c b/apps/plugin.c index bc8419d313..518fdeff44 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -88,7 +88,8 @@ extern unsigned char pluginbuf[]; /* for actual plugins only, not for codecs */ static bool plugin_loaded = false; static int plugin_size = 0; -static void (*pfn_tsr_exit)(void) = NULL; /* TSR exit callback */ +static bool (*pfn_tsr_exit)(bool) = NULL; /* TSR exit callback */ +static char current_plugin[MAX_PATH]; static const struct plugin_api rockbox_api = { @@ -248,6 +249,7 @@ static const struct plugin_api rockbox_api = { ata_sleep, ata_disk_is_active, #endif + ata_spindown, reload_directory, /* dir */ @@ -317,6 +319,7 @@ static const struct plugin_api rockbox_api = { memchr, memcmp, strcasestr, + strtok_r, /* unicode stuff */ utf8decode, iso_decode, @@ -464,21 +467,21 @@ static const struct plugin_api rockbox_api = { show_logo, tree_get_context, - /* new stuff at the end, sort into place next time - the API gets incompatible */ - - strtok_r, #ifdef HAVE_WHEEL_POSITION wheel_status, wheel_send_events, #endif - ata_spindown, + + /* new stuff at the end, sort into place next time + the API gets incompatible */ + }; int plugin_load(const char* plugin, void* parameter) { int rc; struct plugin_header *hdr; + const char *p = strrchr(plugin,'/'); #ifdef SIMULATOR void *pd; #else @@ -495,14 +498,23 @@ int plugin_load(const char* plugin, void* parameter) fb_data* old_backdrop; #endif + if (!p) + p = plugin; + action_signalscreenchange(); + if (pfn_tsr_exit != NULL) /* if we have a resident old plugin: */ { - pfn_tsr_exit(); /* force it to exit now */ + if (pfn_tsr_exit(!strcmp(current_plugin,p)) == false ) + { + /* not allowing another plugin to load */ + return PLUGIN_OK; + } pfn_tsr_exit = NULL; plugin_loaded = false; } - + gui_syncsplash(0, true, str(LANG_WAIT)); + strcpy(current_plugin,p); #ifdef SIMULATOR hdr = sim_plugin_load((char *)plugin, &pd); @@ -635,7 +647,6 @@ int plugin_load(const char* plugin, void* parameter) gui_syncsplash(HZ*2, true, str(LANG_PLUGIN_ERROR)); break; } - action_signalscreenchange(); return PLUGIN_OK; } @@ -675,7 +686,7 @@ void* plugin_get_audio_buffer(int* buffer_size) /* The plugin wants to stay resident after leaving its main function, e.g. runs from timer or own thread. The callback is registered to later instruct it to free its resources before a new plugin gets loaded. */ -void plugin_tsr(void (*exit_callback)(void)) +void plugin_tsr(bool (*exit_callback)(bool)) { pfn_tsr_exit = exit_callback; /* remember the callback for later */ } diff --git a/apps/plugin.h b/apps/plugin.h index 609f4cc65b..a7ed88985d 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -105,12 +105,12 @@ #define PLUGIN_MAGIC 0x526F634B /* RocK */ /* increase this every time the api struct changes */ -#define PLUGIN_API_VERSION 33 +#define PLUGIN_API_VERSION 34 /* update this to latest version if a change to the api struct breaks backwards compatibility (and please take the opportunity to sort in any new function which are "waiting" at the end of the function table) */ -#define PLUGIN_MIN_API_VERSION 30 +#define PLUGIN_MIN_API_VERSION 34 /* plugin return codes */ enum plugin_status { @@ -304,6 +304,7 @@ struct plugin_api { void (*ata_sleep)(void); bool (*ata_disk_is_active)(void); #endif + void (*ata_spindown)(int seconds); void (*reload_directory)(void); /* dir */ @@ -378,6 +379,7 @@ struct plugin_api { void *(*memchr)(const void *s1, int c, size_t n); int (*memcmp)(const void *s1, const void *s2, size_t n); char *(*strcasestr) (const char* phaystack, const char* pneedle); + char* (*strtok_r)(char *ptr, const char *sep, char **end); /* unicode stuff */ const unsigned char* (*utf8decode)(const unsigned char *utf8, unsigned short *ucs); unsigned char* (*iso_decode)(const unsigned char *iso, unsigned char *utf8, int cp, int count); @@ -511,7 +513,7 @@ struct plugin_api { int (*set_time)(const struct tm *tm); void* (*plugin_get_buffer)(int* buffer_size); void* (*plugin_get_audio_buffer)(int* buffer_size); - void (*plugin_tsr)(void (*exit_callback)(void)); + void (*plugin_tsr)(bool (*exit_callback)(bool reenter)); #if defined(DEBUG) || defined(SIMULATOR) void (*debugf)(const char *fmt, ...); #endif @@ -543,16 +545,15 @@ struct plugin_api { int (*show_logo)(void); struct tree_context* (*tree_get_context)(void); - /* new stuff at the end, sort into place next time - the API gets incompatible */ - - char* (*strtok_r)(char *ptr, const char *sep, char **end); - #ifdef HAVE_WHEEL_POSITION int (*wheel_status)(void); void (*wheel_send_events)(bool send); #endif - void (*ata_spindown)(int seconds); + + /* new stuff at the end, sort into place next time + the API gets incompatible */ + + }; /* plugin header */ @@ -584,7 +585,11 @@ extern unsigned char plugin_end_addr[]; int plugin_load(const char* plugin, void* parameter); void* plugin_get_buffer(int *buffer_size); void* plugin_get_audio_buffer(int *buffer_size); -void plugin_tsr(void (*exit_callback)(void)); + +/* plugin_tsr, + callback returns true to allow the new plugin to load, + reenter means the currently running plugin is being reloaded */ +void plugin_tsr(bool (*exit_callback)(bool reenter)); /* defined by the plugin */ enum plugin_status plugin_start(struct plugin_api* rockbox, void* parameter) diff --git a/apps/plugins/alpine_cdc.c b/apps/plugins/alpine_cdc.c index 134bb3dee6..65108680c6 100644 --- a/apps/plugins/alpine_cdc.c +++ b/apps/plugins/alpine_cdc.c @@ -1122,8 +1122,10 @@ void thread(void) } /* callback to end the TSR plugin, called before a new one gets loaded */ -void exit_tsr(void) +bool exit_tsr(bool reenter) { + if (reenter) + return false; /* dont let it start again */ gTread.exiting = true; /* tell the thread to end */ while (!gTread.ended) /* wait until it did */ rb->yield(); @@ -1133,6 +1135,7 @@ void exit_tsr(void) timer_set_mode(TM_OFF); /* timer interrupt off */ sound_normal(); /* restore sound settings */ + return true; } /****************** main ******************/ diff --git a/apps/plugins/battery_bench.c b/apps/plugins/battery_bench.c index 75d5cbcabd..85d35b003e 100644 --- a/apps/plugins/battery_bench.c +++ b/apps/plugins/battery_bench.c @@ -92,7 +92,7 @@ PLUGIN_HEADER /****************************** Plugin Entry Point ****************************/ static struct plugin_api* rb; int main(void); -void exit_tsr(void); +bool exit_tsr(bool); void thread(void); @@ -119,13 +119,27 @@ struct batt_info struct event_queue thread_q; -void exit_tsr(void) +bool exit_tsr(bool reenter) { - rb->queue_post(&thread_q, EV_EXIT, NULL); - while (!s_thread.ended) - rb->yield(); - /* remove the thread's queue from the broadcast list */ - rb->queue_delete(&thread_q); + bool exit = true; + (void)reenter; + rb->lcd_clear_display(); + rb->lcd_puts_scroll(0, 0, "Batt.Bench is currently running."); + rb->lcd_puts_scroll(0, 1, "Press OFF to cancel the test"); + rb->lcd_puts_scroll(0, 2, "Anything else will resume"); + rb->lcd_update(); + if (rb->button_get(true) != BATTERY_OFF) + exit = false; + if (exit) + { + rb->queue_post(&thread_q, EV_EXIT, NULL); + while (!s_thread.ended) + rb->yield(); + /* remove the thread's queue from the broadcast list */ + rb->queue_delete(&thread_q); + return true; + } + else return false; } #define BIT_CHARGER 0x1000