static void init_tagcache(void) { bool clear = false; #if CONFIG_CODEC == SWCODEC long talked_tick = 0; #endif tagcache_init(); while (!tagcache_is_initialized()) { int ret = tagcache_get_commit_step(); if (ret > 0) { #if CONFIG_CODEC == SWCODEC /* hwcodec can't use voice here, as the database commit * uses the audio buffer. */ if(global_settings.talk_menu && (talked_tick == 0 || TIME_AFTER(current_tick, talked_tick+7*HZ))) { talked_tick = current_tick; talk_id(LANG_TAGCACHE_INIT, false); talk_number(ret, true); talk_id(VOICE_OF, true); talk_number(tagcache_get_max_commit_step(), true); } #endif #ifdef HAVE_LCD_BITMAP if (lang_is_rtl()) { splashf(0, "[%d/%d] %s", ret, tagcache_get_max_commit_step(), str(LANG_TAGCACHE_INIT)); } else { splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), ret, tagcache_get_max_commit_step()); } #else lcd_double_height(false); lcd_putsf(0, 1, " DB [%d/%d]", ret, tagcache_get_max_commit_step()); lcd_update(); #endif clear = true; } sleep(HZ/4); } tagtree_init(); if (clear) { backlight_on(); show_logo(); } }
/* Store the logf log to logf.txt in the .rockbox directory. The order of the * entries will be "reversed" so that the most recently logged entry is on the * top of the file */ bool logfdump(void) { int fd; splashf(HZ, "Log File Dumped"); /* nothing to print ? */ if(logfindex == 0 && !logfwrap) /* nothing is logged just yet */ return false; fd = open(ROCKBOX_DIR "/logf.txt", O_CREAT|O_WRONLY|O_TRUNC); if(-1 != fd) { int i; if(logfwrap) i = logfindex; else i = 0; do { if(logfbuffer[i]=='\0') fdprintf(fd, "\n"); else fdprintf(fd, "%c", logfbuffer[i]); i++; if(i >= MAX_LOGF_SIZE) i = 0; } while(i != logfindex); close(fd); } return false; }
static bool create_dir(void) { char dirname[MAX_PATH]; char *cwd; int rc; int pathlen; cwd = getcwd(NULL, 0); memset(dirname, 0, sizeof dirname); snprintf(dirname, sizeof dirname, "%s/", cwd[1] ? cwd : ""); pathlen = strlen(dirname); rc = kbd_input(dirname + pathlen, (sizeof dirname)-pathlen); if (rc < 0) return false; rc = mkdir(dirname); if (rc < 0) { cond_talk_ids_fq(LANG_CREATE_DIR, LANG_FAILED); splashf(HZ, (unsigned char *)"%s %s", str(LANG_CREATE_DIR), str(LANG_FAILED)); } else { onplay_result = ONPLAY_RELOAD_DIR; } return true; }
void splash(int ticks, const char *str) { #if !defined(SIMULATOR) || CONFIG_CODEC == SWCODEC long id; /* fmt may be a so called virtual pointer. See settings.h. */ if((id = P2ID((const unsigned char*)str)) >= 0) /* If fmt specifies a voicefont ID, and voice menus are enabled, then speak it. */ cond_talk_ids_fq(id); #endif splashf(ticks, "%s", P2STR((const unsigned char*)str)); }
/* display number of tracks inserted into playlists. Used for directory insert */ static void display_insert_count(int count) { static long talked_tick = 0; if(global_settings.talk_menu && count && (talked_tick == 0 || TIME_AFTER(current_tick, talked_tick+5*HZ))) { talked_tick = current_tick; talk_number(count, false); talk_id(LANG_PLAYLIST_INSERT_COUNT, true); } splashf(0, str(LANG_PLAYLIST_INSERT_COUNT), count, str(LANG_OFF_ABORT)); }
bool create_playlist(void) { char filename[MAX_PATH]; snprintf(filename, sizeof filename, "%s.m3u8", tc.currdir[1] ? tc.currdir : "/root"); splashf(0, "%s %s", str(LANG_CREATING), filename); trigger_cpu_boost(); catalog_add_to_a_playlist(tc.currdir, ATTR_DIRECTORY, true, filename); cancel_cpu_boost(); return true; }
static int initialize_catalog(void) { if (!initialized) { bool default_dir = true; /* directory config is of the format: "dir: /path/to/dir" */ if (global_settings.playlist_catalog_dir[0] && strcmp(global_settings.playlist_catalog_dir, PLAYLIST_CATALOG_DEFAULT_DIR)) { strcpy(playlist_dir, global_settings.playlist_catalog_dir); default_dir = false; } /* fall back to default directory if no or invalid config */ if (default_dir) { strcpy(playlist_dir, PLAYLIST_CATALOG_DEFAULT_DIR); if (!dir_exists(playlist_dir)) mkdir(playlist_dir); } playlist_dir_length = strlen(playlist_dir); if (dir_exists(playlist_dir)) { playlist_dir_exists = true; memset(most_recent_playlist, 0, sizeof(most_recent_playlist)); initialized = true; } } if (!playlist_dir_exists) { if (mkdir(playlist_dir) < 0) { splashf(HZ*2, ID2P(LANG_CATALOG_NO_DIRECTORY), playlist_dir); return -1; } else { playlist_dir_exists = true; memset(most_recent_playlist, 0, sizeof(most_recent_playlist)); initialized = true; } } return 0; }
int codec_load_file(const char *plugin, struct codec_api *api) { char path[MAX_PATH]; void *handle; codec_get_full_path(path, plugin); handle = lc_open(path, codecbuf, CODEC_SIZE); if (handle == NULL) { logf("Codec load error"); splashf(HZ*2, "Couldn't load codec: %s", path); return CODEC_ERROR; } return codec_load_ram(handle, api); }
static bool rename_file(void) { char newname[MAX_PATH]; char* ptr = strrchr(selected_file, '/') + 1; int pathlen = (ptr - selected_file); strlcpy(newname, selected_file, sizeof(newname)); if (!kbd_input(newname + pathlen, (sizeof newname)-pathlen)) { if (!strlen(newname + pathlen) || (rename(selected_file, newname) < 0)) { cond_talk_ids_fq(LANG_RENAME, LANG_FAILED); splashf(HZ*2, "%s %s", str(LANG_RENAME), str(LANG_FAILED)); } else onplay_result = ONPLAY_RELOAD_DIR; } return false; }
bool create_playlist(void) { char filename[MAX_PATH]; if (tc.currdir[1]) snprintf(filename, sizeof filename, "%s.m3u8", tc.currdir); else snprintf(filename, sizeof filename, "%s/all.m3u8", catalog_get_directory()); if (kbd_input(filename, MAX_PATH)) return false; splashf(0, "%s %s", str(LANG_CREATING), filename); trigger_cpu_boost(); catalog_add_to_a_playlist(tc.currdir, ATTR_DIRECTORY, true, filename); cancel_cpu_boost(); return true; }
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; }
bool alarm_screen(void) { int h, m; bool done = false; struct tm *tm; int togo; int button; bool update = true; bool hour_wrapped = false; struct viewport vp[NB_SCREENS]; rtc_get_alarm(&h, &m); /* After a battery change the RTC values are out of range */ if (m > 60 || h > 24) { m = 0; h = 12; } else { m = m / 5 * 5; /* 5 min accuracy should be enough */ } FOR_NB_SCREENS(i) { viewport_set_defaults(&vp[i], i); } while(!done) { if(update) { FOR_NB_SCREENS(i) { screens[i].set_viewport(&vp[i]); screens[i].clear_viewport(); screens[i].puts(0, 4, str(LANG_ALARM_MOD_KEYS)); } /* Talk when entering the wakeup screen */ speak_time(h, m, true, true); update = false; } FOR_NB_SCREENS(i) { screens[i].set_viewport(&vp[i]); screens[i].putsf(0, 1, str(LANG_ALARM_MOD_TIME)); screens[i].putsf(0, 2, "%02d:%02d", h, m); screens[i].update_viewport(); screens[i].set_viewport(NULL); } button = get_action(CONTEXT_SETTINGS,HZ); switch(button) { case ACTION_STD_OK: /* prevent that an alarm occurs in the shutdown procedure */ /* accept alarms only if they are in 2 minutes or more */ tm = get_time(); togo = (m + h * 60 - tm->tm_min - tm->tm_hour * 60 + 1440) % 1440; if (togo > 1) { rtc_init(); rtc_set_alarm(h,m); rtc_enable_alarm(true); if (global_settings.talk_menu) { talk_id(LANG_ALARM_MOD_TIME_TO_GO, true); talk_value(togo / 60, UNIT_HOUR, true); talk_value(togo % 60, UNIT_MIN, true); talk_force_enqueue_next(); } splashf(HZ*2, str(LANG_ALARM_MOD_TIME_TO_GO), togo / 60, togo % 60); done = true; } else { splash(HZ, ID2P(LANG_ALARM_MOD_ERROR)); update = true; } break; /* inc(m) */ case ACTION_SETTINGS_INC: case ACTION_SETTINGS_INCREPEAT: m += 5; if (m == 60) { h += 1; m = 0; hour_wrapped = true; } if (h == 24) h = 0; speak_time(h, m, hour_wrapped, false); break; /* dec(m) */ case ACTION_SETTINGS_DEC: case ACTION_SETTINGS_DECREPEAT: m -= 5; if (m == -5) { h -= 1; m = 55; hour_wrapped = true; } if (h == -1) h = 23; speak_time(h, m, hour_wrapped, false); break; /* inc(h) */ case ACTION_STD_NEXT: case ACTION_STD_NEXTREPEAT: h = (h+1) % 24; if (global_settings.talk_menu) talk_value(h, UNIT_HOUR, false); break; /* dec(h) */ case ACTION_STD_PREV: case ACTION_STD_PREVREPEAT: h = (h+23) % 24; if (global_settings.talk_menu) talk_value(h, UNIT_HOUR, false); break; case ACTION_STD_CANCEL: rtc_enable_alarm(false); splash(HZ*2, ID2P(LANG_ALARM_MOD_DISABLE)); done = true; break; case ACTION_NONE: hour_wrapped = false; break; default: if(default_event_handler(button) == SYS_USB_CONNECTED) { rtc_enable_alarm(false); return true; } break; } } return false; }
/* Paste the clipboard to the current directory */ static bool clipboard_paste(void) { char target[MAX_PATH]; char *cwd, *nameptr; bool success; static const char *lines[]={ID2P(LANG_REALLY_OVERWRITE)}; static const struct text_message message={lines, 1}; /* Get the name of the current directory */ cwd = getcwd(NULL, 0); /* Figure out the name of the selection */ nameptr = strrchr(clipboard_selection, '/'); /* Final target is current directory plus name of selection */ snprintf(target, sizeof(target), "%s%s", cwd[1] ? cwd : "", nameptr); /* If the target existed but they choose not to overwite, exit */ if (file_exists(target) && (gui_syncyesno_run(&message, NULL, NULL) == YESNO_NO)) { return false; } if (clipboard_is_copy) { splash(0, ID2P(LANG_COPYING)); } else { splash(0, ID2P(LANG_MOVING)); } /* Now figure out what we're doing */ cpu_boost(true); if (clipboard_selection_attr & ATTR_DIRECTORY) { /* Recursion. Set up external stack */ char srcpath[MAX_PATH]; char targetpath[MAX_PATH]; if (!strncmp(clipboard_selection, target, strlen(clipboard_selection))) { /* Do not allow the user to paste a directory into a dir they are copying */ success = 0; } else { strlcpy(srcpath, clipboard_selection, sizeof(srcpath)); strlcpy(targetpath, target, sizeof(targetpath)); success = clipboard_pastedirectory(srcpath, sizeof(srcpath), target, sizeof(targetpath), clipboard_is_copy); if (success && !clipboard_is_copy) { strlcpy(srcpath, clipboard_selection, sizeof(srcpath)); remove_dir(srcpath, sizeof(srcpath)); } } } else { success = clipboard_pastefile(clipboard_selection, target, clipboard_is_copy); } cpu_boost(false); /* Did it work? */ if (success) { /* Reset everything */ clipboard_selection[0] = 0; clipboard_selection_attr = 0; clipboard_is_copy = false; /* Force reload of the current directory */ onplay_result = ONPLAY_RELOAD_DIR; } else { cond_talk_ids_fq(LANG_PASTE, LANG_FAILED); splashf(HZ, (unsigned char *)"%s %s", str(LANG_PASTE), str(LANG_FAILED)); } return true; }
/* Main viewer function. Filename identifies playlist to be viewed. If NULL, view current playlist. */ enum playlist_viewer_result playlist_viewer_ex(const char* filename) { enum playlist_viewer_result ret = PLAYLIST_VIEWER_OK; bool exit = false; /* exit viewer */ int button; bool dirty = false; struct gui_synclist playlist_lists; if (!playlist_viewer_init(&viewer, filename, false)) goto exit; push_current_activity(ACTIVITY_PLAYLISTVIEWER); gui_synclist_init(&playlist_lists, playlist_callback_name, &viewer, false, 1, NULL); gui_synclist_set_voice_callback(&playlist_lists, playlist_callback_voice); gui_synclist_set_icon_callback(&playlist_lists, global_settings.playlist_viewer_icons? &playlist_callback_icons:NULL); gui_synclist_set_nb_items(&playlist_lists, viewer.num_tracks); gui_synclist_set_title(&playlist_lists, str(LANG_PLAYLIST), Icon_Playlist); gui_synclist_select_item(&playlist_lists, viewer.selected_track); gui_synclist_draw(&playlist_lists); gui_synclist_speak_item(&playlist_lists); while (!exit) { int track; if (global_status.resume_index != -1 && !viewer.playlist) playlist_get_resume_info(&track); else track = -1; if (track != viewer.current_playing_track || playlist_amount_ex(viewer.playlist) != viewer.num_tracks) { /* Playlist has changed (new track started?) */ if (!update_playlist(false)) goto exit; /*Needed because update_playlist gives wrong value when playing is stopped*/ viewer.current_playing_track = track; gui_synclist_set_nb_items(&playlist_lists, viewer.num_tracks); gui_synclist_draw(&playlist_lists); } /* Timeout so we can determine if play status has changed */ bool res = list_do_action(CONTEXT_TREE, HZ/2, &playlist_lists, &button, LIST_WRAP_UNLESS_HELD); /* during moving, another redraw is going to be needed, * since viewer.selected_track is updated too late (after the first draw) * drawing the moving item needs it */ viewer.selected_track=gui_synclist_get_sel_pos(&playlist_lists); if (res) { bool reload = playlist_buffer_needs_reload(&viewer.buffer, viewer.selected_track); if (reload) playlist_buffer_load_entries_screen(&viewer.buffer, button == ACTION_STD_NEXT ? FORWARD : BACKWARD); if (reload || viewer.moving_track >= 0) gui_synclist_draw(&playlist_lists); } switch (button) { case ACTION_TREE_WPS: case ACTION_STD_CANCEL: { if (viewer.moving_track >= 0) { viewer.selected_track = viewer.moving_track; gui_synclist_select_item(&playlist_lists, viewer.moving_track); viewer.moving_track = -1; viewer.moving_playlist_index = -1; gui_synclist_draw(&playlist_lists); } else { exit = true; ret = PLAYLIST_VIEWER_CANCEL; } break; } case ACTION_STD_OK: { struct playlist_entry * current_track = playlist_buffer_get_track(&viewer.buffer, viewer.selected_track); if (viewer.moving_track >= 0) { /* Move track */ int ret_val; ret_val = playlist_move(viewer.playlist, viewer.moving_playlist_index, current_track->index); if (ret_val < 0) splashf(HZ, (unsigned char *)"%s %s", str(LANG_MOVE), str(LANG_FAILED)); update_playlist(true); viewer.moving_track = -1; viewer.moving_playlist_index = -1; dirty = true; } else if (!viewer.playlist) { /* play new track */ if (!global_settings.party_mode) { playlist_start(current_track->index, 0); update_playlist(false); } } else if (!global_settings.party_mode) { int start_index = current_track->index; if (!warn_on_pl_erase()) { gui_synclist_draw(&playlist_lists); break; } /* New playlist */ if (playlist_set_current(viewer.playlist) < 0) goto exit; if (global_settings.playlist_shuffle) start_index = playlist_shuffle(current_tick, start_index); playlist_start(start_index, 0); /* Our playlist is now the current list */ if (!playlist_viewer_init(&viewer, NULL, true)) goto exit; exit = true; } gui_synclist_draw(&playlist_lists); break; } case ACTION_STD_CONTEXT: { /* ON+PLAY menu */ int ret_val; ret_val = onplay_menu(viewer.selected_track); if (ret_val < 0) { ret = PLAYLIST_VIEWER_USB; goto exit; } else if (ret_val > 0) { /* Playlist changed */ gui_synclist_del_item(&playlist_lists); update_playlist(true); if (viewer.num_tracks <= 0) exit = true; if (viewer.selected_track >= viewer.num_tracks) viewer.selected_track = viewer.num_tracks-1; dirty = true; } gui_synclist_draw(&playlist_lists); break; } case ACTION_STD_MENU: ret = PLAYLIST_VIEWER_MAINMENU; goto exit; default: if(default_event_handler(button) == SYS_USB_CONNECTED) { ret = PLAYLIST_VIEWER_USB; goto exit; } break; } } exit: pop_current_activity(); if (viewer.playlist) { if(dirty && yesno_pop(ID2P(LANG_SAVE_CHANGES))) save_playlist_screen(viewer.playlist); playlist_close(viewer.playlist); } return ret; }
bool search_playlist(void) { char search_str[32] = ""; bool ret = false, exit = false; int i, playlist_count; int found_indicies[MAX_PLAYLIST_ENTRIES]; int found_indicies_count = 0, last_found_count = -1; int button; struct gui_synclist playlist_lists; struct playlist_track_info track; if (!playlist_viewer_init(&viewer, 0, false)) return ret; if (kbd_input(search_str, sizeof(search_str)) < 0) return ret; lcd_clear_display(); playlist_count = playlist_amount_ex(viewer.playlist); cpu_boost(true); for (i = 0; i < playlist_count && found_indicies_count < MAX_PLAYLIST_ENTRIES; i++) { if (found_indicies_count != last_found_count) { splashf(0, str(LANG_PLAYLIST_SEARCH_MSG), found_indicies_count, str(LANG_OFF_ABORT)); last_found_count = found_indicies_count; } if (action_userabort(TIMEOUT_NOBLOCK)) break; playlist_get_track_info(viewer.playlist, i, &track); if (strcasestr(track.filename,search_str)) found_indicies[found_indicies_count++] = track.index; yield(); } cpu_boost(false); if (!found_indicies_count) { return ret; } backlight_on(); gui_synclist_init(&playlist_lists, playlist_search_callback_name, found_indicies, false, 1, NULL); gui_synclist_set_title(&playlist_lists, str(LANG_SEARCH_RESULTS), NOICON); gui_synclist_set_icon_callback(&playlist_lists, NULL); gui_synclist_set_nb_items(&playlist_lists, found_indicies_count); gui_synclist_select_item(&playlist_lists, 0); gui_synclist_draw(&playlist_lists); while (!exit) { if (list_do_action(CONTEXT_LIST, HZ/4, &playlist_lists, &button, LIST_WRAP_UNLESS_HELD)) continue; switch (button) { case ACTION_STD_CANCEL: exit = true; break; case ACTION_STD_OK: { int sel = gui_synclist_get_sel_pos(&playlist_lists); playlist_start(found_indicies[sel], 0); exit = 1; } break; default: if (default_event_handler(button) == SYS_USB_CONNECTED) { ret = true; exit = true; } break; } } return ret; }
static bool clean_shutdown(void (*callback)(void *), void *parameter) { #ifdef SIMULATOR (void)callback; (void)parameter; bookmark_autobookmark(); call_storage_idle_notifys(true); exit(0); #else long msg_id = -1; int i; scrobbler_poweroff(); #if CONFIG_CHARGING && !defined(HAVE_POWEROFF_WHILE_CHARGING) if(!charger_inserted()) #endif { bool batt_safe = battery_level_safe(); int audio_stat = audio_status(); FOR_NB_SCREENS(i) { screens[i].clear_display(); screens[i].update(); } if (batt_safe) { #ifdef HAVE_TAGCACHE if (!tagcache_prepare_shutdown()) { cancel_shutdown(); splash(HZ, ID2P(LANG_TAGCACHE_BUSY)); return false; } #endif if (battery_level() > 10) splash(0, str(LANG_SHUTTINGDOWN)); else { msg_id = LANG_WARNING_BATTERY_LOW; splashf(0, "%s %s", str(LANG_WARNING_BATTERY_LOW), str(LANG_SHUTTINGDOWN)); } } else { msg_id = LANG_WARNING_BATTERY_EMPTY; splashf(0, "%s %s", str(LANG_WARNING_BATTERY_EMPTY), str(LANG_SHUTTINGDOWN)); } if (global_settings.fade_on_stop && (audio_stat & AUDIO_STATUS_PLAY)) { fade(false, false); } if (batt_safe) /* do not save on critical battery */ { #if defined(HAVE_RECORDING) && CONFIG_CODEC == SWCODEC if (audio_stat & AUDIO_STATUS_RECORD) { rec_command(RECORDING_CMD_STOP); /* wait for stop to complete */ while (audio_status() & AUDIO_STATUS_RECORD) sleep(1); } #endif bookmark_autobookmark(); /* audio_stop_recording == audio_stop for HWCODEC */ audio_stop(); if (callback != NULL) callback(parameter); #if CONFIG_CODEC != SWCODEC /* wait for audio_stop or audio_stop_recording to complete */ while (audio_status()) sleep(1); #endif #if defined(HAVE_RECORDING) && CONFIG_CODEC == SWCODEC audio_close_recording(); #endif if(global_settings.talk_menu) { bool enqueue = false; if(msg_id != -1) { talk_id(msg_id, enqueue); enqueue = true; } talk_id(LANG_SHUTTINGDOWN, enqueue); #if CONFIG_CODEC == SWCODEC voice_wait(); #endif } system_flush(); #ifdef HAVE_EEPROM_SETTINGS if (firmware_settings.initialized) { firmware_settings.disk_clean = true; firmware_settings.bl_version = 0; eeprom_settings_store(); } #endif } #ifdef HAVE_DIRCACHE else dircache_disable(); #endif shutdown_hw(); }
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; }
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; }
int do_shortcut_menu(void *ignored) { (void)ignored; struct simplelist_info list; struct shortcut *sc; int done = GO_TO_PREVIOUS; if (first_handle == 0) shortcuts_init(); simplelist_info_init(&list, P2STR(ID2P(LANG_SHORTCUTS)), shortcut_count, NULL); list.get_name = shortcut_menu_get_name; list.action_callback = shortcut_menu_get_action; if (global_settings.show_icons) list.get_icon = shortcut_menu_get_icon; list.title_icon = Icon_Bookmark; if (global_settings.talk_menu) list.get_talk = shortcut_menu_speak_item; push_current_activity(ACTIVITY_SHORTCUTSMENU); while (done == GO_TO_PREVIOUS) { if (simplelist_show_list(&list)) break; /* some error happened?! */ if (list.selection == -1) break; else { sc = get_shortcut(list.selection); if (!sc) continue; switch (sc->type) { case SHORTCUT_PLAYLISTMENU: if (!file_exists(sc->u.path)) { splash(HZ, ID2P(LANG_NO_FILES)); break; } else { onplay_show_playlist_menu(sc->u.path); } break; case SHORTCUT_FILE: if (!file_exists(sc->u.path)) { splash(HZ, ID2P(LANG_NO_FILES)); break; } /* else fall through */ case SHORTCUT_BROWSER: { struct browse_context browse; browse_context_init(&browse, global_settings.dirfilter, 0, NULL, NOICON, sc->u.path, NULL); if (sc->type == SHORTCUT_FILE) browse.flags |= BROWSE_RUNFILE; done = rockbox_browse(&browse); } break; case SHORTCUT_SETTING: do_setting_screen(sc->u.setting, sc->name[0] ? sc->name : P2STR(ID2P(sc->u.setting->lang_id)),NULL); break; case SHORTCUT_DEBUGITEM: run_debug_screen(sc->u.path); break; case SHORTCUT_SHUTDOWN: #if CONFIG_CHARGING if (charger_inserted()) charging_splash(); else #endif sys_poweroff(); break; case SHORTCUT_TIME: #if CONFIG_RTC if (sc->u.timedata.talktime) { talk_timedate(); talk_force_enqueue_next(); } else #endif { char timer_buf[10]; set_sleep_timer(sc->u.timedata.sleep_timeout * 60); splashf(HZ, "%s (%s)", str(LANG_SLEEP_TIMER), sleep_timer_formatter(timer_buf, sizeof(timer_buf), sc->u.timedata.sleep_timeout, NULL)); } break; case SHORTCUT_UNDEFINED: default: break; } } } pop_current_activity(); return done; }
static int init_dircache(bool preinit) { #ifdef HAVE_DIRCACHE int result = 0; bool clear = false; if (preinit) dircache_init(); if (!global_settings.dircache) return 0; # ifdef HAVE_EEPROM_SETTINGS if (firmware_settings.initialized && firmware_settings.disk_clean && preinit) { result = dircache_load(); if (result < 0) { firmware_settings.disk_clean = false; if (global_status.dircache_size <= 0) { /* This will be in default language, settings are not applied yet. Not really any easy way to fix that. */ splash(0, str(LANG_SCANNING_DISK)); clear = true; } dircache_build(global_status.dircache_size); } } else # endif { if (preinit) return -1; if (!dircache_is_enabled() && !dircache_is_initializing()) { if (global_status.dircache_size <= 0) { splash(0, str(LANG_SCANNING_DISK)); clear = true; } result = dircache_build(global_status.dircache_size); } if (result < 0) { /* Initialization of dircache failed. Manual action is * necessary to enable dircache again. */ splashf(0, "Dircache failed, disabled. Result: %d", result); global_settings.dircache = false; } } if (clear) { backlight_on(); show_logo(); global_status.dircache_size = dircache_get_cache_size(); status_save(); } return result; #else (void)preinit; return 0; #endif }