int plugin_load(const char* plugin, const void* parameter) { struct plugin_header *p_hdr; struct lc_header *hdr; if (current_plugin_handle && pfn_tsr_exit) { /* if we have a resident old plugin and a callback */ if (pfn_tsr_exit(!strcmp(current_plugin, plugin)) == false ) { /* not allowing another plugin to load */ return PLUGIN_OK; } lc_close(current_plugin_handle); current_plugin_handle = pfn_tsr_exit = NULL; if (plugin_buffer_handle > 0) plugin_buffer_handle = core_free(plugin_buffer_handle); } splash(0, ID2P(LANG_WAIT)); strcpy(current_plugin, plugin); current_plugin_handle = lc_open(plugin, pluginbuf, PLUGIN_BUFFER_SIZE); if (current_plugin_handle == NULL) { splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin); return -1; } p_hdr = lc_get_header(current_plugin_handle); hdr = p_hdr ? &p_hdr->lc_hdr : NULL; if (hdr == NULL || hdr->magic != PLUGIN_MAGIC || hdr->target_id != TARGET_ID #if (CONFIG_PLATFORM & PLATFORM_NATIVE) || hdr->load_addr != pluginbuf || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE #endif ) { lc_close(current_plugin_handle); splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL)); return -1; } if (hdr->api_version > PLUGIN_API_VERSION || hdr->api_version < PLUGIN_MIN_API_VERSION) { lc_close(current_plugin_handle); splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION)); return -1; } #if (CONFIG_PLATFORM & PLATFORM_NATIVE) plugin_size = hdr->end_addr - pluginbuf; #else plugin_size = 0; #endif *(p_hdr->api) = &rockbox_api; lcd_clear_display(); lcd_update(); #ifdef HAVE_REMOTE_LCD lcd_remote_clear_display(); lcd_remote_update(); #endif push_current_activity(ACTIVITY_PLUGIN); /* some plugins assume the entry cache doesn't move and save pointers to it * they should be fixed properly instead of this lock */ tree_lock_cache(tree_get_context()); FOR_NB_SCREENS(i) viewportmanager_theme_enable(i, false, NULL); #ifdef HAVE_TOUCHSCREEN touchscreen_set_mode(TOUCHSCREEN_BUTTON); #endif /* allow voice to back off if the plugin needs lots of memory */ talk_buffer_set_policy(TALK_BUFFER_LOOSE); plugin_check_open_close__enter(); int rc = p_hdr->entry_point(parameter); tree_unlock_cache(tree_get_context()); pop_current_activity(); if (!pfn_tsr_exit) { /* close handle if plugin is no tsr one */ lc_close(current_plugin_handle); current_plugin_handle = NULL; if (plugin_buffer_handle > 0) plugin_buffer_handle = core_free(plugin_buffer_handle); } talk_buffer_set_policy(TALK_BUFFER_DEFAULT); /* Go back to the global setting in case the plugin changed it */ #ifdef HAVE_TOUCHSCREEN touchscreen_set_mode(global_settings.touch_mode); #endif #ifdef HAVE_LCD_BITMAP screen_helper_setfont(FONT_UI); #if LCD_DEPTH > 1 #ifdef HAVE_LCD_COLOR lcd_set_drawinfo(DRMODE_SOLID, global_settings.fg_color, global_settings.bg_color); #else lcd_set_drawinfo(DRMODE_SOLID, LCD_DEFAULT_FG, LCD_DEFAULT_BG); #endif #else /* LCD_DEPTH == 1 */ lcd_set_drawmode(DRMODE_SOLID); #endif /* LCD_DEPTH */ #endif /* HAVE_LCD_BITMAP */ #ifdef HAVE_REMOTE_LCD #if LCD_REMOTE_DEPTH > 1 lcd_remote_set_drawinfo(DRMODE_SOLID, LCD_REMOTE_DEFAULT_FG, LCD_REMOTE_DEFAULT_BG); #else lcd_remote_set_drawmode(DRMODE_SOLID); #endif #endif lcd_clear_display(); #ifdef HAVE_REMOTE_LCD lcd_remote_clear_display(); #endif FOR_NB_SCREENS(i) viewportmanager_theme_undo(i, true); plugin_check_open_close__exit(); if (rc == PLUGIN_ERROR) splash(HZ*2, str(LANG_PLUGIN_ERROR)); return rc; }
static int browser(void* param) { int ret_val; #ifdef HAVE_TAGCACHE struct tree_context* tc = tree_get_context(); #endif int filter = SHOW_SUPPORTED; char folder[MAX_PATH] = "/"; /* stuff needed to remember position in file browser */ static char last_folder[MAX_PATH] = "/"; /* and stuff for the database browser */ #ifdef HAVE_TAGCACHE static int last_db_dirlevel = 0, last_db_selection = 0; #endif switch ((intptr_t)param) { case GO_TO_FILEBROWSER: filter = global_settings.dirfilter; if (global_settings.browse_current && last_screen == GO_TO_WPS && current_track_path[0]) { strcpy(folder, current_track_path); } else if (!strcmp(last_folder, "/")) { strcpy(folder, global_settings.start_directory); } else { #ifdef HAVE_HOTSWAP bool in_hotswap = false; /* handle entering an ejected drive */ int i; for (i = 0; i < NUM_VOLUMES; i++) { char vol_string[VOL_ENUM_POS + 8]; if (!storage_removable(i)) continue; /* VOL_NAMES contains a %d */ snprintf(vol_string, sizeof(vol_string), "/"VOL_NAMES, i); /* test whether we would browse the external card */ if (!storage_present(i) && (strstr(last_folder, vol_string) #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN || (i == 0) #endif )) { /* leave folder as "/" to avoid crash when trying * to access an ejected drive */ strcpy(folder, "/"); in_hotswap = true; break; } } if (!in_hotswap) #endif strcpy(folder, last_folder); } break; #ifdef HAVE_TAGCACHE case GO_TO_DBBROWSER: if (!tagcache_is_usable()) { bool reinit_attempted = false; /* Now display progress until it's ready or the user exits */ while(!tagcache_is_usable()) { struct tagcache_stat *stat = tagcache_get_stat(); /* Allow user to exit */ if (action_userabort(HZ/2)) break; /* Maybe just needs to reboot due to delayed commit */ if (stat->commit_delayed) { splash(HZ*2, ID2P(LANG_PLEASE_REBOOT)); break; } /* Check if ready status is known */ if (!stat->readyvalid) { splash(0, str(LANG_TAGCACHE_BUSY)); continue; } /* Re-init if required */ if (!reinit_attempted && !stat->ready && stat->processed_entries == 0 && stat->commit_step == 0) { /* Prompt the user */ reinit_attempted = true; static const char *lines[]={ ID2P(LANG_TAGCACHE_BUSY), ID2P(LANG_TAGCACHE_FORCE_UPDATE)}; static const struct text_message message={lines, 2}; if(gui_syncyesno_run(&message, NULL, NULL) == YESNO_NO) break; int i; FOR_NB_SCREENS(i) screens[i].clear_display(); /* Start initialisation */ tagcache_rebuild(); } /* Display building progress */ static long talked_tick = 0; if(global_settings.talk_menu && (talked_tick == 0 || TIME_AFTER(current_tick, talked_tick+7*HZ))) { talked_tick = current_tick; if (stat->commit_step > 0) { talk_id(LANG_TAGCACHE_INIT, false); talk_number(stat->commit_step, true); talk_id(VOICE_OF, true); talk_number(tagcache_get_max_commit_step(), true); } else if(stat->processed_entries) { talk_number(stat->processed_entries, false); talk_id(LANG_BUILDING_DATABASE, true); } } if (stat->commit_step > 0) { if (lang_is_rtl()) { splashf(0, "[%d/%d] %s", stat->commit_step, tagcache_get_max_commit_step(), str(LANG_TAGCACHE_INIT)); } else { splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), stat->commit_step, tagcache_get_max_commit_step()); } } else { splashf(0, str(LANG_BUILDING_DATABASE), stat->processed_entries); } } } if (!tagcache_is_usable()) return GO_TO_PREVIOUS; filter = SHOW_ID3DB; tc->dirlevel = last_db_dirlevel; tc->selected_item = last_db_selection; break; #endif case GO_TO_BROWSEPLUGINS: filter = SHOW_PLUGINS; strlcpy(folder, PLUGIN_DIR, MAX_PATH); break; } ret_val = rockbox_browse(folder, filter); switch ((intptr_t)param) { case GO_TO_FILEBROWSER: if (!get_current_file(last_folder, MAX_PATH) || (!strchr(&last_folder[1], '/') && global_settings.start_directory[1] != '\0')) { last_folder[0] = '/'; last_folder[1] = '\0'; } break; #ifdef HAVE_TAGCACHE case GO_TO_DBBROWSER: last_db_dirlevel = tc->dirlevel; last_db_selection = tc->selected_item; break; #endif } return ret_val; }
int plugin_load(const char* plugin, const void* parameter) { struct plugin_header *p_hdr; struct lc_header *hdr; if (current_plugin_handle && pfn_tsr_exit) { /* if we have a resident old plugin and a callback */ if (pfn_tsr_exit(!strcmp(current_plugin, plugin)) == false ) { /* not allowing another plugin to load */ return PLUGIN_OK; } lc_close(current_plugin_handle); current_plugin_handle = pfn_tsr_exit = NULL; } splash(0, ID2P(LANG_WAIT)); strcpy(current_plugin, plugin); current_plugin_handle = lc_open(plugin, pluginbuf, PLUGIN_BUFFER_SIZE); if (current_plugin_handle == NULL) { splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin); return -1; } p_hdr = lc_get_header(current_plugin_handle); hdr = p_hdr ? &p_hdr->lc_hdr : NULL; if (hdr == NULL || hdr->magic != PLUGIN_MAGIC || hdr->target_id != TARGET_ID #if (CONFIG_PLATFORM & PLATFORM_NATIVE) || hdr->load_addr != pluginbuf || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE #endif ) { lc_close(current_plugin_handle); splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL)); return -1; } if (hdr->api_version > PLUGIN_API_VERSION || hdr->api_version < PLUGIN_MIN_API_VERSION) { lc_close(current_plugin_handle); splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION)); return -1; } #if (CONFIG_PLATFORM & PLATFORM_NATIVE) plugin_size = hdr->end_addr - pluginbuf; #else plugin_size = 0; #endif *(p_hdr->api) = &rockbox_api; lcd_clear_display(); lcd_update(); #ifdef HAVE_REMOTE_LCD lcd_remote_clear_display(); lcd_remote_update(); #endif push_current_activity(ACTIVITY_PLUGIN); /* some plugins assume the entry cache doesn't move and save pointers to it * they should be fixed properly instead of this lock */ tree_lock_cache(tree_get_context()); FOR_NB_SCREENS(i) viewportmanager_theme_enable(i, false, NULL); #ifdef HAVE_TOUCHSCREEN touchscreen_set_mode(TOUCHSCREEN_BUTTON); #endif #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE open_files = 0; #endif int rc = p_hdr->entry_point(parameter); tree_unlock_cache(tree_get_context()); pop_current_activity(); if (!pfn_tsr_exit) { /* close handle if plugin is no tsr one */ lc_close(current_plugin_handle); current_plugin_handle = NULL; } /* Go back to the global setting in case the plugin changed it */ #ifdef HAVE_TOUCHSCREEN touchscreen_set_mode(global_settings.touch_mode); #endif #ifdef HAVE_LCD_BITMAP screen_helper_setfont(FONT_UI); #if LCD_DEPTH > 1 #ifdef HAVE_LCD_COLOR lcd_set_drawinfo(DRMODE_SOLID, global_settings.fg_color, global_settings.bg_color); #else lcd_set_drawinfo(DRMODE_SOLID, LCD_DEFAULT_FG, LCD_DEFAULT_BG); #endif #else /* LCD_DEPTH == 1 */ lcd_set_drawmode(DRMODE_SOLID); #endif /* LCD_DEPTH */ #endif /* HAVE_LCD_BITMAP */ #ifdef HAVE_REMOTE_LCD #if LCD_REMOTE_DEPTH > 1 lcd_remote_set_drawinfo(DRMODE_SOLID, LCD_REMOTE_DEFAULT_FG, LCD_REMOTE_DEFAULT_BG); #else lcd_remote_set_drawmode(DRMODE_SOLID); #endif #endif lcd_clear_display(); #ifdef HAVE_REMOTE_LCD lcd_remote_clear_display(); #endif FOR_NB_SCREENS(i) viewportmanager_theme_undo(i, true); #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE if(open_files != 0 && !current_plugin_handle) { int fd; logf("Plugin '%s' leaks file handles", plugin); static const char *lines[] = { ID2P(LANG_PLUGIN_ERROR), "#leak-file-handles" }; static const struct text_message message={ lines, 2 }; button_clear_queue(); /* Empty the keyboard buffer */ gui_syncyesno_run(&message, NULL, NULL); for(fd=0; fd < MAX_OPEN_FILES; fd++) if(open_files & (1<<fd)) close_wrapper(fd); } #endif if (rc == PLUGIN_ERROR) splash(HZ*2, str(LANG_PLUGIN_ERROR)); return rc; }