diff options
Diffstat (limited to 'apps')
324 files changed, 19614 insertions, 10347 deletions
diff --git a/apps/abrepeat.h b/apps/abrepeat.h index f7ee65247c..4d2c4ea001 100644 --- a/apps/abrepeat.h +++ b/apps/abrepeat.h @@ -20,9 +20,38 @@ ****************************************************************************/ #ifndef _ABREPEAT_H_ #define _ABREPEAT_H_ - -#ifdef AB_REPEAT_ENABLE #include <stdbool.h> + +#ifndef AB_REPEAT_ENABLE /* Dummy functions */ +static inline bool ab_repeat_mode_enabled(void) +{ + return false; +} +static inline bool ab_bool_dummy_marker(unsigned int song_position) +{ + (void) song_position; + return false; +} +static inline void ab_void_dummy_marker(unsigned int song_position) +{ + (void) song_position; +} +static inline void ab_dummy_voidfn(void){} + +#define ab_repeat_init ab_dummy_voidfn +#define ab_before_A_marker ab_bool_dummy_marker +#define ab_after_A_marker ab_bool_dummy_marker +#define ab_jump_to_A_marker ab_dummy_voidfn +#define ab_reset_markers ab_dummy_voidfn +#define ab_set_A_marker ab_void_dummy_marker +#define ab_set_B_marker ab_void_dummy_marker +#define ab_get_A_marker ab_bool_dummy_marker +#define ab_get_B_marker ab_bool_dummy_marker +#define ab_end_of_track_report ab_dummy_voidfn +#define ab_reached_B_marker ab_bool_dummy_marker +#define ab_position_report ab_void_dummy_marker + +#else /*def AB_REPEAT_ENABLE*/ #include "audio.h" #include "kernel.h" /* needed for HZ */ diff --git a/apps/action.c b/apps/action.c index 9ef10936f2..208fea4a97 100644 --- a/apps/action.c +++ b/apps/action.c @@ -34,6 +34,7 @@ #include "button.h" #include "action.h" #include "kernel.h" +#include "core_alloc.h" #include "splash.h" #include "settings.h" @@ -70,7 +71,7 @@ static action_last_t action_last = .wait_for_release = false, #ifndef DISABLE_ACTION_REMAP - .core_keymap = NULL, + .key_remap = 0, #endif #ifdef HAVE_TOUCHSCREEN @@ -124,7 +125,7 @@ static bool is_action_filtered(int action, unsigned int mask, int context) { case ACTION_NONE: break; -/*Actions that are not mapped will not turn on the backlight option NOUNMAPPED*/ + /* Actions that are not mapped will not turn on the backlight */ case ACTION_UNKNOWN: match = has_flag(mask, SEL_ACTION_NOUNMAPPED); break; @@ -132,15 +133,15 @@ static bool is_action_filtered(int action, unsigned int mask, int context) case ACTION_FM_PLAY: match = has_flag(mask, SEL_ACTION_PLAY); break; - //case ACTION_STD_PREVREPEAT: // seek not exempted outside of WPS - //case ACTION_STD_NEXTREPEAT: + /* case ACTION_STD_PREVREPEAT:*/ /* seek not exempted outside of WPS */ + /* case ACTION_STD_NEXTREPEAT: */ case ACTION_WPS_SEEKBACK: case ACTION_WPS_SEEKFWD: case ACTION_WPS_STOPSEEK: match = has_flag(mask, SEL_ACTION_SEEK); break; - //case ACTION_STD_PREV: // skip/scrollwheel not exempted outside of WPS - //case ACTION_STD_NEXT: + /* case ACTION_STD_PREV: */ /* skip/scrollwheel not */ + /* case ACTION_STD_NEXT: */ /* exempted outside of WPS */ case ACTION_WPS_SKIPNEXT: case ACTION_WPS_SKIPPREV: case ACTION_FM_NEXT_PRESET: @@ -148,8 +149,8 @@ static bool is_action_filtered(int action, unsigned int mask, int context) match = has_flag(mask, SEL_ACTION_SKIP); break; #ifdef HAVE_VOLUME_IN_LIST - case ACTION_LIST_VOLUP: // volume exempted outside of WPS if the device supports it - case ACTION_LIST_VOLDOWN: + case ACTION_LIST_VOLUP: /* volume exempted outside of WPS */ + case ACTION_LIST_VOLDOWN: /* ( if the device supports it )*/ #endif case ACTION_WPS_VOLUP: case ACTION_WPS_VOLDOWN: @@ -587,13 +588,14 @@ static inline int get_next_context(const struct button_mapping *items, int i) * for a more in-depth explanation * places action into current_action */ + static inline void action_code_lookup(action_last_t *last, action_cur_t *cur) { int action, i; int context = cur->context; cur->is_prebutton = false; -#ifdef HAVE_LOCKED_ACTIONS +#if !defined(HAS_BUTTON_HOLD) && !defined(BOOTLOADER) /* This only applies to the first context, to allow locked contexts to * specify a fall through to their non-locked version */ if (is_keys_locked()) @@ -601,17 +603,14 @@ static inline void action_code_lookup(action_last_t *last, action_cur_t *cur) #endif #ifndef DISABLE_ACTION_REMAP - bool check_remap = (last->core_keymap != NULL); /* attempt to look up the button in user supplied remap */ - if(check_remap && (context & CONTEXT_PLUGIN) == 0) + if(last->key_remap && (context & CONTEXT_PLUGIN) == 0) { -#if 0 /*Disable the REMOTE context for remap for now (BUTTON_REMOTE != 0)*/ if ((cur->button & BUTTON_REMOTE) != 0) { context |= CONTEXT_REMOTE; } -#endif - cur->items = last->core_keymap; + cur->items = core_get_data(last->key_remap); i = 0; action = ACTION_UNKNOWN; /* check the lut at the beginning for the desired context */ @@ -1001,7 +1000,8 @@ static inline int do_backlight(action_last_t *last, action_cur_t *cur, int actio && power_input_present()); #endif /* skip if backlight on | incorrect context | SEL_ACTION_NOEXT + ext pwr */ - if ((cur->context == CONTEXT_FM || cur->context == CONTEXT_WPS) && bl_is_off) + if (bl_is_off && (cur->context == CONTEXT_FM || cur->context == CONTEXT_WPS || + cur->context == CONTEXT_MAINMENU)) { filtered = is_action_filtered(action, last->backlight_mask, cur->context); bl_activate = !is_action_discarded(cur, filtered, &last->bl_filter_tick); @@ -1193,66 +1193,88 @@ int get_action(int context, int timeout) int action_set_keymap(struct button_mapping* core_keymap, int count) { +#ifdef DISABLE_ACTION_REMAP + (void)core_keymap; + (void)count; + return -1; +#else + if (count <= 0 || core_keymap == NULL) + return action_set_keymap_handle(0, 0); + + size_t keyremap_buf_size = count * sizeof(struct button_mapping); + int handle = core_alloc(keyremap_buf_size); + if (handle < 0) + return -6; + memcpy(core_get_data(handle), core_keymap, keyremap_buf_size); + return action_set_keymap_handle(handle, count); +#endif +} + +int action_set_keymap_handle(int handle, int count) +{ #ifdef DISABLE_ACTION_REMAP - count = -1; + (void)core_keymap; + (void)count; + return -1; #else - if (count > 0 && core_keymap != NULL) /* saf-tey checks :) */ + /* free an existing remap */ + action_last.key_remap = core_free(action_last.key_remap); + + /* if clearing the remap, we're done */ + if (count <= 0 || handle <= 0) + return 0; + + /* validate the keymap */ + struct button_mapping* core_keymap = core_get_data(handle); + struct button_mapping* entry = &core_keymap[count - 1]; + if (entry->action_code != (int) CONTEXT_STOPSEARCHING || + entry->button_code != BUTTON_NONE) /* check for sentinel at end*/ { - int i = 0; - struct button_mapping* entry = &core_keymap[count - 1]; - if (entry->action_code != (int) CONTEXT_STOPSEARCHING || - entry->button_code != BUTTON_NONE) /* check for sentinel at end*/ - { - count = -1; - } + /* missing sentinel entry */ + return -1; + } - while (count > 0 && /* check the lut at the beginning for invalid offsets */ - (entry = &core_keymap[i])->action_code != (int) CONTEXT_STOPSEARCHING) - { - - if ((entry->action_code & CONTEXT_REMAPPED) == CONTEXT_REMAPPED) - { - int firstbtn = entry->button_code; - int endpos = firstbtn + entry->pre_button_code; - if (firstbtn > count || firstbtn < i || endpos > count) - { - /* offset out of bounds */ - count = -2; - break; - } + /* check the lut at the beginning for invalid offsets */ + for (int i = 0; i < count; ++i) + { + entry = &core_keymap[i]; + if (entry->action_code == (int)CONTEXT_STOPSEARCHING) + break; - if (core_keymap[endpos].button_code != BUTTON_NONE) - { - /* stop sentinel is not at end of action lut*/ - count = -3; - } - } - else /* something other than a context remap in the lut */ + if ((entry->action_code & CONTEXT_REMAPPED) == CONTEXT_REMAPPED) + { + int firstbtn = entry->button_code; + int endpos = firstbtn + entry->pre_button_code; + if (firstbtn > count || firstbtn < i || endpos > count) { - count = -4; - break; + /* offset out of bounds */ + return -2; } - i++; - - if (i >= count) /* no sentinel in the lut */ + if (core_keymap[endpos].button_code != BUTTON_NONE) { - count = -5; - break; + /* stop sentinel is not at end of action lut */ + return -3; } } + else + { + /* something other than a context remap in the lut */ + return -4; + } - if (count <= 0) - core_keymap = NULL; - } - else -#endif - { - core_keymap = NULL; + if (i+1 >= count) + { + /* no sentinel in the lut */ + return -5; + } } - action_last.core_keymap = core_keymap; + + /* success */ + action_last.key_remap = handle; return count; +#endif } int get_custom_action(int context,int timeout, diff --git a/apps/action.h b/apps/action.h index 35f08a3dbd..6e1278b33c 100644 --- a/apps/action.h +++ b/apps/action.h @@ -35,9 +35,8 @@ #define CONTEXT_PLUGIN 0x10000000 /* for plugins using get_custom_action */ #define CONTEXT_REMAPPED 0x08000000 /* marker for key remap context table */ #define CORE_CONTEXT_REMAP(context) (CONTEXT_REMAPPED | context) -#ifdef HAVE_LOCKED_ACTIONS #define CONTEXT_LOCKED 0x04000000 /* flag to use alternate keymap when screen is locked */ -#endif + #define LAST_ITEM_IN_LIST { CONTEXT_STOPSEARCHING, BUTTON_NONE, BUTTON_NONE } #define LAST_ITEM_IN_LIST__NEXTLIST(a) { a, BUTTON_NONE, BUTTON_NONE } @@ -95,7 +94,7 @@ void set_selective_backlight_actions(bool selective, unsigned int mask, enum { CONTEXT_STD = 0, /* These CONTEXT_ values were here before me, - there values may have significance, so dont touch! */ + their values may have significance, so dont touch! */ CONTEXT_WPS = 1, CONTEXT_TREE = 2, CONTEXT_RECORD = 3, @@ -419,7 +418,7 @@ typedef struct bool wait_for_release; #ifndef DISABLE_ACTION_REMAP - struct button_mapping* core_keymap; + int key_remap; #endif #ifdef HAVE_TOUCHSCREEN @@ -449,7 +448,9 @@ bool action_userabort(int timeout); const struct button_mapping* get_context_mapping(int context); /* load a key map to allow buttons for actions to be remapped see: core_keymap */ -int action_set_keymap(struct button_mapping* core_button_map, int count); +int action_set_keymap(struct button_mapping* core_keymap, int count); +/* load keymap in a handle: takes ownership of the handle on success */ +int action_set_keymap_handle(int handle, int count); /* returns the status code variable from action.c for the button just pressed If button != NULL it will be set to the actual button code */ diff --git a/apps/apps.make b/apps/apps.make index 6afcd12b5c..47b015bc92 100644 --- a/apps/apps.make +++ b/apps/apps.make @@ -24,7 +24,7 @@ $(BUILDDIR)/apps/features: $(APPSDIR)/features.txt $(BUILDDIR)/firmware/common/ $(call PRINTS,PP $(<F)) $(SILENT)$(CC) $(PPCFLAGS) \ -E -P -imacros "config.h" -imacros "button.h" -x c $< | \ - grep -v "^\#" | grep -v "^ *$$" > $(BUILDDIR)/apps/features; \ + grep -v "^#" | grep -v "^ *$$" > $(BUILDDIR)/apps/features; \ $(BUILDDIR)/apps/genlang-features: $(BUILDDIR)/apps/features $(call PRINTS,GEN $(subst $(BUILDDIR)/,,$@))tr \\n : < $< > $@ diff --git a/apps/bookmark.c b/apps/bookmark.c index 70dbd8075d..2411ddb0ee 100644 --- a/apps/bookmark.c +++ b/apps/bookmark.c @@ -43,6 +43,9 @@ #include "file.h" #include "pathfuncs.h" +/*#define LOGF_ENABLE*/ +#include "logf.h" + #define MAX_BOOKMARKS 10 #define MAX_BOOKMARK_SIZE 350 #define RECENT_BOOKMARK_FILE ROCKBOX_DIR "/most-recent.bmark" @@ -66,286 +69,289 @@ struct bookmark_list #define BM_SPEED 0x02 /* bookmark values */ -static struct { +struct resume_info{ + const struct mp3entry *id3; int resume_index; unsigned long resume_offset; int resume_seed; - long resume_time; + long resume_elapsed; int repeat_mode; bool shuffle; /* optional values */ int pitch; int speed; -} bm; - -static bool add_bookmark(const char* bookmark_file_name, const char* bookmark, - bool most_recent); -static char* create_bookmark(void); -static bool delete_bookmark(const char* bookmark_file_name, int bookmark_id); -static void say_bookmark(const char* bookmark, - int bookmark_id, bool show_playlist_name); -static bool play_bookmark(const char* bookmark); -static bool generate_bookmark_file_name(const char *in); -static bool parse_bookmark(const char *bookmark, const bool get_filenames, const bool strip_dir); -static int buffer_bookmarks(struct bookmark_list* bookmarks, int first_line); -static const char* get_bookmark_info(int list_index, - void* data, - char *buffer, - size_t buffer_len); -static int select_bookmark(const char* bookmark_file_name, bool show_dont_resume, char** selected_bookmark); -static bool write_bookmark(bool create_bookmark_file, const char *bookmark); -static int get_bookmark_count(const char* bookmark_file_name); +}; -#define TEMP_BUF_SIZE (MAX_PATH + 1) +/* Temp buffer used for reading, create_bookmark and filename creation */ +#define TEMP_BUF_SIZE (MAX(MAX_BOOKMARK_SIZE, MAX_PATH + 1)) static char global_temp_buffer[TEMP_BUF_SIZE]; -/* File name created by generate_bookmark_file_name */ -static char global_bookmark_file_name[MAX_PATH]; -static char global_read_buffer[MAX_BOOKMARK_SIZE]; -/* Bookmark created by create_bookmark*/ -static char global_bookmark[MAX_BOOKMARK_SIZE]; -/* Filename from parsed bookmark (can be made local where needed) */ -static char global_filename[MAX_PATH]; -/* ----------------------------------------------------------------------- */ -/* This is an interface function from the context menu. */ -/* Returns true on successful bookmark creation. */ -/* ----------------------------------------------------------------------- */ -bool bookmark_create_menu(void) +static inline void get_hash(const char *key, uint32_t *hash, int len) { - return write_bookmark(true, create_bookmark()); + *hash = crc_32(key, len, *hash); /* this is probably sufficient */ } -/* ----------------------------------------------------------------------- */ -/* This function acts as the load interface from the context menu. */ -/* This function determines the bookmark file name and then loads that file*/ -/* for the user. The user can then select or delete previous bookmarks. */ -/* This function returns BOOKMARK_SUCCESS on the selection of a track to */ -/* resume, BOOKMARK_FAIL if the menu is exited without a selection and */ -/* BOOKMARK_USB_CONNECTED if the menu is forced to exit due to a USB */ -/* connection. */ -/* ----------------------------------------------------------------------- */ -int bookmark_load_menu(void) +static const char* skip_tokens(const char* s, int ntokens) { - char* bookmark; - int ret = BOOKMARK_FAIL; - - push_current_activity(ACTIVITY_BOOKMARKSLIST); - - char* name = playlist_get_name(NULL, global_temp_buffer, - sizeof(global_temp_buffer)); - if (generate_bookmark_file_name(name)) + for (int i = 0; i < ntokens; i++) { - ret = select_bookmark(global_bookmark_file_name, false, &bookmark); - if (bookmark != NULL) + while (*s && *s != ';') { - ret = play_bookmark(bookmark) ? BOOKMARK_SUCCESS : BOOKMARK_FAIL; + s++; + } + + if (*s) + { + s++; } } + return s; +} - pop_current_activity(); +static int int_token(const char **s) +{ + int ret = atoi(*s); + *s = skip_tokens(*s, 1); return ret; } -/* ----------------------------------------------------------------------- */ -/* Gives the user a list of the Most Recent Bookmarks. This is an */ -/* interface function */ -/* Returns true on the successful selection of a recent bookmark. */ -/* ----------------------------------------------------------------------- */ -bool bookmark_mrb_load() +static long long_token(const char **s) { - char* bookmark; - bool ret = false; + /* Should be atol, but we don't have it. */ + return int_token(s); +} - push_current_activity(ACTIVITY_BOOKMARKSLIST); - select_bookmark(RECENT_BOOKMARK_FILE, false, &bookmark); - if (bookmark != NULL) +/*-------------------------------------------------------------------------*/ +/* Get the name of the playlist and the name of the track from a bookmark. */ +/* Returns true iff both were extracted. */ +/*-------------------------------------------------------------------------*/ +static bool bookmark_get_playlist_and_track_hash(const char *bookmark, + uint32_t *pl_hash, + uint32_t *track_hash) +{ + *pl_hash = 0; + *track_hash = 0; + int pl_len; + const char *pl_start, *pl_end, *track; + + logf("%s", __func__); + + pl_start = strchr(bookmark,'/'); + if (!(pl_start)) + return false; + + pl_end = skip_tokens(pl_start, 1) - 1; + pl_len = pl_end - pl_start; + + track = pl_end + 1; + get_hash(pl_start, pl_hash, pl_len); + + if (global_settings.usemrb == BOOKMARK_ONE_PER_TRACK) { - ret = play_bookmark(bookmark); + get_hash(track, track_hash, strlen(track)); } - pop_current_activity(); - return ret; + + return true; } /* ----------------------------------------------------------------------- */ -/* This function handles an autobookmark creation. This is an interface */ -/* function. */ -/* Returns true on successful bookmark creation. */ +/* This function takes a bookmark and parses it. This function also */ +/* validates the bookmark. Valid filenamebuf indicates whether */ +/* the filename tokens are to be extracted. */ +/* Returns true on successful bookmark parse. */ /* ----------------------------------------------------------------------- */ -bool bookmark_autobookmark(bool prompt_ok) +static bool parse_bookmark(char *filenamebuf, + size_t filenamebufsz, + const char *bookmark, + struct resume_info *resume_info, + const bool strip_dir) { - char* bookmark; - bool update; - - if (!bookmark_is_bookmarkable_state()) - return false; + const char* s = bookmark; + const char* end; - audio_pause(); /* first pause playback */ - update = (global_settings.autoupdatebookmark && bookmark_exists()); - bookmark = create_bookmark(); +#define GET_INT_TOKEN(var) var = int_token(&s) +#define GET_LONG_TOKEN(var) var = long_token(&s) +#define GET_BOOL_TOKEN(var) var = (int_token(&s) != 0) - if (update) - return write_bookmark(true, bookmark); + /* if new format bookmark, extract the optional content flags, + otherwise treat as an original format bookmark */ + int opt_flags = 0; + int opt_pitch = 0; + int opt_speed = 0; + int old_format = ((strchr(s, '>') == s) ? 0 : 1); + if (old_format == 0) /* this is a new format bookmark */ + { + s++; + GET_INT_TOKEN(opt_flags); + opt_pitch = (opt_flags & BM_PITCH) ? 1:0; + opt_speed = (opt_flags & BM_SPEED) ? 1:0; + } - switch (global_settings.autocreatebookmark) + /* extract all original bookmark tokens */ + if (resume_info) { - case BOOKMARK_YES: - return write_bookmark(true, bookmark); + GET_INT_TOKEN(resume_info->resume_index); + GET_LONG_TOKEN(resume_info->resume_offset); + GET_INT_TOKEN(resume_info->resume_seed); - case BOOKMARK_NO: - return false; + s = skip_tokens(s, old_format); /* skip deprecated token */ - case BOOKMARK_RECENT_ONLY_YES: - return write_bookmark(false, bookmark); - } - const char *lines[]={ID2P(LANG_AUTO_BOOKMARK_QUERY)}; - const struct text_message message={lines, 1}; + GET_LONG_TOKEN(resume_info->resume_elapsed); + GET_INT_TOKEN(resume_info->repeat_mode); + GET_BOOL_TOKEN(resume_info->shuffle); - if(prompt_ok && gui_syncyesno_run(&message, NULL, NULL)==YESNO_YES) + /* extract all optional bookmark tokens */ + if (opt_pitch != 0) + GET_INT_TOKEN(resume_info->pitch); + if (opt_speed != 0) + GET_INT_TOKEN(resume_info->speed); + } + else /* no resume info we just want the file name strings */ { - if (global_settings.autocreatebookmark == BOOKMARK_RECENT_ONLY_ASK) - return write_bookmark(false, bookmark); - else - return write_bookmark(true, bookmark); + #define DEFAULT_BM_TOKENS 6 + int skipct = DEFAULT_BM_TOKENS + old_format + opt_pitch + opt_speed; + s = skip_tokens(s, skipct); + #undef DEFAULT_BM_TOKENS } - return false; -} -/* ----------------------------------------------------------------------- */ -/* This function takes the current current resume information and writes */ -/* that to the beginning of the bookmark file. */ -/* This file will contain N number of bookmarks in the following format: */ -/* resume_index*resume_offset*resume_seed*resume_first_index* */ -/* resume_file*milliseconds*MP3 Title* */ -/* Returns true on successful bookmark write. */ -/* Returns false if any part of the bookmarking process fails. It is */ -/* possible that a bookmark is successfully added to the most recent */ -/* bookmark list but fails to be added to the bookmark file or vice versa. */ -/* ------------------------------------------------------------------------*/ -static bool write_bookmark(bool create_bookmark_file, const char *bookmark) -{ - bool ret=true; - - if (!bookmark) + if (*s == 0) { - ret = false; /* something didn't happen correctly, do nothing */ + return false; } - else - { - if (global_settings.usemrb) - ret = add_bookmark(RECENT_BOOKMARK_FILE, bookmark, true); + end = strchr(s, ';'); - /* writing the bookmark */ - if (create_bookmark_file) + /* extract file names */ + if(filenamebuf) + { + size_t len = (end == NULL) ? strlen(s) : (size_t) (end - s); + len = MIN(TEMP_BUF_SIZE - 1, len); + strmemccpy(global_temp_buffer, s, len + 1); + + if (end != NULL) { - char* name = playlist_get_name(NULL, global_temp_buffer, - sizeof(global_temp_buffer)); - if (generate_bookmark_file_name(name)) - { - ret = ret & add_bookmark(global_bookmark_file_name, bookmark, false); - } - else + end++; + if (strip_dir) { - ret = false; /* generating bookmark file failed */ + s = strrchr(end, '/'); + if (s) + { + end = s; + end++; + } } + strmemccpy(filenamebuf, end, filenamebufsz); } - } - - splash(HZ, ret ? ID2P(LANG_BOOKMARK_CREATE_SUCCESS) - : ID2P(LANG_BOOKMARK_CREATE_FAILURE)); + } - return ret; + return true; } -/* Get the name of the playlist and the name of the track from a bookmark. */ -/* Returns true iff both were extracted. */ -static bool get_playlist_and_track(const char *bookmark, char **pl_start, - char **pl_end, char **track) +/* ------------------------------------------------------------------------- */ +/* This function takes a filename and appends .tmp. This function also opens */ +/* the resulting file based on oflags, filename will be in buf on return */ +/* Returns file descriptor */ +/* --------------------------------------------------------------------------*/ +static int open_temp_bookmark(char *buf, + size_t bufsz, + int oflags, + const char* filename) { - *pl_start = strchr(bookmark,'/'); - if (!(*pl_start)) - return false; - *pl_end = strrchr(bookmark,';'); - *track = *pl_end + 1; - return true; + if(filename[0] == '/') + filename++; + /* Opening up a temp bookmark file */ + int fd = open_pathfmt(buf, bufsz, oflags, "/%s.tmp", filename); +#ifdef LOGF_ENABLE + if (oflags & O_PATH) + logf("tempfile path %s", buf); + else + logf("opening tempfile %s", buf); +#endif + return fd; } /* ----------------------------------------------------------------------- */ /* This function adds a bookmark to a file. */ /* Returns true on successful bookmark add. */ /* ------------------------------------------------------------------------*/ -static bool add_bookmark(const char* bookmark_file_name, const char* bookmark, +static bool add_bookmark(const char* bookmark_file_name, + const char* bookmark, bool most_recent) { - int temp_bookmark_file = 0; - int bookmark_file = 0; - int bookmark_count = 0; - char *pl_start = NULL, *bm_pl_start; - char *pl_end = NULL, *bm_pl_end; - int pl_len = 0, bm_pl_len; - char *track = NULL, *bm_track; - bool comp_playlist = false; - bool comp_track = false; - bool equal; + char fnamebuf[MAX_PATH]; + int temp_bookmark_file = 0; + int bookmark_file = 0; + int bookmark_count = 0; + bool comp_playlist = false; + bool comp_track = false; + bool equal; + uint32_t pl_hash, pl_track_hash; + uint32_t bm_pl_hash, bm_pl_track_hash; /* Opening up a temp bookmark file */ - snprintf(global_temp_buffer, sizeof(global_temp_buffer), - "%s.tmp", bookmark_file_name); - temp_bookmark_file = open(global_temp_buffer, - O_WRONLY | O_CREAT | O_TRUNC, 0666); - if (temp_bookmark_file < 0) - return false; /* can't open the temp file */ + temp_bookmark_file = open_temp_bookmark(fnamebuf, + sizeof(fnamebuf), + O_WRONLY | O_CREAT | O_TRUNC, + bookmark_file_name); + + if (temp_bookmark_file < 0 || !bookmark) + return false; /* can't open the temp file or no bookmark */ if (most_recent && ((global_settings.usemrb == BOOKMARK_ONE_PER_PLAYLIST) || (global_settings.usemrb == BOOKMARK_ONE_PER_TRACK))) { - if (get_playlist_and_track(bookmark, &pl_start, &pl_end, &track)) + + if (bookmark_get_playlist_and_track_hash(bookmark, &pl_hash, &pl_track_hash)) { comp_playlist = true; - pl_len = pl_end - pl_start; - if (global_settings.usemrb == BOOKMARK_ONE_PER_TRACK) - comp_track = true; + comp_track = (global_settings.usemrb == BOOKMARK_ONE_PER_TRACK); } } + logf("adding bookmark to %s [%s]", fnamebuf, bookmark); /* Writing the new bookmark to the begining of the temp file */ write(temp_bookmark_file, bookmark, strlen(bookmark)); write(temp_bookmark_file, "\n", 1); bookmark_count++; + /* WARNING underlying buffer to *bookmrk gets overwritten after this point! */ + /* Reading in the previous bookmarks and writing them to the temp file */ + logf("opening old bookmark %s", bookmark_file_name); bookmark_file = open(bookmark_file_name, O_RDONLY); if (bookmark_file >= 0) { - while (read_line(bookmark_file, global_read_buffer, - sizeof(global_read_buffer)) > 0) + while (read_line(bookmark_file, global_temp_buffer, + sizeof(global_temp_buffer)) > 0) { /* The MRB has a max of MAX_BOOKMARKS in it */ /* This keeps it from getting too large */ if (most_recent && (bookmark_count >= MAX_BOOKMARKS)) break; - if (!parse_bookmark(global_read_buffer, false, false)) + if (!parse_bookmark(NULL, 0, global_temp_buffer, NULL, false)) break; equal = false; if (comp_playlist) { - if (get_playlist_and_track(global_read_buffer, &bm_pl_start, - &bm_pl_end, &bm_track)) + if (bookmark_get_playlist_and_track_hash(global_temp_buffer, + &bm_pl_hash, &bm_pl_track_hash)) { - bm_pl_len = bm_pl_end - bm_pl_start; - equal = (pl_len == bm_pl_len) && !strncmp(pl_start, bm_pl_start, pl_len); + equal = (pl_hash == bm_pl_hash); if (equal && comp_track) - equal = !strcmp(track, bm_track); + { + equal = (pl_track_hash == bm_pl_track_hash); + } } } if (!equal) { bookmark_count++; - write(temp_bookmark_file, global_read_buffer, - strlen(global_read_buffer)); + /*logf("copying old bookmark [%s]", global_temp_buffer);*/ + write(temp_bookmark_file, global_temp_buffer, + strlen(global_temp_buffer)); write(temp_bookmark_file, "\n", 1); } } @@ -354,180 +360,237 @@ static bool add_bookmark(const char* bookmark_file_name, const char* bookmark, close(temp_bookmark_file); remove(bookmark_file_name); - rename(global_temp_buffer, bookmark_file_name); + rename(fnamebuf, bookmark_file_name); return true; } +/* ----------------------------------------------------------------------- */ +/* This function is used by multiple functions and is used to generate a */ +/* bookmark named based off of the input. */ +/* Changing this function could result in how the bookmarks are stored. */ +/* it would be here that the centralized/decentralized bookmark code */ +/* could be placed. */ +/* Returns true if the file name is generated, false if it was too long */ +/* ----------------------------------------------------------------------- */ +static bool generate_bookmark_file_name(char *filenamebuf, + size_t filenamebufsz, + const char *bmarknamein, + size_t bmarknamelen) +{ + /* if this is a root dir MP3, rename the bookmark file root_dir.bmark */ + /* otherwise, name it based on the bmarknamein variable */ + if (!strncmp("/", bmarknamein, bmarknamelen)) + strmemccpy(filenamebuf, "/root_dir.bmark", filenamebufsz); + else + { + size_t buflen, len; + /* strmemccpy considers the NULL so bmarknamelen is one off */ + buflen = MIN(filenamebufsz -1 , bmarknamelen); + if (buflen >= filenamebufsz) + return false; + + strmemccpy(filenamebuf, bmarknamein, buflen + 1); + + len = strlen(filenamebuf); + +#ifdef HAVE_MULTIVOLUME + /* The "root" of an extra volume need special handling too. */ + const char *filename; + path_strip_volume(filenamebuf, &filename, true); + bool volume_root = *filename == '\0'; +#endif + if(filenamebuf[len-1] == '/') { + filenamebuf[len-1] = '\0'; + } + + const char *name = ".bmark"; +#ifdef HAVE_MULTIVOLUME + if (volume_root) + name = "/volume_dir.bmark"; +#endif + len = strlcat(filenamebuf, name, filenamebufsz); + + if(len >= filenamebufsz) + return false; + } + logf ("generated name '%s' from '%.*s'", + filenamebuf, (int)bmarknamelen, bmarknamein); + return true; +} + /* GCC 7 and up complain about the snprintf in create_bookmark() when compiled with -D_FORTIFY_SOURCE or -Wformat-truncation This is a false positive, so disable it here only */ -#if __GNUC__ >= 7 +/* SHOULD NO LONGER BE NEEDED --Bilgus 11-2022 */ +#if 0 /* __GNUC__ >= 7 */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-truncation" #endif /* ----------------------------------------------------------------------- */ /* This function takes the system resume data and formats it into a valid */ /* bookmark. */ -/* Returns not NULL on successful bookmark format. */ +/* playlist name and name len are passed back through the name/namelen */ +/* Return is not NULL on successful bookmark format. */ /* ----------------------------------------------------------------------- */ -static char* create_bookmark() +static char* create_bookmark(char **name, + size_t *namelen, + struct resume_info *resume_info) { - int resume_index = 0; - char *file; - - if (!bookmark_is_bookmarkable_state()) - return NULL; /* something didn't happen correctly, do nothing */ + const char *file; + char *buf = global_temp_buffer; + size_t bufsz = sizeof(global_temp_buffer); - /* grab the currently playing track */ - struct mp3entry *id3 = audio_current_track(); - if(!id3) + if(!resume_info->id3) return NULL; - /* Get some basic resume information */ - /* queue_resume and queue_resume_index are not used and can be ignored.*/ - playlist_get_resume_info(&resume_index); - - /* Get the currently playing file minus the path */ - /* This is used when displaying the available bookmarks */ - file = strrchr(id3->path,'/'); - if(NULL == file) - return NULL; - - /* create the bookmark */ - playlist_get_name(NULL, global_temp_buffer, sizeof(global_temp_buffer)); - if (global_temp_buffer[strlen(global_temp_buffer) - 1] != '/') - file = id3->path; - else file++; - snprintf(global_bookmark, sizeof(global_bookmark), - /* new optional bookmark token descriptors should be inserted - just before the "%s;%s" in this line... */ + size_t bmarksz= snprintf(buf, bufsz, + /* new optional bookmark token descriptors should + be inserted just after ';"' in this line... */ #if defined(HAVE_PITCHCONTROL) - ">%d;%d;%ld;%d;%ld;%d;%d;%ld;%ld;%s;%s", + ">%d;%d;%ld;%d;%ld;%d;%d;%ld;%ld;", #else - ">%d;%d;%ld;%d;%ld;%d;%d;%s;%s", + ">%d;%d;%ld;%d;%ld;%d;%d;", #endif - /* ... their flags should go here ... */ + /* ... their flags should go here ... */ #if defined(HAVE_PITCHCONTROL) - BM_PITCH | BM_SPEED, + BM_PITCH | BM_SPEED, #else - 0, + 0, #endif - resume_index, - id3->offset, - playlist_get_seed(NULL), - id3->elapsed, - global_settings.repeat_mode, - global_settings.playlist_shuffle, - /* ...and their values should go here */ + resume_info->resume_index, + resume_info->id3->offset, + resume_info->resume_seed, + resume_info->id3->elapsed, + resume_info->repeat_mode, + resume_info->shuffle, + /* ...and their values should go here */ #if defined(HAVE_PITCHCONTROL) - (long)sound_get_pitch(), - (long)dsp_get_timestretch(), + (long)resume_info->pitch, + (long)resume_info->speed #endif - /* more mandatory tokens */ - global_temp_buffer, - file); + ); /*sprintf*/ +/* mandatory tokens */ + if (bmarksz >= bufsz) /* include NULL*/ + return NULL; + buf += bmarksz; + bufsz -= bmarksz; + + /* create the bookmark */ + playlist_get_name(NULL, buf, bufsz); + bmarksz = strlen(buf); + + if (bmarksz == 0 || (bmarksz + 1) >= bufsz) /* include the separator & NULL*/ + return NULL; + + *name = buf; /* return the playlist name through the *pointer */ + *namelen = bmarksz; /* return the name length through the pointer */ + + /* Get the currently playing file minus the path */ + /* This is used when displaying the available bookmarks */ + file = strrchr(resume_info->id3->path,'/'); + if(NULL == file) + return NULL; + + if (buf[bmarksz - 1] != '/') + file = resume_info->id3->path; + else file++; + + buf += bmarksz; + bufsz -= (bmarksz + 1); + buf[0] = ';'; + buf[1] = '\0'; + + strlcat(buf, file, bufsz); + logf("%s [%s]", __func__, global_temp_buffer); /* checking to see if the bookmark is valid */ - if (parse_bookmark(global_bookmark, false, false)) - return global_bookmark; + if (parse_bookmark(NULL, 0, global_temp_buffer, NULL, false)) + return global_temp_buffer; else return NULL; } -#if __GNUC__ >= 7 +#if 0/* __GNUC__ >= 7*/ #pragma GCC diagnostic pop /* -Wformat-truncation */ #endif /* ----------------------------------------------------------------------- */ -/* This function will determine if an autoload is necessary. This is an */ -/* interface function. */ -/* Returns true on bookmark load or bookmark selection. */ -/* ------------------------------------------------------------------------*/ -bool bookmark_autoload(const char* file) +/* This function gets some basic resume information for the current song */ +/* from rockbox, */ +/* ----------------------------------------------------------------------- */ +static void get_track_resume_info(struct resume_info *resume_info) { - char* bookmark; - - if(global_settings.autoloadbookmark == BOOKMARK_NO) - return false; - - /*Checking to see if a bookmark file exists.*/ - if(!generate_bookmark_file_name(file)) - { - return false; - } - - if(!file_exists(global_bookmark_file_name)) - return false; - - if(global_settings.autoloadbookmark == BOOKMARK_YES) - { - return bookmark_load(global_bookmark_file_name, true); - } + if (global_settings.playlist_shuffle) + playlist_get_resume_info(&(resume_info->resume_index)); else - { - int ret = select_bookmark(global_bookmark_file_name, true, &bookmark); - - if (bookmark != NULL) - { - if (!play_bookmark(bookmark)) - { - /* Selected bookmark not found. */ - splash(HZ*2, ID2P(LANG_NOTHING_TO_RESUME)); - } + resume_info->resume_index = playlist_get_display_index() - 1; - /* Act as if autoload was done even if it failed, since the - * user did make an active selection. - */ - return true; - } - - return ret != BOOKMARK_SUCCESS; - } + resume_info->resume_seed = playlist_get_seed(NULL); + resume_info->id3 = audio_current_track(); + resume_info->repeat_mode = global_settings.repeat_mode; + resume_info->shuffle = global_settings.playlist_shuffle; +#if defined(HAVE_PITCHCONTROL) + resume_info->pitch = sound_get_pitch(); + resume_info->speed = dsp_get_timestretch(); +#endif } /* ----------------------------------------------------------------------- */ -/* This function loads the bookmark information into the resume memory. */ -/* This is an interface function. */ -/* Returns true on successful bookmark load. */ +/* This function takes the current current resume information and writes */ +/* that to the beginning of the bookmark file. */ +/* This file will contain N number of bookmarks in the following format: */ +/* resume_index*resume_offset*resume_seed*resume_first_index* */ +/* resume_file*milliseconds*MP3 Title* */ +/* Returns true on successful bookmark write. */ +/* Returns false if any part of the bookmarking process fails. It is */ +/* possible that a bookmark is successfully added to the most recent */ +/* bookmark list but fails to be added to the bookmark file or vice versa. */ /* ------------------------------------------------------------------------*/ -bool bookmark_load(const char* file, bool autoload) +static bool write_bookmark(bool create_bookmark_file) { - int fd; - char* bookmark = NULL; + logf("%s", __func__); + char bm_filename[MAX_PATH]; + bool ret=true; - if(autoload) + char *name = NULL; + size_t namelen = 0; + char* bm; + struct resume_info resume_info; + + if (bookmark_is_bookmarkable_state()) { - fd = open(file, O_RDONLY); - if(fd >= 0) + get_track_resume_info(&resume_info); + /* writing the most recent bookmark */ + if (global_settings.usemrb) { - if(read_line(fd, global_read_buffer, sizeof(global_read_buffer)) > 0) - bookmark=global_read_buffer; - close(fd); + /* since we use the same buffer bookmark needs created each time */ + bm = create_bookmark(&name, &namelen, &resume_info); + ret = add_bookmark(RECENT_BOOKMARK_FILE, bm, true); } - } - else - { - /* This is not an auto-load, so list the bookmarks */ - select_bookmark(file, false, &bookmark); - } - if (bookmark != NULL) - { - if (!play_bookmark(bookmark)) + /* writing the directory bookmark */ + if (create_bookmark_file) { - /* Selected bookmark not found. */ - if (!autoload) + bm = create_bookmark(&name, &namelen, &resume_info); + if (generate_bookmark_file_name(bm_filename, + sizeof(bm_filename), name, namelen)) { - splash(HZ*2, ID2P(LANG_NOTHING_TO_RESUME)); + ret &= add_bookmark(bm_filename, bm, false); + } + else + { + ret = false; /* generating bookmark file failed */ } - - return false; } } + else + ret = false; - return true; -} + splash(HZ, ret ? ID2P(LANG_BOOKMARK_CREATE_SUCCESS) + : ID2P(LANG_BOOKMARK_CREATE_FAILURE)); + return ret; +} static int get_bookmark_count(const char* bookmark_file_name) { @@ -537,7 +600,7 @@ static int get_bookmark_count(const char* bookmark_file_name) if(file < 0) return -1; - while(read_line(file, global_read_buffer, sizeof(global_read_buffer)) > 0) + while(read_line(file, global_temp_buffer, sizeof(global_temp_buffer)) > 0) { read_count++; } @@ -568,13 +631,13 @@ static int buffer_bookmarks(struct bookmark_list* bookmarks, int first_line) bookmarks->count = 0; bookmarks->reload = false; - while(read_line(file, global_read_buffer, sizeof(global_read_buffer)) > 0) + while(read_line(file, global_temp_buffer, sizeof(global_temp_buffer)) > 0) { read_count++; if (read_count >= first_line) { - dest -= strlen(global_read_buffer) + 1; + dest -= strlen(global_temp_buffer) + 1; if (dest < ((char*) bookmarks) + sizeof(*bookmarks) + (sizeof(char*) * (bookmarks->count + 1))) @@ -582,7 +645,7 @@ static int buffer_bookmarks(struct bookmark_list* bookmarks, int first_line) break; } - strcpy(dest, global_read_buffer); + strcpy(dest, global_temp_buffer); bookmarks->items[bookmarks->count] = dest; bookmarks->count++; } @@ -597,6 +660,8 @@ static const char* get_bookmark_info(int list_index, char *buffer, size_t buffer_len) { + char fnamebuf[MAX_PATH]; + struct resume_info resume_info; struct bookmark_list* bookmarks = (struct bookmark_list*) data; int index = list_index / 2; @@ -652,7 +717,8 @@ static const char* get_bookmark_info(int list_index, } } - if (!parse_bookmark(bookmarks->items[index - bookmarks->start], true, true)) + if (!parse_bookmark(fnamebuf, sizeof(fnamebuf), + bookmarks->items[index - bookmarks->start], &resume_info, true)) { return list_index % 2 == 0 ? (char*) str(LANG_BOOKMARK_INVALID) : " "; } @@ -686,25 +752,73 @@ static const char* get_bookmark_info(int list_index, } else { - name = global_filename; + name = fnamebuf; format = "%s"; } - strrsplt(global_filename, '.'); - snprintf(buffer, buffer_len, format, name, global_filename); + strrsplt(fnamebuf, '.'); + snprintf(buffer, buffer_len, format, name, fnamebuf); return buffer; } else { char time_buf[32]; - format_time(time_buf, sizeof(time_buf), bm.resume_time); - snprintf(buffer, buffer_len, "%s, %d%s", time_buf, bm.resume_index + 1, - bm.shuffle ? (char*) str(LANG_BOOKMARK_SHUFFLE) : ""); + format_time(time_buf, sizeof(time_buf), resume_info.resume_elapsed); + snprintf(buffer, buffer_len, "%s, %d%s", time_buf, + resume_info.resume_index + 1, + resume_info.shuffle ? (char*) str(LANG_BOOKMARK_SHUFFLE) : ""); return buffer; } } +/* ----------------------------------------------------------------------- */ +/* This function parses a bookmark, says the voice UI part of it. */ +/* ------------------------------------------------------------------------*/ +static void say_bookmark(const char* bookmark, + int bookmark_id, + bool show_playlist_name) +{ + char fnamebuf[MAX_PATH]; + struct resume_info resume_info; + if (!parse_bookmark(fnamebuf, sizeof(fnamebuf), bookmark, &resume_info, false)) + { + talk_id(LANG_BOOKMARK_INVALID, false); + return; + } + + talk_number(bookmark_id + 1, false); + + bool is_dir = (global_temp_buffer[0] + && global_temp_buffer[strlen(global_temp_buffer)-1] == '/'); + + /* HWCODEC cannot enqueue voice file entries and .talk thumbnails + together, because there is no guarantee that the same mp3 + parameters are used. */ + if(show_playlist_name) + { /* It's useful to know which playlist this is */ + if(is_dir) + talk_dir_or_spell(global_temp_buffer, + TALK_IDARRAY(VOICE_DIR), true); + else talk_file_or_spell(NULL, global_temp_buffer, + TALK_IDARRAY(LANG_PLAYLIST), true); + } + + if(resume_info.shuffle) + talk_id(LANG_SHUFFLE, true); + + talk_id(VOICE_BOOKMARK_SELECT_INDEX_TEXT, true); + talk_number(resume_info.resume_index + 1, true); + talk_id(LANG_TIME, true); + talk_value(resume_info.resume_elapsed / 1000, UNIT_TIME, true); + + /* Track filename */ + if(!is_dir) + global_temp_buffer[0] = 0; + talk_file_or_spell(global_temp_buffer, fnamebuf, + TALK_IDARRAY(VOICE_FILE), true); +} + static int bookmark_list_voice_cb(int list_index, void* data) { struct bookmark_list* bookmarks = (struct bookmark_list*) data; @@ -722,6 +836,57 @@ static int bookmark_list_voice_cb(int list_index, void* data) } /* ----------------------------------------------------------------------- */ +/* This function takes a location in a bookmark file and deletes that */ +/* bookmark. */ +/* Returns true on successful bookmark deletion. */ +/* ------------------------------------------------------------------------*/ +static bool delete_bookmark(const char* bookmark_file_name, int bookmark_id) +{ + int temp_bookmark_file = 0; + int bookmark_file = 0; + int bookmark_count = 0; + + /* Opening up a temp bookmark file */ + temp_bookmark_file = open_temp_bookmark(global_temp_buffer, + sizeof(global_temp_buffer), + O_WRONLY | O_CREAT | O_TRUNC, + bookmark_file_name); + + if (temp_bookmark_file < 0) + return false; /* can't open the temp file */ + + /* Reading in the previous bookmarks and writing them to the temp file */ + bookmark_file = open(bookmark_file_name, O_RDONLY); + if (bookmark_file >= 0) + { + while (read_line(bookmark_file, global_temp_buffer, + sizeof(global_temp_buffer)) > 0) + { + if (bookmark_id != bookmark_count) + { + write(temp_bookmark_file, global_temp_buffer, + strlen(global_temp_buffer)); + write(temp_bookmark_file, "\n", 1); + } + bookmark_count++; + } + close(bookmark_file); + } + close(temp_bookmark_file); + + /* only retrieve the path*/ + open_temp_bookmark(global_temp_buffer, + sizeof(global_temp_buffer), + O_PATH, + bookmark_file_name); + + remove(bookmark_file_name); + rename(global_temp_buffer, bookmark_file_name); + + return true; +} + +/* ----------------------------------------------------------------------- */ /* This displays the bookmarks in a file and allows the user to */ /* select one to play. */ /* *selected_bookmark contains a non NULL value on successful bookmark */ @@ -730,7 +895,9 @@ static int bookmark_list_voice_cb(int list_index, void* data) /* if no selection was made and BOOKMARK_USB_CONNECTED if the selection */ /* menu is forced to exit due to a USB connection. */ /* ------------------------------------------------------------------------*/ -static int select_bookmark(const char* bookmark_file_name, bool show_dont_resume, char** selected_bookmark) +static int select_bookmark(const char* bookmark_file_name, + bool show_dont_resume, + char** selected_bookmark) { struct bookmark_list* bookmarks; struct gui_synclist list; @@ -747,12 +914,13 @@ static int select_bookmark(const char* bookmark_file_name, bool show_dont_resume bookmarks->filename = bookmark_file_name; bookmarks->start = 0; bookmarks->show_playlist_name - = strcmp(bookmark_file_name, RECENT_BOOKMARK_FILE) == 0; - gui_synclist_init(&list, &get_bookmark_info, (void*) bookmarks, false, 2, NULL); + = (strcmp(bookmark_file_name, RECENT_BOOKMARK_FILE) == 0); + + gui_synclist_init(&list, &get_bookmark_info, + (void*) bookmarks, false, 2, NULL); + if(global_settings.talk_menu) gui_synclist_set_voice_callback(&list, bookmark_list_voice_cb); - gui_synclist_set_title(&list, str(LANG_BOOKMARK_SELECT_BOOKMARK), - Icon_Bookmark); while (!exit) { @@ -787,14 +955,15 @@ static int select_bookmark(const char* bookmark_file_name, bool show_dont_resume } buffer_bookmarks(bookmarks, bookmarks->start); + gui_synclist_set_title(&list, str(LANG_BOOKMARK_SELECT_BOOKMARK), + Icon_Bookmark); gui_synclist_draw(&list); cond_talk_ids_fq(VOICE_EXT_BMARK); gui_synclist_speak_item(&list); refresh = false; } - list_do_action(CONTEXT_BOOKMARKSCREEN, HZ / 2, - &list, &action, LIST_WRAP_UNLESS_HELD); + list_do_action(CONTEXT_BOOKMARKSCREEN, HZ / 2, &list, &action); item = gui_synclist_get_sel_pos(&list) / 2; if (bookmarks->show_dont_resume) @@ -843,17 +1012,7 @@ static int select_bookmark(const char* bookmark_file_name, bool show_dont_resume case ACTION_BMS_DELETE: if (item >= 0) { - const char *lines[]={ - ID2P(LANG_REALLY_DELETE) - }; - const char *yes_lines[]={ - ID2P(LANG_DELETING) - }; - - const struct text_message message={lines, 1}; - const struct text_message yes_message={yes_lines, 1}; - - if(gui_syncyesno_run(&message, &yes_message, NULL)==YESNO_YES) + if (confirm_delete_yesno("") == YESNO_YES) { delete_bookmark(bookmark_file_name, item); bookmarks->reload = true; @@ -879,264 +1038,247 @@ static int select_bookmark(const char* bookmark_file_name, bool show_dont_resume } /* ----------------------------------------------------------------------- */ -/* This function takes a location in a bookmark file and deletes that */ -/* bookmark. */ -/* Returns true on successful bookmark deletion. */ +/* This function parses a bookmark and then plays it. */ +/* Returns true on successful bookmark play. */ /* ------------------------------------------------------------------------*/ -static bool delete_bookmark(const char* bookmark_file_name, int bookmark_id) +static bool play_bookmark(const char* bookmark) { - int temp_bookmark_file = 0; - int bookmark_file = 0; - int bookmark_count = 0; - - /* Opening up a temp bookmark file */ - snprintf(global_temp_buffer, sizeof(global_temp_buffer), - "%s.tmp", bookmark_file_name); - temp_bookmark_file = open(global_temp_buffer, - O_WRONLY | O_CREAT | O_TRUNC, 0666); - - if (temp_bookmark_file < 0) - return false; /* can't open the temp file */ + char fnamebuf[MAX_PATH]; + struct resume_info resume_info; +#if defined(HAVE_PITCHCONTROL) + /* preset pitch and speed to 100% in case bookmark doesn't have info */ + resume_info.pitch = sound_get_pitch(); + resume_info.speed = dsp_get_timestretch(); +#endif - /* Reading in the previous bookmarks and writing them to the temp file */ - bookmark_file = open(bookmark_file_name, O_RDONLY); - if (bookmark_file >= 0) + if (parse_bookmark(fnamebuf, sizeof(fnamebuf), bookmark, &resume_info, true)) { - while (read_line(bookmark_file, global_read_buffer, - sizeof(global_read_buffer)) > 0) + global_settings.repeat_mode = resume_info.repeat_mode; + global_settings.playlist_shuffle = resume_info.shuffle; +#if defined(HAVE_PITCHCONTROL) + sound_set_pitch(resume_info.pitch); + dsp_set_timestretch(resume_info.speed); +#endif + if (!warn_on_pl_erase()) + return false; + bool success = bookmark_play(global_temp_buffer, resume_info.resume_index, + resume_info.resume_elapsed, resume_info.resume_offset, + resume_info.resume_seed, fnamebuf); + if (success) /* verify we loaded the correct track */ { - if (bookmark_id != bookmark_count) + const struct mp3entry *id3 = audio_current_track(); + if (id3) { - write(temp_bookmark_file, global_read_buffer, - strlen(global_read_buffer)); - write(temp_bookmark_file, "\n", 1); + const char *path; + const char *track; + path_basename(id3->path, &path); + path_basename(fnamebuf, &track); + if (strcmp(path, track) == 0) + { + return true; + } } - bookmark_count++; + audio_stop(); } - close(bookmark_file); } - close(temp_bookmark_file); - - remove(bookmark_file_name); - rename(global_temp_buffer, bookmark_file_name); - return true; + return false; } +/*-------------------------------------------------------------------------*/ +/* PUBLIC INTERFACE -------------------------------------------------------*/ +/*-------------------------------------------------------------------------*/ + + /* ----------------------------------------------------------------------- */ -/* This function parses a bookmark, says the voice UI part of it. */ -/* ------------------------------------------------------------------------*/ -static void say_bookmark(const char* bookmark, - int bookmark_id, bool show_playlist_name) +/* This is an interface function from the context menu. */ +/* Returns true on successful bookmark creation. */ +/* ----------------------------------------------------------------------- */ +bool bookmark_create_menu(void) { - if (!parse_bookmark(bookmark, true, false)) - { - talk_id(LANG_BOOKMARK_INVALID, false); - return; - } - - talk_number(bookmark_id + 1, false); + return write_bookmark(true); +} +/* ----------------------------------------------------------------------- */ +/* This function acts as the load interface from the context menu. */ +/* This function determines the bookmark file name and then loads that file*/ +/* for the user. The user can then select or delete previous bookmarks. */ +/* This function returns BOOKMARK_SUCCESS on the selection of a track to */ +/* resume, BOOKMARK_FAIL if the menu is exited without a selection and */ +/* BOOKMARK_USB_CONNECTED if the menu is forced to exit due to a USB */ +/* connection. */ +/* ----------------------------------------------------------------------- */ +int bookmark_load_menu(void) +{ + char bm_filename[MAX_PATH]; + char* bookmark; + int ret = BOOKMARK_FAIL; - bool is_dir = (global_temp_buffer[0] - && global_temp_buffer[strlen(global_temp_buffer)-1] == '/'); + push_current_activity(ACTIVITY_BOOKMARKSLIST); - /* HWCODEC cannot enqueue voice file entries and .talk thumbnails - together, because there is no guarantee that the same mp3 - parameters are used. */ - if(show_playlist_name) - { /* It's useful to know which playlist this is */ - if(is_dir) - talk_dir_or_spell(global_temp_buffer, - TALK_IDARRAY(VOICE_DIR), true); - else talk_file_or_spell(NULL, global_temp_buffer, - TALK_IDARRAY(LANG_PLAYLIST), true); + char* name = playlist_get_name(NULL, global_temp_buffer, + sizeof(global_temp_buffer)); + if (generate_bookmark_file_name(bm_filename, sizeof(bm_filename), name, -1)) + { + ret = select_bookmark(bm_filename, false, &bookmark); + if (bookmark != NULL) + { + ret = play_bookmark(bookmark) ? BOOKMARK_SUCCESS : BOOKMARK_FAIL; + } } - if(bm.shuffle) - talk_id(LANG_SHUFFLE, true); - - talk_id(VOICE_BOOKMARK_SELECT_INDEX_TEXT, true); - talk_number(bm.resume_index + 1, true); - talk_id(LANG_TIME, true); - talk_value(bm.resume_time / 1000, UNIT_TIME, true); - - /* Track filename */ - if(!is_dir) - global_temp_buffer[0] = 0; - talk_file_or_spell(global_temp_buffer, global_filename, - TALK_IDARRAY(VOICE_FILE), true); + pop_current_activity(); + return ret; } /* ----------------------------------------------------------------------- */ -/* This function parses a bookmark and then plays it. */ -/* Returns true on successful bookmark play. */ -/* ------------------------------------------------------------------------*/ -static bool play_bookmark(const char* bookmark) +/* Gives the user a list of the Most Recent Bookmarks. This is an */ +/* interface function */ +/* Returns true on the successful selection of a recent bookmark. */ +/* ----------------------------------------------------------------------- */ +bool bookmark_mrb_load() { -#if defined(HAVE_PITCHCONTROL) - /* preset pitch and speed to 100% in case bookmark doesn't have info */ - bm.pitch = sound_get_pitch(); - bm.speed = dsp_get_timestretch(); -#endif + char* bookmark; + bool ret = false; - if (parse_bookmark(bookmark, true, true)) + push_current_activity(ACTIVITY_BOOKMARKSLIST); + select_bookmark(RECENT_BOOKMARK_FILE, false, &bookmark); + if (bookmark != NULL) { - global_settings.repeat_mode = bm.repeat_mode; - global_settings.playlist_shuffle = bm.shuffle; -#if defined(HAVE_PITCHCONTROL) - sound_set_pitch(bm.pitch); - dsp_set_timestretch(bm.speed); -#endif - if (!warn_on_pl_erase()) - return false; - return bookmark_play(global_temp_buffer, bm.resume_index, - bm.resume_time, bm.resume_offset, bm.resume_seed, global_filename); + ret = play_bookmark(bookmark); } - return false; + pop_current_activity(); + return ret; } -static const char* skip_token(const char* s) +/* ----------------------------------------------------------------------- */ +/* This function handles an autobookmark creation. This is an interface */ +/* function. */ +/* Returns true on successful bookmark creation. */ +/* ----------------------------------------------------------------------- */ +bool bookmark_autobookmark(bool prompt_ok) { - while (*s && *s != ';') - { - s++; - } + logf("%s", __func__); + bool update; + + if (!bookmark_is_bookmarkable_state()) + return false; + + audio_pause(); /* first pause playback */ + update = (global_settings.autoupdatebookmark && bookmark_exists()); - if (*s) + if (update) + return write_bookmark(true); + + switch (global_settings.autocreatebookmark) { - s++; - } + case BOOKMARK_YES: + return write_bookmark(true); - return s; -} + case BOOKMARK_NO: + return false; -static const char* int_token(const char* s, int* dest) -{ - *dest = atoi(s); - return skip_token(s); -} + case BOOKMARK_RECENT_ONLY_YES: + return write_bookmark(false); + } + const char *lines[]={ID2P(LANG_AUTO_BOOKMARK_QUERY)}; + const struct text_message message={lines, 1}; -static const char* long_token(const char* s, long* dest) -{ - *dest = atoi(s); /* Should be atol, but we don't have it. */ - return skip_token(s); + if(prompt_ok && gui_syncyesno_run(&message, NULL, NULL)==YESNO_YES) + { + if (global_settings.autocreatebookmark == BOOKMARK_RECENT_ONLY_ASK) + return write_bookmark(false); + else + return write_bookmark(true); + } + return false; } /* ----------------------------------------------------------------------- */ -/* This function takes a bookmark and parses it. This function also */ -/* validates the bookmark. The parse_filenames flag indicates whether */ -/* the filename tokens are to be extracted. */ -/* Returns true on successful bookmark parse. */ -/* ----------------------------------------------------------------------- */ -static bool parse_bookmark(const char *bookmark, const bool parse_filenames, const bool strip_dir) +/* This function will determine if an autoload is necessary. This is an */ +/* interface function. */ +/* Returns */ +/* BOOKMARK_DO_RESUME on bookmark load or bookmark selection. */ +/* BOOKMARK_DONT_RESUME if we're not going to resume */ +/* BOOKMARK_CANCEL if user canceled */ +/* ------------------------------------------------------------------------*/ +int bookmark_autoload(const char* file) { - const char* s = bookmark; - const char* end; + logf("%s", __func__); + char bm_filename[MAX_PATH]; + char* bookmark; -#define GET_INT_TOKEN(var) s = int_token(s, &var) -#define GET_LONG_TOKEN(var) s = long_token(s, &var) -#define GET_BOOL_TOKEN(var) var = (atoi(s)!=0); s = skip_token(s) + if(global_settings.autoloadbookmark == BOOKMARK_NO) + return BOOKMARK_DONT_RESUME; - /* if new format bookmark, extract the optional content flags, - otherwise treat as an original format bookmark */ - int opt_flags = 0; - bool new_format = (strchr(s, '>') == s); - if (new_format) + /*Checking to see if a bookmark file exists.*/ + if(!generate_bookmark_file_name(bm_filename, sizeof(bm_filename), file, -1)) { - s++; - GET_INT_TOKEN(opt_flags); + return BOOKMARK_DONT_RESUME; } - /* extract all original bookmark tokens */ - GET_INT_TOKEN(bm.resume_index); - GET_LONG_TOKEN(bm.resume_offset); - GET_INT_TOKEN(bm.resume_seed); - if (!new_format) /* skip deprecated token */ - s = skip_token(s); - GET_LONG_TOKEN(bm.resume_time); - GET_INT_TOKEN(bm.repeat_mode); - GET_BOOL_TOKEN(bm.shuffle); - - /* extract all optional bookmark tokens */ - if (opt_flags & BM_PITCH) - GET_INT_TOKEN(bm.pitch); - if (opt_flags & BM_SPEED) - GET_INT_TOKEN(bm.speed); + if(!file_exists(bm_filename)) + return BOOKMARK_DONT_RESUME; - if (*s == 0) + if(global_settings.autoloadbookmark == BOOKMARK_YES) { - return false; + return (bookmark_load(bm_filename, true) + ? BOOKMARK_DO_RESUME : BOOKMARK_DONT_RESUME); } - - end = strchr(s, ';'); - - /* extract file names */ - if (parse_filenames) + else { - size_t len = (end == NULL) ? strlen(s) : (size_t) (end - s); - len = MIN(TEMP_BUF_SIZE - 1, len); - strlcpy(global_temp_buffer, s, len + 1); + int ret = select_bookmark(bm_filename, true, &bookmark); - if (end != NULL) + if (bookmark != NULL) { - end++; - if (strip_dir) - { - s = strrchr(end, '/'); - if (s) - { - end = s; - end++; - } - } - strlcpy(global_filename, end, MAX_PATH); + if (!play_bookmark(bookmark)) + return BOOKMARK_CANCEL; + return BOOKMARK_DO_RESUME; } - } - return true; + return (ret != BOOKMARK_SUCCESS) ? BOOKMARK_CANCEL : BOOKMARK_DONT_RESUME; + } } /* ----------------------------------------------------------------------- */ -/* This function is used by multiple functions and is used to generate a */ -/* bookmark named based off of the input. */ -/* Changing this function could result in how the bookmarks are stored. */ -/* it would be here that the centralized/decentralized bookmark code */ -/* could be placed. */ -/* Returns true if the file name is generated, false if it was too long */ -/* ----------------------------------------------------------------------- */ -static bool generate_bookmark_file_name(const char *in) +/* This function loads the bookmark information into the resume memory. */ +/* This is an interface function. */ +/* Returns true on successful bookmark load. */ +/* ------------------------------------------------------------------------*/ +bool bookmark_load(const char* file, bool autoload) { - /* if this is a root dir MP3, rename the bookmark file root_dir.bmark */ - /* otherwise, name it based on the in variable */ - if (!strcmp("/", in)) - strcpy(global_bookmark_file_name, "/root_dir.bmark"); - else - { -#ifdef HAVE_MULTIVOLUME - /* The "root" of an extra volume need special handling too. */ - const char *filename; - path_strip_volume(in, &filename, true); - bool volume_root = *filename == '\0'; -#endif - size_t len = strlcpy(global_bookmark_file_name, in, MAX_PATH); - if(len >= MAX_PATH) - return false; + logf("%s", __func__); + int fd; + char* bookmark = NULL; - if(global_bookmark_file_name[len-1] == '/') { - global_bookmark_file_name[len-1] = '\0'; - len--; + if(autoload) + { + fd = open(file, O_RDONLY); + if(fd >= 0) + { + if(read_line(fd, global_temp_buffer, sizeof(global_temp_buffer)) > 0) + bookmark=global_temp_buffer; + close(fd); } + } + else + { + /* This is not an auto-load, so list the bookmarks */ + select_bookmark(file, false, &bookmark); + } -#ifdef HAVE_MULTIVOLUME - if (volume_root) - len = strlcat(global_bookmark_file_name, "/volume_dir.bmark", MAX_PATH); - else -#endif - len = strlcat(global_bookmark_file_name, ".bmark", MAX_PATH); + if (bookmark != NULL) + { + if (!play_bookmark(bookmark)) + { + /* Selected bookmark not found. */ + if (!autoload) + { + splash(HZ*2, ID2P(LANG_NOTHING_TO_RESUME)); + } - if(len >= MAX_PATH) return false; + } } return true; @@ -1148,13 +1290,15 @@ static bool generate_bookmark_file_name(const char *in) /* ----------------------------------------------------------------------- */ bool bookmark_exists(void) { + char bm_filename[MAX_PATH]; bool exist=false; char* name = playlist_get_name(NULL, global_temp_buffer, sizeof(global_temp_buffer)); - if (generate_bookmark_file_name(name)) + if (!playlist_dynamic_only() && + generate_bookmark_file_name(bm_filename, sizeof(bm_filename), name, -1)) { - exist = file_exists(global_bookmark_file_name); + exist = file_exists(bm_filename); } return exist; } @@ -1172,12 +1316,13 @@ bool bookmark_is_bookmarkable_state(void) /* no track playing */ (playlist_get_resume_info(&resume_index) == -1) || /* invalid queue info */ - (playlist_modified(NULL))) - /* can't bookmark while in the queue */ + (playlist_modified(NULL)) || + /* can't bookmark playlists modified by user */ + (playlist_dynamic_only())) + /* can't bookmark playlists without associated folder or playlist file */ { return false; } return true; } - diff --git a/apps/bookmark.h b/apps/bookmark.h index ff7b87c1bf..192e577ce6 100644 --- a/apps/bookmark.h +++ b/apps/bookmark.h @@ -29,11 +29,17 @@ enum { BOOKMARK_USB_CONNECTED = 1 }; +enum { + BOOKMARK_CANCEL, + BOOKMARK_DONT_RESUME, + BOOKMARK_DO_RESUME +}; + int bookmark_load_menu(void); bool bookmark_autobookmark(bool prompt_ok); bool bookmark_create_menu(void); bool bookmark_mrb_load(void); -bool bookmark_autoload(const char* file); +int bookmark_autoload(const char* file); bool bookmark_load(const char* file, bool autoload); bool bookmark_exists(void); bool bookmark_is_bookmarkable_state(void); diff --git a/apps/buffering.c b/apps/buffering.c index 8661a42ab8..81b861ccf1 100644 --- a/apps/buffering.c +++ b/apps/buffering.c @@ -20,7 +20,6 @@ ****************************************************************************/ #include "config.h" #include <string.h> -#include "strlcpy.h" #include "system.h" #include "storage.h" #include "thread.h" @@ -417,7 +416,8 @@ add_handle(unsigned int flags, size_t data_size, const char *path, h->signaled = 0; /* Data can be waited for */ /* Save the provided path */ - memcpy(h->path, path, pathsize); + if (path) + memcpy(h->path, path, pathsize); /* Return the start of the data area */ *data_out = ringbuf_add(index, handlesize); diff --git a/apps/codecs.c b/apps/codecs.c index 4d2dd34ce0..9f34d26e14 100644 --- a/apps/codecs.c +++ b/apps/codecs.c @@ -203,8 +203,9 @@ static int codec_load_ram(struct codec_api *api) return CODEC_ERROR; } - if (hdr->api_version > CODEC_API_VERSION - || hdr->api_version < CODEC_MIN_API_VERSION) { + if (hdr->api_version != CODEC_API_VERSION || + c_hdr->api_size > sizeof(struct codec_api)) + { logf("codec api version error"); lc_close(curr_handle); curr_handle = NULL; diff --git a/apps/core_keymap.c b/apps/core_keymap.c index dbe7ae0072..89e7913c33 100644 --- a/apps/core_keymap.c +++ b/apps/core_keymap.c @@ -27,119 +27,68 @@ #include "logf.h" #if !defined(__PCTOOL__) || defined(CHECKWPS) -static int keymap_handle = -1; - -static int core_alloc_keymap(size_t bufsz) +int core_set_keyremap(struct button_mapping* core_keymap, int count) { - keymap_handle = core_alloc_ex("key remap", bufsz, &buflib_ops_locked); - return keymap_handle; + return action_set_keymap(core_keymap, count); } -static void core_free_keymap(void) +static int open_key_remap(const char *filename, int *countp) { - action_set_keymap(NULL, -1); - if (keymap_handle > 0) /* free old buffer */ + int fd = open(filename, O_RDONLY); + if (fd < 0) + return fd; + + size_t fsize = filesize(fd); + int count = fsize / sizeof(struct button_mapping); + if (count == 0 || (size_t)(count * sizeof(struct button_mapping)) != fsize) { - keymap_handle = core_free(keymap_handle); + logf("core_keyremap: bad filesize %d / %lu", count, (unsigned long)fsize); + goto error; } -} - -/* Allocates buffer from core and copies keymap into it */ -int core_set_keyremap(struct button_mapping* core_keymap, int count) -{ - core_free_keymap(); - if (count > 0) + struct button_mapping header; + if(read(fd, &header, sizeof(header)) != (ssize_t)sizeof(header)) { - size_t bufsize = count * sizeof(struct button_mapping); - if (core_keymap != NULL && core_alloc_keymap(bufsize) > 0) - { - char *buf = core_get_data(keymap_handle); - memcpy(buf, core_keymap, bufsize); - count = action_set_keymap((struct button_mapping *) buf, count); - } - else - count = -1; + logf("core_keyremap: read error"); + goto error; } - return count; -} -int core_load_key_remap(const char *filename) -{ - char *buf; - int fd = -1; - int count = 0; - size_t fsize = 0; - core_free_keymap(); - - if (filename != NULL) - count = open_key_remap(filename, &fd, &fsize); - while (count > 0) + if (header.action_code != KEYREMAP_VERSION || + header.button_code != KEYREMAP_HEADERID || + header.pre_button_code != count) { - if (core_alloc_keymap(fsize) <= 0) - { - count = -30; - logf("core_keymap: %d Failed to allocate buffer", count); - break; - } - buf = core_get_data(keymap_handle); - if (read(fd, buf, fsize) == (ssize_t) fsize) - { - count = action_set_keymap((struct button_mapping *) buf, count); - } - else - { - count = -40; - logf("core_keymap: %d Failed to read", count); - } - break; + logf("core_keyremap: bad header %d", count); + goto error; } + + *countp = count - 1; + return fd; + + error: close(fd); - return count; + return -1; } -int open_key_remap(const char *filename, int *fd, size_t *fsize) +int core_load_key_remap(const char *filename) { - int count = 0; + int count = 0; /* gcc falsely believes this may be used uninitialized */ + int fd = open_key_remap(filename, &count); + if (fd < 0) + return -1; - while (filename && fd && fsize) + size_t bufsize = count * sizeof(struct button_mapping); + int handle = core_alloc(bufsize); + if (handle > 0) { - *fsize = 0; - *fd = open(filename, O_RDONLY); - if (*fd) - { - *fsize = filesize(*fd); - - count = *fsize / sizeof(struct button_mapping); + void *data = core_get_data_pinned(handle); - if (count * sizeof(struct button_mapping) != *fsize) - { - count = -10; - logf("core_keymap: %d Size mismatch", count); - break; - } + if (read(fd, data, bufsize) == (ssize_t)bufsize) + count = action_set_keymap_handle(handle, count); - if (count > 1) - { - struct button_mapping header = {0}; - read(*fd, &header, sizeof(struct button_mapping)); - if (KEYREMAP_VERSION == header.action_code && - KEYREMAP_HEADERID == header.button_code && - header.pre_button_code == count) - { - count--; - *fsize -= sizeof(struct button_mapping); - } - else /* Header mismatch */ - { - count = -20; - logf("core_keymap: %d Header mismatch", count); - break; - } - } - } - break; + core_put_data_pinned(data); } + + close(fd); return count; } diff --git a/apps/core_keymap.h b/apps/core_keymap.h index dad9875364..2077daa685 100644 --- a/apps/core_keymap.h +++ b/apps/core_keymap.h @@ -34,13 +34,6 @@ /* Allocates core buffer, copies keymap to allow buttons for actions to be remapped*/ int core_set_keyremap(struct button_mapping* core_keymap, int count); -/* open_key_remap(filename , *fd (you must close file_descriptor), *fsize) - * checks/strips header and returns remaining count - * fd is opened and set to first record - * filesize contains the size of the remaining records -*/ -int open_key_remap(const char *filename, int *fd, size_t *filesize); - /* load a remap file to allow buttons for actions to be remapped */ int core_load_key_remap(const char *filename); diff --git a/apps/cuesheet.c b/apps/cuesheet.c index 98040f9992..bbdc93746e 100644 --- a/apps/cuesheet.c +++ b/apps/cuesheet.c @@ -58,28 +58,28 @@ static bool search_for_cuesheet(const char *path, struct cuesheet_file *cue_file slash_cuepath = &cuepath[slash - path]; dot = strrchr(slash_cuepath, '.'); if (dot) - strlcpy(dot, ".cue", MAX_PATH - (dot-cuepath)); + strmemccpy(dot, ".cue", MAX_PATH - (dot-cuepath)); if (!dot || !file_exists(cuepath)) { strcpy(cuepath, CUE_DIR); if (strlcat(cuepath, slash, MAX_PATH) >= MAX_PATH) goto skip; /* overflow */ - char *dot = strrchr(cuepath, '.'); + dot = strrchr(cuepath, '.'); strcpy(dot, ".cue"); if (!file_exists(cuepath)) { skip: if ((len+4) >= MAX_PATH) return false; - strlcpy(cuepath, path, MAX_PATH); + strmemccpy(cuepath, path, MAX_PATH); strlcat(cuepath, ".cue", MAX_PATH); if (!file_exists(cuepath)) return false; } } - strlcpy(cue_file->path, cuepath, MAX_PATH); + strmemccpy(cue_file->path, cuepath, MAX_PATH); return true; } @@ -91,7 +91,7 @@ bool look_for_cuesheet_file(struct mp3entry *track_id3, struct cuesheet_file *cu cue_file->pos = track_id3->embedded_cuesheet.pos; cue_file->size = track_id3->embedded_cuesheet.size; cue_file->encoding = track_id3->embedded_cuesheet.encoding; - strlcpy(cue_file->path, track_id3->path, MAX_PATH); + strmemccpy(cue_file->path, track_id3->path, MAX_PATH); return true; } @@ -139,7 +139,7 @@ static unsigned long parse_cue_index(const char *line) while (isdigit(*line)) { value = 10 * value + (*line - '0'); - if (value > field_max[field]) /* Sanity check bail early */ + if (field >= 0 && value > field_max[field]) /* Sanity check bail early */ return 0; line++; } @@ -363,7 +363,7 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue) } else { - strlcpy(dest, string, count); + strmemccpy(dest, string, count); } } } @@ -386,7 +386,7 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue) strcpy(cue->file, cue->path); char *slash = strrchr(cue->file, '/'); if (!slash++) slash = cue->file; - strlcpy(slash, line, MAX_PATH - (slash - cue->file)); + strmemccpy(slash, line, MAX_PATH - (slash - cue->file)); } /* If some songs don't have performer info, we copy the cuesheet performer */ @@ -394,10 +394,10 @@ bool parse_cuesheet(struct cuesheet_file *cue_file, struct cuesheet *cue) for (i = 0; i < cue->track_count; i++) { if (*(cue->tracks[i].performer) == '\0') - strlcpy(cue->tracks[i].performer, cue->performer, MAX_NAME*3); + strmemccpy(cue->tracks[i].performer, cue->performer, MAX_NAME*3); if (*(cue->tracks[i].songwriter) == '\0') - strlcpy(cue->tracks[i].songwriter, cue->songwriter, MAX_NAME*3); + strmemccpy(cue->tracks[i].songwriter, cue->songwriter, MAX_NAME*3); } return true; @@ -441,7 +441,7 @@ static const char* list_get_name_cb(int selected_item, struct cuesheet *cue = (struct cuesheet *)data; if (selected_item & 1) - strlcpy(buffer, cue->tracks[selected_item/2].title, buffer_len); + strmemccpy(buffer, cue->tracks[selected_item/2].title, buffer_len); else snprintf(buffer, buffer_len, "%02d. %s", selected_item/2+1, cue->tracks[selected_item/2].performer); @@ -481,7 +481,7 @@ void browse_cuesheet(struct cuesheet *cue) { gui_synclist_draw(&lists); action = get_action(CONTEXT_LIST,TIMEOUT_BLOCK); - if (gui_synclist_do_button(&lists, &action, LIST_WRAP_UNLESS_HELD)) + if (gui_synclist_do_button(&lists, &action)) continue; switch (action) { @@ -508,7 +508,7 @@ void browse_cuesheet(struct cuesheet *cue) /* check that this cue is the same one that would be found by a search from playback */ char file[MAX_PATH]; - strlcpy(file, cue->file, MAX_PATH); + strmemccpy(file, cue->file, MAX_PATH); if (!strcmp(cue->path, file) || /* if embedded */ (search_for_cuesheet(file, &cue_file) && @@ -523,6 +523,8 @@ void browse_cuesheet(struct cuesheet *cue) case ACTION_STD_CANCEL: done = true; + default: + break; } } } @@ -535,7 +537,7 @@ bool display_cuesheet_content(char* filename) if (!cue || bufsize < sizeof(struct cuesheet)) return false; - strlcpy(cue_file.path, filename, MAX_PATH); + strmemccpy(cue_file.path, filename, MAX_PATH); cue_file.pos = 0; cue_file.size = 0; @@ -565,12 +567,12 @@ bool curr_cuesheet_skip(struct cuesheet *cue, int direction, unsigned long curr_ if (!(direction <= 0 && track == 0)) { /* If skipping forward, skip to next cuesheet segment. If skipping - backward before DEFAULT_SKIP_TRESH milliseconds have elapsed, skip + backward before DEFAULT_SKIP_THRESH milliseconds have elapsed, skip to previous cuesheet segment. If skipping backward after - DEFAULT_SKIP_TRESH seconds have elapsed, skip to the start of the + DEFAULT_SKIP_THRESH seconds have elapsed, skip to the start of the current cuesheet segment */ if (direction == 1 || - ((curr_pos - cue->tracks[track].offset) < DEFAULT_SKIP_TRESH)) + ((curr_pos - cue->tracks[track].offset) < DEFAULT_SKIP_THRESH)) { track += direction; } diff --git a/apps/debug_menu.c b/apps/debug_menu.c index f510597ad2..5b73f8badd 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -23,13 +23,12 @@ #include <stdlib.h> #include <stdio.h> #include <stdbool.h> -#include <string.h> +#include <string-extra.h> #include "lcd.h" #include "lang.h" #include "menu.h" #include "debug_menu.h" #include "kernel.h" -#include "structec.h" #include "action.h" #include "debug.h" #include "thread.h" @@ -210,6 +209,10 @@ static int dbg_threads_action_callback(int action, struct gui_synclist *lists) *x_offset += 1; action = ACTION_REDRAW; } + else if (IS_SYSEVENT(action)) + { + return ACTION_REDRAW; + } else if (action != ACTION_UNKNOWN) { *x_offset = 0; @@ -227,7 +230,6 @@ static bool dbg_os(void) simplelist_info_init(&info, IF_COP("Core and ") "Stack usage:", MAXTHREADS IF_COP( + NUM_CORES ), &xoffset); - info.hide_selection = true; info.scroll_all = false; info.action_callback = dbg_threads_action_callback; info.get_name = threads_getname; @@ -341,7 +343,6 @@ static bool dbg_cpuinfo(void) info.get_name = get_cpuinfo; info.action_callback = cpuinfo_cb; info.timeout = HZ; - info.hide_selection = true; info.scroll_all = true; return simplelist_show_list(&info); } @@ -498,6 +499,7 @@ static bool dbg_buffering_thread(void) #undef STR_DATAREM } +#ifdef BUFLIB_DEBUG_PRINT static const char* bf_getname(int selected_item, void *data, char *buffer, size_t buffer_len) { @@ -517,13 +519,12 @@ static int bf_action_cb(int action, struct gui_synclist* list) else { splash(HZ/1, "Attempting a 64k allocation"); - int handle = core_alloc("test", 64<<10); + int handle = core_alloc(64<<10); splash(HZ/2, (handle > 0) ? "Success":"Fail"); /* for some reason simplelist doesn't allow adding items here if * info.get_name is given, so use normal list api */ gui_synclist_set_nb_items(list, core_get_num_blocks()); - if (handle > 0) - core_free(handle); + core_free(handle); } action = ACTION_REDRAW; } @@ -539,6 +540,7 @@ static bool dbg_buflib_allocs(void) info.timeout = HZ; return simplelist_show_list(&info); } +#endif /* BUFLIB_DEBUG_PRINT */ #if (CONFIG_PLATFORM & PLATFORM_NATIVE) static const char* dbg_partitions_getname(int selected_item, void *data, @@ -568,7 +570,6 @@ static bool dbg_partitions(void) struct simplelist_info info; simplelist_info_init(&info, "Partition Info", NUM_DRIVES * 4, NULL); info.selection_size = 2; - info.hide_selection = true; info.scroll_all = true; info.get_name = dbg_partitions_getname; return simplelist_show_list(&info); @@ -870,7 +871,7 @@ static int tsc2100debug_action_callback(int action, struct gui_synclist *lists) if (action == ACTION_STD_OK) { *page = (*page+1)%3; - snprintf(lists->title, 32, "tsc2100 registers - Page %d", *page); + snprintf((char*)lists->title, 32, "tsc2100 registers - Page %d", *page); return ACTION_REDRAW; } return action; @@ -1247,7 +1248,8 @@ static int disk_callback(int btn, struct gui_synclist *lists) int *cardnum = (int*)lists->data; unsigned char card_name[6]; unsigned char pbuf[32]; - char *title = lists->title; + /* Casting away const is safe; the buffer is defined as non-const. */ + char *title = (char *)lists->title; static const unsigned char i_vmin[] = { 0, 1, 5, 10, 25, 35, 60, 100 }; static const unsigned char i_vmax[] = { 1, 5, 10, 25, 35, 45, 80, 200 }; static const unsigned char * const kbit_units[] = { "kBit/s", "MBit/s", "GBit/s" }; @@ -1277,7 +1279,7 @@ static int disk_callback(int btn, struct gui_synclist *lists) { card_name[i] = card_extract_bits(card->cid, (103-8*i), 8); } - strlcpy(card_name, card_name, sizeof(card_name)); + strmemccpy(card_name, card_name, sizeof(card_name)); simplelist_addline( "%s Rev %d.%d", card_name, (int) card_extract_bits(card->cid, 63, 4), @@ -1630,7 +1632,8 @@ static int ata_smart_attr_to_string( if (len >= name_sz) len = name_sz-1; slen += len; } - snprintf(str+slen, size-slen, "%s", buf); + + strmemccpy(str+slen, buf, size-slen); } return 1; /* ok */ @@ -1721,7 +1724,6 @@ static bool dbg_ata_smart(void) struct simplelist_info info; simplelist_info_init(&info, "S.M.A.R.T. Data [CONTEXT to dump]", 1, NULL); info.action_callback = ata_smart_callback; - info.hide_selection = true; info.scroll_all = true; return simplelist_show_list(&info); } @@ -1753,10 +1755,16 @@ static bool dbg_identify_info(void) int fd = creat("/identify_info.bin", 0666); if(fd >= 0) { + const unsigned short *identify_info = ata_get_identify(); #ifdef ROCKBOX_LITTLE_ENDIAN - ecwrite(fd, ata_get_identify(), SECTOR_SIZE/2, "s", true); + /* this is a pointer to a driver buffer so we can't modify it */ + for (int i = 0; i < SECTOR_SIZE/2; ++i) + { + unsigned short word = swap16(identify_info[i]); + write(fd, &word, 2); + } #else - write(fd, ata_get_identify(), SECTOR_SIZE); + write(fd, identify_info, SECTOR_SIZE); #endif close(fd); } @@ -1775,7 +1783,6 @@ static bool dbg_disk_info(void) info.title = title; #endif info.action_callback = disk_callback; - info.hide_selection = true; info.scroll_all = true; return simplelist_show_list(&info); } @@ -1844,7 +1851,6 @@ static bool dbg_dircache_info(void) int syncbuild = 0; simplelist_info_init(&info, "Dircache Info", 8, &syncbuild); info.action_callback = dircache_callback; - info.hide_selection = true; info.scroll_all = true; return simplelist_show_list(&info); } @@ -1857,6 +1863,7 @@ static int database_callback(int btn, struct gui_synclist *lists) (void)lists; struct tagcache_stat *stat = tagcache_get_stat(); static bool synced = false; + static int update_entries = 0; simplelist_set_line_count(0); @@ -1868,6 +1875,8 @@ static int database_callback(int btn, struct gui_synclist *lists) stat->ramcache ? "Yes" : "No"); simplelist_addline("RAM: %d/%d B", stat->ramcache_used, stat->ramcache_allocated); + simplelist_addline("Total entries: %d", + stat->total_entries); simplelist_addline("Progress: %d%% (%d entries)", stat->progress, stat->processed_entries); simplelist_addline("Curfile: %s", @@ -1889,12 +1898,19 @@ static int database_callback(int btn, struct gui_synclist *lists) if (!btn && stat->curentry) { synced = true; - return ACTION_REDRAW; + if (update_entries <= stat->processed_entries) + { + update_entries = stat->processed_entries + 100; + return ACTION_REDRAW; + } + return ACTION_NONE; } if (btn == ACTION_STD_CANCEL) + { + update_entries = 0; tagcache_screensync_enable(false); - + } return btn; } static bool dbg_tagcache_info(void) @@ -1902,7 +1918,6 @@ static bool dbg_tagcache_info(void) struct simplelist_info info; simplelist_info_init(&info, "Database Info", 8, NULL); info.action_callback = database_callback; - info.hide_selection = true; info.scroll_all = true; /* Don't do nonblock here, must give enough processing time @@ -2175,7 +2190,6 @@ static bool dbg_fm_radio(void) radio_hardware_present() ? "yes" : "no"); info.action_callback = radio_hardware_present()?radio_callback : NULL; - info.hide_selection = true; return simplelist_show_list(&info); } #endif /* CONFIG_TUNER */ @@ -2211,7 +2225,7 @@ static bool dbg_set_memory_guard(void) }; int mode = system_memory_guard(MEMGUARD_KEEP); - set_option( "Catch mem accesses", &mode, INT, names, MAXMEMGUARD, NULL); + set_option( "Catch mem accesses", &mode, RB_INT, names, MAXMEMGUARD, NULL); system_memory_guard(mode); return false; @@ -2304,11 +2318,6 @@ static bool cpu_boost_log(void) static bool cpu_boost_log_dump(void) { int fd; -#if CONFIG_RTC - struct tm *nowtm; - char fname[MAX_PATH]; -#endif - int count = cpu_boost_log_getcount(); char *str = cpu_boost_log_getlog_first(); @@ -2319,11 +2328,12 @@ static bool cpu_boost_log_dump(void) return false; #if CONFIG_RTC - nowtm = get_time(); - snprintf(fname, MAX_PATH, "%s/boostlog_%04d%02d%02d%02d%02d%02d.txt", ROCKBOX_DIR, - nowtm->tm_year + 1900, nowtm->tm_mon + 1, nowtm->tm_mday, - nowtm->tm_hour, nowtm->tm_min, nowtm->tm_sec); - fd = open(fname, O_CREAT|O_WRONLY|O_TRUNC); + char fname[MAX_PATH]; + struct tm *nowtm = get_time(); + fd = open_pathfmt(fname, sizeof(fname), O_CREAT|O_WRONLY|O_TRUNC, + "%s/boostlog_%04d%02d%02d%02d%02d%02d.txt", ROCKBOX_DIR, + nowtm->tm_year + 1900, nowtm->tm_mon + 1, nowtm->tm_mday, + nowtm->tm_hour, nowtm->tm_min, nowtm->tm_sec); #else fd = open(ROCKBOX_DIR "/boostlog.txt", O_CREAT|O_WRONLY|O_TRUNC, 0666); #endif @@ -2447,7 +2457,6 @@ static bool dbg_talk(void) else simplelist_info_init(&list, "Voice Information:", 2, &data); list.scroll_all = true; - list.hide_selection = true; list.timeout = HZ; list.get_name = dbg_talk_get_name; @@ -2487,7 +2496,6 @@ static bool dbg_isp1583(void) isp1583.scroll_all = true; simplelist_info_init(&isp1583, "ISP1583", dbg_usb_num_items(), NULL); isp1583.timeout = HZ/100; - isp1583.hide_selection = true; isp1583.get_name = dbg_usb_item; isp1583.action_callback = isp1583_action_callback; return simplelist_show_list(&isp1583); @@ -2513,67 +2521,12 @@ static bool dbg_pic(void) pic.scroll_all = true; simplelist_info_init(&pic, "PIC", pic_dbg_num_items(), NULL); pic.timeout = HZ/100; - pic.hide_selection = true; pic.get_name = pic_dbg_item; pic.action_callback = pic_action_callback; return simplelist_show_list(&pic); } #endif -static bool dbg_skin_engine(void) -{ - struct simplelist_info info; - int i, total = 0; -#if defined(HAVE_BACKDROP_IMAGE) - int ref_count; - char *path; - size_t bytes; - int path_prefix_len = strlen(ROCKBOX_DIR "/wps/"); -#endif - simplelist_info_init(&info, "Skin engine usage", 0, NULL); - simplelist_set_line_count(0); - info.hide_selection = true; - FOR_NB_SCREENS(j) { -#if NB_SCREENS > 1 - simplelist_addline("%s display:", - j == 0 ? "Main" : "Remote"); -#endif - for (i = 0; i < skin_get_num_skins(); i++) { - struct skin_stats *stats = skin_get_stats(i, j); - if (stats->buflib_handles) - { - simplelist_addline("Skin ID: %d, %d allocations", - i, stats->buflib_handles); - simplelist_addline("\tskin: %d bytes", - stats->tree_size); - simplelist_addline("\tImages: %d bytes", - stats->images_size); - simplelist_addline("\tTotal: %d bytes", - stats->tree_size + stats->images_size); - total += stats->tree_size + stats->images_size; - } - } - } - simplelist_addline("Skin total usage: %d bytes", total); -#if defined(HAVE_BACKDROP_IMAGE) - simplelist_addline("Backdrop Images:"); - i = 0; - while (skin_backdrop_get_debug(i++, &path, &ref_count, &bytes)) { - if (ref_count > 0) { - - if (!strncasecmp(path, ROCKBOX_DIR "/wps/", path_prefix_len)) - path += path_prefix_len; - simplelist_addline("%s", path); - simplelist_addline("\tref_count: %d", ref_count); - simplelist_addline("\tsize: %d", bytes); - total += bytes; - } - } - simplelist_addline("Total usage: %d bytes", total); -#endif - return simplelist_show_list(&info); -} - #if defined(HAVE_BOOTDATA) && !defined(SIMULATOR) static bool dbg_boot_data(void) { @@ -2611,7 +2564,6 @@ static bool dbg_boot_data(void) boot_data.payload[i+1], boot_data.payload[i+2], boot_data.payload[i+3]); } - info.hide_selection = true; return simplelist_show_list(&info); } #endif /* defined(HAVE_BOOTDATA) && !defined(SIMULATOR) */ @@ -2688,7 +2640,9 @@ static const struct { #ifdef PM_DEBUG { "pm histogram", peak_meter_histogram}, #endif /* PM_DEBUG */ +#ifdef BUFLIB_DEBUG_PRINT { "View buflib allocs", dbg_buflib_allocs }, +#endif #ifndef SIMULATOR #if CONFIG_TUNER { "FM Radio", dbg_fm_radio }, diff --git a/apps/enc_config.c b/apps/enc_config.c index 65ef65667a..d06ac84b5f 100644 --- a/apps/enc_config.c +++ b/apps/enc_config.c @@ -183,7 +183,7 @@ static bool mp3_enc_bitrate(struct menucallback_data *data) int index = round_value_to_list32(cfg->mp3_enc.bitrate, rate_list, n_rates, false); - bool res = set_option(str(LANG_BITRATE), &index, INT, + bool res = set_option(str(LANG_BITRATE), &index, RB_INT, items, n_rates, NULL); index = round_value_to_list32(rate_list[index], mp3_enc_bitr, MP3_ENC_NUM_BITR, false); @@ -193,9 +193,9 @@ static bool mp3_enc_bitrate(struct menucallback_data *data) } /* mp3_enc_bitrate */ /* mp3_enc configuration menu */ -MENUITEM_FUNCTION(mp3_bitrate, MENU_FUNC_USEPARAM, ID2P(LANG_BITRATE), - mp3_enc_bitrate, - &menu_callback_data, enc_menuitem_callback, Icon_NOICON); +MENUITEM_FUNCTION_W_PARAM(mp3_bitrate, 0, ID2P(LANG_BITRATE), + mp3_enc_bitrate, &menu_callback_data, + enc_menuitem_callback, Icon_NOICON); MAKE_MENU( mp3_enc_menu, ID2P(LANG_ENCODER_SETTINGS), enc_menuitem_enteritem, Icon_NOICON, &mp3_bitrate); @@ -286,7 +286,7 @@ static int enc_menuitem_callback(int action, { (void)this_list; struct menucallback_data *data = - (struct menucallback_data*)this_item->function->param; + (struct menucallback_data*)this_item->function_param->param; if (action == ACTION_EXIT_MENUITEM) { diff --git a/apps/features.txt b/apps/features.txt index 45e06e5e64..bafaa11599 100644 --- a/apps/features.txt +++ b/apps/features.txt @@ -289,3 +289,14 @@ multi_boot #if defined(HIBY_LINUX) hibylinux #endif + +#if defined(BUTTON_REC) || \ + (CONFIG_KEYPAD == GIGABEAT_PAD) || \ + (CONFIG_KEYPAD == IPOD_4G_PAD) || \ + (CONFIG_KEYPAD == IRIVER_H10_PAD) +clear_settings_on_hold +#endif + +#if defined(HAVE_PERCEPTUAL_VOLUME) +perceptual_volume +#endif diff --git a/apps/filetree.c b/apps/filetree.c index 1944713d13..eb429c83e3 100644 --- a/apps/filetree.c +++ b/apps/filetree.c @@ -51,33 +51,69 @@ #endif #include "wps.h" -static int compare_sort_dir; /* qsort key for sorting directories */ +static struct compare_data +{ + int sort_dir; /* qsort key for sorting directories */ + int(*_compar)(const char*, const char*, size_t); +} cmp_data; + +/* dummmy functions to allow compatibility with strncmp & strncasecmp */ +static int strnatcmp_n(const char *a, const char *b, size_t n) +{ + (void)n; + return strnatcmp(a, b); +} +static int strnatcasecmp_n(const char *a, const char *b, size_t n) +{ + (void)n; + return strnatcasecmp(a, b); +} int ft_build_playlist(struct tree_context* c, int start_index) { int i; int start=start_index; + int res; + struct playlist_info *playlist = playlist_get_current(); tree_lock_cache(c); struct entry *entries = tree_get_entries(c); - for(i = 0;i < c->filesindir;i++) + struct playlist_insert_context pl_context; + + res = playlist_insert_context_create(playlist, &pl_context, + PLAYLIST_REPLACE, false, false); + if (res >= 0) { - if((entries[i].attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO) + cpu_boost(true); + for(i = 0;i < c->filesindir;i++) { - if (playlist_add(entries[i].name) < 0) +#if 0 /*only needed if displaying progress */ + /* user abort */ + if (action_userabort(TIMEOUT_NOBLOCK)) + { break; + } +#endif + if((entries[i].attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO) + { + res = playlist_insert_context_add(&pl_context, entries[i].name); + if (res < 0) + break; + } + else + { + /* Adjust the start index when se skip non-MP3 entries */ + if(i < start) + start_index--; + } } - else - { - /* Adjust the start index when se skip non-MP3 entries */ - if(i < start) - start_index--; - } + cpu_boost(false); } + + playlist_insert_context_release(&pl_context); tree_unlock_cache(c); - return start_index; } @@ -89,7 +125,8 @@ int ft_build_playlist(struct tree_context* c, int start_index) * avoid allocating yet another path buffer on the stack (and save some * code; the caller typically needs to create the full pathname anyway)... */ -bool ft_play_playlist(char* pathname, char* dirname, char* filename, bool skip_dyn_warning) +bool ft_play_playlist(char* pathname, char* dirname, + char* filename, bool skip_warn_and_bookmarks) { if (global_settings.party_mode && audio_status()) { @@ -97,28 +134,19 @@ bool ft_play_playlist(char* pathname, char* dirname, char* filename, bool skip_d return false; } - if (bookmark_autoload(pathname)) + if (!skip_warn_and_bookmarks) { - return false; + int res = bookmark_autoload(pathname); + if (res == BOOKMARK_CANCEL || res == BOOKMARK_DO_RESUME || !warn_on_pl_erase()) + return false; } splash(0, ID2P(LANG_WAIT)); - /* about to create a new current playlist... - * allow user to cancel the operation. - * Do not show if skip_dyn_warning is true */ - if (!skip_dyn_warning) - { - if (!warn_on_pl_erase()) - return false; - } - if (playlist_create(dirname, filename) != -1) { if (global_settings.playlist_shuffle) - { playlist_shuffle(current_tick, -1); - } playlist_start(0, 0, 0); return true; @@ -198,7 +226,7 @@ static int compare(const void* p1, const void* p2) if (e1->attr & ATTR_DIRECTORY && e2->attr & ATTR_DIRECTORY) { /* two directories */ - criteria = compare_sort_dir; + criteria = cmp_data.sort_dir; #ifdef HAVE_MULTIVOLUME if (e1->attr & ATTR_VOLUME || e2->attr & ATTR_VOLUME) @@ -233,41 +261,23 @@ static int compare(const void* p1, const void* p2) if (t1 != t2) /* if different */ return (t1 - t2) * (criteria == SORT_TYPE_REVERSED ? -1 : 1); - /* else fall through to alphabetical sorting */ + /* else alphabetical sorting */ + return cmp_data._compar(e1->name, e2->name, MAX_PATH); } case SORT_DATE: case SORT_DATE_REVERSED: - /* Ignore SORT_TYPE */ - if (criteria == SORT_DATE || criteria == SORT_DATE_REVERSED) - { - if (e1->time_write != e2->time_write) - return (e1->time_write - e2->time_write) - * (criteria == SORT_DATE_REVERSED ? -1 : 1); - /* else fall through to alphabetical sorting */ - } - + { + if (e1->time_write != e2->time_write) + return (e1->time_write - e2->time_write) + * (criteria == SORT_DATE_REVERSED ? -1 : 1); + /* else fall through to alphabetical sorting */ + } case SORT_ALPHA: case SORT_ALPHA_REVERSED: { - if (global_settings.sort_case) - { - if (global_settings.interpret_numbers == SORT_INTERPRET_AS_NUMBER) - return strnatcmp(e1->name, e2->name) - * (criteria == SORT_ALPHA_REVERSED ? -1 : 1); - else - return strncmp(e1->name, e2->name, MAX_PATH) - * (criteria == SORT_ALPHA_REVERSED ? -1 : 1); - } - else - { - if (global_settings.interpret_numbers == SORT_INTERPRET_AS_NUMBER) - return strnatcasecmp(e1->name, e2->name) - * (criteria == SORT_ALPHA_REVERSED ? -1 : 1); - else - return strncasecmp(e1->name, e2->name, MAX_PATH) - * (criteria == SORT_ALPHA_REVERSED ? -1 : 1); - } + return cmp_data._compar(e1->name, e2->name, MAX_PATH) * + (criteria == SORT_ALPHA_REVERSED ? -1 : 1); } } @@ -277,12 +287,18 @@ static int compare(const void* p1, const void* p2) /* load and sort directory into the tree's cache. returns NULL on failure. */ int ft_load(struct tree_context* c, const char* tempdir) { + if (c->out_of_tree > 0) /* something else is loaded */ + return 0; + int files_in_dir = 0; int name_buffer_used = 0; struct dirent *entry; bool (*callback_show_item)(char *, int, struct tree_context *) = NULL; DIR *dir; + if (!c->is_browsing) + c->browse = NULL; + if (tempdir) dir = opendir(tempdir); else @@ -392,7 +408,22 @@ int ft_load(struct tree_context* c, const char* tempdir) c->dirlength = files_in_dir; closedir(dir); - compare_sort_dir = c->sort_dir; + cmp_data.sort_dir = c->sort_dir; + if (global_settings.sort_case) + { + if (global_settings.interpret_numbers == SORT_INTERPRET_AS_NUMBER) + cmp_data._compar = strnatcmp_n; + else + cmp_data._compar = strncmp; + } + else + { + if (global_settings.interpret_numbers == SORT_INTERPRET_AS_NUMBER) + cmp_data._compar = strnatcasecmp_n; + else + cmp_data._compar = strncasecmp; + } + qsort(tree_get_entries(c), files_in_dir, sizeof(struct entry), compare); /* If thumbnail talking is enabled, make an extra run to mark files with @@ -488,7 +519,9 @@ int ft_enter(struct tree_context* c) break; case FILE_ATTR_AUDIO: - if (bookmark_autoload(c->currdir)) + { + int res = bookmark_autoload(c->currdir); + if (res == BOOKMARK_CANCEL || res == BOOKMARK_DO_RESUME) break; splash(0, ID2P(LANG_WAIT)); @@ -522,7 +555,7 @@ int ft_enter(struct tree_context* c) play = true; } break; - + } #if CONFIG_TUNER /* fmr preset file */ case FILE_ATTR_FMR: @@ -674,7 +707,7 @@ int ft_enter(struct tree_context* c) break; } - struct entry* file = tree_get_entry_at(c, c->selected_item); + file = tree_get_entry_at(c, c->selected_item); if (!file) { splashf(HZ, str(LANG_READ_FAILED), str(LANG_UNKNOWN)); @@ -733,6 +766,7 @@ int ft_enter(struct tree_context* c) } } } + return rc; } @@ -775,5 +809,7 @@ int ft_exit(struct tree_context* c) if (exit_func) rc = 3; + c->out_of_tree = 0; + return rc; } diff --git a/apps/filetree.h b/apps/filetree.h index 178ba0e973..7931c3c454 100644 --- a/apps/filetree.h +++ b/apps/filetree.h @@ -26,6 +26,7 @@ int ft_load(struct tree_context* c, const char* tempdir); int ft_enter(struct tree_context* c); int ft_exit(struct tree_context* c); int ft_build_playlist(struct tree_context* c, int start_index); -bool ft_play_playlist(char* pathname, char* dirname, char* filename, bool skip_dyn_warning); +bool ft_play_playlist(char* pathname, char* dirname, + char* filename, bool skip_warn_and_bookmarks); #endif diff --git a/apps/filetypes.c b/apps/filetypes.c index 02d2af282e..bda7018381 100644 --- a/apps/filetypes.c +++ b/apps/filetypes.c @@ -38,6 +38,7 @@ #include "splash.h" #include "core_alloc.h" #include "icons.h" +/*#define LOGF_ENABLE*/ #include "logf.h" /* max filetypes (plugins & icons stored here) */ @@ -45,112 +46,172 @@ /* max viewer plugins */ #define MAX_VIEWERS 56 +static void read_builtin_types_init(void) INIT_ATTR; +static void read_viewers_config_init(void) INIT_ATTR; +static void read_config_init(int fd) INIT_ATTR; + /* a table for the known file types */ static const struct filetype inbuilt_filetypes[] = { - { "mp3", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "mp2", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "mpa", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "mp1", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "ogg", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "oga", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "wma", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "wmv", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "asf", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "wav", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "flac",FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "ac3", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "a52", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "mpc", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "wv", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "m4a", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "m4b", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "mp4", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "mod", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "mpga", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "shn", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "aif", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "aiff",FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "spx" ,FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "opus",FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "sid", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "adx", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "nsf", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "nsfe",FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "spc", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "ape", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "mac", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "sap" ,FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "rm", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "ra", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "rmvb",FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "cmc", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "cm3", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "cmr", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "cms", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "dmc", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "dlt", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "mpt", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "mpd", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "rmt", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "tmc", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "tm8", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "tm2", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "oma", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "aa3", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "at3", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "mmf", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "au", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "snd", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "vox", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "w64", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "tta", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "ay", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "vtx", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "gbs", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "hes", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "sgc", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "vgm", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "vgz", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "kss", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "aac", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, - { "m3u", FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, - { "m3u8",FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, - { "cfg", FILE_ATTR_CFG, Icon_Config, VOICE_EXT_CFG }, - { "wps", FILE_ATTR_WPS, Icon_Wps, VOICE_EXT_WPS }, + { "mp3", FILE_ATTR_AUDIO }, + { "mp2", FILE_ATTR_AUDIO }, + { "mpa", FILE_ATTR_AUDIO }, + { "mp1", FILE_ATTR_AUDIO }, + { "ogg", FILE_ATTR_AUDIO }, + { "oga", FILE_ATTR_AUDIO }, + { "wma", FILE_ATTR_AUDIO }, + { "wmv", FILE_ATTR_AUDIO }, + { "asf", FILE_ATTR_AUDIO }, + { "wav", FILE_ATTR_AUDIO }, + { "flac", FILE_ATTR_AUDIO }, + { "ac3", FILE_ATTR_AUDIO }, + { "a52", FILE_ATTR_AUDIO }, + { "mpc", FILE_ATTR_AUDIO }, + { "wv", FILE_ATTR_AUDIO }, + { "m4a", FILE_ATTR_AUDIO }, + { "m4b", FILE_ATTR_AUDIO }, + { "mp4", FILE_ATTR_AUDIO }, + { "mod", FILE_ATTR_AUDIO }, + { "mpga", FILE_ATTR_AUDIO }, + { "shn", FILE_ATTR_AUDIO }, + { "aif", FILE_ATTR_AUDIO }, + { "aiff", FILE_ATTR_AUDIO }, + { "spx" , FILE_ATTR_AUDIO }, + { "opus", FILE_ATTR_AUDIO }, + { "sid", FILE_ATTR_AUDIO }, + { "adx", FILE_ATTR_AUDIO }, + { "nsf", FILE_ATTR_AUDIO }, + { "nsfe", FILE_ATTR_AUDIO }, + { "spc", FILE_ATTR_AUDIO }, + { "ape", FILE_ATTR_AUDIO }, + { "mac", FILE_ATTR_AUDIO }, + { "sap" , FILE_ATTR_AUDIO }, + { "rm", FILE_ATTR_AUDIO }, + { "ra", FILE_ATTR_AUDIO }, + { "rmvb", FILE_ATTR_AUDIO }, + { "cmc", FILE_ATTR_AUDIO }, + { "cm3", FILE_ATTR_AUDIO }, + { "cmr", FILE_ATTR_AUDIO }, + { "cms", FILE_ATTR_AUDIO }, + { "dmc", FILE_ATTR_AUDIO }, + { "dlt", FILE_ATTR_AUDIO }, + { "mpt", FILE_ATTR_AUDIO }, + { "mpd", FILE_ATTR_AUDIO }, + { "rmt", FILE_ATTR_AUDIO }, + { "tmc", FILE_ATTR_AUDIO }, + { "tm8", FILE_ATTR_AUDIO }, + { "tm2", FILE_ATTR_AUDIO }, + { "oma", FILE_ATTR_AUDIO }, + { "aa3", FILE_ATTR_AUDIO }, + { "at3", FILE_ATTR_AUDIO }, + { "mmf", FILE_ATTR_AUDIO }, + { "au", FILE_ATTR_AUDIO }, + { "snd", FILE_ATTR_AUDIO }, + { "vox", FILE_ATTR_AUDIO }, + { "w64", FILE_ATTR_AUDIO }, + { "tta", FILE_ATTR_AUDIO }, + { "ay", FILE_ATTR_AUDIO }, + { "vtx", FILE_ATTR_AUDIO }, + { "gbs", FILE_ATTR_AUDIO }, + { "hes", FILE_ATTR_AUDIO }, + { "sgc", FILE_ATTR_AUDIO }, + { "vgm", FILE_ATTR_AUDIO }, + { "vgz", FILE_ATTR_AUDIO }, + { "kss", FILE_ATTR_AUDIO }, + { "aac", FILE_ATTR_AUDIO }, + { "m3u", FILE_ATTR_M3U }, + { "m3u8", FILE_ATTR_M3U }, + { "cfg", FILE_ATTR_CFG }, + { "wps", FILE_ATTR_WPS }, #ifdef HAVE_REMOTE_LCD - { "rwps",FILE_ATTR_RWPS, Icon_Wps, VOICE_EXT_RWPS }, + { "rwps", FILE_ATTR_RWPS }, #endif #if CONFIG_TUNER - { "fmr", FILE_ATTR_FMR, Icon_Preset, LANG_FMR }, - { "fms", FILE_ATTR_FMS, Icon_Wps, VOICE_EXT_FMS }, + { "fmr", FILE_ATTR_FMR }, + { "fms", FILE_ATTR_FMS }, #endif - { "lng", FILE_ATTR_LNG, Icon_Language, LANG_LANGUAGE }, - { "rock",FILE_ATTR_ROCK,Icon_Plugin, VOICE_EXT_ROCK }, - { "lua", FILE_ATTR_LUA, Icon_Plugin, VOICE_EXT_ROCK }, - { "opx", FILE_ATTR_OPX, Icon_Plugin, VOICE_EXT_ROCK }, - { "fnt", FILE_ATTR_FONT,Icon_Font, VOICE_EXT_FONT }, - { "kbd", FILE_ATTR_KBD, Icon_Keyboard, VOICE_EXT_KBD }, - { "bmark",FILE_ATTR_BMARK, Icon_Bookmark, VOICE_EXT_BMARK }, - { "cue", FILE_ATTR_CUE, Icon_Bookmark, VOICE_EXT_CUESHEET }, - { "sbs", FILE_ATTR_SBS, Icon_Wps, VOICE_EXT_SBS }, + { "log", FILE_ATTR_LOG }, + { "lng", FILE_ATTR_LNG }, + { "rock", FILE_ATTR_ROCK }, + { "lua", FILE_ATTR_LUA }, + { "opx", FILE_ATTR_OPX }, + { "fnt", FILE_ATTR_FONT }, + { "kbd", FILE_ATTR_KBD }, + { "bmark",FILE_ATTR_BMARK }, + { "cue", FILE_ATTR_CUE }, + { "sbs", FILE_ATTR_SBS }, #ifdef HAVE_REMOTE_LCD - { "rsbs", FILE_ATTR_RSBS, Icon_Wps, VOICE_EXT_RSBS }, + { "rsbs", FILE_ATTR_RSBS }, #if CONFIG_TUNER - { "rfms", FILE_ATTR_RFMS, Icon_Wps, VOICE_EXT_RFMS }, + { "rfms", FILE_ATTR_RFMS }, #endif #endif #ifdef BOOTFILE_EXT - { BOOTFILE_EXT, FILE_ATTR_MOD, Icon_Firmware, VOICE_EXT_AJZ }, + { BOOTFILE_EXT, FILE_ATTR_MOD }, #endif #ifdef BOOTFILE_EXT2 - { BOOTFILE_EXT2, FILE_ATTR_MOD, Icon_Firmware, VOICE_EXT_AJZ }, + { BOOTFILE_EXT2, FILE_ATTR_MOD }, +#endif +}; + +struct fileattr_icon_voice { + int tree_attr; + uint16_t icon; + uint16_t voiceclip; +}; + +/* a table for the known file types icons & voice clips */ +static const struct fileattr_icon_voice inbuilt_attr_icons_voices[] = { + { FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, + { FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, + { FILE_ATTR_CFG, Icon_Config, VOICE_EXT_CFG }, + { FILE_ATTR_WPS, Icon_Wps, VOICE_EXT_WPS }, +#ifdef HAVE_REMOTE_LCD + {FILE_ATTR_RWPS, Icon_Wps, VOICE_EXT_RWPS }, +#endif +#if CONFIG_TUNER + { FILE_ATTR_FMR, Icon_Preset, LANG_FMR }, + { FILE_ATTR_FMS, Icon_Wps, VOICE_EXT_FMS }, +#endif + { FILE_ATTR_LNG, Icon_Language, LANG_LANGUAGE }, + { FILE_ATTR_ROCK, Icon_Plugin, VOICE_EXT_ROCK }, + { FILE_ATTR_LUA, Icon_Plugin, VOICE_EXT_ROCK }, + { FILE_ATTR_OPX, Icon_Plugin, VOICE_EXT_ROCK }, + { FILE_ATTR_FONT, Icon_Font, VOICE_EXT_FONT }, + { FILE_ATTR_KBD, Icon_Keyboard, VOICE_EXT_KBD }, + { FILE_ATTR_BMARK, Icon_Bookmark, VOICE_EXT_BMARK }, + { FILE_ATTR_CUE, Icon_Bookmark, VOICE_EXT_CUESHEET }, + { FILE_ATTR_SBS, Icon_Wps, VOICE_EXT_SBS }, +#ifdef HAVE_REMOTE_LCD + { FILE_ATTR_RSBS, Icon_Wps, VOICE_EXT_RSBS }, +#if CONFIG_TUNER + { FILE_ATTR_RFMS, Icon_Wps, VOICE_EXT_RFMS }, +#endif +#endif +#if defined(BOOTFILE_EXT) || defined(BOOTFILE_EXT2) + { FILE_ATTR_MOD, Icon_Firmware, VOICE_EXT_AJZ }, #endif }; -void tree_get_filetypes(const struct filetype** types, int* count) +long tree_get_filetype_voiceclip(int attr) { - *types = inbuilt_filetypes; - *count = sizeof(inbuilt_filetypes) / sizeof(*inbuilt_filetypes); + if (global_settings.talk_filetype) + { + size_t count = ARRAY_SIZE(inbuilt_attr_icons_voices); + /* try to find a voice ID for the extension, if known */ + attr &= FILE_ATTR_MASK; /* file type */ + + for (size_t i = count - 1; i < count; i--) + { + if (attr == inbuilt_attr_icons_voices[i].tree_attr) + { + logf("%s found attr %d id %d", __func__, attr, + inbuilt_attr_icons_voices[i].voiceclip); + return inbuilt_attr_icons_voices[i].voiceclip; + } + } + } + logf("%s not found attr %d", __func__, attr); + return -1; } #define ROCK_EXTENSION "rock" @@ -244,8 +305,6 @@ static int find_extension(const char* extension) return -1; } -static void read_builtin_types(void); -static void read_config(int fd); #ifdef HAVE_LCD_COLOR /* Colors file format is similar to icons: * ext:hex_color @@ -262,9 +321,9 @@ void read_color_theme_file(void) { unknown_file.color = -1; if (!global_settings.colors_file[0] || global_settings.colors_file[0] == '-') return; - snprintf(buffer, MAX_PATH, THEME_DIR "/%s.colours", - global_settings.colors_file); - fd = open(buffer, O_RDONLY); + + fd = open_pathfmt(buffer, sizeof(buffer), O_RDONLY, + THEME_DIR "/%s.colours", global_settings.colors_file); if (fd < 0) return; while (read_line(fd, buffer, MAX_PATH) > 0) @@ -303,11 +362,11 @@ void read_viewer_theme_file(void) custom_filetype_icons[i] = filetypes[i].icon; } - snprintf(buffer, MAX_PATH, "%s/%s.icons", ICON_DIR, - global_settings.viewers_icon_file); - fd = open(buffer, O_RDONLY); + fd = open_pathfmt(buffer, sizeof(buffer), O_RDONLY, + ICON_DIR "/%s.icons", global_settings.viewers_icon_file); if (fd < 0) return; + while (read_line(fd, buffer, MAX_PATH) > 0) { if (!settings_parseline(buffer, &ext, &icon)) @@ -339,7 +398,7 @@ void read_viewer_theme_file(void) custom_icons_loaded = true; } -static void read_viewers_config(void) +static void read_viewers_config_init(void) { int fd = open(VIEWERS_CONFIG, O_RDONLY); if(fd < 0) @@ -351,18 +410,18 @@ static void read_viewers_config(void) /* estimate bufsize with the filesize, will not be larger */ strdup_bufsize = (size_t)filesz; - strdup_handle = core_alloc_ex("filetypes", strdup_bufsize, &ops); + strdup_handle = core_alloc_ex(strdup_bufsize, &ops); if(strdup_handle <= 0) goto out; - read_config(fd); - core_shrink(strdup_handle, core_get_data(strdup_handle), strdup_cur_idx); + read_config_init(fd); + core_shrink(strdup_handle, NULL, strdup_cur_idx); out: close(fd); } -void filetype_init(void) +void filetype_init(void) { /* set the directory item first */ filetypes[0].extension = NULL; @@ -373,8 +432,8 @@ void filetype_init(void) viewer_count = 0; filetype_count = 1; - read_builtin_types(); - read_viewers_config(); + read_builtin_types_init(); + read_viewers_config_init(); read_viewer_theme_file(); #ifdef HAVE_LCD_COLOR read_color_theme_file(); @@ -397,22 +456,35 @@ static void rm_whitespaces(char* str) *s = '\0'; } -static void read_builtin_types(void) +static void read_builtin_types_init(void) { - int count = sizeof(inbuilt_filetypes)/sizeof(*inbuilt_filetypes), i; - for(i=0; i<count && (filetype_count < MAX_FILETYPES); i++) + int tree_attr; + size_t count = ARRAY_SIZE(inbuilt_filetypes); + size_t icon_count = ARRAY_SIZE(inbuilt_attr_icons_voices); + for(size_t i = 0; (i < count) && (filetype_count < MAX_FILETYPES); i++) { filetypes[filetype_count].extension = inbuilt_filetypes[i].extension; filetypes[filetype_count].plugin = NULL; - filetypes[filetype_count].attr = inbuilt_filetypes[i].tree_attr>>8; + + tree_attr = inbuilt_filetypes[i].tree_attr; + filetypes[filetype_count].attr = tree_attr>>8; if (filetypes[filetype_count].attr > highest_attr) highest_attr = filetypes[filetype_count].attr; - filetypes[filetype_count].icon = inbuilt_filetypes[i].icon; + + filetypes[filetype_count].icon = unknown_file.icon; + for (size_t j = icon_count - 1; j < icon_count; j--) + { + if (tree_attr == inbuilt_attr_icons_voices[j].tree_attr) + { + filetypes[filetype_count].icon = inbuilt_attr_icons_voices[j].icon; + break; + } + } filetype_count++; } } -static void read_config(int fd) +static void read_config_init(int fd) { char line[64], *s, *e; char *extension, *plugin; @@ -618,7 +690,7 @@ int filetype_list_viewers(const char* current_file) int i = viewers[info.selection]; snprintf(plugin, MAX_PATH, "%s/%s." ROCK_EXTENSION, PLUGIN_DIR, filetypes[i].plugin); - plugin_load(plugin, current_file); + ret = plugin_load(plugin, current_file); } return ret; } diff --git a/apps/filetypes.h b/apps/filetypes.h index efe9f3f5df..2886fa2850 100644 --- a/apps/filetypes.h +++ b/apps/filetypes.h @@ -48,19 +48,20 @@ #define FILE_ATTR_FMS 0x1200 /* FM screen skin file */ #define FILE_ATTR_RFMS 0x1300 /* FM screen skin file */ #define FILE_ATTR_OPX 0x1400 /* open plugins shortcut */ +#define FILE_ATTR_LOG 0x1500 /* log file */ #define FILE_ATTR_MASK 0xFF00 /* which bits tree.c uses for file types */ struct filetype { char* extension; int tree_attr; - enum themable_icons icon; - int voiceclip; }; -void tree_get_filetypes(const struct filetype**, int*) INIT_ATTR; + +long tree_get_filetype_voiceclip(int attr); /* init the filetypes structs. uses audio buffer for storage, so call early in init... */ void filetype_init(void) INIT_ATTR; + void read_viewer_theme_file(void); #ifdef HAVE_LCD_COLOR void read_color_theme_file(void); diff --git a/apps/gui/bitmap/list-skinned.c b/apps/gui/bitmap/list-skinned.c index a67ac8cb0a..bebff821f8 100644 --- a/apps/gui/bitmap/list-skinned.c +++ b/apps/gui/bitmap/list-skinned.c @@ -213,8 +213,7 @@ bool skinlist_draw(struct screen *display, struct gui_synclist *list) if (list_start_item+cur_line+1 > list->nb_items) break; current_drawing_line = list_start_item+cur_line; - is_selected = list->show_selection_marker && - list_start_item+cur_line == list->selected_item; + is_selected = list_start_item+cur_line == list->selected_item; for (viewport = SKINOFFSETTOPTR(get_skin_buffer(wps.data), listcfg[screen]->data->tree); viewport; diff --git a/apps/gui/bitmap/list.c b/apps/gui/bitmap/list.c index 53874a8dfa..c10f0082d3 100644 --- a/apps/gui/bitmap/list.c +++ b/apps/gui/bitmap/list.c @@ -103,7 +103,7 @@ static void _default_listdraw_fn(struct list_putlineinfo_t *list_info) bool show_cursor = list_info->show_cursor; bool have_icons = list_info->have_icons; struct line_desc *linedes = list_info->linedes; - char *dsp_text = list_info->dsp_text; + const char *dsp_text = list_info->dsp_text; if (is_title) { @@ -196,10 +196,7 @@ void list_draw(struct screen *display, struct gui_synclist *list) const int list_start_item = list->start_item[screen]; const bool scrollbar_in_left = (list->scrollbar == SCROLLBAR_LEFT); const bool scrollbar_in_right = (list->scrollbar == SCROLLBAR_RIGHT); - - const bool show_cursor = list->show_selection_marker && - (list->cursor_style == SYNCLIST_CURSOR_NOSTYLE); - + const bool show_cursor = (list->cursor_style == SYNCLIST_CURSOR_NOSTYLE); const bool have_icons = list->callback_get_item_icon && list->show_icons; struct viewport *parent = (list->parent[screen]); @@ -329,14 +326,16 @@ void list_draw(struct screen *display, struct gui_synclist *list) unsigned const char *s; char entry_buffer[MAX_PATH]; unsigned char *entry_name; - const int text_pos = 0; /* UNUSED */ int line = i - start; int line_indent = 0; int style = STYLE_DEFAULT; bool is_selected = false; s = list->callback_get_item_name(i, list->data, entry_buffer, sizeof(entry_buffer)); - entry_name = P2STR(s); + if (P2ID((unsigned char *)s) > VOICEONLY_DELIMITER) + entry_name = ""; + else + entry_name = P2STR(s); while (*entry_name == '\t') { @@ -355,7 +354,7 @@ void list_draw(struct screen *display, struct gui_synclist *list) /* position the string at the correct offset place */ int item_width,h; display->getstringsize(entry_name, &item_width, &h); - item_offset = gui_list_get_item_offset(list, item_width, text_pos, + item_offset = gui_list_get_item_offset(list, item_width, indent + (list->show_icons ? icon_w : 0), display, list_text_vp); /* draw the selected line */ @@ -365,8 +364,7 @@ void list_draw(struct screen *display, struct gui_synclist *list) !hide_selection && #endif i >= list->selected_item - && i < list->selected_item + list->selected_size - && list->show_selection_marker) + && i < list->selected_item + list->selected_size) {/* The selected item must be displayed scrolling */ #ifdef HAVE_LCD_COLOR if (list->selection_color) diff --git a/apps/gui/color_picker.c b/apps/gui/color_picker.c index a32f1ee179..ef17c0a230 100644 --- a/apps/gui/color_picker.c +++ b/apps/gui/color_picker.c @@ -154,7 +154,6 @@ static void draw_screen(struct screen *display, char *title, { unsigned text_color = LCD_BLACK; unsigned background_color = LCD_WHITE; - char buf[32]; int i, char_height, line_height; int max_label_width; int text_x, text_top; @@ -253,17 +252,16 @@ static void draw_screen(struct screen *display, char *title, set_drawinfo(display, mode, fg, bg); /* Draw label */ - buf[0] = str(LANG_COLOR_RGB_LABELS)[i]; - buf[1] = '\0'; vp.flags &= ~VP_FLAG_ALIGNMENT_MASK; - display->putsxy(text_x, text_top, buf); + display->putsxyf(text_x, text_top, "%c", str(LANG_COLOR_RGB_LABELS)[i]); /* Draw color value */ + vp.flags |= VP_FLAG_ALIGN_RIGHT; if (display->depth >= 24) - snprintf(buf, 4, "%03d", rgb->rgb_val[i] & 0xFF); + display->putsxyf(text_x, text_top, "%03d", rgb->rgb_val[i] & 0xFF); else - snprintf(buf, 3, "%02d", rgb->rgb_val[i] & 0x3F); - vp.flags |= VP_FLAG_ALIGN_RIGHT; - display->putsxy(text_x, text_top, buf); + display->putsxyf(text_x, text_top, "%02d", rgb->rgb_val[i] & 0x3F); + + /* Draw scrollbar */ gui_scrollbar_draw(display, /* screen */ @@ -280,9 +278,6 @@ static void draw_screen(struct screen *display, char *title, text_top += line_height; } /* end for */ - /* Format RGB: #rrggbb */ - snprintf(buf, sizeof(buf), str(LANG_COLOR_RGB_VALUE), - rgb->red, rgb->green, rgb->blue); vp.flags |= VP_FLAG_ALIGN_CENTER; if (display->depth >= 16) { @@ -301,8 +296,9 @@ static void draw_screen(struct screen *display, char *title, /* Draw RGB: #rrggbb in middle of swatch */ set_drawinfo(display, DRMODE_FG, get_black_or_white(rgb), background_color); - - display->putsxy(0, top + (height - char_height) / 2, buf); + /* Format RGB: #rrggbb */ + display->putsxyf(0, top + (height - char_height) / 2, + str(LANG_COLOR_RGB_VALUE), rgb->red, rgb->green, rgb->blue); /* Draw border around the rect */ set_drawinfo(display, DRMODE_SOLID, text_color, background_color); @@ -318,7 +314,9 @@ static void draw_screen(struct screen *display, char *title, if (height >= char_height) { set_drawinfo(display, DRMODE_SOLID, text_color, background_color); - display->putsxy(0, top + (height - char_height) / 2, buf); + /* Format RGB: #rrggbb */ + display->putsxyf(0, top + (height - char_height) / 2, + str(LANG_COLOR_RGB_VALUE), rgb->red, rgb->green, rgb->blue); } } diff --git a/apps/gui/folder_select.c b/apps/gui/folder_select.c index cef95e179e..a76d77562b 100644 --- a/apps/gui/folder_select.c +++ b/apps/gui/folder_select.c @@ -185,7 +185,7 @@ static struct folder* load_folder(struct folder* parent, char *folder) if (len >= sizeof(fullpath)) goto fail; } - strlcpy(&fullpath[len], folder, sizeof(fullpath) - len); + strmemccpy(&fullpath[len], folder, sizeof(fullpath) - len); logf("load_folder: [%s]", fullpath); dir = opendir(fullpath); @@ -208,7 +208,7 @@ static struct folder* load_folder(struct folder* parent, char *folder) if ((dn[0] == '.') && (dn[1] == '\0' || (dn[1] == '.' && dn[2] == '\0'))) continue; /* copy entry name to end of buffer, save pointer */ - int len = strlen((char *)entry->d_name); + len = strlen((char *)entry->d_name); char *name = folder_alloc_from_end(len+1); /*for NULL*/ if (name == NULL) { @@ -518,7 +518,7 @@ static int select_paths(struct folder* root, const char* filenames) lastfnp = fnp; if (len <= 0 || len + 1 >= buflen) continue; - strlcpy(buf, sstr, len + 1); + strmemccpy(buf, sstr, len + 1); struct child *item = find_from_filename(buf, root); if (item) item->state = SELECTED; @@ -563,7 +563,7 @@ static void save_folders_r(struct folder *root, char* dst, size_t maxlen, size_t int dlen = strlen(dst); if (dlen + len >= maxlen) continue; - strlcpy(&dst[dlen], buffer_front, maxlen - dlen); + strmemccpy(&dst[dlen], buffer_front, maxlen - dlen); } else { diff --git a/apps/gui/icon.c b/apps/gui/icon.c index 9fe7090f4a..7a59a72151 100644 --- a/apps/gui/icon.c +++ b/apps/gui/icon.c @@ -32,6 +32,7 @@ #include "bmp.h" #include "filetypes.h" #include "language.h" +#include "misc.h" #include "bitmaps/default_icons.h" #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) @@ -63,7 +64,6 @@ static struct iconset { struct bitmap bmp; bool loaded; int handle; - int handle_locked; } iconsets[Iconset_Count][NB_SCREENS]; #define ICON_HEIGHT(screen) (!iconsets[Iconset_user][screen].loaded ? \ @@ -160,8 +160,6 @@ static int buflib_move_callback(int handle, void* current, void* new) struct iconset *set = &iconsets[i][j]; if (set->bmp.data == current) { - if (set->handle_locked > 0) - return BUFLIB_CB_CANNOT_MOVE; set->bmp.data = new; return BUFLIB_CB_OK; } @@ -169,59 +167,27 @@ static int buflib_move_callback(int handle, void* current, void* new) } return BUFLIB_CB_OK; } -static struct buflib_callbacks buflib_ops = {buflib_move_callback, NULL, NULL}; static void load_icons(const char* filename, enum Iconset iconset, enum screen_type screen) { - ssize_t size_read; - ssize_t buf_size; - int fd; - int bmpformat = (FORMAT_ANY|FORMAT_DITHER|FORMAT_TRANSPARENT); + static struct buflib_callbacks buflib_ops = {buflib_move_callback, NULL, NULL}; + const int bmpformat = (FORMAT_ANY|FORMAT_DITHER|FORMAT_TRANSPARENT); struct iconset *ic = &iconsets[iconset][screen]; + ssize_t buf_reqd; ic->loaded = false; - ic->handle = 0; + ic->handle = CLB_ALOC_ERR; if (filename[0] && filename[0] != '-') { - char path[MAX_PATH]; - - snprintf(path, sizeof(path), ICON_DIR "/%s.bmp", filename); - fd = open(path, O_RDONLY); - if (fd < 0) - return; - buf_size = read_bmp_fd(fd, &ic->bmp, 0, - bmpformat|FORMAT_RETURN_SIZE, NULL); - if (buf_size > 0) - ic->handle = core_alloc_ex(filename, (size_t) buf_size, &buflib_ops); - - if (ic->handle <= 0) - { - /* error */ - goto finished; - } - lseek(fd, 0, SEEK_SET); - ic->bmp.data = core_get_data(ic->handle); - - ic->handle_locked = 1; - size_read = read_bmp_fd(fd, &ic->bmp, buf_size, bmpformat, NULL); - ic->handle_locked = 0; - - if (size_read < 0) + char fname[MAX_PATH]; + snprintf(fname, sizeof(fname), ICON_DIR "/%s.bmp", filename); + ic->handle = core_load_bmp(fname, &ic->bmp, bmpformat, &buf_reqd, &buflib_ops); + if (ic->handle != CLB_ALOC_ERR) { - /* error */ - size_read = 0; - } - /* free unused alpha channel, if any */ - core_shrink(ic->handle, ic->bmp.data, size_read); - - if (size_read == 0) - ic->handle = core_free(ic->handle); - else + ic->bmp.data = core_get_data(ic->handle); ic->loaded = true; -finished: - close(fd); - return; + } } } diff --git a/apps/gui/line.c b/apps/gui/line.c index d319ff3c51..7e84aa7b31 100644 --- a/apps/gui/line.c +++ b/apps/gui/line.c @@ -264,8 +264,7 @@ next: else { /* any other character here is an erroneous format string */ - snprintf(tempbuf, sizeof(tempbuf), "<E:%c>", ch); - display->putsxy(xpos, y, tempbuf); + display->putsxyf(xpos, y, "<E:%c>", ch); /* Don't consider going forward, fix the caller */ return; } diff --git a/apps/gui/list.c b/apps/gui/list.c index 29c80574c2..85046ead54 100644 --- a/apps/gui/list.c +++ b/apps/gui/list.c @@ -47,12 +47,6 @@ */ #define FRAMEDROP_TRIGGER 6 -static int offset_step = 16; /* pixels per screen scroll step */ -/* should lines scroll out of the screen */ -static bool offset_out_of_view = false; - -static void gui_list_select_at_offset(struct gui_synclist * gui_list, - int offset); void list_draw(struct screen *display, struct gui_synclist *list); static long last_dirty_tick; @@ -129,7 +123,7 @@ void list_init_item_height(struct gui_synclist *list, enum screen_type screen) #endif } -void gui_synclist_init_display_settings(struct gui_synclist * list) +static void gui_synclist_init_display_settings(struct gui_synclist * list) { struct user_settings *gs = &global_settings; list->scrollbar = gs->scrollbar; @@ -182,7 +176,6 @@ void gui_synclist_init(struct gui_synclist * gui_list, list_init_viewports(gui_list); FOR_NB_SCREENS(i) list_init_item_height(gui_list, i); - gui_list->limit_scroll = false; gui_list->data = data; gui_list->scroll_all = scroll_all; gui_list->selected_size = selected_size; @@ -191,7 +184,6 @@ void gui_synclist_init(struct gui_synclist * gui_list, gui_list->scheduled_talk_tick = gui_list->last_talked_tick = 0; gui_list->dirty_tick = current_tick; - gui_list->show_selection_marker = true; #ifdef HAVE_LCD_COLOR gui_list->title_color = -1; @@ -200,13 +192,6 @@ void gui_synclist_init(struct gui_synclist * gui_list, #endif } -/* this toggles the selection bar or cursor */ -void gui_synclist_hide_selection_marker(struct gui_synclist * lists, bool hide) -{ - lists->show_selection_marker = !hide; -} - - int gui_list_get_item_offset(struct gui_synclist * gui_list, int item_width, int text_pos, @@ -215,7 +200,7 @@ int gui_list_get_item_offset(struct gui_synclist * gui_list, { int item_offset; - if (offset_out_of_view) + if (global_settings.offset_out_of_view) { item_offset = gui_list->offset_position[display->screen_type]; } @@ -269,11 +254,7 @@ static void gui_list_put_selection_on_screen(struct gui_synclist * gui_list, const int scroll_limit_up = (nb_lines < gui_list->selected_size+2 ? 0:1); const int scroll_limit_down = (scroll_limit_up+gui_list->selected_size); - if (gui_list->show_selection_marker == false) - { - new_start_item = gui_list->selected_item; - } - else if (gui_list->selected_size >= nb_lines) + if (gui_list->selected_size >= nb_lines) { new_start_item = gui_list->selected_item; } @@ -398,7 +379,7 @@ void gui_synclist_select_item(struct gui_synclist * gui_list, int item_number) } static void gui_list_select_at_offset(struct gui_synclist * gui_list, - int offset) + int offset, bool allow_wrap) { int new_selection; if (gui_list->selected_size > 1) @@ -410,41 +391,15 @@ static void gui_list_select_at_offset(struct gui_synclist * gui_list, if (new_selection >= gui_list->nb_items) { - new_selection = gui_list->limit_scroll ? - gui_list->nb_items - gui_list->selected_size : 0; - edge_beep(gui_list, !gui_list->limit_scroll); + new_selection = allow_wrap ? 0 : gui_list->nb_items - gui_list->selected_size; + edge_beep(gui_list, allow_wrap); } else if (new_selection < 0) { - new_selection = gui_list->limit_scroll ? - 0 : gui_list->nb_items - gui_list->selected_size; - edge_beep(gui_list, !gui_list->limit_scroll); + new_selection = allow_wrap ? gui_list->nb_items - gui_list->selected_size : 0; + edge_beep(gui_list, allow_wrap); } - else if (gui_list->show_selection_marker == false) - { - FOR_NB_SCREENS(i) - { - int nb_lines = list_get_nb_lines(gui_list, i); - if (offset > 0) - { - int screen_top = MAX(0, gui_list->nb_items - nb_lines); - gui_list->start_item[i] = MIN(screen_top, gui_list->start_item[i] + - gui_list->selected_size); - gui_list->selected_item = gui_list->start_item[i]; - } - else - { - gui_list->start_item[i] = MAX(0, gui_list->start_item[i] - - gui_list->selected_size); - gui_list->selected_item = gui_list->start_item[i] + nb_lines; - } -#ifdef HAVE_TOUCHSCREEN - gui_list->y_pos = gui_list->start_item[SCREEN_MAIN] * gui_list->line_height[SCREEN_MAIN]; -#endif - } - return; - } gui_synclist_select_item(gui_list, new_selection); } @@ -475,22 +430,12 @@ void gui_synclist_del_item(struct gui_synclist * gui_list) } } -void gui_list_screen_scroll_step(int ofs) -{ - offset_step = ofs; -} - -void gui_list_screen_scroll_out_of_view(bool enable) -{ - offset_out_of_view = enable; -} - /* * Set the title and title icon of the list. Setting title to NULL disables * both the title and icon. Use NOICON if there is no icon. */ void gui_synclist_set_title(struct gui_synclist * gui_list, - char * title, enum themable_icons icon) + const char * title, enum themable_icons icon) { gui_list->title = title; gui_list->title_icon = icon; @@ -558,26 +503,25 @@ void gui_synclist_set_sel_color(struct gui_synclist * lists, #endif static void gui_synclist_select_next_page(struct gui_synclist * lists, - enum screen_type screen) + enum screen_type screen, + bool allow_wrap) { int nb_lines = list_get_nb_lines(lists, screen); if (lists->selected_size > 1) nb_lines = MAX(1, nb_lines/lists->selected_size); - gui_list_select_at_offset(lists, nb_lines); + + gui_list_select_at_offset(lists, nb_lines, allow_wrap); } static void gui_synclist_select_previous_page(struct gui_synclist * lists, - enum screen_type screen) + enum screen_type screen, + bool allow_wrap) { int nb_lines = list_get_nb_lines(lists, screen); if (lists->selected_size > 1) nb_lines = MAX(1, nb_lines/lists->selected_size); - gui_list_select_at_offset(lists, -nb_lines); -} -void gui_synclist_limit_scroll(struct gui_synclist * lists, bool scroll) -{ - lists->limit_scroll = scroll; + gui_list_select_at_offset(lists, -nb_lines, allow_wrap); } /* @@ -592,7 +536,7 @@ static void gui_synclist_scroll_right(struct gui_synclist * lists) /* FIXME: This is a fake right boundry limiter. there should be some * callback function to find the longest item on the list in pixels, * to stop the list from scrolling past that point */ - lists->offset_position[i] += offset_step; + lists->offset_position[i] += global_settings.screen_scroll_step; if (lists->offset_position[i] > 1000) lists->offset_position[i] = 1000; } @@ -606,7 +550,7 @@ static void gui_synclist_scroll_left(struct gui_synclist * lists) { FOR_NB_SCREENS(i) { - lists->offset_position[i] -= offset_step; + lists->offset_position[i] -= global_settings.screen_scroll_step; if (lists->offset_position[i] < 0) lists->offset_position[i] = 0; } @@ -616,18 +560,24 @@ bool gui_synclist_keyclick_callback(int action, void* data) { struct gui_synclist *lists = (struct gui_synclist *)data; - /* block the beep if we are at the end of the list and we are not wrapping. - * CAVEAT: mosts lists don't set limit_scroll untill it sees a repeat - * press at the end of the list so this can cause an extra beep. - */ - if (lists->limit_scroll == false) - return true; + /* Block the beep if we're at the end of the list and we're not wrapping. */ if (lists->selected_item == 0) - return (action != ACTION_STD_PREV && action != ACTION_STD_PREVREPEAT); + { + if (action == ACTION_STD_PREVREPEAT) + return false; + if (action == ACTION_STD_PREV && !lists->wraparound) + return false; + } + if (lists->selected_item == lists->nb_items - lists->selected_size) - return (action != ACTION_STD_NEXT && action != ACTION_STD_NEXTREPEAT); + { + if (action == ACTION_STD_NEXTREPEAT) + return false; + if (action == ACTION_STD_NEXT && !lists->wraparound) + return false; + } - return action != ACTION_NONE; + return action != ACTION_NONE && !IS_SYSEVENT(action); } /* @@ -650,8 +600,7 @@ static void _lists_uiviewport_update_callback(unsigned short id, void *data) gui_synclist_draw(current_lists); } -bool gui_synclist_do_button(struct gui_synclist * lists, - int *actionptr, enum list_wrap wrap) +bool gui_synclist_do_button(struct gui_synclist * lists, int *actionptr) { int action = *actionptr; static bool pgleft_allow_cancel = false; @@ -662,6 +611,9 @@ bool gui_synclist_do_button(struct gui_synclist * lists, static int next_item_modifier = 1; static int last_accel_tick = 0; + if (IS_SYSEVENT(action)) + return false; + if (action != ACTION_TOUCHSCREEN) { if (global_settings.list_accel_start_delay) @@ -697,23 +649,9 @@ bool gui_synclist_do_button(struct gui_synclist * lists, /* Disable the skin redraw callback */ current_lists = NULL; - switch (wrap) - { - case LIST_WRAP_ON: - gui_synclist_limit_scroll(lists, !(lists->wraparound)); - break; - case LIST_WRAP_OFF: - gui_synclist_limit_scroll(lists, true); - break; - case LIST_WRAP_UNLESS_HELD: - if (action == ACTION_STD_PREVREPEAT || - action == ACTION_STD_NEXTREPEAT || - action == ACTION_LISTTREE_PGUP || - action == ACTION_LISTTREE_PGDOWN) - gui_synclist_limit_scroll(lists, true); - else gui_synclist_limit_scroll(lists, !(lists->wraparound)); - break; - }; + + /* repeat actions block list wraparound */ + bool allow_wrap = lists->wraparound; switch (action) { @@ -723,17 +661,18 @@ bool gui_synclist_do_button(struct gui_synclist * lists, #ifdef HAVE_VOLUME_IN_LIST case ACTION_LIST_VOLUP: - global_settings.volume += sound_steps(SOUND_VOLUME); - setvol(); + adjust_volume(1); return true; case ACTION_LIST_VOLDOWN: - global_settings.volume -= sound_steps(SOUND_VOLUME); - setvol(); + adjust_volume(-1); return true; #endif - case ACTION_STD_PREV: case ACTION_STD_PREVREPEAT: - gui_list_select_at_offset(lists, -next_item_modifier); + allow_wrap = false; /* Prevent list wraparound on repeating actions */ + /*Fallthrough*/ + case ACTION_STD_PREV: + + gui_list_select_at_offset(lists, -next_item_modifier, allow_wrap); #ifndef HAVE_WHEEL_ACCELERATION if (button_queue_count() < FRAMEDROP_TRIGGER) #endif @@ -742,9 +681,11 @@ bool gui_synclist_do_button(struct gui_synclist * lists, *actionptr = ACTION_STD_PREV; return true; - case ACTION_STD_NEXT: case ACTION_STD_NEXTREPEAT: - gui_list_select_at_offset(lists, next_item_modifier); + allow_wrap = false; /* Prevent list wraparound on repeating actions */ + /*Fallthrough*/ + case ACTION_STD_NEXT: + gui_list_select_at_offset(lists, next_item_modifier, allow_wrap); #ifndef HAVE_WHEEL_ACCELERATION if (button_queue_count() < FRAMEDROP_TRIGGER) #endif @@ -795,7 +736,7 @@ bool gui_synclist_do_button(struct gui_synclist * lists, SCREEN_REMOTE : #endif SCREEN_MAIN; - gui_synclist_select_previous_page(lists, screen); + gui_synclist_select_previous_page(lists, screen, false); gui_synclist_draw(lists); yield(); *actionptr = ACTION_STD_NEXT; @@ -810,7 +751,7 @@ bool gui_synclist_do_button(struct gui_synclist * lists, SCREEN_REMOTE : #endif SCREEN_MAIN; - gui_synclist_select_next_page(lists, screen); + gui_synclist_select_next_page(lists, screen, false); gui_synclist_draw(lists); yield(); *actionptr = ACTION_STD_PREV; @@ -849,8 +790,7 @@ int list_do_action_timeout(struct gui_synclist *lists, int timeout) } bool list_do_action(int context, int timeout, - struct gui_synclist *lists, int *action, - enum list_wrap wrap) + struct gui_synclist *lists, int *action) /* Combines the get_action() (with possibly overridden timeout) and gui_synclist_do_button() calls. Returns the list action from do_button, and places the action from get_action in *action. */ @@ -858,14 +798,7 @@ bool list_do_action(int context, int timeout, timeout = list_do_action_timeout(lists, timeout); keyclick_set_callback(gui_synclist_keyclick_callback, lists); *action = get_action(context, timeout); - return gui_synclist_do_button(lists, action, wrap); -} - -bool gui_synclist_item_is_onscreen(struct gui_synclist *lists, - enum screen_type screen, int item) -{ - int nb_lines = list_get_nb_lines(lists, screen); - return (unsigned)(item - lists->start_item[screen]) < (unsigned) nb_lines; + return gui_synclist_do_button(lists, action); } /* Simple use list implementation */ @@ -925,7 +858,6 @@ bool simplelist_show_list(struct simplelist_info *info) struct gui_synclist lists; int action, old_line_count = simplelist_line_count; list_get_name *getname; - int wrap = global_settings.list_wraparound ? LIST_WRAP_UNLESS_HELD : LIST_WRAP_OFF; if (info->get_name) getname = info->get_name; else @@ -950,12 +882,6 @@ bool simplelist_show_list(struct simplelist_info *info) gui_synclist_set_sel_color(&lists, info->selection_color); #endif - if (info->hide_selection) - { - gui_synclist_hide_selection_marker(&lists, true); - wrap = LIST_WRAP_OFF; - } - if (info->action_callback) info->action_callback(ACTION_REDRAW, &lists); @@ -974,8 +900,7 @@ bool simplelist_show_list(struct simplelist_info *info) while(1) { - list_do_action(CONTEXT_LIST, info->timeout, - &lists, &action, wrap); + list_do_action(CONTEXT_LIST, info->timeout, &lists, &action); /* We must yield in this case or no other thread can run */ if (info->timeout == TIMEOUT_NOBLOCK) @@ -1039,7 +964,6 @@ void simplelist_info_init(struct simplelist_info *info, char* title, info->title = title; info->count = count; info->selection_size = 1; - info->hide_selection = false; info->scroll_all = false; info->hide_theme = false; info->speak_onshow = true; diff --git a/apps/gui/list.h b/apps/gui/list.h index 4dc83a1b27..40a27d1061 100644 --- a/apps/gui/list.h +++ b/apps/gui/list.h @@ -30,12 +30,6 @@ #define SCROLLBAR_WIDTH global_settings.scrollbar_width -enum list_wrap { - LIST_WRAP_ON = 0, - LIST_WRAP_OFF, - LIST_WRAP_UNLESS_HELD, -}; - enum synclist_cursor { SYNCLIST_CURSOR_NOSTYLE = 0, @@ -96,7 +90,7 @@ struct list_putlineinfo_t { struct viewport *vp; struct line_desc *linedes; struct gui_synclist * list; - char *dsp_text; + const char *dsp_text; bool is_selected; bool is_title; @@ -155,13 +149,9 @@ struct gui_synclist bool talk_menu; bool wraparound; bool scroll_paginated; - /* defines wether the list should stop when reaching the top/bottom - * or should continue (by going to bottom/top) */ - bool limit_scroll; /* whether the text of the whole items of the list have to be * scrolled or only for the selected item */ bool scroll_all; - bool show_selection_marker; /* set to true by default */ int nb_items; int selected_item; @@ -185,7 +175,7 @@ struct gui_synclist /* The data that will be passed to the callback function YOU implement */ void * data; /* The optional title, set to NULL for none */ - char * title; + const char * title; /* Optional title icon */ enum themable_icons title_icon; @@ -199,12 +189,7 @@ struct gui_synclist extern void list_init(void); -/* parse global setting to static int */ -extern void gui_list_screen_scroll_step(int ofs); -/* parse global setting to static bool */ -extern void gui_list_screen_scroll_out_of_view(bool enable); -extern void gui_synclist_init_display_settings(struct gui_synclist * list); extern void gui_synclist_init( struct gui_synclist * lists, list_get_name callback_get_item_name, @@ -232,13 +217,8 @@ extern void gui_synclist_select_item(struct gui_synclist * lists, int item_number); extern void gui_synclist_add_item(struct gui_synclist * lists); extern void gui_synclist_del_item(struct gui_synclist * lists); -extern void gui_synclist_limit_scroll(struct gui_synclist * lists, bool scroll); -extern void gui_synclist_set_title(struct gui_synclist * lists, char * title, +extern void gui_synclist_set_title(struct gui_synclist * lists, const char * title, enum themable_icons icon); -extern void gui_synclist_hide_selection_marker(struct gui_synclist *lists, - bool hide); -extern bool gui_synclist_item_is_onscreen(struct gui_synclist *lists, - enum screen_type screen, int item); extern bool gui_synclist_keyclick_callback(int action, void* data); /* @@ -246,20 +226,9 @@ extern bool gui_synclist_keyclick_callback(int action, void* data); * returns true if the action was handled. * NOTE: *action may be changed regardless of return value */ -extern bool gui_synclist_do_button(struct gui_synclist * lists, - int *action, - enum list_wrap); +extern bool gui_synclist_do_button(struct gui_synclist * lists, int *action); #if !defined(PLUGIN) -struct listitem_viewport_cfg { - struct wps_data *data; - OFFSETTYPE(char *) label; - int width; - int height; - int xmargin; - int ymargin; - bool tile; - struct skin_viewport selected_item_vp; -}; +struct listitem_viewport_cfg; bool skinlist_get_item(struct screen *display, struct gui_synclist *list, int x, int y, int *item); bool skinlist_draw(struct screen *display, struct gui_synclist *list); @@ -291,8 +260,7 @@ extern int list_do_action_timeout(struct gui_synclist *lists, int timeout); list_do_action_timeout) with the gui_synclist_do_button call, for convenience. */ extern bool list_do_action(int context, int timeout, - struct gui_synclist *lists, int *action, - enum list_wrap wrap); + struct gui_synclist *lists, int *action); /** Simplelist implementation. @@ -301,10 +269,9 @@ extern bool list_do_action(int context, int timeout, **/ struct simplelist_info { - char *title; /* title to show on the list */ + const char *title; /* title to show on the list */ int count; /* number of items in the list, each item is selection_size high */ int selection_size; /* list selection size, usually 1 */ - bool hide_selection; bool scroll_all; bool hide_theme; bool speak_onshow; /* list speaks first item or 'empty list' */ @@ -350,7 +317,6 @@ void simplelist_addline(const char *fmt, ...); /* setup the info struct. members not setup in this function need to be assigned manually members set in this function: info.selection_size = 1; - info.hide_selection = false; info.scroll_all = false; info.hide_theme = false; info.speak_onshow = true; diff --git a/apps/gui/option_select.c b/apps/gui/option_select.c index 7068fee510..afc11fc4ee 100644 --- a/apps/gui/option_select.c +++ b/apps/gui/option_select.c @@ -36,6 +36,8 @@ #include "menu.h" #include "quickscreen.h" +/* HASFLAG compares value to flags returns true if set, false otherwise */ +#define HASFLAG(settings_list, flag) ((settings_list->flags & (flag)) == (flag)) static int selection_to_val(const struct settings_list *setting, int selection); int option_value_as_int(const struct settings_list *setting) @@ -65,29 +67,29 @@ const char *option_get_valuestring(const struct settings_list *setting, intptr_t temp_var) { const char* str = buffer; - if ((setting->flags & F_BOOL_SETTING) == F_BOOL_SETTING) + if (HASFLAG(setting, F_BOOL_SETTING)) { bool val = (bool)temp_var; - strlcpy(buffer, str(val? setting->bool_setting->lang_yes : - setting->bool_setting->lang_no), buf_len); + strmemccpy(buffer, str(val? setting->bool_setting->lang_yes : + setting->bool_setting->lang_no), buf_len); } #if 0 /* probably dont need this one */ - else if ((setting->flags & F_FILENAME) == F_FILENAME) + else if (HASFLAG(setting, F_FILENAME)) { struct filename_setting *info = setting->filename_setting; snprintf(buffer, buf_len, "%s%s%s", info->prefix, (char*)temp_var, info->suffix); } #endif - else if (((setting->flags & F_INT_SETTING) == F_INT_SETTING) || - ((setting->flags & F_TABLE_SETTING) == F_TABLE_SETTING)) + else if ((HASFLAG(setting, F_INT_SETTING)) || + HASFLAG(setting, F_TABLE_SETTING)) { const struct int_setting *int_info = setting->int_setting; const struct table_setting *tbl_info = setting->table_setting; int info_unit; const char *str_unit; const char* (*formatter)(char*, size_t, int, const char*); - if ((setting->flags & F_INT_SETTING) == F_INT_SETTING) + if (HASFLAG(setting, F_INT_SETTING)) { formatter = int_info->formatter; info_unit = int_info->unit; @@ -98,67 +100,68 @@ const char *option_get_valuestring(const struct settings_list *setting, info_unit = tbl_info->unit; } - if ((setting->flags & F_TIME_SETTING) == F_TIME_SETTING) + bool is_time_setting = HASFLAG(setting, F_TIME_SETTING); + if (is_time_setting) str = option_get_timestring(buffer, buf_len, (long)temp_var, info_unit); str_unit = unit_strings_core[info_unit]; + if (formatter) str = formatter(buffer, buf_len, (int)temp_var, str_unit); - else if ((setting->flags & F_TIME_SETTING) != F_TIME_SETTING) + else if (!is_time_setting) snprintf(buffer, buf_len, "%d %s", (int)temp_var, str_unit?str_unit:""); } - else if ((setting->flags & F_T_SOUND) == F_T_SOUND) + else if (HASFLAG(setting, F_T_SOUND)) { format_sound_value(buffer, buf_len, setting->sound_setting->setting, temp_var); } - else if ((setting->flags & F_CHOICE_SETTING) == F_CHOICE_SETTING) + else if (HASFLAG(setting, F_CHOICE_SETTING)) { - if (setting->flags & F_CHOICETALKS) + if (HASFLAG(setting, F_CHOICETALKS)) { - int setting_id; const struct choice_setting *info = setting->choice_setting; if (info->talks[(int)temp_var] < LANG_LAST_INDEX_IN_ARRAY) { - strlcpy(buffer, str(info->talks[(int)temp_var]), buf_len); + strmemccpy(buffer, str(info->talks[(int)temp_var]), buf_len); } else { - find_setting(setting->setting, &setting_id); - cfg_int_to_string(setting_id, (int)temp_var, buffer, buf_len); + cfg_int_to_string(setting, (int)temp_var, buffer, buf_len); } } else { int value = (int)temp_var; char *val = P2STR(setting->choice_setting->desc[value]); - strlcpy(buffer, val, buf_len); + strmemccpy(buffer, val, buf_len); } } return str; } void option_talk_value(const struct settings_list *setting, int value, bool enqueue) { - if ((setting->flags & F_BOOL_SETTING) == F_BOOL_SETTING) + + if (HASFLAG(setting, F_BOOL_SETTING)) { bool val = (value==1); talk_id(val? setting->bool_setting->lang_yes : setting->bool_setting->lang_no, enqueue); } #if 0 /* probably dont need this one */ - else if ((setting->flags & F_FILENAME) == F_FILENAME) + else if (HASFLAG(setting, F_FILENAME)) { } #endif - else if (((setting->flags & F_INT_SETTING) == F_INT_SETTING) || - ((setting->flags & F_TABLE_SETTING) == F_TABLE_SETTING)) + else if ((HASFLAG(setting, F_INT_SETTING)) || + HASFLAG(setting, F_TABLE_SETTING)) { const struct int_setting *int_info = setting->int_setting; const struct table_setting *tbl_info = setting->table_setting; int unit; int32_t (*get_talk_id)(int, int); - if ((setting->flags & F_INT_SETTING) == F_INT_SETTING) + if (HASFLAG(setting, F_INT_SETTING)) { unit = int_info->unit; get_talk_id = int_info->get_talk_id; @@ -170,12 +173,12 @@ void option_talk_value(const struct settings_list *setting, int value, bool enqu } if (get_talk_id) talk_id(get_talk_id(value, unit), enqueue); - else if ((setting->flags & F_TIME_SETTING) == F_TIME_SETTING) + else if (HASFLAG(setting, F_TIME_SETTING)) talk_time_intervals(value, unit, enqueue); else talk_value(value, unit, enqueue); } - else if ((setting->flags & F_T_SOUND) == F_T_SOUND) + else if (HASFLAG(setting, F_T_SOUND)) { int talkunit = UNIT_INT; int sound_setting = setting->sound_setting->setting; @@ -190,9 +193,9 @@ void option_talk_value(const struct settings_list *setting, int value, bool enqu talkunit = UNIT_HERTZ; talk_value_decimal(phys, talkunit, decimals, enqueue); } - else if ((setting->flags & F_CHOICE_SETTING) == F_CHOICE_SETTING) + else if (HASFLAG(setting, F_CHOICE_SETTING)) { - if (setting->flags & F_CHOICETALKS) + if (HASFLAG(setting, F_CHOICETALKS)) { talk_id(setting->choice_setting->talks[value], enqueue); } @@ -218,14 +221,14 @@ void option_select_next_val(const struct settings_list *setting, { int val = 0; int *value = setting->setting; - if ((setting->flags & F_BOOL_SETTING) == F_BOOL_SETTING) + if (HASFLAG(setting, F_BOOL_SETTING)) { *(bool*)value = !*(bool*)value; if (apply && setting->bool_setting->option_callback) setting->bool_setting->option_callback(*(bool*)value); return; } - else if ((setting->flags & F_INT_SETTING) == F_INT_SETTING) + else if (HASFLAG(setting, F_INT_SETTING)) { struct int_setting *info = (struct int_setting *)setting->int_setting; bool neg_step = (info->step < 0); @@ -245,7 +248,7 @@ void option_select_next_val(const struct settings_list *setting, if (apply && info->option_callback) info->option_callback(val); } - else if ((setting->flags & F_T_SOUND) == F_T_SOUND) + else if (HASFLAG(setting, F_T_SOUND)) { int setting_id = setting->sound_setting->setting; int steps = sound_steps(setting_id); @@ -267,7 +270,7 @@ void option_select_next_val(const struct settings_list *setting, if (apply) sound_set(setting_id, val); } - else if ((setting->flags & F_CHOICE_SETTING) == F_CHOICE_SETTING) + else if (HASFLAG(setting, F_CHOICE_SETTING)) { struct choice_setting *info = (struct choice_setting *)setting->choice_setting; if (!previous) @@ -286,7 +289,7 @@ void option_select_next_val(const struct settings_list *setting, if (apply && info->option_callback) info->option_callback(val); } - else if ((setting->flags & F_TABLE_SETTING) == F_TABLE_SETTING) + else if (HASFLAG(setting, F_TABLE_SETTING)) { const struct table_setting *tbl_info = setting->table_setting; int i, add; @@ -314,13 +317,15 @@ static int selection_to_val(const struct settings_list *setting, int selection) int min = 0; */ int max = 0, step = 1; - if (((setting->flags & F_BOOL_SETTING) == F_BOOL_SETTING) || - ((setting->flags & F_CHOICE_SETTING) == F_CHOICE_SETTING)) + if ((HASFLAG(setting, F_BOOL_SETTING)) || + HASFLAG(setting, F_CHOICE_SETTING)) + { return selection; - else if ((setting->flags & F_TABLE_SETTING) == F_TABLE_SETTING) + } + else if (HASFLAG(setting, F_TABLE_SETTING)) { const struct table_setting *info = setting->table_setting; - if (setting->flags&F_ALLOW_ARBITRARY_VALS && + if (HASFLAG(setting, F_ALLOW_ARBITRARY_VALS) && table_setting_array_position != -1 && (selection >= table_setting_array_position)) { @@ -331,7 +336,7 @@ static int selection_to_val(const struct settings_list *setting, int selection) else return info->values[selection]; } - else if ((setting->flags & F_T_SOUND) == F_T_SOUND) + else if (HASFLAG(setting, F_T_SOUND)) { int setting_id = setting->sound_setting->setting; if(global_settings.list_order == LIST_ORDER_DESCENDING) @@ -348,7 +353,7 @@ static int selection_to_val(const struct settings_list *setting, int selection) max = sound_min(setting_id); } } - else if ((setting->flags & F_INT_SETTING) == F_INT_SETTING) + else if (HASFLAG(setting, F_INT_SETTING)) { const struct int_setting *info = setting->int_setting; if(global_settings.list_order == LIST_ORDER_DESCENDING) @@ -394,13 +399,13 @@ static void val_to_selection(const struct settings_list *setting, int oldvalue, /* set the number of items and current selection */ if (var_type == F_T_INT || var_type == F_T_UINT) { - if (setting->flags&F_CHOICE_SETTING) + if (HASFLAG(setting, F_CHOICE_SETTING)) { *nb_items = setting->choice_setting->count; *selected = oldvalue; *function = setting->choice_setting->option_callback; } - else if (setting->flags&F_TABLE_SETTING) + else if (HASFLAG(setting, F_TABLE_SETTING)) { const struct table_setting *info = setting->table_setting; int i; @@ -409,7 +414,7 @@ static void val_to_selection(const struct settings_list *setting, int oldvalue, table_setting_array_position = -1; for (i=0;*selected==-1 && i<*nb_items;i++) { - if (setting->flags&F_ALLOW_ARBITRARY_VALS && + if (HASFLAG(setting, F_ALLOW_ARBITRARY_VALS) && (oldvalue < info->values[i])) { table_setting_oldval = oldvalue; @@ -422,7 +427,7 @@ static void val_to_selection(const struct settings_list *setting, int oldvalue, } *function = info->option_callback; } - else if (setting->flags&F_T_SOUND) + else if (HASFLAG(setting, F_T_SOUND)) { int setting_id = setting->sound_setting->setting; int steps = sound_steps(setting_id); @@ -470,9 +475,10 @@ bool option_screen(const struct settings_list *setting, struct gui_synclist lists; int oldvalue, nb_items = 0, selected = 0, temp_var; int *variable; - bool allow_wrap = setting->flags & F_NO_WRAP ? false : true; - bool cb_on_select_only = - ((setting->flags & F_CB_ON_SELECT_ONLY) == F_CB_ON_SELECT_ONLY); + bool allow_wrap = (!HASFLAG(setting, F_NO_WRAP)); + bool cb_on_select_only = HASFLAG(setting, F_CB_ON_SELECT_ONLY); + bool cb_on_changed = HASFLAG(setting, F_CB_ONLY_IF_CHANGED); + int var_type = setting->flags&F_T_MASK; void (*function)(int) = NULL; char *title; @@ -506,15 +512,18 @@ bool option_screen(const struct settings_list *setting, gui_synclist_set_nb_items(&lists, nb_items); gui_synclist_select_item(&lists, selected); - gui_synclist_limit_scroll(&lists, true); gui_synclist_draw(&lists); /* talk the item */ gui_synclist_speak_item(&lists); while (!done) { + /* override user wraparound setting; used mainly by EQ settings. + * Not sure this is justified? */ + if (!allow_wrap) + lists.wraparound = false; + if (list_do_action(CONTEXT_LIST, HZ, /* HZ so the status bar redraws */ - &lists, &action, - allow_wrap? LIST_WRAP_UNLESS_HELD: LIST_WRAP_OFF)) + &lists, &action)) { /* setting changed */ selected = gui_synclist_get_sel_pos(&lists); @@ -524,7 +533,7 @@ bool option_screen(const struct settings_list *setting, } else if (action == ACTION_NONE) continue; - else if (action == ACTION_STD_CANCEL) + else if (action == ACTION_STD_CANCEL || action == ACTION_STD_MENU) { /* setting canceled, restore old value if changed */ if (*variable != oldvalue) @@ -560,26 +569,33 @@ bool option_screen(const struct settings_list *setting, } settings_save(); done = true; - if (cb_on_select_only && function) - function(*variable); + cb_on_select_only = false; /* unset the flag so callback can be called */ } else if(default_event_handler(action) == SYS_USB_CONNECTED) + { + pop_current_activity(); return true; + } + /* callback */ - if (function && !cb_on_select_only) - function(*variable); + if (!cb_on_select_only && function) + { + if (!cb_on_changed || (*variable != oldvalue)) + { + function(*variable); + /* if the volume is changing we need to let the skins know */ + if (function == sound_get_fn(SOUND_VOLUME)) + global_status.last_volume_change = current_tick; + } + } - /* if the volume is changing we need to let the skins know */ - if (function == sound_get_fn(SOUND_VOLUME)) - global_status.last_volume_change = current_tick; } pop_current_activity(); return false; } -int get_setting_info_for_bar(int setting_id, int *count, int *val) +int get_setting_info_for_bar(const struct settings_list *setting, int *count, int *val) { - const struct settings_list *setting = &settings[setting_id]; int var_type = setting->flags&F_T_MASK; void (*function)(int) = NULL; int oldvalue; @@ -604,9 +620,8 @@ int get_setting_info_for_bar(int setting_id, int *count, int *val) } #ifdef HAVE_TOUCHSCREEN -void update_setting_value_from_touch(int setting_id, int selection) +void update_setting_value_from_touch(const struct settings_list *setting, int selection) { - const struct settings_list *setting = &settings[setting_id]; int new_val = selection_to_val(setting, selection); int var_type = setting->flags&F_T_MASK; diff --git a/apps/gui/option_select.h b/apps/gui/option_select.h index 104e86f64d..eabe5825e7 100644 --- a/apps/gui/option_select.h +++ b/apps/gui/option_select.h @@ -46,9 +46,9 @@ void option_talk_value(const struct settings_list *setting, int value, bool enqu /* only use this for int and bool settings */ int option_value_as_int(const struct settings_list *setting); -int get_setting_info_for_bar(int setting_id, int *count, int *val); +int get_setting_info_for_bar(const struct settings_list *setting, int *count, int *val); #ifdef HAVE_TOUCHSCREEN -void update_setting_value_from_touch(int setting_id, int selection); +void update_setting_value_from_touch(const struct settings_list *setting, int selection); #endif #endif /* _GUI_OPTION_SELECT_H_ */ diff --git a/apps/gui/quickscreen.c b/apps/gui/quickscreen.c index e403e13e6c..109414336f 100644 --- a/apps/gui/quickscreen.c +++ b/apps/gui/quickscreen.c @@ -320,13 +320,13 @@ static int quickscreen_touchscreen_button(void) } #endif -static bool gui_syncquickscreen_run(struct gui_quickscreen * qs, int button_enter, bool *usb) +static int gui_syncquickscreen_run(struct gui_quickscreen * qs, int button_enter, bool *usb) { int button; struct viewport parent[NB_SCREENS]; struct viewport vps[NB_SCREENS][QUICKSCREEN_ITEM_COUNT]; struct viewport vp_icons[NB_SCREENS]; - bool changed = false; + int ret = QUICKSCREEN_OK; /* To quit we need either : * - a second press on the button that made us enter * - an action taken while pressing the enter button, @@ -367,7 +367,7 @@ static bool gui_syncquickscreen_run(struct gui_quickscreen * qs, int button_ente } if (gui_quickscreen_do_button(qs, button)) { - changed = true; + ret |= QUICKSCREEN_CHANGED; can_quit = true; FOR_NB_SCREENS(i) gui_quickscreen_draw(qs, &screens[i], &parent[i], @@ -378,17 +378,20 @@ static bool gui_syncquickscreen_run(struct gui_quickscreen * qs, int button_ente else if (button == button_enter) can_quit = true; else if (button == ACTION_QS_VOLUP) { - global_settings.volume += sound_steps(SOUND_VOLUME); - setvol(); + adjust_volume(1); FOR_NB_SCREENS(i) skin_update(CUSTOM_STATUSBAR, i, SKIN_REFRESH_NON_STATIC); } else if (button == ACTION_QS_VOLDOWN) { - global_settings.volume -= sound_steps(SOUND_VOLUME); - setvol(); + adjust_volume(-1); FOR_NB_SCREENS(i) skin_update(CUSTOM_STATUSBAR, i, SKIN_REFRESH_NON_STATIC); } + else if (button == ACTION_STD_CONTEXT) + { + ret |= QUICKSCREEN_GOTO_SHORTCUTS_MENU; + break; + } if ((button == button_enter) && can_quit) break; @@ -401,80 +404,60 @@ static bool gui_syncquickscreen_run(struct gui_quickscreen * qs, int button_ente { /* stop scrolling before exiting */ for (int j = 0; j < QUICKSCREEN_ITEM_COUNT; j++) screens[i].scroll_stop_viewport(&vps[i][j]); - viewportmanager_theme_undo(i, true); + viewportmanager_theme_undo(i, !(ret & QUICKSCREEN_GOTO_SHORTCUTS_MENU)); } - pop_current_activity(); - return changed; -} + if (ret & QUICKSCREEN_GOTO_SHORTCUTS_MENU) /* Eliminate flashing of parent during */ + pop_current_activity_without_refresh(); /* transition to Shortcuts */ + else + pop_current_activity(); -static const struct settings_list *get_setting(int gs_value, - const struct settings_list *defaultval) -{ - if (gs_value != -1 && gs_value < nb_settings && - is_setting_quickscreenable(&settings[gs_value])) - return &settings[gs_value]; - return defaultval; + return ret; } int quick_screen_quick(int button_enter) { struct gui_quickscreen qs; - bool oldshuffle = global_settings.playlist_shuffle; - int oldrepeat = global_settings.repeat_mode; #ifdef HAVE_ALBUMART int old_album_art = global_settings.album_art; #endif bool usb = false; - if (global_settings.shortcuts_replaces_qs) - return do_shortcut_menu(NULL); + for (int i = 0; i < 4; ++i) + { + qs.items[i] = global_settings.qs_items[i]; - qs.items[QUICKSCREEN_TOP] = - get_setting(global_settings.qs_items[QUICKSCREEN_TOP], NULL); - qs.items[QUICKSCREEN_LEFT] = - get_setting(global_settings.qs_items[QUICKSCREEN_LEFT], - find_setting(&global_settings.playlist_shuffle, NULL)); - qs.items[QUICKSCREEN_RIGHT] = - get_setting(global_settings.qs_items[QUICKSCREEN_RIGHT], - find_setting(&global_settings.repeat_mode, NULL)); - qs.items[QUICKSCREEN_BOTTOM] = - get_setting(global_settings.qs_items[QUICKSCREEN_BOTTOM], NULL); + if (!is_setting_quickscreenable(qs.items[i])) + qs.items[i] = NULL; + } qs.callback = NULL; - if (gui_syncquickscreen_run(&qs, button_enter, &usb)) + int ret = gui_syncquickscreen_run(&qs, button_enter, &usb); + if (ret & QUICKSCREEN_CHANGED) { settings_save(); - /* make sure repeat/shuffle/any other nasty ones get updated */ - if ( oldrepeat != global_settings.repeat_mode && - (audio_status() & AUDIO_STATUS_PLAY) ) - { - audio_flush_and_reload_tracks(); - } - if (oldshuffle != global_settings.playlist_shuffle - && audio_status() & AUDIO_STATUS_PLAY) - { - replaygain_update(); - if (global_settings.playlist_shuffle) - playlist_randomise(NULL, current_tick, true); - else - playlist_sort(NULL, true); - } #ifdef HAVE_ALBUMART if (old_album_art != global_settings.album_art) set_albumart_mode(global_settings.album_art); #endif } - return (usb ? 1:0); + if (usb) + return QUICKSCREEN_IN_USB; + return ret & QUICKSCREEN_GOTO_SHORTCUTS_MENU ? QUICKSCREEN_GOTO_SHORTCUTS_MENU : + QUICKSCREEN_OK; } /* stuff to make the quickscreen configurable */ bool is_setting_quickscreenable(const struct settings_list *setting) { + if (!setting) + return true; + /* to keep things simple, only settings which have a lang_id set are ok */ - if (setting->lang_id < 0 || (setting->flags&F_BANFROMQS)) + if (setting->lang_id < 0 || (setting->flags & F_BANFROMQS)) return false; - switch (setting->flags&F_T_MASK) + + switch (setting->flags & F_T_MASK) { case F_T_BOOL: return true; @@ -485,16 +468,3 @@ bool is_setting_quickscreenable(const struct settings_list *setting) return false; } } - -void set_as_qs_item(const struct settings_list *setting, - enum quickscreen_item item) -{ - int i; - for (i = 0; i < nb_settings; i++) - { - if (&settings[i] == setting) - break; - } - - global_settings.qs_items[item] = i; -} diff --git a/apps/gui/quickscreen.h b/apps/gui/quickscreen.h index 015928ee8a..bd8008bd34 100644 --- a/apps/gui/quickscreen.h +++ b/apps/gui/quickscreen.h @@ -36,6 +36,13 @@ enum quickscreen_item { QUICKSCREEN_ITEM_COUNT, }; +enum quickscreen_return { + QUICKSCREEN_OK = 0, + QUICKSCREEN_IN_USB = 0x1, + QUICKSCREEN_GOTO_SHORTCUTS_MENU = 0x2, + QUICKSCREEN_CHANGED = 0x4, +}; + struct gui_quickscreen { const struct settings_list *items[QUICKSCREEN_ITEM_COUNT]; @@ -46,7 +53,6 @@ struct gui_quickscreen extern int quick_screen_quick(int button_enter); int quickscreen_set_option(void *data); bool is_setting_quickscreenable(const struct settings_list *setting); -void set_as_qs_item(const struct settings_list *setting, - enum quickscreen_item item); + #endif /*_GUI_QUICK_SCREEN_H_*/ #endif /* HAVE_QUICKSCREEN */ diff --git a/apps/gui/skin_engine/skin_backdrops.c b/apps/gui/skin_engine/skin_backdrops.c index 146dccb18a..eecf5b0433 100644 --- a/apps/gui/skin_engine/skin_backdrops.c +++ b/apps/gui/skin_engine/skin_backdrops.c @@ -41,7 +41,6 @@ static struct skin_backdrop { } backdrops[NB_BDROPS]; #define NB_BDROPS SKINNABLE_SCREENS_COUNT*NB_SCREENS -static int handle_being_loaded; static int current_lcd_backdrop[NB_SCREENS]; bool skin_backdrop_get_debug(int index, char **path, int *ref_count, size_t *size) @@ -65,8 +64,8 @@ bool skin_backdrop_get_debug(int index, char **path, int *ref_count, size_t *siz static int buflib_move_callback(int handle, void* current, void* new) { - if (handle == handle_being_loaded) - return BUFLIB_CB_CANNOT_MOVE; + (void)handle; + for (int i=0; i<NB_BDROPS; i++) { if (backdrops[i].buffer == current) @@ -96,7 +95,6 @@ bool skin_backdrop_init(void) } FOR_NB_SCREENS(i) current_lcd_backdrop[i] = -1; - handle_being_loaded = -1; first_go = false; } return go_status; @@ -139,7 +137,7 @@ int skin_backdrop_assign(char* backdrop, char *bmpdir, } if (free >= 0) { - strlcpy(backdrops[free].name, filename, MAX_PATH); + strmemccpy(backdrops[free].name, filename, MAX_PATH); backdrops[free].buffer = NULL; backdrops[free].screen = screen; backdrops[free].ref_count = 1; @@ -176,22 +174,22 @@ bool skin_backdrops_preload(void) } if (*filename && *filename != '-') { - backdrops[i].buflib_handle = core_alloc_ex(filename, buf_size, &buflib_ops); + backdrops[i].buflib_handle = core_alloc_ex(buf_size, &buflib_ops); if (backdrops[i].buflib_handle > 0) { backdrops[i].buffer = core_get_data(backdrops[i].buflib_handle); if (strcmp(filename, BACKDROP_BUFFERNAME)) { - handle_being_loaded = backdrops[i].buflib_handle; + core_pin(backdrops[i].buflib_handle); backdrops[i].loaded = screens[screen].backdrop_load(filename, backdrops[i].buffer); + core_unpin(backdrops[i].buflib_handle); if (!backdrops[i].loaded) { core_free(backdrops[i].buflib_handle); backdrops[i].buflib_handle = -1; retval = false; } - handle_being_loaded = -1; } else backdrops[i].loaded = true; @@ -267,8 +265,7 @@ void skin_backdrop_unload(int backdrop_id) backdrops[backdrop_id].ref_count--; if (backdrops[backdrop_id].ref_count <= 0) { - if (backdrops[backdrop_id].buflib_handle > 0) - core_free(backdrops[backdrop_id].buflib_handle); + core_free(backdrops[backdrop_id].buflib_handle); backdrops[backdrop_id].buffer = NULL; backdrops[backdrop_id].buflib_handle = -1; backdrops[backdrop_id].loaded = false; @@ -290,18 +287,17 @@ void skin_backdrop_load_setting(void) if (backdrops[i].buflib_handle <= 0) { backdrops[i].buflib_handle = - core_alloc_ex(global_settings.backdrop_file, - LCD_BACKDROP_BYTES, &buflib_ops); + core_alloc_ex(LCD_BACKDROP_BYTES, &buflib_ops); if (backdrops[i].buflib_handle <= 0) return; } bool loaded; + core_pin(backdrops[i].buflib_handle); backdrops[i].buffer = core_get_data(backdrops[i].buflib_handle); - handle_being_loaded = backdrops[i].buflib_handle; loaded = screens[SCREEN_MAIN].backdrop_load( global_settings.backdrop_file, backdrops[i].buffer); - handle_being_loaded = -1; + core_unpin(backdrops[i].buflib_handle); backdrops[i].name[2] = loaded ? '.' : '\0'; backdrops[i].loaded = loaded; return; diff --git a/apps/gui/skin_engine/skin_display.c b/apps/gui/skin_engine/skin_display.c index 4a3dcc2177..913bdcfbc4 100644 --- a/apps/gui/skin_engine/skin_display.c +++ b/apps/gui/skin_engine/skin_display.c @@ -46,6 +46,7 @@ #include "tagcache.h" #include "list.h" #include "option_select.h" +#include "buffering.h" #include "peakmeter.h" /* Image stuff */ @@ -64,7 +65,7 @@ #endif #include "root_menu.h" - +#include "wps.h" #include "wps_internals.h" #include "skin_engine.h" #include "statusbar-skinned.h" @@ -82,7 +83,7 @@ void skin_update(enum skinnable_screens skin, enum screen_type screen, struct gui_wps *gwps = skin_get_gwps(skin, screen); /* This maybe shouldnt be here, * This is also safe for skined screen which dont use the id3 */ - struct mp3entry *id3 = skin_get_global_state()->id3; + struct mp3entry *id3 = get_wps_state()->id3; bool cuesheet_update = (id3 != NULL ? cuesheet_subtrack_changed(id3) : false); if (cuesheet_update) skin_request_full_update(skin); @@ -157,11 +158,12 @@ void ab_draw_markers(struct screen * screen, int capacity, #endif -void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb) +void draw_progressbar(struct gui_wps *gwps, struct skin_viewport* skin_viewport, + int line, struct progressbar *pb) { struct screen *display = gwps->display; - struct viewport *vp = SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->vp); - struct wps_state *state = skin_get_global_state(); + struct viewport *vp = &skin_viewport->vp; + struct wps_state *state = get_wps_state(); struct mp3entry *id3 = state->id3; int x = pb->x, y = pb->y, width = pb->width, height = pb->height; unsigned long length, end; @@ -183,8 +185,13 @@ void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb) { int minvol = sound_min(SOUND_VOLUME); int maxvol = sound_max(SOUND_VOLUME); - length = maxvol-minvol; - end = global_settings.volume-minvol; +#if defined(HAVE_PERCEPTUAL_VOLUME) || defined(HAVE_TOUCHSCREEN) + length = 1000; + end = to_normalized_volume(global_settings.volume, minvol, maxvol, length); +#else + length = maxvol - minvol; + end = global_settings.volume - minvol; +#endif } else if (pb->type == SKIN_TOKEN_BATTERY_PERCENTBAR) { @@ -210,7 +217,7 @@ void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb) else if (pb->type == SKIN_TOKEN_SETTINGBAR) { int val, count; - get_setting_info_for_bar(pb->setting_id, &count, &val); + get_setting_info_for_bar(pb->setting, &count, &val); length = count - 1; end = val; } @@ -411,8 +418,7 @@ void wps_display_images(struct gui_wps *gwps, struct viewport* vp) #ifdef HAVE_ALBUMART /* now draw the AA */ struct skin_albumart *aa = SKINOFFSETTOPTR(get_skin_buffer(data), data->albumart); - if (aa && SKINOFFSETTOPTR(get_skin_buffer(data), aa->vp) == vp - && aa->draw_handle >= 0) + if (aa && aa->draw_handle >= 0) { draw_album_art(gwps, aa->draw_handle, false); aa->draw_handle = -1; @@ -499,78 +505,82 @@ void write_line(struct screen *display, struct align_pos *format_align, /* CASE 1: left and centered string overlap */ /* there is a left string, need to merge left and center */ - if ((left_width != 0 && center_width != 0) && - (left_width + space_width > center_xpos)) { - /* replace the former separator '\0' of left and - center string with a space */ - *(--format_align->center) = ' '; - /* calculate the new width and position of the merged string */ - left_width = left_width + space_width + center_width; - /* there is no centered string anymore */ - center_width = 0; - } - /* there is no left string, move center to left */ - if ((left_width == 0 && center_width != 0) && - (left_width > center_xpos)) { - /* move the center string to the left string */ - format_align->left = format_align->center; - /* calculate the new width and position of the string */ - left_width = center_width; - /* there is no centered string anymore */ - center_width = 0; - } + if (center_width != 0) + { + if (left_width != 0 && left_width + space_width > center_xpos) { + /* replace the former separator '\0' of left and + center string with a space */ + *(--format_align->center) = ' '; + /* calculate the new width and position of the merged string */ + left_width = left_width + space_width + center_width; + /* there is no centered string anymore */ + center_width = 0; + } + /* there is no left string, move center to left */ + else if (left_width == 0 && center_xpos < 0) { + /* move the center string to the left string */ + format_align->left = format_align->center; + /* calculate the new width and position of the string */ + left_width = center_width; + /* there is no centered string anymore */ + center_width = 0; + } + } /*(center_width != 0)*/ /* CASE 2: centered and right string overlap */ /* there is a right string, need to merge center and right */ - if ((center_width != 0 && right_width != 0) && - (center_xpos + center_width + space_width > right_xpos)) { - /* replace the former separator '\0' of center and - right string with a space */ - *(--format_align->right) = ' '; - /* move the center string to the right after merge */ - format_align->right = format_align->center; - /* calculate the new width and position of the merged string */ - right_width = center_width + space_width + right_width; - right_xpos = (viewport_width - right_width); - /* there is no centered string anymore */ - center_width = 0; - } - /* there is no right string, move center to right */ - if ((center_width != 0 && right_width == 0) && - (center_xpos + center_width > right_xpos)) { - /* move the center string to the right string */ - format_align->right = format_align->center; - /* calculate the new width and position of the string */ - right_width = center_width; - right_xpos = (viewport_width - right_width); - /* there is no centered string anymore */ - center_width = 0; - } + if (center_width != 0) + { + int center_left_x = center_xpos + center_width; + if (right_width != 0 && center_left_x + space_width > right_xpos) { + /* replace the former separator '\0' of center and + right string with a space */ + *(--format_align->right) = ' '; + /* move the center string to the right after merge */ + format_align->right = format_align->center; + /* calculate the new width and position of the merged string */ + right_width = center_width + space_width + right_width; + right_xpos = (viewport_width - right_width); + /* there is no centered string anymore */ + center_width = 0; + } + /* there is no right string, move center to right */ + else if (right_width == 0 && center_left_x > right_xpos) { + /* move the center string to the right string */ + format_align->right = format_align->center; + /* calculate the new width and position of the string */ + right_width = center_width; + right_xpos = (viewport_width - right_width); + /* there is no centered string anymore */ + center_width = 0; + } + } /*(center_width != 0)*/ /* CASE 3: left and right overlap There is no center string anymore, either there never was one or it has been merged in case 1 or 2 */ /* there is a left string, need to merge left and right */ - if ((left_width != 0 && center_width == 0 && right_width != 0) && - (left_width + space_width > right_xpos)) { - /* replace the former separator '\0' of left and - right string with a space */ - *(--format_align->right) = ' '; - /* calculate the new width and position of the string */ - left_width = left_width + space_width + right_width; - /* there is no right string anymore */ - right_width = 0; - } - /* there is no left string, move right to left */ - if ((left_width == 0 && center_width == 0 && right_width != 0) && - (left_width > right_xpos)) { - /* move the right string to the left string */ - format_align->left = format_align->right; - /* calculate the new width and position of the string */ - left_width = right_width; - /* there is no right string anymore */ - right_width = 0; - } + if (center_width == 0 && right_width != 0) + { + if (left_width != 0 && left_width + space_width > right_xpos) { + /* replace the former separator '\0' of left and + right string with a space */ + *(--format_align->right) = ' '; + /* calculate the new width and position of the string */ + left_width = left_width + space_width + right_width; + /* there is no right string anymore */ + right_width = 0; + } + /* there is no left string, move right to left */ + else if (left_width == 0 && right_xpos < 0) { + /* move the right string to the left string */ + format_align->left = format_align->right; + /* calculate the new width and position of the string */ + left_width = right_width; + /* there is no right string anymore */ + right_width = 0; + } + } /* (center_width == 0 && right_width != 0)*/ if (scroll && ((left_width > scroll_width) || (center_width > scroll_width) || @@ -601,9 +611,9 @@ void write_line(struct screen *display, struct align_pos *format_align, char *center = format_align->center ?: ""; char *right = format_align->right ?: ""; - display->put_line(0, line, linedes, "$t$*s$t$*s$t", left, - center_xpos - left_width, center, - right_xpos - (center_xpos + center_width), right); + display->put_line(0, line, linedes, "$t$*s$t$*s$t", left_width == 0 ? "" : left , + center_xpos - left_width, center_width == 0 ? "" : center, + right_xpos - center_xpos - center_width, right_width == 0 ? "" : right); } } @@ -632,14 +642,86 @@ void draw_peakmeters(struct gui_wps *gwps, int line_number, } } -bool skin_has_sbs(enum screen_type screen, struct wps_data *data) +#ifdef HAVE_ALBUMART +/* Draw the album art bitmap from the given handle ID onto the given WPS. + Call with clear = true to clear the bitmap instead of drawing it. */ +void draw_album_art(struct gui_wps *gwps, int handle_id, bool clear) +{ + if (!gwps || !gwps->data || !gwps->display || handle_id < 0) + return; + + struct wps_data *data = gwps->data; + struct skin_albumart *aa = SKINOFFSETTOPTR(get_skin_buffer(data), data->albumart); + + if (!aa) + return; + + struct bitmap *bmp; + if (bufgetdata(handle_id, 0, (void *)&bmp) <= 0) + return; + + short x = aa->x; + short y = aa->y; + short width = bmp->width; + short height = bmp->height; + + if (aa->width > 0) + { + /* Crop if the bitmap is too wide */ + width = MIN(bmp->width, aa->width); + + /* Align */ + if (aa->xalign & WPS_ALBUMART_ALIGN_RIGHT) + x += aa->width - width; + else if (aa->xalign & WPS_ALBUMART_ALIGN_CENTER) + x += (aa->width - width) / 2; + } + + if (aa->height > 0) + { + /* Crop if the bitmap is too high */ + height = MIN(bmp->height, aa->height); + + /* Align */ + if (aa->yalign & WPS_ALBUMART_ALIGN_BOTTOM) + y += aa->height - height; + else if (aa->yalign & WPS_ALBUMART_ALIGN_CENTER) + y += (aa->height - height) / 2; + } + + if (!clear) + { + /* Draw the bitmap */ + gwps->display->bitmap_part((fb_data*)bmp->data, 0, 0, + STRIDE(gwps->display->screen_type, + bmp->width, bmp->height), + x, y, width, height); +#ifdef HAVE_LCD_INVERT + if (global_settings.invert) { + gwps->display->set_drawmode(DRMODE_COMPLEMENT); + gwps->display->fillrect(x, y, width, height); + gwps->display->set_drawmode(DRMODE_SOLID); + } +#endif + } + else + { + /* Clear the bitmap */ + gwps->display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + gwps->display->fillrect(x, y, width, height); + gwps->display->set_drawmode(DRMODE_SOLID); + } +} +#endif + +bool skin_has_sbs(struct gui_wps *gwps) { - (void)screen; - (void)data; + struct wps_data *data = gwps->data; + bool draw = false; if (data->wps_sb_tag) draw = data->show_sb_on_wps; - else if (statusbar_position(screen) != STATUSBAR_OFF) + else if (statusbar_position(gwps->display->screen_type) != STATUSBAR_OFF) draw = true; return draw; } diff --git a/apps/gui/skin_engine/skin_display.h b/apps/gui/skin_engine/skin_display.h index de1b0b20b5..56af12aa03 100644 --- a/apps/gui/skin_engine/skin_display.h +++ b/apps/gui/skin_engine/skin_display.h @@ -29,7 +29,8 @@ #define _SKIN_DISPLAY_H_ -void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb); +void draw_progressbar(struct gui_wps *gwps, struct skin_viewport* skin_viewport, + int line, struct progressbar *pb); void draw_playlist_viewer_list(struct gui_wps *gwps, struct playlistviewer *viewer); /* clears the area where the image was shown */ void clear_image_pos(struct gui_wps *gwps, struct gui_img *img); @@ -54,4 +55,10 @@ void write_line(struct screen *display, struct align_pos *format_align, int line, bool scroll, struct line_desc *line_desc); void draw_peakmeters(struct gui_wps *gwps, int line_number, struct viewport *viewport); +#ifdef HAVE_ALBUMART +/* Draw the album art bitmap from the given handle ID onto the given Skin. + Call with clear = true to clear the bitmap instead of drawing it. */ +void draw_album_art(struct gui_wps *gwps, int handle_id, bool clear); +#endif + #endif diff --git a/apps/gui/skin_engine/skin_engine.c b/apps/gui/skin_engine/skin_engine.c index 8ba76e5739..c007ed35d4 100644 --- a/apps/gui/skin_engine/skin_engine.c +++ b/apps/gui/skin_engine/skin_engine.c @@ -34,9 +34,11 @@ #if CONFIG_TUNER #include "radio.h" #endif +#include "gui/list.h" #include "skin_engine.h" #include "skin_buffer.h" #include "statusbar-skinned.h" +#include "wps_internals.h" #define FAILSAFENAME "rockbox_failsafe" @@ -51,7 +53,6 @@ static bool skins_initialised = false; static char* get_skin_filename(char *buf, size_t buf_size, enum skinnable_screens skin, enum screen_type screen); -struct wps_state wps_state = { .id3 = NULL }; static struct gui_skin_helper { int (*preproccess)(enum screen_type screen, struct wps_data *data); int (*postproccess)(enum screen_type screen, struct wps_data *data); @@ -308,11 +309,6 @@ struct gui_wps *skin_get_gwps(enum skinnable_screens skin, enum screen_type scre return &skins[skin][screen].gui_wps; } -struct wps_state *skin_get_global_state(void) -{ - return &wps_state; -} - /* This is called to find out if we the screen needs a full update. * if true you MUST do a full update as the next call will return false */ bool skin_do_full_update(enum skinnable_screens skin, @@ -334,3 +330,56 @@ void skin_request_full_update(enum skinnable_screens skin) FOR_NB_SCREENS(i) skins[skin][i].needs_full_update = true; } + +bool dbg_skin_engine(void) +{ + struct simplelist_info info; + int i, total = 0; +#if defined(HAVE_BACKDROP_IMAGE) + int ref_count; + char *path; + size_t bytes; + int path_prefix_len = strlen(ROCKBOX_DIR "/wps/"); +#endif + simplelist_info_init(&info, "Skin engine usage", 0, NULL); + simplelist_set_line_count(0); + FOR_NB_SCREENS(j) { +#if NB_SCREENS > 1 + simplelist_addline("%s display:", + j == 0 ? "Main" : "Remote"); +#endif + for (i = 0; i < skin_get_num_skins(); i++) { + struct skin_stats *stats = skin_get_stats(i, j); + if (stats->buflib_handles) + { + simplelist_addline("Skin ID: %d, %d allocations", + i, stats->buflib_handles); + simplelist_addline("\tskin: %d bytes", + stats->tree_size); + simplelist_addline("\tImages: %d bytes", + stats->images_size); + simplelist_addline("\tTotal: %d bytes", + stats->tree_size + stats->images_size); + total += stats->tree_size + stats->images_size; + } + } + } + simplelist_addline("Skin total usage: %d bytes", total); +#if defined(HAVE_BACKDROP_IMAGE) + simplelist_addline("Backdrop Images:"); + i = 0; + while (skin_backdrop_get_debug(i++, &path, &ref_count, &bytes)) { + if (ref_count > 0) { + + if (!strncasecmp(path, ROCKBOX_DIR "/wps/", path_prefix_len)) + path += path_prefix_len; + simplelist_addline("%s", path); + simplelist_addline("\tref_count: %d", ref_count); + simplelist_addline("\tsize: %d", bytes); + total += bytes; + } + } + simplelist_addline("Total usage: %d bytes", total); +#endif + return simplelist_show_list(&info); +} diff --git a/apps/gui/skin_engine/skin_engine.h b/apps/gui/skin_engine/skin_engine.h index e26ec34d1f..d04c873e84 100644 --- a/apps/gui/skin_engine/skin_engine.h +++ b/apps/gui/skin_engine/skin_engine.h @@ -26,8 +26,7 @@ #ifndef PLUGIN #include "tag_table.h" - -#include "wps_internals.h" /* TODO: remove this line.. shoudlnt be needed */ +#include "screen_access.h" enum skinnable_screens { CUSTOM_STATUSBAR, @@ -39,24 +38,20 @@ enum skinnable_screens { SKINNABLE_SCREENS_COUNT }; +struct skin_stats; +struct skin_viewport; +struct gui_wps; + #ifdef HAVE_TOUCHSCREEN -int skin_get_touchaction(struct wps_data *data, int* edge_offset, - struct touchregion **retregion); -void skin_disarm_touchregions(struct wps_data *data); +int skin_get_touchaction(struct gui_wps *gwps, int* edge_offset); +void skin_disarm_touchregions(struct gui_wps *gwps); #endif /* Do a update_type update of the skinned screen */ void skin_update(enum skinnable_screens skin, enum screen_type screen, unsigned int update_type); -/* - * setup up the skin-data from a format-buffer (isfile = false) - * or from a skinfile (isfile = true) - */ -bool skin_data_load(enum screen_type screen, struct wps_data *wps_data, - const char *buf, bool isfile, struct skin_stats *stats); - -bool skin_has_sbs(enum screen_type screen, struct wps_data *data); +bool skin_has_sbs(struct gui_wps *gwps); /* load a backdrop into the skin buffer. @@ -81,7 +76,6 @@ int skin_wait_for_action(enum skinnable_screens skin, int context, int timeout); void skin_load(enum skinnable_screens skin, enum screen_type screen, const char *buf, bool isfile); struct gui_wps *skin_get_gwps(enum skinnable_screens skin, enum screen_type screen); -struct wps_state *skin_get_global_state(void); void gui_sync_skin_init(void); void skin_unload_all(void); @@ -89,5 +83,7 @@ void skin_unload_all(void); bool skin_do_full_update(enum skinnable_screens skin, enum screen_type screen); void skin_request_full_update(enum skinnable_screens skin); +bool dbg_skin_engine(void); + #endif /* !PLUGIN */ #endif diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index d89ca8b534..4d1526fcbc 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c @@ -426,12 +426,16 @@ static int parse_image_load(struct skin_element *element, img->buflib_handle = -1; img->is_9_segment = false; img->loaded = false; - - /* save current viewport */ - img->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp); + img->dither = false; if (token->type == SKIN_TOKEN_IMAGE_DISPLAY) + { token->value.data = PTRTOSKINOFFSET(skin_buffer, img); +#ifdef HAVE_BACKDROP_IMAGE + if (curr_vp) + img->dither = curr_vp->output_to_backdrop_buffer; +#endif + } if (!strcmp(img->bm.data, "__list_icons__")) { @@ -497,7 +501,6 @@ static int parse_playlistview(struct skin_element *element, struct playlistviewer *viewer = skin_buffer_alloc(sizeof(*viewer)); if (!viewer) return WPS_ERROR_INVALID_PARAM; - viewer->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp); viewer->show_icons = true; viewer->start_offset = get_param(element, 0)->data.number; viewer->line = PTRTOSKINOFFSET(skin_buffer, get_param_code(element, 1)); @@ -615,7 +618,8 @@ static int parse_viewporttextstyle(struct skin_element *element, if (element->params_count < 2 || !parse_color(curr_screen, get_param_text(element, 1), &colour)) return 1; - line->style = STYLE_COLORED; + /* STYLE_COLORED is only a modifier and can't be used on its own */ + line->style = STYLE_COLORED | STYLE_DEFAULT; line->text_color = colour; } #ifdef HAVE_LCD_COLOR @@ -714,8 +718,35 @@ static int parse_viewportcolour(struct skin_element *element, return -1; if (isdefault(param)) { - colour->colour = get_viewport_default_colour(curr_screen, - token->type == SKIN_TOKEN_VIEWPORT_FGCOLOUR); + unsigned int fg_color; + unsigned int bg_color; + + switch (curr_screen) + { +#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 + case SCREEN_REMOTE: + fg_color = LCD_REMOTE_DEFAULT_FG; + bg_color = LCD_REMOTE_DEFAULT_BG; + break; +#endif + default: +#if defined(HAVE_LCD_COLOR) + fg_color = global_settings.fg_color; + bg_color = global_settings.bg_color; +#elif LCD_DEPTH > 1 + fg_color = LCD_DEFAULT_FG; + bg_color = LCD_DEFAULT_BG; +#else + fg_color = 0; + bg_color = 0; +#endif + break; + } + + if (token->type == SKIN_TOKEN_VIEWPORT_FGCOLOUR) + colour->colour = fg_color; + else + colour->colour = bg_color; } else { @@ -723,7 +754,6 @@ static int parse_viewportcolour(struct skin_element *element, &colour->colour)) return -1; } - colour->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp); token->value.data = PTRTOSKINOFFSET(skin_buffer, colour); if (element->line == curr_viewport_element->line) { @@ -780,14 +810,14 @@ static int parse_setting_and_lang(struct skin_element *element, */ (void)wps_data; char *temp = get_param_text(element, 0); - int i; if (token->type == SKIN_TOKEN_TRANSLATEDSTRING) { #ifndef __PCTOOL__ - i = lang_english_to_id(temp); + int i = lang_english_to_id(temp); if (i < 0) i = LANG_LAST_INDEX_IN_ARRAY; + token->value.i = i; #endif } else if (element->params_count > 1) @@ -800,12 +830,13 @@ static int parse_setting_and_lang(struct skin_element *element, else { #ifndef __PCTOOL__ - if (find_setting_by_cfgname(temp, &i) == NULL) + const struct settings_list *setting = find_setting_by_cfgname(temp); + if (!setting) return WPS_ERROR_INVALID_PARAM; + + token->value.xdata = (void *)setting; #endif } - /* Store the setting number */ - token->value.i = i; return 0; } @@ -942,7 +973,6 @@ static int parse_progressbar_tag(struct skin_element* element, if (!pb) return WPS_ERROR_INVALID_PARAM; - pb->vp = PTRTOSKINOFFSET(skin_buffer, vp); pb->follow_lang_direction = follow_lang_direction > 0; pb->nofill = false; pb->noborder = false; @@ -950,7 +980,7 @@ static int parse_progressbar_tag(struct skin_element* element, pb->image = PTRTOSKINOFFSET(skin_buffer, NULL); pb->slider = PTRTOSKINOFFSET(skin_buffer, NULL); pb->backdrop = PTRTOSKINOFFSET(skin_buffer, NULL); - pb->setting_id = -1; + pb->setting = NULL; pb->invert_fill_direction = false; pb->horizontal = true; @@ -1051,7 +1081,7 @@ static int parse_progressbar_tag(struct skin_element* element, enum { eINVERT = 0, eNOFILL, eNOBORDER, eNOBAR, eSLIDER, eIMAGE, - eBACKDROP, eVERTICAL, eHORIZONTAL, eNOTOUCH, eSETTING, + eBACKDROP, eVERTICAL, eHORIZONTAL, eNOTOUCH, eSETTING, e_PB_TAG_COUNT }; @@ -1135,7 +1165,8 @@ static int parse_progressbar_tag(struct skin_element* element, param++; text = SKINOFFSETTOPTR(skin_buffer, param->data.text); #ifndef __PCTOOL__ - if (find_setting_by_cfgname(text, &pb->setting_id) == NULL) + pb->setting = find_setting_by_cfgname(text); + if (!pb->setting) return WPS_ERROR_INVALID_PARAM; #endif } @@ -1169,7 +1200,6 @@ static int parse_progressbar_tag(struct skin_element* element, img->display = -1; img->using_preloaded_icons = false; img->buflib_handle = -1; - img->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp); img->loaded = false; struct skin_token_list *item = new_skin_token_list_item(NULL, img); if (!item) @@ -1296,7 +1326,6 @@ static int parse_albumart_load(struct skin_element* element, if (!isdefault(param3) && param3->type == PERCENT) aa->height = param3->data.number * curr_vp->vp.height / 1000; - aa->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp); aa->draw_handle = -1; /* if we got here, we parsed everything ok .. ! */ @@ -1526,48 +1555,48 @@ static int touchregion_setup_setting(struct skin_element *element, int param_no, #ifndef __PCTOOL__ int p = param_no; char *name = get_param_text(element, p++); - int j; - - region->setting_data.setting = find_setting_by_cfgname(name, &j); - if (region->setting_data.setting == NULL) + const struct settings_list *setting = find_setting_by_cfgname(name); + if (!setting) return WPS_ERROR_INVALID_PARAM; + region->setting_data.setting = setting; + if (region->action == ACTION_SETTINGS_SET) { char* text; int temp; - struct touchsetting *setting = + struct touchsetting *touchsetting = ®ion->setting_data; if (element->params_count < p+1) return -1; text = get_param_text(element, p++); - switch (settings[j].flags&F_T_MASK) + switch (setting->flags & F_T_MASK) { case F_T_CUSTOM: - setting->value.text = PTRTOSKINOFFSET(skin_buffer, text); + touchsetting->value.text = PTRTOSKINOFFSET(skin_buffer, text); break; case F_T_INT: case F_T_UINT: - if (settings[j].cfg_vals == NULL) + if (setting->cfg_vals == NULL) { - setting->value.number = atoi(text); + touchsetting->value.number = atoi(text); } - else if (cfg_string_to_int(j, &temp, text)) + else if (cfg_string_to_int(setting, &temp, text)) { - if (settings[j].flags&F_TABLE_SETTING) - setting->value.number = - settings[j].table_setting->values[temp]; + if (setting->flags & F_TABLE_SETTING) + touchsetting->value.number = + setting->table_setting->values[temp]; else - setting->value.number = temp; + touchsetting->value.number = temp; } else return -1; break; case F_T_BOOL: - if (cfg_string_to_int(j, &temp, text)) + if (cfg_string_to_int(setting, &temp, text)) { - setting->value.number = temp; + touchsetting->value.number = temp; } else return -1; @@ -1828,9 +1857,7 @@ void skin_data_free_buflib_allocs(struct wps_data *wps_data) abort: wps_data->font_ids = PTRTOSKINOFFSET(skin_buffer, NULL); /* Safe if skin_buffer is NULL */ wps_data->images = PTRTOSKINOFFSET(skin_buffer, NULL); - if (wps_data->buflib_handle > 0) - core_free(wps_data->buflib_handle); - wps_data->buflib_handle = -1; + wps_data->buflib_handle = core_free(wps_data->buflib_handle); #endif } @@ -1871,13 +1898,11 @@ static void skin_data_reset(struct wps_data *wps_data) } #ifndef __PCTOOL__ -static int currently_loading_handle = -1; static int buflib_move_callback(int handle, void* current, void* new) { + (void)handle; (void)current; (void)new; - if (handle == currently_loading_handle) - return BUFLIB_CB_CANNOT_MOVE; /* Any active skins may be scrolling - which means using viewports which * will be moved after this callback returns. This is a hammer to make that * safe. TODO: use a screwdriver instead. @@ -1890,85 +1915,63 @@ static int buflib_move_callback(int handle, void* current, void* new) return BUFLIB_CB_OK; } -static struct buflib_callbacks buflib_ops = {buflib_move_callback, NULL, NULL}; -static void lock_handle(int handle) -{ - currently_loading_handle = handle; -} -static void unlock_handle(void) -{ - currently_loading_handle = -1; -} #endif -static int load_skin_bmp(struct wps_data *wps_data, struct bitmap *bitmap, char* bmpdir) +static int load_skin_bmp(struct wps_data *wps_data, struct gui_img *img, char* bmpdir) { + (void)wps_data; /* only needed for remote targets */ char img_path[MAX_PATH]; - int fd; - int handle; + struct bitmap *bitmap = &img->bm; + get_image_filename(bitmap->data, bmpdir, img_path, sizeof(img_path)); - /* load the image */ - int format; -#ifdef HAVE_REMOTE_LCD - if (curr_screen == SCREEN_REMOTE) - format = FORMAT_ANY|FORMAT_REMOTE; - else -#endif - format = FORMAT_ANY|FORMAT_TRANSPARENT; - - fd = open(img_path, O_RDONLY); +#ifdef __PCTOOL__ /* just check if image exists */ + int fd = open(img_path, O_RDONLY); if (fd < 0) { DEBUGF("Couldn't open %s\n", img_path); return fd; } -#ifndef __PCTOOL__ - int buf_size = read_bmp_fd(fd, bitmap, 0, - format|FORMAT_RETURN_SIZE, NULL); - if(buf_size < 0) - { - close(fd); - return buf_size; - } + close(fd); + return 1; +#else /* load the image */ + static struct buflib_callbacks buflib_ops = {buflib_move_callback, NULL, NULL}; + int handle; + int bmpformat; + ssize_t buf_reqd; +#ifdef HAVE_REMOTE_LCD + if (curr_screen == SCREEN_REMOTE) + bmpformat = FORMAT_ANY|FORMAT_REMOTE; + else +#endif + bmpformat = img->dither ? FORMAT_ANY|FORMAT_DITHER|FORMAT_TRANSPARENT : + FORMAT_ANY|FORMAT_TRANSPARENT; - handle = core_alloc_ex(bitmap->data, buf_size, &buflib_ops); - if (handle <= 0) + handle = core_load_bmp(img_path, bitmap, bmpformat, &buf_reqd, &buflib_ops); + if (handle != CLB_ALOC_ERR) { - DEBUGF("Not enough skin buffer: need %zd more.\n", - buf_size - skin_buffer_freespace()); - close(fd); + /* NOTE!: bitmap->data == NULL to force a crash later if the + caller doesnt call core_get_data() */ + _stats->buflib_handles++; + _stats->images_size += buf_reqd; return handle; } - _stats->buflib_handles++; - _stats->images_size += buf_size; - lseek(fd, 0, SEEK_SET); - lock_handle(handle); - bitmap->data = core_get_data(handle); - int ret = read_bmp_fd(fd, bitmap, buf_size, format, NULL); - bitmap->data = NULL; /* do this to force a crash later if the - caller doesnt call core_get_data() */ - unlock_handle(); - close(fd); - if (ret > 0) + + if (buf_reqd == CLB_READ_ERR) { - /* free unused alpha channel, if any */ - core_shrink(handle, core_get_data(handle), ret); - return handle; + /* Abort if we can't load an image */ + DEBUGF("Couldn't load '%s' (%zu)\n", img_path, buf_reqd); } else { - /* Abort if we can't load an image */ - DEBUGF("Couldn't load '%s'\n", img_path); - core_free(handle); - return -1; + DEBUGF("Not enough skin buffer: need %zd more.\n", + buf_reqd - skin_buffer_freespace()); } -#else /* !__PCTOOL__ */ - close(fd); - return 1; -#endif + + return -1; +#endif/* !__PCTOOL__ */ } static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir) @@ -1996,14 +1999,15 @@ static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir) char path[MAX_PATH]; int handle; strcpy(path, img->bm.data); - handle = load_skin_bmp(wps_data, &img->bm, bmpdir); + handle = load_skin_bmp(wps_data, img, bmpdir); img->buflib_handle = handle; - img->loaded = img->buflib_handle >= 0; + img->loaded = img->buflib_handle > 0; if (img->loaded) { struct skin_token_list *imglist = SKINOFFSETTOPTR(skin_buffer, list->next); img->subimage_height = img->bm.height / img->num_subimages; + struct bitmap* loaded_bm = &img->bm; while (imglist) { token = SKINOFFSETTOPTR(skin_buffer, imglist->token); @@ -2013,6 +2017,7 @@ static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir) { img->loaded = true; img->buflib_handle = handle; + img->bm = *loaded_bm; img->subimage_height = img->bm.height / img->num_subimages; } } @@ -2396,13 +2401,6 @@ static int skin_element_callback(struct skin_element* element, void* data) break; #endif #ifdef HAVE_ALBUMART - case SKIN_TOKEN_ALBUMART_DISPLAY: - if (SKINOFFSETTOPTR(skin_buffer, wps_data->albumart)) - { - struct skin_albumart *aa = SKINOFFSETTOPTR(skin_buffer, wps_data->albumart); - aa->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp); - } - break; case SKIN_TOKEN_ALBUMART_LOAD: function = parse_albumart_load; break; @@ -2563,7 +2561,7 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data, { /* get the bitmap dir */ char *dot = strrchr(buf, '.'); - strlcpy(bmpdir, buf, dot - buf + 1); + strmemccpy(bmpdir, buf, dot - buf + 1); } else { @@ -2587,8 +2585,7 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data, } #endif #ifndef __PCTOOL__ - wps_data->buflib_handle = core_alloc(isfile ? buf : "failsafe skin", - skin_buffer_usage()); + wps_data->buflib_handle = core_alloc(skin_buffer_usage()); if (wps_data->buflib_handle > 0) { wps_data->wps_loaded = true; diff --git a/apps/gui/skin_engine/skin_render.c b/apps/gui/skin_engine/skin_render.c index 1f777b6672..06f7d9798d 100644 --- a/apps/gui/skin_engine/skin_render.c +++ b/apps/gui/skin_engine/skin_render.c @@ -50,6 +50,7 @@ #include "root_menu.h" #include "misc.h" #include "list.h" +#include "wps.h" #define MAX_LINE 1024 @@ -66,7 +67,6 @@ struct skin_draw_info { bool no_line_break; bool line_scrolls; bool force_redraw; - bool viewport_change; char *buf; size_t buf_size; @@ -74,6 +74,8 @@ struct skin_draw_info { int offset; /* used by the playlist viewer */ }; +extern void sb_set_info_vp(enum screen_type screen, OFFSETTYPE(char*) label); + typedef bool (*skin_render_func)(struct skin_element* alternator, struct skin_draw_info *info); bool skin_render_alternator(struct skin_element* alternator, struct skin_draw_info *info); @@ -93,11 +95,11 @@ get_child(OFFSETTYPE(struct skin_element**) children, int child) static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, - struct skin_element *element, struct skin_viewport* skin_vp) + struct skin_element *element) { struct wps_token *token = (struct wps_token *)SKINOFFSETTOPTR(skin_buffer, element->data); if (!token) return false; - struct viewport *vp = &skin_vp->vp; + struct skin_viewport *skin_vp = info->skin_vp; struct wps_data *data = gwps->data; bool do_refresh = (element->tag->flags & info->refresh_type) > 0; @@ -108,9 +110,7 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, { struct viewport_colour *col = SKINOFFSETTOPTR(skin_buffer, token->value.data); if (!col) return false; - struct viewport *vp = SKINOFFSETTOPTR(skin_buffer, col->vp); - if (!vp) return false; - vp->fg_pattern = col->colour; + skin_vp->vp.fg_pattern = col->colour; skin_vp->fgbg_changed = true; } break; @@ -118,9 +118,7 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, { struct viewport_colour *col = SKINOFFSETTOPTR(skin_buffer, token->value.data); if (!col) return false; - struct viewport *vp = SKINOFFSETTOPTR(skin_buffer, col->vp); - if (!vp) return false; - vp->bg_pattern = col->colour; + skin_vp->vp.bg_pattern = col->colour; skin_vp->fgbg_changed = true; } break; @@ -196,7 +194,7 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, case SKIN_TOKEN_PEAKMETER: data->peak_meter_enabled = true; if (do_refresh) - draw_peakmeters(gwps, info->line_number, vp); + draw_peakmeters(gwps, info->line_number, &skin_vp->vp); break; case SKIN_TOKEN_DRAWRECTANGLE: if (do_refresh) @@ -215,13 +213,13 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, #endif { #if LCD_DEPTH > 1 - unsigned backup = vp->fg_pattern; - vp->fg_pattern = rect->start_colour; + unsigned backup = skin_vp->vp.fg_pattern; + skin_vp->vp.fg_pattern = rect->start_colour; #endif gwps->display->fillrect(rect->x, rect->y, rect->width, rect->height); #if LCD_DEPTH > 1 - vp->fg_pattern = backup; + skin_vp->vp.fg_pattern = backup; #endif } } @@ -239,7 +237,7 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, { struct progressbar *bar = (struct progressbar*)SKINOFFSETTOPTR(skin_buffer, token->value.data); if (do_refresh) - draw_progressbar(gwps, info->line_number, bar); + draw_progressbar(gwps, info->skin_vp, info->line_number, bar); } break; case SKIN_TOKEN_IMAGE_DISPLAY: @@ -582,7 +580,7 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i { break; } - if (!do_non_text_tags(info->gwps, info, child, info->skin_vp)) + if (!do_non_text_tags(info->gwps, info, child)) { static char tempbuf[128]; const char *valuestr = get_token_value(info->gwps, SKINOFFSETTOPTR(skin_buffer, child->data), @@ -590,10 +588,6 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i sizeof(tempbuf), NULL); if (valuestr) { -#if defined(ONDA_VX747) || defined(ONDA_VX747P) - /* Doesn't redraw (in sim at least) */ - needs_update = true; -#endif #if CONFIG_RTC if (child->tag->flags&SKIN_RTC_REFRESH) needs_update = needs_update || info->refresh_type&SKIN_REFRESH_DYNAMIC; @@ -606,10 +600,6 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i } break; case TEXT: -#if defined(ONDA_VX747) || defined(ONDA_VX747P) - /* Doesn't redraw (in sim at least) */ - needs_update = true; -#endif strlcat(info->cur_align_start, SKINOFFSETTOPTR(skin_buffer, child->data), info->buf_size - (info->cur_align_start-info->buf)); needs_update = needs_update || @@ -943,7 +933,7 @@ void skin_render_playlistviewer(struct playlistviewer* viewer, struct align_pos * align = &info.align; bool needs_update; int cur_pos, start_item, max; - int nb_lines = viewport_get_nb_lines(SKINOFFSETTOPTR(skin_buffer, viewer->vp)); + int nb_lines = viewport_get_nb_lines(&skin_viewport->vp); #if CONFIG_TUNER if (get_current_activity() == ACTIVITY_FM) { @@ -954,8 +944,8 @@ void skin_render_playlistviewer(struct playlistviewer* viewer, else #endif { - struct cuesheet *cue = skin_get_global_state()->id3 ? - skin_get_global_state()->id3->cuesheet : NULL; + struct wps_state *state = get_wps_state(); + struct cuesheet *cue = state->id3 ? state->id3->cuesheet : NULL; cur_pos = playlist_get_display_index(); max = playlist_amount()+1; if (cue) @@ -989,7 +979,7 @@ void skin_render_playlistviewer(struct playlistviewer* viewer, /* only update if the line needs to be, and there is something to write */ if (refresh_type && needs_update) { - struct viewport *vp = SKINOFFSETTOPTR(skin_buffer, viewer->vp); + struct viewport *vp = &skin_viewport->vp; if (!info.force_redraw) display->scroll_stop_viewport_rect(vp, 0, info.line_number*display->getcharheight(), diff --git a/apps/gui/skin_engine/skin_tokens.c b/apps/gui/skin_engine/skin_tokens.c index 27022b87d1..f6c166b140 100644 --- a/apps/gui/skin_engine/skin_tokens.c +++ b/apps/gui/skin_engine/skin_tokens.c @@ -66,11 +66,10 @@ #include "fixedpoint.h" #endif #include "list.h" +#include "wps.h" #define NOINLINE __attribute__ ((noinline)) -extern struct wps_state wps_state; - static const char* get_codectype(const struct mp3entry* id3) { if (id3 && id3->codectype < AFMT_NUM_CODECS) { @@ -115,7 +114,7 @@ char* get_dir(char* buf, int buf_size, const char* path, int level) return NULL; len = MIN(last_sep - sep, buf_size - 1); - strlcpy(buf, sep + 1, len + 1); + strmemccpy(buf, sep + 1, len + 1); return buf; } @@ -228,7 +227,7 @@ static const char* get_filename_token(struct wps_token *token, char* filename, const char *get_id3_token(struct wps_token *token, struct mp3entry *id3, char *filename, char *buf, int buf_size, int limit, int *intval) { - struct wps_state *state = &wps_state; + struct wps_state *state = get_wps_state(); if (id3) { unsigned long length = id3->length; @@ -540,7 +539,7 @@ const char *get_radio_token(struct wps_token *token, int preset_offset, static struct mp3entry* get_mp3entry_from_offset(int offset, char **filename) { struct mp3entry* pid3 = NULL; - struct wps_state *state = skin_get_global_state(); + struct wps_state *state = get_wps_state(); struct cuesheet *cue = state->id3 ? state->id3->cuesheet : NULL; const char *fname = NULL; if (cue && cue->curr_track_idx + offset < cue->track_count) @@ -678,7 +677,7 @@ const char *get_token_value(struct gui_wps *gwps, return NULL; struct wps_data *data = gwps->data; - struct wps_state *state = skin_get_global_state(); + struct wps_state *state = get_wps_state(); struct mp3entry *id3; /* Think very carefully about using this. maybe get_id3_token() is the better place? */ const char *out_text = NULL; @@ -1040,37 +1039,19 @@ const char *get_token_value(struct gui_wps *gwps, case SKIN_TOKEN_PLAYBACK_STATUS: { int status = current_playmode(); - /* music */ - int mode = 1; /* stop */ - if (status == STATUS_PLAY) - mode = 2; /* play */ - if (state->is_fading || - (status == STATUS_PAUSE && !status_get_ffmode())) - mode = 3; /* pause */ - else - { /* ff / rwd */ - if (status_get_ffmode() == STATUS_FASTFORWARD) - mode = 4; - if (status_get_ffmode() == STATUS_FASTBACKWARD) - mode = 5; + switch (status) { + case STATUS_STOP: + numeric_ret = 1; + break; + case STATUS_PLAY: + numeric_ret = 2; + break; + default: + numeric_ret = status + 1; + break; } -#ifdef HAVE_RECORDING - /* recording */ - if (status == STATUS_RECORD) - mode = 6; - else if (status == STATUS_RECORD_PAUSE) - mode = 7; -#endif -#if CONFIG_TUNER - /* radio */ - if (status == STATUS_RADIO) - mode = 8; - else if (status == STATUS_RADIO_PAUSE) - mode = 9; -#endif - numeric_ret = mode; - snprintf(buf, buf_size, "%d", mode-1); + snprintf(buf, buf_size, "%d", numeric_ret-1); numeric_buf = buf; goto gtv_ret_numeric_tag_info; } @@ -1390,7 +1371,7 @@ const char *get_token_value(struct gui_wps *gwps, case SKIN_TOKEN_SETTING: { - const struct settings_list *s = settings+token->value.i; + const struct settings_list *s = token->value.xdata; if (intval) { /* Handle contionals */ @@ -1461,7 +1442,7 @@ const char *get_token_value(struct gui_wps *gwps, goto gtv_ret_numeric_tag_info; } } - cfg_to_string(token->value.i,buf,buf_size); + cfg_to_string(s, buf, buf_size); numeric_buf = buf; goto gtv_ret_numeric_tag_info; } diff --git a/apps/gui/skin_engine/skin_touchsupport.c b/apps/gui/skin_engine/skin_touchsupport.c index 045bc809c8..b952709562 100644 --- a/apps/gui/skin_engine/skin_touchsupport.c +++ b/apps/gui/skin_engine/skin_touchsupport.c @@ -35,8 +35,9 @@ #include "dsp_misc.h" /** Disarms all touchregions. */ -void skin_disarm_touchregions(struct wps_data *data) +void skin_disarm_touchregions(struct gui_wps *gwps) { + struct wps_data *data = gwps->data; char* skin_buffer = get_skin_buffer(data); struct skin_token_list *regions = SKINOFFSETTOPTR(skin_buffer, data->touchregions); while (regions) @@ -52,9 +53,9 @@ void skin_disarm_touchregions(struct wps_data *data) * egde_offset is a percentage value for the position of the touch * inside the bar for regions which arnt WPS_TOUCHREGION_ACTION type. */ -int skin_get_touchaction(struct wps_data *data, int* edge_offset, - struct touchregion **retregion) +int skin_get_touchaction(struct gui_wps *gwps, int* edge_offset) { + struct wps_data *data = gwps->data; int returncode = ACTION_NONE; short x,y; short vx, vy; @@ -162,9 +163,7 @@ int skin_get_touchaction(struct wps_data *data, int* edge_offset, /* On release, all regions are disarmed. */ if (released) - skin_disarm_touchregions(data); - if (retregion && temp) - *retregion = temp; + skin_disarm_touchregions(gwps); if (temp && temp->press_length == LONG_PRESS) temp->armed = false; @@ -301,7 +300,7 @@ int skin_get_touchaction(struct wps_data *data, int* edge_offset, case ACTION_TOUCH_REPMODE: /* cycle the repeat mode setting */ { const struct settings_list *rep_setting = - find_setting(&global_settings.repeat_mode, NULL); + find_setting(&global_settings.repeat_mode); option_select_next_val(rep_setting, false, true); audio_flush_and_reload_tracks(); returncode = ACTION_REDRAW; @@ -314,9 +313,9 @@ int skin_get_touchaction(struct wps_data *data, int* edge_offset, if (bar && edge_offset) { int val, count; - get_setting_info_for_bar(bar->setting_id, &count, &val); + get_setting_info_for_bar(bar->setting, &count, &val); val = *edge_offset * count / 1000; - update_setting_value_from_touch(bar->setting_id, val); + update_setting_value_from_touch(bar->setting, val); } } break; diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h index bf368bc4f3..8ad8325e66 100644 --- a/apps/gui/skin_engine/wps_internals.h +++ b/apps/gui/skin_engine/wps_internals.h @@ -31,6 +31,8 @@ #include "core_alloc.h" #endif +struct wps_data; + struct skin_stats { size_t buflib_handles; size_t tree_size; @@ -42,6 +44,13 @@ struct skin_stats *skin_get_stats(int number, int screen); #define skin_clear_stats(stats) memset(stats, 0, sizeof(struct skin_stats)) bool skin_backdrop_get_debug(int index, char **path, int *ref_count, size_t *size); +/* + * setup up the skin-data from a format-buffer (isfile = false) + * or from a skinfile (isfile = true) + */ +bool skin_data_load(enum screen_type screen, struct wps_data *wps_data, + const char *buf, bool isfile, struct skin_stats *stats); + /* Timeout unit expressed in HZ. In WPS, all timeouts are given in seconds (possibly with a decimal fraction) but stored as integer values. E.g. 2.5 is stored as 25. This means 25 tenth of a second, i.e. 25 units. @@ -64,6 +73,7 @@ struct wps_token { unsigned short i; long l; OFFSETTYPE(void*) data; + void *xdata; } value; enum skin_token_type type; /* enough to store the token type */ @@ -81,7 +91,6 @@ struct skin_token_list { }; struct gui_img { - OFFSETTYPE(struct viewport*) vp; /* The viewport to display this image in */ short int x; /* x-pos */ short int y; /* y-pos */ short int num_subimages; /* number of sub-images */ @@ -93,6 +102,7 @@ struct gui_img { int display; bool using_preloaded_icons; /* using the icon system instead of a bmp */ bool is_9_segment; + bool dither; }; struct image_display { @@ -104,7 +114,6 @@ struct image_display { struct progressbar { enum skin_token_type type; - OFFSETTYPE(struct viewport *) vp; /* regular pb */ short x; /* >=0: explicitly set in the tag -> y-coord within the viewport @@ -124,7 +133,7 @@ struct progressbar { OFFSETTYPE(struct gui_img *) slider; bool horizontal; OFFSETTYPE(struct gui_img *) backdrop; - int setting_id; /* for the setting bar type */ + const struct settings_list *setting; }; @@ -189,7 +198,6 @@ struct skin_viewport { #endif }; struct viewport_colour { - OFFSETTYPE(struct viewport *) vp; unsigned colour; }; @@ -236,7 +244,6 @@ struct touchregion_lastpress { #endif struct playlistviewer { - OFFSETTYPE(struct viewport *) vp; bool show_icons; int start_offset; OFFSETTYPE(struct skin_element *) line; @@ -267,7 +274,6 @@ struct skin_albumart { unsigned char yalign; /* WPS_ALBUMART_ALIGN_TOP, _CENTER, _BOTTOM */ unsigned char state; /* WPS_ALBUMART_NONE, _CHECK, _LOAD */ - OFFSETTYPE(struct viewport *) vp; int draw_handle; }; #endif @@ -313,6 +319,17 @@ struct listitem { short offset; }; +struct listitem_viewport_cfg { + struct wps_data *data; + OFFSETTYPE(char *) label; + int width; + int height; + int xmargin; + int ymargin; + bool tile; + struct skin_viewport selected_item_vp; +}; + #ifdef HAVE_SKIN_VARIABLES struct skin_var { OFFSETTYPE(const char *) label; @@ -372,7 +389,7 @@ struct wps_data #ifndef __PCTOOL__ static inline char* get_skin_buffer(struct wps_data* data) { - if (data->buflib_handle >= 0) + if (data->buflib_handle > 0) return core_get_data(data->buflib_handle); return NULL; } @@ -382,30 +399,6 @@ static inline char* get_skin_buffer(struct wps_data* data) /* wps_data end */ -/* wps_state - holds the data which belongs to the current played track, - the track which will be played afterwards, current path to the track - and some status infos */ -struct wps_state -{ - struct mp3entry* id3; - struct mp3entry* nid3; - int ff_rewind_count; - bool ff_rewind; - bool paused; - bool is_fading; -}; - -/* change the ff/rew-status - if ff_rew = true then we are in skipping mode - else we are in normal mode */ -/* void wps_state_update_ff_rew(bool ff_rew); Currently unused */ - -/* change the tag-information of the current played track - and the following track */ -/* void wps_state_update_id3_nid3(struct mp3entry *id3, struct mp3entry *nid3); Currently unused */ -/* wps_state end*/ - /* gui_wps defines a wps with its data, state, and the screen on which the wps-content should be drawn */ diff --git a/apps/gui/splash.c b/apps/gui/splash.c index b85e4693aa..d0f1fbb67c 100644 --- a/apps/gui/splash.c +++ b/apps/gui/splash.c @@ -29,71 +29,84 @@ #include "talk.h" #include "splash.h" #include "viewport.h" -#include "strtok_r.h" +#include "strptokspn_r.h" +#include "scrollbar.h" +#include "font.h" + +static long progress_next_tick = 0; #define MAXLINES (LCD_HEIGHT/6) #define MAXBUFFER 512 #define RECT_SPACING 2 #define SPLASH_MEMORY_INTERVAL (HZ) -static void splash_internal(struct screen * screen, const char *fmt, va_list ap) +static bool splash_internal(struct screen * screen, const char *fmt, va_list ap, + struct viewport *vp, int addl_lines) { char splash_buf[MAXBUFFER]; - char *lines[MAXLINES]; - - char *next; - char *lastbreak = NULL; - char *store = NULL; + struct splash_lines { + const char *str; + size_t len; + } lines[MAXLINES]; + const char *next; + const char *lastbreak = NULL; + const char *store = NULL; int line = 0; int x = 0; int y, i; - int space_w, w, h; - struct viewport vp; + int space_w, w, chr_h; int width, height; int maxw = 0; + int fontnum = vp->font; - viewport_set_defaults(&vp, screen->screen_type); - struct viewport *last_vp = screen->set_viewport(&vp); - - screen->getstringsize(" ", &space_w, &h); - y = h; + char lastbrkchr; + size_t len, next_len; + const char matchstr[] = "\r\n\f\v\t "; + font_getstringsize(" ", &space_w, &chr_h, fontnum); + y = chr_h + (addl_lines * chr_h); vsnprintf(splash_buf, sizeof(splash_buf), fmt, ap); va_end(ap); /* break splash string into display lines, doing proper word wrap */ - - next = strtok_r(splash_buf, " ", &store); + next = strptokspn_r(splash_buf, matchstr, &next_len, &store); if (!next) - goto end; /* nothing to display */ + return false; /* nothing to display */ - lines[0] = next; + lines[line].len = next_len; + lines[line].str = next; while (true) { - screen->getstringsize(next, &w, NULL); + w = font_getstringnsize(next, next_len, NULL, NULL, fontnum); if (lastbreak) { - if (x + (next - lastbreak) * space_w + w - > vp.width - RECT_SPACING*2) - { /* too wide, wrap */ + len = next - lastbreak; + int next_w = len * space_w; + if (x + next_w + w > vp->width - RECT_SPACING*2 || lastbrkchr != ' ') + { /* too wide, or control character wrap */ if (x > maxw) maxw = x; - if ((y + h > vp.height) || (line >= (MAXLINES-1))) + if ((y + chr_h * 2 > vp->height) || (line >= (MAXLINES-1))) break; /* screen full or out of lines */ x = 0; - y += h; - lines[++line] = next; + y += chr_h; + lines[++line].len = next_len; + lines[line].str = next; } else { /* restore & calculate spacing */ - *lastbreak = ' '; - x += (next - lastbreak) * space_w; + lines[line].len += next_len + 1; + x += next_w; } } x += w; - lastbreak = next + strlen(next); - next = strtok_r(NULL, " ", &store); + + lastbreak = next + next_len; + lastbrkchr = *lastbreak; + + next = strptokspn_r(NULL, matchstr, &next_len, &store); + if (!next) { /* no more words */ if (x > maxw) @@ -111,53 +124,48 @@ static void splash_internal(struct screen * screen, const char *fmt, va_list ap) width = maxw + 2*RECT_SPACING; height = y + 2*RECT_SPACING; - if (width > vp.width) - width = vp.width; - if (height > vp.height) - height = vp.height; + if (width > vp->width) + width = vp->width; + if (height > vp->height) + height = vp->height; - vp.x += (vp.width - width) / 2; - vp.y += (vp.height - height) / 2; - vp.width = width; - vp.height = height; + vp->x += (vp->width - width) / 2; + vp->y += (vp->height - height) / 2; + vp->width = width; + vp->height = height; - vp.flags |= VP_FLAG_ALIGN_CENTER; + vp->flags |= VP_FLAG_ALIGN_CENTER; #if LCD_DEPTH > 1 if (screen->depth > 1) { - vp.drawmode = DRMODE_FG; - /* can't do vp.fg_pattern here, since set_foreground does a bit more on + vp->drawmode = DRMODE_FG; + /* can't do vp->fg_pattern here, since set_foreground does a bit more on * greyscale */ screen->set_foreground(SCREEN_COLOR_TO_NATIVE(screen, LCD_LIGHTGRAY)); } else #endif - vp.drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID); + vp->drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID); screen->fill_viewport(); #if LCD_DEPTH > 1 if (screen->depth > 1) - /* can't do vp.fg_pattern here, since set_foreground does a bit more on + /* can't do vp->fg_pattern here, since set_foreground does a bit more on * greyscale */ screen->set_foreground(SCREEN_COLOR_TO_NATIVE(screen, LCD_BLACK)); else #endif - vp.drawmode = DRMODE_SOLID; + vp->drawmode = DRMODE_SOLID; screen->draw_border_viewport(); - /* prepare putting the text */ - y = RECT_SPACING; - /* print the message to screen */ - for (i = 0; i <= line; i++, y+=h) + for(i = 0, y = RECT_SPACING; i <= line; i++, y+= chr_h) { - screen->putsxy(0, y, lines[i]); + screen->putsxyf(0, y, "%.*s", lines[i].len, lines[i].str); } - screen->update_viewport(); -end: - screen->set_viewport(last_vp); + return true; /* needs update */ } void splashf(int ticks, const char *fmt, ...) @@ -169,9 +177,17 @@ void splashf(int ticks, const char *fmt, ...) fmt = P2STR((unsigned char *)fmt); FOR_NB_SCREENS(i) { + struct screen * screen = &(screens[i]); + struct viewport vp; + viewport_set_defaults(&vp, screen->screen_type); + struct viewport *last_vp = screen->set_viewport(&vp); + va_start(ap, fmt); - splash_internal(&(screens[i]), fmt, ap); + if (splash_internal(screen, fmt, ap, &vp, 0)) + screen->update_viewport(); va_end(ap); + + screen->set_viewport(last_vp); } if (ticks) sleep(ticks); @@ -189,3 +205,59 @@ void splash(int ticks, const char *str) #endif splashf(ticks, "%s", P2STR((const unsigned char*)str)); } + +/* set delay before progress meter is shown */ +void splash_progress_set_delay(long delay_ticks) +{ + progress_next_tick = current_tick + delay_ticks; +} + +/* splash a progress meter */ +void splash_progress(int current, int total, const char *fmt, ...) +{ + va_list ap; + int vp_flag = VP_FLAG_VP_DIRTY; + /* progress update tick */ + long now = current_tick; + + if (current < total) + { + if(TIME_BEFORE(now, progress_next_tick)) + return; + /* limit to 20fps */ + progress_next_tick = now + HZ/20; + vp_flag = 0; /* don't mark vp dirty to prevent flashing */ + } + + /* If fmt is a lang ID then get the corresponding string (which + still might contain % place holders). */ + fmt = P2STR((unsigned char *)fmt); + FOR_NB_SCREENS(i) + { + struct screen * screen = &(screens[i]); + struct viewport vp; + viewport_set_defaults(&vp, screen->screen_type); + struct viewport *last_vp = screen->set_viewport_ex(&vp, vp_flag); + + va_start(ap, fmt); + if (splash_internal(screen, fmt, ap, &vp, 1)) + { + int size = screen->getcharheight(); + int x = RECT_SPACING; + int y = vp.height - size - RECT_SPACING; + int w = vp.width - RECT_SPACING * 2; + int h = size; +#ifdef HAVE_LCD_COLOR + const int sb_flags = HORIZONTAL | FOREGROUND; +#else + const int sb_flags = HORIZONTAL; +#endif + gui_scrollbar_draw(screen, x, y, w, h, total, 0, current, sb_flags); + + screen->update_viewport(); + } + va_end(ap); + + screen->set_viewport(last_vp); + } +} diff --git a/apps/gui/splash.h b/apps/gui/splash.h index 76b4c16d0c..f7ff44e00b 100644 --- a/apps/gui/splash.h +++ b/apps/gui/splash.h @@ -39,4 +39,15 @@ extern void splashf(int ticks, const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3); * it will be voiced */ extern void splash(int ticks, const char *str); + +/* set a delay before displaying the progress meter the first time */ +extern void splash_progress_set_delay(long delay_ticks); +/* + * Puts a splash message centered on all the screens with a progressbar + * - current : current progress increment + * - total : total increments + * - fmt : what to say *printf style + * updates limited internally to 20 fps - call repeatedly to update progress + */ +extern void splash_progress(int current, int total, const char *fmt, ...) ATTRIBUTE_PRINTF(3, 4); #endif /* _GUI_ICON_H_ */ diff --git a/apps/gui/statusbar-skinned.c b/apps/gui/statusbar-skinned.c index fd695bf6b6..8dd66641dd 100644 --- a/apps/gui/statusbar-skinned.c +++ b/apps/gui/statusbar-skinned.c @@ -27,7 +27,6 @@ #include "appevents.h" #include "screens.h" #include "screen_access.h" -#include "strlcpy.h" #include "skin_parser.h" #include "skin_buffer.h" #include "skin_engine/skin_engine.h" @@ -49,11 +48,13 @@ static int update_delay = DEFAULT_UPDATE_DELAY; static bool sbs_has_title[NB_SCREENS]; -static char* sbs_title[NB_SCREENS]; +static const char* sbs_title[NB_SCREENS]; static enum themable_icons sbs_icon[NB_SCREENS]; static bool sbs_loaded[NB_SCREENS] = { false }; -bool sb_set_title_text(char* title, enum themable_icons icon, enum screen_type screen) +void sb_set_info_vp(enum screen_type screen, OFFSETTYPE(char*) label); + +bool sb_set_title_text(const char* title, enum themable_icons icon, enum screen_type screen) { sbs_title[screen] = title; /* Icon_NOICON == -1 which the skin engine wants at position 1, so + 2 */ @@ -305,18 +306,17 @@ void sb_bypass_touchregions(bool enable) int sb_touch_to_button(int context) { - struct touchregion *region; static int last_context = -1; int button, offset; if (bypass_sb_touchregions) return ACTION_TOUCHSCREEN; - + + struct gui_wps *gwps = skin_get_gwps(CUSTOM_STATUSBAR, SCREEN_MAIN); if (last_context != context) - skin_disarm_touchregions(skin_get_gwps(CUSTOM_STATUSBAR, SCREEN_MAIN)->data); + skin_disarm_touchregions(gwps); last_context = context; - button = skin_get_touchaction(skin_get_gwps(CUSTOM_STATUSBAR, SCREEN_MAIN)->data, - &offset, ®ion); - + + button = skin_get_touchaction(gwps, &offset); switch (button) { #ifdef HAVE_VOLUME_IN_LIST diff --git a/apps/gui/statusbar-skinned.h b/apps/gui/statusbar-skinned.h index 3ed36f1a84..e8fa14e676 100644 --- a/apps/gui/statusbar-skinned.h +++ b/apps/gui/statusbar-skinned.h @@ -30,16 +30,15 @@ #include "icon.h" #include "skin_engine/skin_engine.h" -void sb_skin_data_load(enum screen_type screen, const char *buf, bool isfile); +struct wps_data; char* sb_create_from_settings(enum screen_type screen); void sb_skin_init(void) INIT_ATTR; -void sb_set_info_vp(enum screen_type screen, OFFSETTYPE(char*) label); struct viewport *sb_skin_get_info_vp(enum screen_type screen); void sb_skin_update(enum screen_type screen, bool force); void sb_skin_set_update_delay(int delay); -bool sb_set_title_text(char* title, enum themable_icons icon, enum screen_type screen); +bool sb_set_title_text(const char* title, enum themable_icons icon, enum screen_type screen); void sb_skin_has_title(enum screen_type screen); const char* sb_get_title(enum screen_type screen); enum themable_icons sb_get_icon(enum screen_type screen); diff --git a/apps/gui/usb_screen.c b/apps/gui/usb_screen.c index 31321ec005..fb59f820b6 100644 --- a/apps/gui/usb_screen.c +++ b/apps/gui/usb_screen.c @@ -41,6 +41,7 @@ #include "skin_engine/skin_engine.h" #include "playlist.h" #include "misc.h" +#include "icons.h" #include "bitmaps/usblogo.h" @@ -155,7 +156,24 @@ static void usb_screen_fix_viewports(struct screen *screen, *logo = *parent; logo->x = parent->x + parent->width - logo_width; +#ifdef HAVE_LCD_SPLIT + switch (statusbar_position(screen)) + { + /* start beyond split */ + case STATUSBAR_OFF: + logo->y = parent->y + LCD_SPLIT_POS; + break; + case STATUSBAR_TOP: + logo->y = parent->y + LCD_SPLIT_POS - STATUSBAR_HEIGHT; + break; + /* start at the top for maximum space */ + default: + logo->y = parent->y; + break; + } +#else logo->y = parent->y + (parent->height - logo_height) / 2; +#endif logo->width = logo_width; logo->height = logo_height; diff --git a/apps/gui/viewport.c b/apps/gui/viewport.c index 9f9cb186f5..e90426a132 100644 --- a/apps/gui/viewport.c +++ b/apps/gui/viewport.c @@ -233,7 +233,7 @@ static void viewportmanager_redraw(unsigned short id, void* data) } } -void viewportmanager_init() +void viewportmanager_init(void) { FOR_NB_SCREENS(i) { @@ -348,41 +348,3 @@ void viewport_set_defaults(struct viewport *vp, #endif /* !__PCTOOL__ */ viewport_set_fullscreen(vp, screen); } - - -int get_viewport_default_colour(enum screen_type screen, bool fgcolour) -{ - (void)screen; (void)fgcolour; -#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) - int colour; - if (fgcolour) - { -#if (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) - if (screen == SCREEN_REMOTE) - colour = REMOTE_FG_FALLBACK; - else -#endif -#if defined(HAVE_LCD_COLOR) - colour = global_settings.fg_color; -#else - colour = FG_FALLBACK; -#endif - } - else - { -#if (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) - if (screen == SCREEN_REMOTE) - colour = REMOTE_BG_FALLBACK; - else -#endif -#if defined(HAVE_LCD_COLOR) - colour = global_settings.bg_color; -#else - colour = BG_FALLBACK; -#endif - } - return colour; -#else - return 0; -#endif /* LCD_DEPTH > 1 || LCD_REMOTE_DEPTH > 1 */ -} diff --git a/apps/gui/viewport.h b/apps/gui/viewport.h index 2810be2ac3..c57a58b232 100644 --- a/apps/gui/viewport.h +++ b/apps/gui/viewport.h @@ -43,7 +43,6 @@ void viewport_set_defaults(struct viewport *vp, const enum screen_type screen); void viewport_set_fullscreen(struct viewport *vp, const enum screen_type screen); -int get_viewport_default_colour(enum screen_type screen, bool fgcolour); #ifndef __PCTOOL__ diff --git a/apps/gui/wps.c b/apps/gui/wps.c index 7554892451..260730c4a1 100644 --- a/apps/gui/wps.c +++ b/apps/gui/wps.c @@ -53,6 +53,7 @@ #include "root_menu.h" #include "backdrop.h" #include "quickscreen.h" +#include "shortcuts.h" #include "pitchscreen.h" #include "appevents.h" #include "viewport.h" @@ -61,14 +62,15 @@ #include "playlist_viewer.h" #include "wps.h" #include "statusbar-skinned.h" - -#define RESTORE_WPS_INSTANTLY 0l -#define RESTORE_WPS_NEXT_SECOND ((long)(HZ+current_tick)) +#include "skin_engine/wps_internals.h" +#include "open_plugin.h" #define FF_REWIND_MAX_PERCENT 3 /* cap ff/rewind step size at max % of file */ /* 3% of 30min file == 54s step size */ #define MIN_FF_REWIND_STEP 500 +static struct wps_state wps_state; + /* initial setup of wps_data */ static void wps_state_init(void); static void track_info_callback(unsigned short id, void *param); @@ -114,7 +116,7 @@ static void update_non_static(void) skin_update(WPS, i, SKIN_REFRESH_NON_STATIC); } -void pause_action(bool may_fade, bool updatewps) +void pause_action(bool updatewps) { /* Do audio first, then update, unless skin were to use its local status in which case, reverse it */ @@ -131,11 +133,9 @@ void pause_action(bool may_fade, bool updatewps) - global_settings.pause_rewind * 1000; audio_ff_rewind(newpos > 0 ? newpos : 0); } - - (void)may_fade; } -void unpause_action(bool may_fade, bool updatewps) +void unpause_action(bool updatewps) { /* Do audio first, then update, unless skin were to use its local status in which case, reverse it */ @@ -143,24 +143,15 @@ void unpause_action(bool may_fade, bool updatewps) if (updatewps) update_non_static(); - - (void)may_fade; -} - -static bool update_onvol_change(enum screen_type screen) -{ - skin_update(WPS, screen, SKIN_REFRESH_NON_STATIC); - - return false; } - #ifdef HAVE_TOUCHSCREEN -static int skintouch_to_wps(struct wps_data *data) +static int skintouch_to_wps(void) { int offset = 0; - struct touchregion *region; - int button = skin_get_touchaction(data, &offset, ®ion); + struct wps_state *gstate = get_wps_state(); + struct gui_wps *gwps = skin_get_gwps(WPS, SCREEN_MAIN); + int button = skin_get_touchaction(gwps, &offset); switch (button) { case ACTION_STD_PREV: @@ -182,17 +173,17 @@ static int skintouch_to_wps(struct wps_data *data) return ACTION_WPS_HOTKEY; #endif case ACTION_TOUCH_SCROLLBAR: - skin_get_global_state()->id3->elapsed = skin_get_global_state()->id3->length*offset/1000; + gstate->id3->elapsed = gstate->id3->length*offset/1000; audio_pre_ff_rewind(); - audio_ff_rewind(skin_get_global_state()->id3->elapsed); + audio_ff_rewind(gstate->id3->elapsed); return ACTION_TOUCHSCREEN; case ACTION_TOUCH_VOLUME: { const int min_vol = sound_min(SOUND_VOLUME); const int max_vol = sound_max(SOUND_VOLUME); const int step_vol = sound_steps(SOUND_VOLUME); - global_settings.volume = (offset * (max_vol - min_vol)) / 1000; - global_settings.volume += min_vol; + + global_settings.volume = from_normalized_volume(offset, min_vol, max_vol, 1000); global_settings.volume -= (global_settings.volume % step_vol); setvol(); } @@ -202,7 +193,7 @@ static int skintouch_to_wps(struct wps_data *data) } #endif /* HAVE_TOUCHSCREEN */ -bool ffwd_rew(int button) +static bool ffwd_rew(int button, bool seek_from_end) { unsigned int step = 0; /* current ff/rewind step */ unsigned int max_step = 0; /* maximum ff/rewind step */ @@ -210,7 +201,10 @@ bool ffwd_rew(int button) int direction = -1; /* forward=1 or backward=-1 */ bool exit = false; bool usb = false; + bool ff_rewind = false; const long ff_rw_accel = (global_settings.ff_rewind_accel + 3); + struct wps_state *gstate = get_wps_state(); + struct mp3entry *old_id3 = gstate->id3; if (button == ACTION_NONE) { @@ -219,27 +213,37 @@ bool ffwd_rew(int button) } while (!exit) { + struct mp3entry *id3 = gstate->id3; + if (id3 != old_id3) + { + ff_rewind = false; + ff_rewind_count = 0; + old_id3 = id3; + } + if (id3 && seek_from_end) + id3->elapsed = id3->length; + switch ( button ) { case ACTION_WPS_SEEKFWD: direction = 1; /* Fallthrough */ case ACTION_WPS_SEEKBACK: - if (skin_get_global_state()->ff_rewind) + if (ff_rewind) { if (direction == 1) { /* fast forwarding, calc max step relative to end */ - max_step = (skin_get_global_state()->id3->length - - (skin_get_global_state()->id3->elapsed + + max_step = (id3->length - + (id3->elapsed + ff_rewind_count)) * FF_REWIND_MAX_PERCENT / 100; } else { /* rewinding, calc max step relative to start */ - max_step = (skin_get_global_state()->id3->elapsed + ff_rewind_count) * - FF_REWIND_MAX_PERCENT / 100; + max_step = (id3->elapsed + ff_rewind_count) * + FF_REWIND_MAX_PERCENT / 100; } max_step = MAX(max_step, MIN_FF_REWIND_STEP); @@ -254,8 +258,7 @@ bool ffwd_rew(int button) } else { - if ( (audio_status() & AUDIO_STATUS_PLAY) && - skin_get_global_state()->id3 && skin_get_global_state()->id3->length ) + if ((audio_status() & AUDIO_STATUS_PLAY) && id3 && id3->length ) { audio_pre_ff_rewind(); if (direction > 0) @@ -263,7 +266,7 @@ bool ffwd_rew(int button) else status_set_ffmode(STATUS_FASTBACKWARD); - skin_get_global_state()->ff_rewind = true; + ff_rewind = true; step = 1000 * global_settings.ff_rewind_min_step; } @@ -272,19 +275,17 @@ bool ffwd_rew(int button) } if (direction > 0) { - if ((skin_get_global_state()->id3->elapsed + ff_rewind_count) > - skin_get_global_state()->id3->length) - ff_rewind_count = skin_get_global_state()->id3->length - - skin_get_global_state()->id3->elapsed; + if ((id3->elapsed + ff_rewind_count) > id3->length) + ff_rewind_count = id3->length - id3->elapsed; } else { - if ((int)(skin_get_global_state()->id3->elapsed + ff_rewind_count) < 0) - ff_rewind_count = -skin_get_global_state()->id3->elapsed; + if ((int)(id3->elapsed + ff_rewind_count) < 0) + ff_rewind_count = -id3->elapsed; } /* set the wps state ff_rewind_count so the progess info displays corectly */ - skin_get_global_state()->ff_rewind_count = ff_rewind_count; + gstate->ff_rewind_count = ff_rewind_count; FOR_NB_SCREENS(i) { @@ -296,10 +297,10 @@ bool ffwd_rew(int button) break; case ACTION_WPS_STOPSEEK: - skin_get_global_state()->id3->elapsed = skin_get_global_state()->id3->elapsed+ff_rewind_count; - audio_ff_rewind(skin_get_global_state()->id3->elapsed); - skin_get_global_state()->ff_rewind_count = 0; - skin_get_global_state()->ff_rewind = false; + id3->elapsed = id3->elapsed + ff_rewind_count; + audio_ff_rewind(id3->elapsed); + gstate->ff_rewind_count = 0; + ff_rewind = false; status_set_ffmode(0); exit = true; break; @@ -317,20 +318,21 @@ bool ffwd_rew(int button) button = get_action(CONTEXT_WPS|ALLOW_SOFTLOCK,TIMEOUT_BLOCK); #ifdef HAVE_TOUCHSCREEN if (button == ACTION_TOUCHSCREEN) - button = skintouch_to_wps(skin_get_gwps(WPS, SCREEN_MAIN)->data); + button = skintouch_to_wps(); #endif - if (button != ACTION_WPS_SEEKFWD && - button != ACTION_WPS_SEEKBACK) + if (button != ACTION_WPS_SEEKFWD + && button != ACTION_WPS_SEEKBACK + && button != 0 && !IS_SYSEVENT(button)) button = ACTION_WPS_STOPSEEK; } } return usb; } -#if defined(HAVE_BACKLIGHT) || defined(HAVE_REMOTE_LCD) static void gwps_caption_backlight(struct wps_state *state) { - if (state && state->id3) +#if defined(HAVE_BACKLIGHT) || defined(HAVE_REMOTE_LCD) + if (state->id3) { #ifdef HAVE_BACKLIGHT if (global_settings.caption_backlight) @@ -366,9 +368,10 @@ static void gwps_caption_backlight(struct wps_state *state) } #endif } +#else + (void) state; +#endif /* def HAVE_BACKLIGHT || def HAVE_REMOTE_LCD */ } -#endif - static void change_dir(int direction) { @@ -385,7 +388,7 @@ static void change_dir(int direction) static void prev_track(unsigned long skip_thresh) { - struct wps_state *state = skin_get_global_state(); + struct wps_state *state = get_wps_state(); if (state->id3->elapsed < skip_thresh) { audio_prev(); @@ -406,7 +409,7 @@ static void prev_track(unsigned long skip_thresh) static void next_track(void) { - struct wps_state *state = skin_get_global_state(); + struct wps_state *state = get_wps_state(); /* take care of if we're playing a cuesheet */ if (state->id3->cuesheet) { @@ -423,7 +426,7 @@ static void next_track(void) static void play_hop(int direction) { - struct wps_state *state = skin_get_global_state(); + struct wps_state *state = get_wps_state(); struct cuesheet *cue = state->id3->cuesheet; long step = global_settings.skip_length*1000; long elapsed = state->id3->elapsed; @@ -442,26 +445,40 @@ static void play_hop(int direction) { if (direction < 0) { - prev_track(DEFAULT_SKIP_TRESH); + prev_track(DEFAULT_SKIP_THRESH); return; } - else if (remaining < DEFAULT_SKIP_TRESH*2) + else if (remaining < DEFAULT_SKIP_THRESH*2) { next_track(); return; } else - elapsed += (remaining - DEFAULT_SKIP_TRESH*2); + elapsed += (remaining - DEFAULT_SKIP_THRESH*2); } else if (!global_settings.prevent_skip && (!step || (direction > 0 && step >= remaining) || - (direction < 0 && elapsed < DEFAULT_SKIP_TRESH))) + (direction < 0 && elapsed < DEFAULT_SKIP_THRESH))) { /* Do normal track skipping */ if (direction > 0) next_track(); else if (direction < 0) - prev_track(DEFAULT_SKIP_TRESH); + { + if (step > 0 && global_settings.rewind_across_tracks && elapsed < DEFAULT_SKIP_THRESH && playlist_check(-1)) + { + bool audio_paused = (audio_status() & AUDIO_STATUS_PAUSE)?true:false; + if (!audio_paused) + audio_pause(); + audio_prev(); + audio_ff_rewind(-step); + if (!audio_paused) + audio_resume(); + return; + } + + prev_track(DEFAULT_SKIP_THRESH); + } return; } else if (direction == 1 && step >= remaining) @@ -485,7 +502,6 @@ static void play_hop(int direction) audio_ff_rewind(elapsed); } - #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) /* * If the user is unable to see the wps, because the display is deactivated, @@ -502,16 +518,19 @@ static void wps_lcd_activation_hook(unsigned short id, void *param) } #endif -static void gwps_leave_wps(void) +static void gwps_leave_wps(bool theme_enabled) { FOR_NB_SCREENS(i) { - skin_get_gwps(WPS, i)->display->scroll_stop(); + struct gui_wps *gwps = skin_get_gwps(WPS, i); + gwps->display->scroll_stop(); + if (theme_enabled) + { #ifdef HAVE_BACKDROP_IMAGE - skin_backdrop_show(sb_get_backdrop(i)); + skin_backdrop_show(sb_get_backdrop(i)); #endif - viewportmanager_theme_undo(i, skin_has_sbs(i, skin_get_gwps(WPS, i)->data)); - + viewportmanager_theme_undo(i, skin_has_sbs(gwps)); + } } #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) @@ -525,19 +544,30 @@ static void gwps_leave_wps(void) #endif } +static void restore_theme(void) +{ + FOR_NB_SCREENS(i) + { + struct gui_wps *gwps = skin_get_gwps(WPS, i); + struct screen *display = gwps->display; + display->scroll_stop(); + viewportmanager_theme_enable(i, skin_has_sbs(gwps), NULL); + } +} + /* * display the wps on entering or restoring */ -static void gwps_enter_wps(void) +static void gwps_enter_wps(bool theme_enabled) { struct gui_wps *gwps; struct screen *display; + if (theme_enabled) + restore_theme(); FOR_NB_SCREENS(i) { gwps = skin_get_gwps(WPS, i); display = gwps->display; display->scroll_stop(); - viewportmanager_theme_enable(i, skin_has_sbs(i, skin_get_gwps(WPS, i)->data), NULL); - /* Update the values in the first (default) viewport - in case the user has modified the statusbar or colour settings */ #if LCD_DEPTH > 1 @@ -563,7 +593,7 @@ static void gwps_enter_wps(void) } #ifdef HAVE_TOUCHSCREEN gwps = skin_get_gwps(WPS, SCREEN_MAIN); - skin_disarm_touchregions(gwps->data); + skin_disarm_touchregions(gwps); if (gwps->data->touchregions < 0) touchscreen_set_mode(TOUCHSCREEN_BUTTON); #endif @@ -573,16 +603,16 @@ static void gwps_enter_wps(void) void wps_do_playpause(bool updatewps) { - struct wps_state *state = skin_get_global_state(); + struct wps_state *state = get_wps_state(); if ( state->paused ) { state->paused = false; - unpause_action(true, updatewps); + unpause_action(updatewps); } else { state->paused = true; - pause_action(true, updatewps); + pause_action(updatewps); settings_save(); #if !defined(HAVE_SW_POWEROFF) call_storage_idle_notifys(true); /* make sure resume info is saved */ @@ -590,6 +620,57 @@ void wps_do_playpause(bool updatewps) } } +static long do_wps_exit(long action, bool bookmark) +{ + audio_pause(); + update_non_static(); + if (bookmark) + bookmark_autobookmark(true); + audio_stop(); + + ab_reset_markers(); + + gwps_leave_wps(true); +#ifdef HAVE_RECORDING + if (action == ACTION_WPS_REC) + return GO_TO_RECSCREEN; +#else + (void)action; +#endif + if (global_settings.browse_current) + return GO_TO_PREVIOUS_BROWSER; + return GO_TO_PREVIOUS; +} + +static long do_party_mode(long action) +{ + if (global_settings.party_mode) + { + switch (action) + { +#ifdef ACTION_WPSAB_SINGLE + case ACTION_WPSAB_SINGLE: + if (!ab_repeat_mode_enabled()) + break; + /* Note: currently all targets use ACTION_WPS_BROWSE + * if mapped to any of below actions this will cause problems */ +#endif + case ACTION_WPS_PLAY: + case ACTION_WPS_SEEKFWD: + case ACTION_WPS_SEEKBACK: + case ACTION_WPS_SKIPPREV: + case ACTION_WPS_SKIPNEXT: + case ACTION_WPS_ABSETB_NEXTDIR: + case ACTION_WPS_ABSETA_PREVDIR: + case ACTION_WPS_STOP: + return ACTION_NONE; + break; + default: + break; + } + } + return action; +} /* The WPS can be left in two ways: * a) call a function, which draws over the wps. In this case, the wps @@ -597,31 +678,28 @@ void wps_do_playpause(bool updatewps) * b) return with a value evaluated by root_menu.c, in this case the wps * is really left, and root_menu will handle the next screen * - * In either way, call gwps_leave_wps(), in order to restore the correct + * In either way, call gwps_leave_wps(true), in order to restore the correct * "main screen" backdrops and statusbars */ long gui_wps_show(void) { long button = 0; bool restore = true; - long restoretimer = RESTORE_WPS_INSTANTLY; /* timer to delay screen redraw temporarily */ bool exit = false; bool bookmark = false; bool update = false; - bool vol_changed = false; + bool theme_enabled = true; long last_left = 0, last_right = 0; - struct wps_state *state = skin_get_global_state(); + struct wps_state *state = get_wps_state(); -#ifdef AB_REPEAT_ENABLE ab_repeat_init(); ab_reset_markers(); -#endif - wps_state_init(); + wps_state_init(); while ( 1 ) { + bool hotkey = false; bool audio_paused = (audio_status() & AUDIO_STATUS_PAUSE)?true:false; - /* did someone else (i.e power thread) change audio pause mode? */ if (state->paused != audio_paused) { state->paused = audio_paused; @@ -635,8 +713,53 @@ long gui_wps_show(void) #endif } } - button = skin_wait_for_action(WPS, CONTEXT_WPS|ALLOW_SOFTLOCK, - restore ? 1 : HZ/5); + + if (restore) + { + restore = false; +#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) + add_event(LCD_EVENT_ACTIVATION, wps_lcd_activation_hook); +#endif + /* we remove the update delay since it's not very usable in the wps, + * e.g. during volume changing or ffwd/rewind */ + sb_skin_set_update_delay(0); + skin_request_full_update(WPS); + update = true; + gwps_enter_wps(theme_enabled); + theme_enabled = true; + } + else + { + gwps_caption_backlight(state); + + FOR_NB_SCREENS(i) + { +#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) + /* currently, all remotes are readable without backlight + * so still update those */ + if (lcd_active() || (i != SCREEN_MAIN)) +#endif + { + bool full_update = skin_do_full_update(WPS, i); + if (update || full_update) + { + skin_update(WPS, i, full_update ? + SKIN_REFRESH_ALL : SKIN_REFRESH_NON_STATIC); + } + } + } + update = false; + } + + if (exit) + { + return do_wps_exit(button, bookmark); + } + + if (button && !IS_SYSEVENT(button) ) + storage_spin(); + + button = skin_wait_for_action(WPS, CONTEXT_WPS|ALLOW_SOFTLOCK, HZ/5); /* Exit if audio has stopped playing. This happens e.g. at end of playlist or if using the sleep timer. */ @@ -644,46 +767,64 @@ long gui_wps_show(void) exit = true; #ifdef HAVE_TOUCHSCREEN if (button == ACTION_TOUCHSCREEN) - button = skintouch_to_wps(skin_get_gwps(WPS, SCREEN_MAIN)->data); + button = skintouch_to_wps(); #endif + button = do_party_mode(button); /* block select actions in party mode */ + /* The iPods/X5/M5 use a single button for the A-B mode markers, defined as ACTION_WPSAB_SINGLE in their config files. */ #ifdef ACTION_WPSAB_SINGLE - if (!global_settings.party_mode && ab_repeat_mode_enabled()) + static int wps_ab_state = 0; + if (button == ACTION_WPSAB_SINGLE && ab_repeat_mode_enabled()) { - static int wps_ab_state = 0; - if (button == ACTION_WPSAB_SINGLE) + switch (wps_ab_state) { - switch (wps_ab_state) - { - case 0: /* set the A spot */ - button = ACTION_WPS_ABSETA_PREVDIR; - break; - case 1: /* set the B spot */ - button = ACTION_WPS_ABSETB_NEXTDIR; - break; - case 2: - button = ACTION_WPS_ABRESET; - break; - } - wps_ab_state = (wps_ab_state+1) % 3; + case 0: /* set the A spot */ + button = ACTION_WPS_ABSETA_PREVDIR; + break; + case 1: /* set the B spot */ + button = ACTION_WPS_ABSETB_NEXTDIR; + break; + case 2: + button = ACTION_WPS_ABRESET; + break; } + wps_ab_state = (wps_ab_state+1) % 3; } -#endif +#endif /* def ACTION_WPSAB_SINGLE */ + switch(button) { #ifdef HAVE_HOTKEY case ACTION_WPS_HOTKEY: + { + hotkey = true; if (!global_settings.hotkey_wps) break; - /* fall through */ -#endif + if (get_hotkey(global_settings.hotkey_wps)->flags & HOTKEY_FLAG_NOSBS) + { + /* leave WPS without re-enabling theme */ + theme_enabled = false; + gwps_leave_wps(theme_enabled); + onplay(state->id3->path, + FILE_ATTR_AUDIO, CONTEXT_WPS, hotkey); + if (!audio_status()) + { + /* re-enable theme since we're returning to SBS */ + gwps_leave_wps(true); + return GO_TO_ROOT; + } + restore = true; + break; + } + } + /* fall through */ +#endif /* def HAVE_HOTKEY */ case ACTION_WPS_CONTEXT: { - bool hotkey = button == ACTION_WPS_HOTKEY; - gwps_leave_wps(); + gwps_leave_wps(true); int retval = onplay(state->id3->path, - FILE_ATTR_AUDIO, CONTEXT_WPS, hotkey); + FILE_ATTR_AUDIO, CONTEXT_WPS, hotkey); /* if music is stopped in the context menu we want to exit the wps */ if (retval == ONPLAY_MAINMENU || !audio_status()) @@ -691,39 +832,46 @@ long gui_wps_show(void) else if (retval == ONPLAY_PLAYLIST) return GO_TO_PLAYLIST_VIEWER; else if (retval == ONPLAY_PLUGIN) - return GO_TO_PLUGIN; + { + restore_theme(); + theme_enabled = false; + open_plugin_run(ID2P(LANG_OPEN_PLUGIN_SET_WPS_CONTEXT_PLUGIN)); + } + restore = true; } break; case ACTION_WPS_BROWSE: - gwps_leave_wps(); + gwps_leave_wps(true); return GO_TO_PREVIOUS_BROWSER; break; /* play/pause */ case ACTION_WPS_PLAY: - if (global_settings.party_mode) - break; wps_do_playpause(true); break; - case ACTION_WPS_VOLUP: - global_settings.volume += sound_steps(SOUND_VOLUME); - vol_changed = true; - break; + case ACTION_WPS_VOLUP: /* fall through */ case ACTION_WPS_VOLDOWN: - global_settings.volume -= sound_steps(SOUND_VOLUME); - vol_changed = true; + if (button == ACTION_WPS_VOLUP) + adjust_volume(1); + else + adjust_volume(-1); + + setvol(); + FOR_NB_SCREENS(i) + { + skin_update(WPS, i, SKIN_REFRESH_NON_STATIC); + } + update = false; break; /* fast forward OR next dir if this is straight after ACTION_WPS_SKIPNEXT */ case ACTION_WPS_SEEKFWD: - if (global_settings.party_mode) - break; if (current_tick -last_right < HZ) { - if (state->id3->cuesheet) + if (state->id3->cuesheet && playlist_check(1)) { audio_next(); } @@ -733,37 +881,42 @@ long gui_wps_show(void) } } else - ffwd_rew(ACTION_WPS_SEEKFWD); + ffwd_rew(ACTION_WPS_SEEKFWD, false); last_right = last_left = 0; break; /* fast rewind OR prev dir if this is straight after ACTION_WPS_SKIPPREV,*/ case ACTION_WPS_SEEKBACK: - if (global_settings.party_mode) - break; - if (current_tick -last_left < HZ) + if (current_tick - last_left < HZ) { - if (state->id3->cuesheet) + if (state->id3->cuesheet && playlist_check(-1)) { - audio_pre_ff_rewind(); - audio_ff_rewind(0); + audio_prev(); } else { change_dir(-1); } + } else if (global_settings.rewind_across_tracks + && get_wps_state()->id3->elapsed < DEFAULT_SKIP_THRESH + && playlist_check(-1)) + { + if (!audio_paused) + audio_pause(); + audio_prev(); + ffwd_rew(ACTION_WPS_SEEKBACK, true); + if (!audio_paused) + audio_resume(); } else - ffwd_rew(ACTION_WPS_SEEKBACK); + ffwd_rew(ACTION_WPS_SEEKBACK, false); last_left = last_right = 0; break; /* prev / restart */ case ACTION_WPS_SKIPPREV: - if (global_settings.party_mode) - break; last_left = current_tick; -#ifdef AB_REPEAT_ENABLE + /* if we're in A/B repeat mode and the current position is past the A marker, jump back to the A marker... */ if ( ab_repeat_mode_enabled() && ab_after_A_marker(state->id3->elapsed) ) @@ -771,19 +924,15 @@ long gui_wps_show(void) ab_jump_to_A_marker(); break; } - else - /* ...otherwise, do it normally */ -#endif + else /* ...otherwise, do it normally */ play_hop(-1); break; /* next OR if skip length set, hop by predetermined amount. */ case ACTION_WPS_SKIPNEXT: - if (global_settings.party_mode) - break; last_right = current_tick; -#ifdef AB_REPEAT_ENABLE + /* if we're in A/B repeat mode and the current position is before the A marker, jump to the A marker... */ if ( ab_repeat_mode_enabled() ) @@ -794,43 +943,33 @@ long gui_wps_show(void) break; } } - else - /* ...otherwise, do it normally */ -#endif + else /* ...otherwise, do it normally */ play_hop(1); break; /* next / prev directories */ /* and set A-B markers if in a-b mode */ case ACTION_WPS_ABSETB_NEXTDIR: - if (global_settings.party_mode) - break; -#if defined(AB_REPEAT_ENABLE) if (ab_repeat_mode_enabled()) { ab_set_B_marker(state->id3->elapsed); ab_jump_to_A_marker(); } else -#endif { change_dir(1); } break; case ACTION_WPS_ABSETA_PREVDIR: - if (global_settings.party_mode) - break; -#if defined(AB_REPEAT_ENABLE) if (ab_repeat_mode_enabled()) ab_set_A_marker(state->id3->elapsed); else -#endif { change_dir(-1); } break; /* menu key functions */ case ACTION_WPS_MENU: - gwps_leave_wps(); + gwps_leave_wps(true); return GO_TO_ROOT; break; @@ -838,16 +977,25 @@ long gui_wps_show(void) #ifdef HAVE_QUICKSCREEN case ACTION_WPS_QUICKSCREEN: { - gwps_leave_wps(); - if (global_settings.shortcuts_replaces_qs) + gwps_leave_wps(true); + bool enter_shortcuts_menu = global_settings.shortcuts_replaces_qs; + if (!enter_shortcuts_menu) { - global_status.last_screen = GO_TO_SHORTCUTMENU; int ret = quick_screen_quick(button); + if (ret == QUICKSCREEN_IN_USB) + return GO_TO_ROOT; + else if (ret == QUICKSCREEN_GOTO_SHORTCUTS_MENU) + enter_shortcuts_menu = true; + else + restore = true; + } + + if (enter_shortcuts_menu) /* enter_shortcuts_menu */ + { + global_status.last_screen = GO_TO_SHORTCUTMENU; + int ret = do_shortcut_menu(NULL); return (ret == GO_TO_PREVIOUS ? GO_TO_WPS : ret); } - else if (quick_screen_quick(button) > 0) - return GO_TO_ROOT; - restore = true; } break; #endif /* HAVE_QUICKSCREEN */ @@ -858,7 +1006,7 @@ long gui_wps_show(void) #ifdef HAVE_PITCHCONTROL case ACTION_WPS_PITCHSCREEN: { - gwps_leave_wps(); + gwps_leave_wps(true); if (1 == gui_syncpitchscreen_run()) return GO_TO_ROOT; restore = true; @@ -866,7 +1014,6 @@ long gui_wps_show(void) break; #endif /* HAVE_PITCHCONTROL */ -#ifdef AB_REPEAT_ENABLE /* reset A&B markers */ case ACTION_WPS_ABRESET: if (ab_repeat_mode_enabled()) @@ -875,18 +1022,15 @@ long gui_wps_show(void) update = true; } break; -#endif /* AB_REPEAT_ENABLE */ /* stop and exit wps */ case ACTION_WPS_STOP: - if (global_settings.party_mode) - break; bookmark = true; exit = true; break; case ACTION_WPS_LIST_BOOKMARKS: - gwps_leave_wps(); + gwps_leave_wps(true); if (bookmark_load_menu() == BOOKMARK_USB_CONNECTED) { return GO_TO_ROOT; @@ -895,17 +1039,17 @@ long gui_wps_show(void) break; case ACTION_WPS_CREATE_BOOKMARK: - gwps_leave_wps(); + gwps_leave_wps(true); bookmark_create_menu(); restore = true; break; case ACTION_WPS_ID3SCREEN: { - gwps_leave_wps(); + gwps_leave_wps(true); if (browse_id3(audio_current_track(), playlist_get_display_index(), - playlist_amount())) + playlist_amount(), NULL, 1)) return GO_TO_ROOT; restore = true; } @@ -917,7 +1061,7 @@ long gui_wps_show(void) break; case ACTION_NONE: /* Timeout, do a partial update */ update = true; - ffwd_rew(button); /* hopefully fix the ffw/rwd bug */ + ffwd_rew(button, false); /* hopefully fix the ffw/rwd bug */ break; #ifdef HAVE_RECORDING case ACTION_WPS_REC: @@ -925,7 +1069,7 @@ long gui_wps_show(void) break; #endif case ACTION_WPS_VIEW_PLAYLIST: - gwps_leave_wps(); + gwps_leave_wps(true); return GO_TO_PLAYLIST_VIEWER; break; default: @@ -934,99 +1078,25 @@ long gui_wps_show(void) case SYS_USB_CONNECTED: case SYS_CALL_INCOMING: case BUTTON_MULTIMEDIA_STOP: - gwps_leave_wps(); + gwps_leave_wps(true); return GO_TO_ROOT; } update = true; break; } - - if (vol_changed) - { - bool res = false; - vol_changed = false; - setvol(); - FOR_NB_SCREENS(i) - { - if(update_onvol_change(i)) - res = true; - } - if (res) { - restore = true; - restoretimer = RESTORE_WPS_NEXT_SECOND; - } - } - - - if (restore && - ((restoretimer == RESTORE_WPS_INSTANTLY) || - TIME_AFTER(current_tick, restoretimer))) - { - restore = false; - restoretimer = RESTORE_WPS_INSTANTLY; -#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) - add_event(LCD_EVENT_ACTIVATION, wps_lcd_activation_hook); -#endif - /* we remove the update delay since it's not very usable in the wps, - * e.g. during volume changing or ffwd/rewind */ - sb_skin_set_update_delay(0); - skin_request_full_update(WPS); - update = true; - gwps_enter_wps(); - } - else - { -#if defined(HAVE_BACKLIGHT) || defined(HAVE_REMOTE_LCD) - gwps_caption_backlight(state); -#endif - FOR_NB_SCREENS(i) - { -#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) - /* currently, all remotes are readable without backlight - * so still update those */ - if (lcd_active() || (i != SCREEN_MAIN)) -#endif - { - bool full_update = skin_do_full_update(WPS, i); - if (update || full_update) - { - skin_update(WPS, i, full_update ? - SKIN_REFRESH_ALL : SKIN_REFRESH_NON_STATIC); - } - } - } - update = false; - } - - if (exit) { - audio_pause(); - update_non_static(); - if (bookmark) - bookmark_autobookmark(true); - audio_stop(); -#ifdef AB_REPEAT_ENABLE - ab_reset_markers(); -#endif - gwps_leave_wps(); -#ifdef HAVE_RECORDING - if (button == ACTION_WPS_REC) - return GO_TO_RECSCREEN; -#endif - if (global_settings.browse_current) - return GO_TO_PREVIOUS_BROWSER; - return GO_TO_PREVIOUS; - } - - if (button && !IS_SYSEVENT(button) ) - storage_spin(); } return GO_TO_ROOT; /* unreachable - just to reduce compiler warnings */ } +struct wps_state *get_wps_state(void) +{ + return &wps_state; +} + /* this is called from the playback thread so NO DRAWING! */ static void track_info_callback(unsigned short id, void *param) { - struct wps_state *state = skin_get_global_state(); + struct wps_state *state = get_wps_state(); if (id == PLAYBACK_EVENT_TRACK_CHANGE || id == PLAYBACK_EVENT_CUR_TRACK_READY) { @@ -1042,14 +1112,13 @@ static void track_info_callback(unsigned short id, void *param) state->id3 = audio_current_track(); } #endif - skin_get_global_state()->nid3 = audio_next_track(); + state->nid3 = audio_next_track(); skin_request_full_update(WPS); } static void wps_state_init(void) { - struct wps_state *state = skin_get_global_state(); - state->ff_rewind = false; + struct wps_state *state = get_wps_state(); state->paused = false; if(audio_status() & AUDIO_STATUS_PLAY) { @@ -1073,16 +1142,3 @@ static void wps_state_init(void) add_event(PLAYBACK_EVENT_TRACK_SKIP, track_info_callback); #endif } - - -#ifdef IPOD_ACCESSORY_PROTOCOL -bool is_wps_fading(void) -{ - return skin_get_global_state()->is_fading; -} - -int wps_get_ff_rewind_count(void) -{ - return skin_get_global_state()->ff_rewind_count; -} -#endif diff --git a/apps/gui/wps.h b/apps/gui/wps.h index a463b0e9bb..001c112a4d 100644 --- a/apps/gui/wps.h +++ b/apps/gui/wps.h @@ -20,35 +20,30 @@ ****************************************************************************/ #ifndef _WPS_H_ #define _WPS_H_ + #include <stdbool.h> -#include "config.h" -#include "screen_access.h" - -long gui_wps_show(void); - -/* wrapper for the wps to load the skin (.wps/.rwps) files */ -void wps_data_load(enum screen_type, const char *, bool); -void gui_sync_wps_init(void) INIT_ATTR; +struct mp3entry; -/* fade (if enabled) and pause the audio, optionally rewind a little */ -void pause_action(bool may_fade, bool updatewps); -void unpause_action(bool may_fade, bool updatewps); +/* Please don't add anything else to here... */ +struct wps_state +{ + struct mp3entry *id3; + struct mp3entry *nid3; + int ff_rewind_count; + bool paused; +}; -/* fades the volume, e.g. on pause or stop */ -void fade(bool fade_in, bool updatewps); +long gui_wps_show(void); -bool ffwd_rew(int button); +/* fade (if enabled) and pause the audio, optionally rewind a little */ +void pause_action(bool updatewps); +void unpause_action(bool updatewps); void wps_do_playpause(bool updatewps); -#ifdef IPOD_ACCESSORY_PROTOCOL -/* whether the wps is fading the volume due to pausing/stopping */ -bool is_wps_fading(void); -/* return length of the current ff or rewin action, IAP needs this */ -int wps_get_ff_rewind_count(void); -#endif /* IPOD_ACCESSORY_PROTOCOL */ +struct wps_state *get_wps_state(void); /* in milliseconds */ -#define DEFAULT_SKIP_TRESH 3000l +#define DEFAULT_SKIP_THRESH 3000l #endif /* _WPS_H_ */ diff --git a/apps/gui/yesno.c b/apps/gui/yesno.c index a79b8ae644..a0fd908727 100644 --- a/apps/gui/yesno.c +++ b/apps/gui/yesno.c @@ -30,6 +30,8 @@ #include "viewport.h" #include "appevents.h" +#include <stdio.h> +#include "splash.h" struct gui_yesno { @@ -38,6 +40,9 @@ struct gui_yesno struct viewport *vp; struct screen * display; + /* timeout data */ + long end_tick; + enum yesno_res tmo_default_res; }; static void talk_text_message(const struct text_message * message, bool enqueue) @@ -80,8 +85,10 @@ static void gui_yesno_draw(struct gui_yesno * yn) struct viewport *vp = yn->vp; int nb_lines, vp_lines, line_shift=0; struct viewport *last_vp; + enum yesno_res def_res = yn->tmo_default_res; + long end_tick = yn->end_tick; - last_vp = display->set_viewport(vp); + last_vp = display->set_viewport_ex(vp, VP_FLAG_VP_SET_CLEAN); display->clear_viewport(); nb_lines = yn->main_message->nb_lines; vp_lines = viewport_get_nb_lines(vp); @@ -91,20 +98,53 @@ static void gui_yesno_draw(struct gui_yesno * yn) line_shift += put_message(display, yn->main_message, line_shift, vp_lines); + #ifdef HAVE_TOUCHSCREEN if (display->screen_type == SCREEN_MAIN) { - int w,h; + int w,h,tmo_w; + int tm_rem = 0; + const char *btn_fmt; int rect_w = vp->width/2, rect_h = vp->height/2; int old_pattern = vp->fg_pattern; vp->fg_pattern = LCD_RGBPACK(0,255,0); display->drawrect(0, rect_h, rect_w, rect_h); display->getstringsize(str(LANG_SET_BOOL_YES), &w, &h); - display->putsxy((rect_w-w)/2, rect_h+(rect_h-h)/2, str(LANG_SET_BOOL_YES)); + + if (def_res == YESNO_YES) + { + display->getstringsize(" (0)", &tmo_w, NULL); + tm_rem = ((end_tick - current_tick) / 100); + btn_fmt = "%s (%d)"; + } + else + { + btn_fmt = "%s\0%d"; + tmo_w = 0; + } + + display->putsxyf((rect_w-(w+tmo_w))/2, rect_h+(rect_h-h)/2, + btn_fmt, str(LANG_SET_BOOL_YES), tm_rem); + vp->fg_pattern = LCD_RGBPACK(255,0,0); display->drawrect(rect_w, rect_h, rect_w, rect_h); display->getstringsize(str(LANG_SET_BOOL_NO), &w, &h); - display->putsxy(rect_w + (rect_w-w)/2, rect_h+(rect_h-h)/2, str(LANG_SET_BOOL_NO)); + + if (def_res == YESNO_NO) + { + display->getstringsize(" (0)", &tmo_w, NULL); + tm_rem = ((end_tick - current_tick) / 100); + btn_fmt = "%s (%d)"; + } + else + { + btn_fmt = "%s\0%d"; + tmo_w = 0; + } + + display->putsxyf(rect_w + (rect_w-(w+tmo_w))/2, rect_h+(rect_h-h)/2, + btn_fmt, str(LANG_SET_BOOL_NO), tm_rem); + vp->fg_pattern = old_pattern; } #else @@ -115,6 +155,15 @@ static void gui_yesno_draw(struct gui_yesno * yn) line_shift++; display->puts(0, line_shift, str(LANG_CONFIRM_WITH_BUTTON)); display->puts(0, line_shift+1, str(LANG_CANCEL_WITH_ANY)); + + if (def_res == YESNO_YES || def_res == YESNO_NO) + { + int tm_rem = ((end_tick - current_tick) / 100); + if (def_res == YESNO_YES) + display->putsf(0, line_shift, "%s (%d)", str(LANG_CONFIRM_WITH_BUTTON), tm_rem); + else + display->putsf(0, line_shift+1, "%s (%d)", str(LANG_CANCEL_WITH_ANY), tm_rem); + } } #endif display->update_viewport(); @@ -124,7 +173,7 @@ static void gui_yesno_draw(struct gui_yesno * yn) /* * Draws the yesno result * - yn : the yesno structure - * - result : the result tha must be displayed : + * - result : the result to be displayed : * YESNO_NO if no * YESNO_YES if yes */ @@ -133,9 +182,10 @@ static bool gui_yesno_draw_result(struct gui_yesno * yn, enum yesno_res result) const struct text_message * message=yn->result_message[result]; struct viewport *vp = yn->vp; struct screen * display=yn->display; + struct viewport *last_vp = display->set_viewport_ex(vp, VP_FLAG_VP_SET_CLEAN); + if(message==NULL) return false; - struct viewport *last_vp = display->set_viewport(vp); display->clear_viewport(); put_message(yn->display, message, 0, viewport_get_nb_lines(vp)); display->update_viewport(); @@ -153,18 +203,44 @@ static void gui_yesno_ui_update(unsigned short id, void *event_data, void *user_ gui_yesno_draw(&yn[i]); } -enum yesno_res gui_syncyesno_run(const struct text_message * main_message, - const struct text_message * yes_message, - const struct text_message * no_message) +/* Display a YES_NO prompt to the user + * + * ticks < HZ will be ignored and the prompt will be blocking + * tmo_default_res is the answer that is returned when the timeout expires + * a default result of YESNO_TMO will also make the prompt blocking + * if tmo_default_res is YESNO_YES or YESNO_NO a seconds countdown will + * be present next to the default option + * + * ticks - timeout if (>=HZ) otherwise ignored + * default_res - result returned on timeout YESNO_TMO creates a blocking prompt + * main_message - prompt to the user + * yes_message - displayed when YESNO_YES is choosen + * no_message - displayed when YESNO_NO is choosen +*/ +enum yesno_res gui_syncyesno_run_w_tmo(int ticks, enum yesno_res tmo_default_res, + const struct text_message * main_message, + const struct text_message * yes_message, + const struct text_message * no_message) { int button; int result=-1; - bool result_displayed; + bool result_displayed = false; struct gui_yesno yn[NB_SCREENS]; struct viewport vp[NB_SCREENS]; long talked_tick = 0; + long end_tick = current_tick + ticks; + long button_scan_tmo = HZ/2; + + if (ticks < HZ) /* Display a prompt with NO timeout to the user */ + { + tmo_default_res = YESNO_TMO; + } + FOR_NB_SCREENS(i) { + yn[i].end_tick = end_tick; + yn[i].tmo_default_res = tmo_default_res; + yn[i].main_message=main_message; yn[i].result_message[YESNO_YES]=yes_message; yn[i].result_message[YESNO_NO]=no_message; @@ -198,7 +274,11 @@ enum yesno_res gui_syncyesno_run(const struct text_message * main_message, talked_tick = current_tick; talk_text_message(main_message, false); } - button = get_action(CONTEXT_YESNOSCREEN, HZ*5); + FOR_NB_SCREENS(i) + gui_yesno_draw(&yn[i]); + + button = get_action(CONTEXT_YESNOSCREEN, button_scan_tmo); + switch (button) { #ifdef HAVE_TOUCHSCREEN @@ -222,6 +302,13 @@ enum yesno_res gui_syncyesno_run(const struct text_message * main_message, result=YESNO_YES; break; case ACTION_NONE: + if(tmo_default_res != YESNO_TMO && TIME_AFTER(current_tick, end_tick)) + { + splash(HZ/2, ID2P(LANG_TIMEOUT)); + result = tmo_default_res; + break; + } + /*fall-through*/ case ACTION_UNKNOWN: case SYS_CHARGER_DISCONNECTED: case SYS_BATTERY_UPDATE: @@ -250,6 +337,11 @@ enum yesno_res gui_syncyesno_run(const struct text_message * main_message, : no_message, false); talk_force_enqueue_next(); } + + + exit: + remove_event_ex(GUI_EVENT_NEED_UI_UPDATE, gui_yesno_ui_update, &yn[0]); + if(result_displayed) sleep(HZ); @@ -259,14 +351,19 @@ enum yesno_res gui_syncyesno_run(const struct text_message * main_message, viewportmanager_theme_undo(i, true); } - exit: - remove_event_ex(GUI_EVENT_NEED_UI_UPDATE, gui_yesno_ui_update, &yn[0]); #ifdef HAVE_TOUCHSCREEN touchscreen_set_mode(old_mode); #endif return result; } +enum yesno_res gui_syncyesno_run(const struct text_message * main_message, + const struct text_message * yes_message, + const struct text_message * no_message) +{ + return gui_syncyesno_run_w_tmo(TIMEOUT_BLOCK, YESNO_TMO, + main_message, yes_message, no_message); +} /* Function to manipulate all yesno dialogues. This function needs the output text as an argument. */ diff --git a/apps/gui/yesno.h b/apps/gui/yesno.h index 61bcf8d3c0..5f67733d79 100644 --- a/apps/gui/yesno.h +++ b/apps/gui/yesno.h @@ -27,7 +27,8 @@ enum yesno_res { YESNO_YES, YESNO_NO, - YESNO_USB + YESNO_USB, + YESNO_TMO }; struct text_message @@ -48,7 +49,13 @@ extern enum yesno_res gui_syncyesno_run( const struct text_message * main_message, const struct text_message * yes_message, const struct text_message * no_message); - + +extern enum yesno_res gui_syncyesno_run_w_tmo( + int ticks, enum yesno_res tmo_default_res, + const struct text_message * main_message, + const struct text_message * yes_message, + const struct text_message * no_message); + bool yesno_pop(const char* text); #endif /* _GUI_YESNO_H_ */ diff --git a/apps/hosted/android/keyboard.c b/apps/hosted/android/keyboard.c index eda951a7c9..b74f67e782 100644 --- a/apps/hosted/android/keyboard.c +++ b/apps/hosted/android/keyboard.c @@ -100,7 +100,7 @@ int kbd_input(char* text, int buflen, unsigned short *kbd) if (accepted) { utf8_string = e->GetStringUTFChars(env_ptr, new_string, 0); - strlcpy(text, utf8_string, buflen); + strmemccpy(text, utf8_string, buflen); e->ReleaseStringUTFChars(env_ptr, new_string, utf8_string); e->DeleteGlobalRef(env_ptr, new_string); } diff --git a/apps/hosted/android/notification.c b/apps/hosted/android/notification.c index 39c8b07737..a5b60c1013 100644 --- a/apps/hosted/android/notification.c +++ b/apps/hosted/android/notification.c @@ -29,6 +29,7 @@ #include "misc.h" #include "thread.h" #include "debug.h" +#include "audio.h" extern JNIEnv *env_ptr; extern jclass RockboxService_class; diff --git a/apps/hosted/android/yesno.c b/apps/hosted/android/yesno.c index bc8672ad76..af7f5a5c7b 100644 --- a/apps/hosted/android/yesno.c +++ b/apps/hosted/android/yesno.c @@ -117,6 +117,17 @@ enum yesno_res gui_syncyesno_run(const struct text_message * main_message, return ret ? YESNO_YES : YESNO_NO; } +enum yesno_res gui_syncyesno_run_w_tmo(int ticks, enum yesno_res tmo_default_res, + const struct text_message * main_message, + const struct text_message * yes_message, + const struct text_message * no_message) +{ + /* FIXME: create a prompt with timeout for android */ + (void)ticks; + (void)tmo_default_res; + return gui_syncyesno_run(main_message, yes_message, no_message); +} + #endif /* Function to manipulate all yesno dialogues. diff --git a/apps/iap/iap-core.c b/apps/iap/iap-core.c index ae05806ae9..da04a67311 100644 --- a/apps/iap/iap-core.c +++ b/apps/iap/iap-core.c @@ -19,8 +19,8 @@ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> -#include <string.h> +#include "string-extra.h" #include "panic.h" #include "iap-core.h" #include "iap-lingo.h" @@ -453,7 +453,7 @@ static void iap_malloc(void) return; #ifdef IAP_MALLOC_DYNAMIC - iap_buffer_handle = core_alloc_ex("iap", IAP_MALLOC_SIZE, &iap_buflib_callbacks); + iap_buffer_handle = core_alloc_ex(IAP_MALLOC_SIZE, &iap_buflib_callbacks); if (iap_buffer_handle < 0) panicf("Could not allocate buffer memory"); iap_buffers = core_get_data(iap_buffer_handle); diff --git a/apps/iap/iap-lingo2.c b/apps/iap/iap-lingo2.c index 946e51222d..51f951c6d9 100644 --- a/apps/iap/iap-lingo2.c +++ b/apps/iap/iap-lingo2.c @@ -187,6 +187,17 @@ void iap_handlepkt_mode2(const unsigned int len, const unsigned char *buf) REMOTE_BUTTON(BUTTON_RC_RIGHT); if(buf[4] & 32) /* frwd */ REMOTE_BUTTON(BUTTON_RC_LEFT); + if(buf[4] & 64) /* menu */ + REMOTE_BUTTON(BUTTON_RC_MENU); + if(buf[4] & 128) /* select */ + REMOTE_BUTTON(BUTTON_RC_SELECT); + } + else if(len >= 6 && buf[5] != 0) + { + if(buf[5] & 1) /* up */ + REMOTE_BUTTON(BUTTON_RC_UP); + if (buf[5] & 2) /* down */ + REMOTE_BUTTON(BUTTON_RC_DOWN); } /* power on released */ diff --git a/apps/iap/iap-lingo4.c b/apps/iap/iap-lingo4.c index 4ec5c462a1..eb629407f2 100644 --- a/apps/iap/iap-lingo4.c +++ b/apps/iap/iap-lingo4.c @@ -24,6 +24,7 @@ #include "filetree.h" #include "wps.h" #include "playback.h" +#include "string-extra.h" /* * This macro is meant to be used inside an IAP mode message handler. @@ -87,7 +88,7 @@ static void get_playlist_name(unsigned char *dest, } } if (playlist_file != NULL) { - strlcpy(dest, playlist_file->d_name, max_length); + strmemccpy(dest, playlist_file->d_name, max_length); } closedir(dp); } @@ -1218,7 +1219,7 @@ void iap_handlepkt_mode4(const unsigned int len, const unsigned char *buf) { memcpy(cur_dbrecord, buf + 3, 5); - int paused = (is_wps_fading() || (audio_status() & AUDIO_STATUS_PAUSE)); + int paused = !!(audio_status() & AUDIO_STATUS_PAUSE); uint32_t index; uint32_t trackcount; index = get_u32(&cur_dbrecord[1]); @@ -1430,7 +1431,6 @@ void iap_handlepkt_mode4(const unsigned int len, const unsigned char *buf) unsigned int number_of_playlists = nbr_total_playlists(); uint32_t trackcount; trackcount = playlist_amount(); - size_t len; if ((buf[3] == 0x05) && ((start_index + read_count ) > trackcount)) { @@ -1465,22 +1465,21 @@ void iap_handlepkt_mode4(const unsigned int len, const unsigned char *buf) switch(buf[3]) { case 0x05: - len = strlcpy((char *)&data[7], id3.title,64); + strmemccpy((char *)&data[7], id3.title,64); break; case 0x02: - len = strlcpy((char *)&data[7], id3.artist,64); + strmemccpy((char *)&data[7], id3.artist,64); break; case 0x03: - len = strlcpy((char *)&data[7], id3.album,64); + strmemccpy((char *)&data[7], id3.album,64); break; case 0x04: case 0x06: - len = strlcpy((char *)&data[7], "Not Supported",14); + strmemccpy((char *)&data[7], "Not Supported",14); break; } break; } - (void)len; /* Shut up, compiler */ put_u32(&data[3], start_index+counter); iap_send_pkt(data, 7 + strlen(data+7) + 1); yield(); @@ -2003,7 +2002,7 @@ void iap_handlepkt_mode4(const unsigned int len, const unsigned char *buf) * */ { - int paused = (is_wps_fading() || (audio_status() & AUDIO_STATUS_PAUSE)); + int paused = !!(audio_status() & AUDIO_STATUS_PAUSE); uint32_t index; uint32_t trackcount; index = get_u32(&buf[3]); @@ -2821,7 +2820,7 @@ void iap_handlepkt_mode4(const unsigned int len, const unsigned char *buf) * */ { - int paused = (is_wps_fading() || (audio_status() & AUDIO_STATUS_PAUSE)); + int paused = !!(audio_status() & AUDIO_STATUS_PAUSE); long tracknum = get_u32(&buf[3]); audio_pause(); @@ -2977,7 +2976,7 @@ void iap_handlepkt_mode4(const unsigned int len, const unsigned char *buf) { memcpy(cur_dbrecord, buf + 3, 5); - int paused = (is_wps_fading() || (audio_status() & AUDIO_STATUS_PAUSE)); + int paused = !!(audio_status() & AUDIO_STATUS_PAUSE); unsigned int number_of_playlists = nbr_total_playlists(); uint32_t index; uint32_t trackcount; diff --git a/apps/keymaps/keymap-agptekrocker.c b/apps/keymaps/keymap-agptekrocker.c index 1fb8465b0a..5ca834ab51 100644 --- a/apps/keymaps/keymap-agptekrocker.c +++ b/apps/keymaps/keymap-agptekrocker.c @@ -139,15 +139,16 @@ static const struct button_mapping button_context_yesno[] = { }; /* button_context_settings_yesno */ static const struct button_mapping button_context_quickscreen[] = { - { ACTION_QS_TOP, BUTTON_UP|BUTTON_REL, BUTTON_NONE }, - { ACTION_QS_TOP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_DOWN, BUTTON_DOWN|BUTTON_REL, BUTTON_NONE }, - { ACTION_QS_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_LEFT, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE }, - { ACTION_QS_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_RIGHT, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE }, - { ACTION_QS_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_SELECT, BUTTON_NONE }, + { ACTION_QS_TOP, BUTTON_UP|BUTTON_REL, BUTTON_NONE }, + { ACTION_QS_TOP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_QS_DOWN, BUTTON_DOWN|BUTTON_REL, BUTTON_NONE }, + { ACTION_QS_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_QS_LEFT, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE }, + { ACTION_QS_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_QS_RIGHT, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE }, + { ACTION_QS_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT }, + { ACTION_STD_CANCEL, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, LAST_ITEM_IN_LIST }; /* button_context_quickscreen */ @@ -220,7 +221,7 @@ static const struct button_mapping button_context_bmark[] = { /* get_context_mapping returns a pointer to one of the above defined arrays depending on the context */ const struct button_mapping* get_context_mapping(int context) { - switch (context) + switch (context & ~CONTEXT_LOCKED) { case CONTEXT_STD: return button_context_standard; diff --git a/apps/keymaps/keymap-clip.c b/apps/keymaps/keymap-clip.c index 3c92f03a07..59ee080364 100644 --- a/apps/keymaps/keymap-clip.c +++ b/apps/keymaps/keymap-clip.c @@ -84,9 +84,9 @@ static const struct button_mapping button_context_wps[] = { { ACTION_WPS_ID3SCREEN, BUTTON_SELECT|BUTTON_DOWN, BUTTON_SELECT }, #ifdef HAVE_HOTKEY /* down|repeat doesn't work in the file browser */ - { ACTION_WPS_HOTKEY, BUTTON_DOWN, BUTTON_NONE }, + { ACTION_WPS_HOTKEY, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_DOWN }, #endif - { ACTION_WPS_VIEW_PLAYLIST, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_WPS_VIEW_PLAYLIST, BUTTON_DOWN|BUTTON_REL, BUTTON_DOWN }, #ifndef HAS_BUTTON_HOLD /* Clip+ */ { ACTION_STD_KEYLOCK, BUTTON_HOME|BUTTON_SELECT, BUTTON_NONE }, @@ -179,7 +179,7 @@ static const struct button_mapping button_context_quickscreen[] = { { ACTION_NONE, BUTTON_LEFT, BUTTON_NONE }, { ACTION_STD_CANCEL, BUTTON_POWER|BUTTON_REL, BUTTON_NONE }, { ACTION_STD_CANCEL, BUTTON_HOME, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_SELECT, BUTTON_NONE }, + { ACTION_STD_CANCEL, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, { ACTION_QS_TOP, BUTTON_UP|BUTTON_REL, BUTTON_NONE }, { ACTION_QS_TOP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_QS_DOWN, BUTTON_DOWN|BUTTON_REL, BUTTON_NONE }, @@ -212,9 +212,11 @@ static const struct button_mapping button_context_pitchscreen[] = { { ACTION_PS_NUDGE_LEFTOFF, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE }, { ACTION_PS_NUDGE_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, { ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE }, - { ACTION_PS_TOGGLE_MODE, BUTTON_HOME|BUTTON_REL, BUTTON_HOME }, - { ACTION_PS_RESET, BUTTON_SELECT, BUTTON_NONE }, + { ACTION_PS_TOGGLE_MODE, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, + { ACTION_PS_RESET, BUTTON_HOME|BUTTON_REPEAT, BUTTON_HOME }, + { ACTION_PS_RESET, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT }, { ACTION_PS_EXIT, BUTTON_POWER, BUTTON_NONE }, + { ACTION_PS_EXIT, BUTTON_HOME|BUTTON_REL, BUTTON_HOME }, { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD), @@ -397,7 +399,7 @@ static const struct button_mapping button_context_usb_hid_mode_mouse[] = { /* get_context_mapping returns a pointer to one of the above defined arrays depending on the context */ const struct button_mapping* get_context_mapping(int context) { - switch (context) + switch (context & ~CONTEXT_LOCKED) { case CONTEXT_STD: return button_context_standard; diff --git a/apps/keymaps/keymap-erosq.c b/apps/keymaps/keymap-erosq.c index d486423a53..054da96201 100644 --- a/apps/keymaps/keymap-erosq.c +++ b/apps/keymaps/keymap-erosq.c @@ -130,6 +130,7 @@ static const struct button_mapping button_context_quickscreen[] = { { ACTION_QS_DOWN, BUTTON_NEXT|BUTTON_REL, BUTTON_NONE }, { ACTION_QS_DOWN, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_STD_CANCEL, BUTTON_BACK, BUTTON_NONE }, + { ACTION_STD_CONTEXT,BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU }, LAST_ITEM_IN_LIST }; /* button_context_quickscreen */ @@ -193,7 +194,7 @@ static const struct button_mapping button_context_bmark[] = { /* get_context_mapping returns a pointer to one of the above defined arrays depending on the context */ const struct button_mapping* get_context_mapping(int context) { - switch (context) + switch (context & ~CONTEXT_LOCKED) { case CONTEXT_STD: return button_context_standard; diff --git a/apps/keymaps/keymap-fiiom3k.c b/apps/keymaps/keymap-fiiom3k.c index d0fbbb2e98..1ccf7e956f 100644 --- a/apps/keymaps/keymap-fiiom3k.c +++ b/apps/keymaps/keymap-fiiom3k.c @@ -175,7 +175,8 @@ static const struct button_mapping button_context_quickscreen[] = { {ACTION_QS_VOLUP, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE}, {ACTION_QS_VOLDOWN, BUTTON_VOL_DOWN, BUTTON_NONE}, {ACTION_QS_VOLDOWN, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE}, - {ACTION_STD_CANCEL, BUTTON_SELECT, BUTTON_NONE}, + {ACTION_STD_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT}, + {ACTION_STD_CANCEL, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT}, {ACTION_STD_CANCEL, BUTTON_POWER, BUTTON_NONE}, {ACTION_STD_CANCEL, BUTTON_BACK, BUTTON_NONE}, {ACTION_STD_CANCEL, BUTTON_MENU, BUTTON_NONE}, @@ -214,10 +215,8 @@ static const struct button_mapping button_context_yesnoscreen[] = { }; /* button_context_yesnoscreen */ static const struct button_mapping button_context_recscreen[] = { - {ACTION_REC_PAUSE, BUTTON_SELECT, BUTTON_NONE}, {ACTION_REC_PAUSE, BUTTON_PLAY, BUTTON_NONE}, - {ACTION_REC_NEWFILE, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT}, - {ACTION_REC_NEWFILE, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY}, + {ACTION_REC_NEWFILE, BUTTON_SELECT, BUTTON_NONE}, {ACTION_STD_MENU, BUTTON_MENU, BUTTON_NONE}, {ACTION_STD_CANCEL, BUTTON_BACK, BUTTON_NONE}, {ACTION_STD_CANCEL, BUTTON_POWER, BUTTON_NONE}, @@ -323,21 +322,14 @@ static const struct button_mapping button_context_usb_hid_mode_browser[] = { const struct button_mapping* get_context_mapping(int context) { - switch (context) - { - case CONTEXT_WPS|CONTEXT_LOCKED: - return button_context_wps_locked; - default: - context &= ~CONTEXT_LOCKED; - break; - } - - switch (context) + switch (context & ~CONTEXT_LOCKED) { default: case CONTEXT_STD: return button_context_standard; case CONTEXT_WPS: + if (context & CONTEXT_LOCKED) + return button_context_wps_locked; return button_context_wps; case CONTEXT_TREE: case CONTEXT_MAINMENU: diff --git a/apps/keymaps/keymap-fiiom3klinux.c b/apps/keymaps/keymap-fiiom3klinux.c index e404d8bfb0..79a7687501 100644 --- a/apps/keymaps/keymap-fiiom3klinux.c +++ b/apps/keymaps/keymap-fiiom3klinux.c @@ -192,7 +192,7 @@ static const struct button_mapping button_context_yesnoscreen[] = { /* get_context_mapping returns a pointer to one of the above defined arrays depending on the context */ const struct button_mapping* get_context_mapping(int context) { - switch (context) + switch (context & ~CONTEXT_LOCKED) { case CONTEXT_LIST: return button_context_list; diff --git a/apps/keymaps/keymap-fuzeplus.c b/apps/keymaps/keymap-fuzeplus.c index 6601316469..052f11085e 100644 --- a/apps/keymaps/keymap-fuzeplus.c +++ b/apps/keymaps/keymap-fuzeplus.c @@ -128,7 +128,8 @@ static const struct button_mapping button_context_keyboard[] = { }; /* button_context_keyboard */ static const struct button_mapping button_context_quickscreen[] = { - { ACTION_STD_CANCEL, BUTTON_SELECT, BUTTON_NONE }, + { ACTION_STD_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT }, + { ACTION_STD_CANCEL, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, { ACTION_STD_CANCEL, BUTTON_BACK, BUTTON_NONE }, { ACTION_STD_CANCEL, BUTTON_PLAYPAUSE, BUTTON_NONE }, { ACTION_STD_CANCEL, BUTTON_BOTTOMRIGHT, BUTTON_NONE }, @@ -406,7 +407,7 @@ static const struct button_mapping button_context_usb_hid_mode_mouse[] = { /* get_context_mapping returns a pointer to one of the above defined arrays depending on the context */ const struct button_mapping* get_context_mapping(int context) { - switch (context) + switch (context & ~CONTEXT_LOCKED) { case CONTEXT_STD: return button_context_standard; diff --git a/apps/keymaps/keymap-ipod.c b/apps/keymaps/keymap-ipod.c index e3a17fffba..aea0c444a2 100644 --- a/apps/keymaps/keymap-ipod.c +++ b/apps/keymaps/keymap-ipod.c @@ -132,7 +132,7 @@ static const struct button_mapping button_context_quickscreen[] = { { ACTION_QS_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_QS_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, { ACTION_QS_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_SELECT, BUTTON_NONE }, + { ACTION_STD_CANCEL, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, { ACTION_QS_VOLDOWN, BUTTON_SCROLL_BACK, BUTTON_NONE }, { ACTION_QS_VOLDOWN, BUTTON_SCROLL_BACK|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_QS_VOLUP, BUTTON_SCROLL_FWD, BUTTON_NONE }, @@ -161,7 +161,7 @@ static const struct button_mapping button_context_pitchscreen[] = { static const struct button_mapping button_context_keyboard[] = { { ACTION_KBD_LEFT, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_KBD_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_KBD_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, { ACTION_KBD_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_KBD_SELECT, BUTTON_SELECT, BUTTON_NONE }, @@ -204,7 +204,7 @@ const struct button_mapping button_context_recscreen[] = { { ACTION_FM_STOP, BUTTON_PLAY | BUTTON_REPEAT, BUTTON_PLAY }, { ACTION_FM_MODE, BUTTON_SELECT, BUTTON_NONE }, { ACTION_FM_EXIT, BUTTON_MENU | BUTTON_REL, BUTTON_MENU }, - { ACTION_FM_PLAY, BUTTON_PLAY | BUTTON_REL, BUTTON_PLAY }, + { ACTION_FM_PLAY, BUTTON_PLAY | BUTTON_REL, BUTTON_PLAY }, { ACTION_SETTINGS_INC, BUTTON_SCROLL_FWD, BUTTON_NONE }, { ACTION_SETTINGS_INCREPEAT,BUTTON_SCROLL_FWD|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_SETTINGS_DEC, BUTTON_SCROLL_BACK, BUTTON_NONE }, @@ -309,11 +309,20 @@ static const struct button_mapping button_context_usb_hid_mode_mouse[] = { *****************************************************************************/ static const struct button_mapping remote_button_context_standard[] = { + { ACTION_STD_PREV, BUTTON_RC_UP, BUTTON_NONE }, + { ACTION_STD_PREVREPEAT, BUTTON_RC_UP|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_NEXT, BUTTON_RC_DOWN, BUTTON_NONE }, + { ACTION_STD_NEXTREPEAT, BUTTON_RC_DOWN|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_PREV, BUTTON_RC_LEFT, BUTTON_NONE }, { ACTION_STD_NEXT, BUTTON_RC_RIGHT, BUTTON_NONE }, { ACTION_STD_CANCEL, BUTTON_RC_STOP, BUTTON_NONE }, { ACTION_STD_OK, BUTTON_RC_PLAY, BUTTON_NONE }, + { ACTION_STD_MENU, BUTTON_RC_MENU|BUTTON_REL, BUTTON_RC_MENU }, + { ACTION_STD_QUICKSCREEN, BUTTON_RC_MENU|BUTTON_REPEAT, BUTTON_RC_MENU }, + { ACTION_STD_CONTEXT, BUTTON_RC_SELECT|BUTTON_REPEAT, BUTTON_RC_SELECT }, + LAST_ITEM_IN_LIST }; /* remote_button_context_standard */ @@ -322,7 +331,7 @@ static const struct button_mapping remote_button_context_wps[] = { { ACTION_WPS_VOLDOWN, BUTTON_RC_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_WPS_VOLUP, BUTTON_RC_VOL_UP, BUTTON_NONE }, { ACTION_WPS_VOLUP, BUTTON_RC_VOL_UP|BUTTON_REPEAT, BUTTON_NONE }, - + // RC_UP and RC_DOWN? { ACTION_WPS_PLAY, BUTTON_RC_PLAY|BUTTON_REL, BUTTON_RC_PLAY }, { ACTION_WPS_STOP, BUTTON_RC_PLAY|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_WPS_SKIPNEXT, BUTTON_RC_RIGHT|BUTTON_REL, BUTTON_RC_RIGHT }, @@ -331,6 +340,12 @@ static const struct button_mapping remote_button_context_wps[] = { { ACTION_WPS_SKIPPREV, BUTTON_RC_LEFT|BUTTON_REL, BUTTON_RC_LEFT }, { ACTION_WPS_SEEKBACK, BUTTON_RC_LEFT|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_WPS_STOPSEEK, BUTTON_RC_LEFT|BUTTON_REL, BUTTON_RC_LEFT|BUTTON_REPEAT }, + { ACTION_WPS_BROWSE, BUTTON_RC_SELECT|BUTTON_REL, BUTTON_RC_SELECT }, + { ACTION_WPS_CONTEXT, BUTTON_RC_SELECT|BUTTON_REPEAT, BUTTON_RC_SELECT }, + { ACTION_WPS_HOTKEY, BUTTON_RC_SELECT|BUTTON_PLAY, BUTTON_NONE }, + { ACTION_WPS_MENU, BUTTON_RC_MENU|BUTTON_REL, BUTTON_RC_MENU }, + { ACTION_WPS_QUICKSCREEN, BUTTON_RC_MENU|BUTTON_REPEAT, BUTTON_RC_MENU }, + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) }; /* remote_button_context_wps */ @@ -338,23 +353,57 @@ static const struct button_mapping remote_button_context_wps[] = { static const struct button_mapping remote_button_context_tree[] = { { ACTION_TREE_WPS, BUTTON_RC_PLAY|BUTTON_REL, BUTTON_RC_PLAY }, { ACTION_TREE_STOP, BUTTON_RC_PLAY|BUTTON_REPEAT, BUTTON_RC_PLAY }, - + { ACTION_TREE_HOTKEY, BUTTON_RC_SELECT|BUTTON_PLAY, BUTTON_NONE }, + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) }; /* remote_button_context_tree */ +static const struct button_mapping remote_button_context_quickscreen[] = { + { ACTION_QS_TOP, BUTTON_RC_MENU, BUTTON_NONE }, + { ACTION_QS_TOP, BUTTON_RC_MENU|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_QS_DOWN, BUTTON_RC_PLAY, BUTTON_NONE }, + { ACTION_QS_DOWN, BUTTON_RC_PLAY|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_QS_LEFT, BUTTON_RC_LEFT, BUTTON_NONE }, + { ACTION_QS_LEFT, BUTTON_RC_LEFT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_QS_RIGHT, BUTTON_RC_RIGHT, BUTTON_NONE }, + { ACTION_QS_RIGHT, BUTTON_RC_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_CANCEL, BUTTON_RC_SELECT|BUTTON_REL, BUTTON_RC_SELECT }, + { ACTION_QS_VOLDOWN, BUTTON_RC_VOL_DOWN, BUTTON_NONE }, + { ACTION_QS_VOLDOWN, BUTTON_RC_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_QS_VOLUP, BUTTON_RC_VOL_UP, BUTTON_NONE }, + { ACTION_QS_VOLUP, BUTTON_RC_VOL_UP|BUTTON_REPEAT, BUTTON_NONE }, + + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) +}; /* button_context_quickscreen */ + #if CONFIG_TUNER static const struct button_mapping remote_button_context_radio[] = { + { ACTION_FM_MENU, BUTTON_RC_SELECT | BUTTON_REPEAT, BUTTON_NONE }, { ACTION_FM_STOP, BUTTON_RC_PLAY | BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_FM_PLAY, BUTTON_RC_PLAY | BUTTON_REL, BUTTON_RC_PLAY }, + { ACTION_FM_MODE, BUTTON_RC_SELECT, BUTTON_NONE }, + { ACTION_FM_EXIT, BUTTON_RC_MENU | BUTTON_REL, BUTTON_RC_MENU }, + + { ACTION_FM_PLAY, BUTTON_RC_PLAY | BUTTON_REL, BUTTON_RC_PLAY }, + { ACTION_SETTINGS_INC, BUTTON_RC_UP, BUTTON_NONE }, + { ACTION_SETTINGS_INCREPEAT,BUTTON_RC_UP|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_SETTINGS_DEC, BUTTON_RC_DOWN, BUTTON_NONE }, + { ACTION_SETTINGS_DECREPEAT,BUTTON_RC_DOWN|BUTTON_REPEAT,BUTTON_NONE }, + { ACTION_STD_NEXT, BUTTON_RC_RIGHT|BUTTON_REL, BUTTON_RC_RIGHT }, { ACTION_STD_NEXTREPEAT, BUTTON_RC_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_STD_PREV, BUTTON_RC_LEFT|BUTTON_REL, BUTTON_RC_LEFT }, { ACTION_STD_PREVREPEAT, BUTTON_RC_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - + LAST_ITEM_IN_LIST }; /* remote_button_context_radio */ #endif +static const struct button_mapping remote_button_context_yesno[] = { + { ACTION_YESNO_ACCEPT, BUTTON_RC_SELECT, BUTTON_NONE }, + { ACTION_STD_CANCEL, BUTTON_RC_PLAY, BUTTON_NONE }, + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) +}; /* button_context_yesno */ + static const struct button_mapping* get_context_mapping_remote( int context ) { context ^= CONTEXT_REMOTE; @@ -364,13 +413,18 @@ static const struct button_mapping* get_context_mapping_remote( int context ) case CONTEXT_WPS: return remote_button_context_wps; case CONTEXT_TREE: + case CONTEXT_MAINMENU: case CONTEXT_CUSTOM|CONTEXT_TREE: return remote_button_context_tree; + case CONTEXT_QUICKSCREEN: + return remote_button_context_quickscreen; #if CONFIG_TUNER case CONTEXT_FM: return remote_button_context_radio; #endif + case CONTEXT_YESNOSCREEN: + return remote_button_context_yesno; default: return remote_button_context_standard; } diff --git a/apps/keymaps/keymap-ma.c b/apps/keymaps/keymap-ma.c index aaf7df0c01..aca006d071 100644 --- a/apps/keymaps/keymap-ma.c +++ b/apps/keymaps/keymap-ma.c @@ -188,7 +188,7 @@ static const struct button_mapping button_context_yesnoscreen[] = { /* get_context_mapping returns a pointer to one of the above defined arrays depending on the context */ const struct button_mapping* get_context_mapping(int context) { - switch (context) + switch (context & ~CONTEXT_LOCKED) { /* anything that uses button_context_standard */ case CONTEXT_LIST: diff --git a/apps/keymaps/keymap-nwz.c b/apps/keymaps/keymap-nwz.c index 028fbf1bfd..36675566d3 100644 --- a/apps/keymaps/keymap-nwz.c +++ b/apps/keymaps/keymap-nwz.c @@ -112,7 +112,8 @@ static const struct button_mapping button_context_keyboard[] = { }; /* button_context_keyboard */ static const struct button_mapping button_context_quickscreen[] = { - { ACTION_STD_CANCEL, BUTTON_PLAY, BUTTON_NONE }, + { ACTION_STD_CONTEXT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY }, + { ACTION_STD_CANCEL, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY }, { ACTION_STD_CANCEL, BUTTON_BACK, BUTTON_NONE }, { ACTION_STD_CANCEL, BUTTON_POWER, BUTTON_NONE }, { ACTION_QS_TOP, BUTTON_UP, BUTTON_NONE }, @@ -356,7 +357,7 @@ static const struct button_mapping button_context_usb_hid_mode_mouse[] = { /* get_context_mapping returns a pointer to one of the above defined arrays depending on the context */ const struct button_mapping* get_context_mapping(int context) { - switch (context) + switch (context & ~CONTEXT_LOCKED) { case CONTEXT_STD: return button_context_standard; diff --git a/apps/keymaps/keymap-nwza860.c b/apps/keymaps/keymap-nwza860.c index d455e23b62..899796552e 100644 --- a/apps/keymaps/keymap-nwza860.c +++ b/apps/keymaps/keymap-nwza860.c @@ -74,7 +74,8 @@ static const struct button_mapping button_context_keyboard[] = { }; /* button_context_keyboard */ static const struct button_mapping button_context_quickscreen[] = { - { ACTION_STD_CANCEL, BUTTON_PLAY, BUTTON_NONE }, + { ACTION_STD_CONTEXT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY }, + { ACTION_STD_CANCEL, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY }, { ACTION_STD_CANCEL, BUTTON_BACK, BUTTON_NONE }, LAST_ITEM_IN_LIST diff --git a/apps/keymaps/keymap-ondavx777.c b/apps/keymaps/keymap-ondavx777.c index ed23350666..c4b68f1ef2 100644 --- a/apps/keymaps/keymap-ondavx777.c +++ b/apps/keymaps/keymap-ondavx777.c @@ -127,7 +127,7 @@ static const struct button_mapping button_context_usb_hid[] = { const struct button_mapping* target_get_context_mapping(int context) { - switch (context) + switch (context & ~CONTEXT_LOCKED) { case CONTEXT_STD: return button_context_standard; diff --git a/apps/keymaps/keymap-rk27xx-generic.c b/apps/keymaps/keymap-rk27xx-generic.c index d837c608fc..4c07384810 100644 --- a/apps/keymaps/keymap-rk27xx-generic.c +++ b/apps/keymaps/keymap-rk27xx-generic.c @@ -164,7 +164,7 @@ static const struct button_mapping button_context_usb_hid_mode_mouse[] = { /* get_context_mapping returns a pointer to one of the above defined arrays depending on the context */ const struct button_mapping* get_context_mapping(int context) { - switch (context) + switch (context & ~CONTEXT_LOCKED) { case CONTEXT_STD: return button_context_standard; diff --git a/apps/keymaps/keymap-shanlingq1.c b/apps/keymaps/keymap-shanlingq1.c index 4caaa36fd2..f8fefe5ff3 100644 --- a/apps/keymaps/keymap-shanlingq1.c +++ b/apps/keymaps/keymap-shanlingq1.c @@ -69,7 +69,7 @@ static const struct button_mapping button_context_yesno[] = { const struct button_mapping* target_get_context_mapping(int context) { - switch (context) + switch (context & ~CONTEXT_LOCKED) { default: case CONTEXT_STD: diff --git a/apps/keymaps/keymap-touchscreen.c b/apps/keymaps/keymap-touchscreen.c index 555cf42f79..07710be78d 100644 --- a/apps/keymaps/keymap-touchscreen.c +++ b/apps/keymaps/keymap-touchscreen.c @@ -383,7 +383,7 @@ const struct button_mapping* get_context_mapping(int context) return target_get_context_mapping(context & ~CONTEXT_CUSTOM2); } - switch (context) + switch (context & ~CONTEXT_LOCKED) { case CONTEXT_STD: return button_context_standard; diff --git a/apps/keymaps/keymap-xduoox20.c b/apps/keymaps/keymap-xduoox20.c index b08db90cfd..fa4076e27d 100644 --- a/apps/keymaps/keymap-xduoox20.c +++ b/apps/keymaps/keymap-xduoox20.c @@ -184,7 +184,7 @@ static const struct button_mapping button_context_yesnoscreen[] = { /* get_context_mapping returns a pointer to one of the above defined arrays depending on the context */ const struct button_mapping* get_context_mapping(int context) { - switch (context) + switch (context & ~CONTEXT_LOCKED) { case CONTEXT_LIST: return button_context_list; diff --git a/apps/keymaps/keymap-xduoox3.c b/apps/keymaps/keymap-xduoox3.c index bbe4c88772..bf588411eb 100644 --- a/apps/keymaps/keymap-xduoox3.c +++ b/apps/keymaps/keymap-xduoox3.c @@ -86,10 +86,12 @@ static const struct button_mapping button_context_wps[] = { { ACTION_WPS_VOLDOWN, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_WPS_BROWSE, BUTTON_HOME|BUTTON_REL, BUTTON_HOME }, { ACTION_WPS_CONTEXT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY }, - { ACTION_WPS_MENU, BUTTON_OPTION|BUTTON_REL, BUTTON_OPTION }, - { ACTION_WPS_QUICKSCREEN, BUTTON_OPTION|BUTTON_REPEAT, BUTTON_OPTION }, { ACTION_WPS_HOTKEY, BUTTON_HOME|BUTTON_REPEAT, BUTTON_HOME }, + { ACTION_WPS_MENU, BUTTON_OPTION|BUTTON_REL, BUTTON_OPTION }, + { ACTION_WPS_QUICKSCREEN, BUTTON_OPTION|BUTTON_REPEAT, BUTTON_OPTION }, + { ACTION_WPS_PITCHSCREEN, BUTTON_OPTION|BUTTON_HOME|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_WPS_ABSETB_NEXTDIR, BUTTON_PWRALT|BUTTON_NEXT, BUTTON_POWER }, { ACTION_WPS_ABSETA_PREVDIR, BUTTON_PWRALT|BUTTON_PREV, BUTTON_POWER }, { ACTION_WPS_ABRESET, BUTTON_PWRALT|BUTTON_PLAY, BUTTON_POWER }, diff --git a/apps/keymaps/keymap-xduoox3ii.c b/apps/keymaps/keymap-xduoox3ii.c index d99c8240a1..c8724ec1f0 100644 --- a/apps/keymaps/keymap-xduoox3ii.c +++ b/apps/keymaps/keymap-xduoox3ii.c @@ -184,7 +184,7 @@ static const struct button_mapping button_context_yesnoscreen[] = { /* get_context_mapping returns a pointer to one of the above defined arrays depending on the context */ const struct button_mapping* get_context_mapping(int context) { - switch (context) + switch (context & ~CONTEXT_LOCKED) { case CONTEXT_LIST: return button_context_list; diff --git a/apps/keymaps/keymap-ypr0.c b/apps/keymaps/keymap-ypr0.c index 2d6be5b7ec..6e493ddf61 100644 --- a/apps/keymaps/keymap-ypr0.c +++ b/apps/keymaps/keymap-ypr0.c @@ -255,7 +255,7 @@ static const struct button_mapping button_context_radio[] = { const struct button_mapping* get_context_mapping(int context) { - switch (context) + switch (context & ~CONTEXT_LOCKED) { case CONTEXT_STD: return button_context_standard; diff --git a/apps/keymaps/keymap-ypr1.c b/apps/keymaps/keymap-ypr1.c index d47047912b..67f42f07c6 100644 --- a/apps/keymaps/keymap-ypr1.c +++ b/apps/keymaps/keymap-ypr1.c @@ -132,7 +132,7 @@ static const struct button_mapping button_context_radio[] = { const struct button_mapping* target_get_context_mapping(int context) { - switch (context) + switch (context & ~CONTEXT_LOCKED) { case CONTEXT_STD: return button_context_standard; diff --git a/apps/keymaps/keymap-zen.c b/apps/keymaps/keymap-zen.c index b0f24af459..04b65b3980 100644 --- a/apps/keymaps/keymap-zen.c +++ b/apps/keymaps/keymap-zen.c @@ -145,7 +145,8 @@ static const struct button_mapping button_context_keyboard[] = { }; /* button_context_keyboard */ static const struct button_mapping button_context_quickscreen[] = { - { ACTION_STD_CANCEL, BUTTON_SELECT, BUTTON_NONE }, + { ACTION_STD_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT }, + { ACTION_STD_CANCEL, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, { ACTION_STD_CANCEL, BUTTON_BACK, BUTTON_NONE }, { ACTION_STD_CANCEL, BUTTON_PLAYPAUSE, BUTTON_NONE }, { ACTION_QS_TOP, BUTTON_UP, BUTTON_NONE }, diff --git a/apps/keymaps/keymap-zenxfi2.c b/apps/keymaps/keymap-zenxfi2.c index c98a4a8405..ba25592246 100644 --- a/apps/keymaps/keymap-zenxfi2.c +++ b/apps/keymaps/keymap-zenxfi2.c @@ -137,7 +137,7 @@ static const struct button_mapping button_context_radio[] = { const struct button_mapping* target_get_context_mapping(int context) { - switch (context) + switch (context & ~CONTEXT_LOCKED) { case CONTEXT_STD: return button_context_standard; diff --git a/apps/lang/chinese-simp.lang b/apps/lang/chinese-simp.lang index 3d1d0ecaa3..b7702ee3c7 100644 --- a/apps/lang/chinese-simp.lang +++ b/apps/lang/chinese-simp.lang @@ -13,6 +13,8 @@ # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY # KIND, either express or implied. # +# LANGUAGE_UNITS_FIRST +# # Simplified Chinese language file, translated by: # - Ye Wei # - Xinlu Huang diff --git a/apps/lang/chinese-trad.lang b/apps/lang/chinese-trad.lang index 02e14645e0..e7ee7ae607 100644 --- a/apps/lang/chinese-trad.lang +++ b/apps/lang/chinese-trad.lang @@ -13,6 +13,8 @@ # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY # KIND, either express or implied. # +# LANGUAGE_UNITS_FIRST +# # Traditional Chinese language file, translated by: # - Wenbin Leo # - Xinlu Huang diff --git a/apps/lang/english-us.lang b/apps/lang/english-us.lang index cc35e2b4a0..5a3eb38ba3 100644 --- a/apps/lang/english-us.lang +++ b/apps/lang/english-us.lang @@ -254,8 +254,7 @@ <dest> *: "PLAY = Yes" cowond2*: "MENU, or top-right = Yes" - creativezen*: "SELECT = Yes" - gigabeat*,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh10_5gb,mrobe100,sansac200*,sansaclip*,sansaconnect,sansae200*,sansafuze*: "SELECT = Yes" + creativezen*,gigabeat*,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh10_5gb,mrobe100,sansac200*,sansaclip*,sansaconnect,sansae200*,sansafuze*: "SELECT = Yes" iriverh100,iriverh120,iriverh300: "NAVI = Yes" mrobe500: "PLAY, POWER, or top-right = Yes" vibe500: "OK = Yes" @@ -1697,10 +1696,10 @@ </phrase> <phrase> id: LANG_AUDIOSCROBBLER - desc: "Last.fm Log" in the playback menu + desc: "Last.fm Logger" in Plugin/apps/scrobbler user: core <source> - *: "Last.fm Log" + *: "Last.fm Logger" </source> <dest> *: "Last.fm Log" @@ -2267,20 +2266,25 @@ charging: "Backlight (While Plugged In)" </voice> </phrase> +### The <source> section for 'LANG_BACKLIGHT_ON_BUTTON_HOLD:*' differs from the english! +### the previously used one is commented below: +### Backlight on Lock +### The <dest> section for 'LANG_BACKLIGHT_ON_BUTTON_HOLD:*' is missing! Copying from english! +### The <voice> section for 'LANG_BACKLIGHT_ON_BUTTON_HOLD:*' is missing! Copying from english! <phrase> id: LANG_BACKLIGHT_ON_BUTTON_HOLD desc: in lcd settings user: core <source> - *: none + *: "Backlight on Lock" hold_button: "Backlight on Hold" </source> <dest> - *: none + *: "Backlight on Lock" hold_button: "Backlight on Hold" </dest> <voice> - *: none + *: "Backlight on Lock" hold_button: "Backlight on hold" </voice> </phrase> @@ -4108,31 +4112,16 @@ </phrase> <phrase> id: LANG_ALARM_MOD_KEYS - desc: Shown key functions in alarm menu (for the RTC alarm mod). + desc: deprecated user: core <source> - *: none - alarm: "PLAY=Set OFF=Cancel" - gigabeats: "SELECT=Set POWER=Cancel" - ipod*: "SELECT=Set MENU=Cancel" - iriverh10,iriverh10_5gb: "SELECT=Set PREV=Cancel" - mpiohd300: "ENTER=Set MENU=Cancel" - sansafuzeplus: "SELECT=Set BACK=Cancel" - vibe500: "OK=Set C=Cancel" + *: "" </source> <dest> - *: none - alarm: "PLAY=Set OFF=Cancel" - gigabeats: "SELECT=Set POWER=Cancel" - ipod*: "SELECT=Set MENU=Cancel" - iriverh10,iriverh10_5gb: "SELECT=Set PREV=Cancel" - mpiohd300: "ENTER=Set MENU=Cancel" - sansafuzeplus: "SELECT=Set BACK=Cancel" - vibe500: "OK=Set C=Cancel" + *: "" </dest> <voice> - *: none - alarm,ipod*: "" + *: "" </voice> </phrase> <phrase> @@ -5351,19 +5340,19 @@ </phrase> <phrase> id: LANG_SET_AS_REC_DIR - desc: used in the onplay menu to set a recording dir + desc: deprecated user: core <source> *: none - recording: "Set As Recording Directory" + recording: "" </source> <dest> *: none - recording: "Set As Recording Directory" + recording: "" </dest> <voice> *: none - recording: "Set As Recording Directory" + recording: "" </voice> </phrase> <phrase> @@ -6065,18 +6054,21 @@ user: core <source> *: none - multivolume: "HD1" + hibylinux: "USB:" + multivolume: "HD1:" sansac200*,sansaclipplus,sansae200*,sansafuze*: "mSD:" xduoox3: "mSD2:" </source> <dest> *: none + hibylinux: "USB:" multivolume: "HD1" sansac200*,sansaclipplus,sansae200*,sansafuze*: "mSD:" xduoox3: "mSD2:" </dest> <voice> *: none + hibylinux: "U S B" multivolume: "H D 1" sansac200*,sansaclipplus,sansae200*,sansafuze*: "micro S D" xduoox3: "micro S D 2" @@ -6168,58 +6160,58 @@ </phrase> <phrase> id: LANG_INSERT - desc: in onplay menu. insert a track/playlist into dynamic playlist. + desc: deprecated user: core <source> - *: "Insert" + *: "" </source> <dest> - *: "Insert" + *: "" </dest> <voice> - *: "Insert" + *: "" </voice> </phrase> <phrase> id: LANG_INSERT_FIRST - desc: in onplay menu. insert a track/playlist into dynamic playlist. + desc: deprecated user: core <source> - *: "Insert Next" + *: "" </source> <dest> - *: "Insert Next" + *: "" </dest> <voice> - *: "Insert Next" + *: "" </voice> </phrase> <phrase> id: LANG_INSERT_LAST - desc: in onplay menu. append a track/playlist into dynamic playlist. + desc: deprecated user: core <source> - *: "Insert Last" + *: "" </source> <dest> - *: "Insert Last" + *: "" </dest> <voice> - *: "Insert Last" + *: "" </voice> </phrase> <phrase> id: LANG_INSERT_SHUFFLED - desc: in onplay menu. insert a track/playlist randomly into dynamic playlist + desc: deprecated user: core <source> - *: "Insert Shuffled" + *: "" </source> <dest> - *: "Insert Shuffled" + *: "" </dest> <voice> - *: "Insert Shuffled" + *: "" </voice> </phrase> <phrase> @@ -6392,16 +6384,16 @@ </phrase> <phrase> id: LANG_CATALOG_ADD_TO - desc: in onplay playlist catalogue submenu + desc: deprecated user: core <source> - *: "Add to Playlist" + *: "" </source> <dest> - *: "Add to Playlist" + *: "" </dest> <voice> - *: "Add to Playlist" + *: "" </voice> </phrase> <phrase> @@ -10892,16 +10884,16 @@ </phrase> <phrase> id: LANG_INSERT_LAST_SHUFFLED - desc: in onplay menu. insert a playlist randomly at end of dynamic playlist + desc: deprecated user: core <source> - *: "Insert Last Shuffled" + *: "" </source> <dest> - *: "Insert Last Shuffled" + *: "" </dest> <voice> - *: "Insert Last Shuffled" + *: "" </voice> </phrase> <phrase> @@ -11499,16 +11491,16 @@ </phrase> <phrase> id: LANG_SET_AS_START_DIR - desc: used in the onplay menu to set a starting browser dir + desc: deprecated user: core <source> - *: "Start File Browser Here" + *: "" </source> <dest> - *: "Start File Browser Here" + *: "" </dest> <voice> - *: "Start File Browser Here" + *: "" </voice> </phrase> <phrase> @@ -11628,16 +11620,16 @@ </phrase> <phrase> id: LANG_SET_AS_PLAYLISTCAT_DIR - desc: used in the onplay menu to set a playlist catalogue dir + desc: deprecated user: core <source> - *: "Set As Playlist Catalogue Directory" + *: "" </source> <dest> - *: "Set As Playlist Catalog Directory" + *: "" </dest> <voice> - *: "Set As Playlist Catalog Directory" + *: "" </voice> </phrase> <phrase> @@ -11704,16 +11696,16 @@ </phrase> <phrase> id: LANG_AUTOMATIC - desc: generic automatic + desc: deprecated user: core <source> - *: "Automatic" + *: "" </source> <dest> - *: "Automatic" + *: "" </dest> <voice> - *: "Automatic" + *: "" </voice> </phrase> <phrase> @@ -12564,10 +12556,10 @@ *: "Exempt Seek" </source> <dest> - *: "Seek" + *: "Exempt Seek" </dest> <voice> - *: "Seek" + *: "Exempt Seek" </voice> </phrase> <phrase> @@ -12637,10 +12629,10 @@ *: "Exempt Play" </source> <dest> - *: "Play" + *: "Exempt Play" </dest> <voice> - *: "Play" + *: "Exempt Play" </voice> </phrase> <phrase> @@ -12926,10 +12918,10 @@ *: "Exempt Skip" </source> <dest> - *: "Skip" + *: "Exempt Skip" </dest> <voice> - *: "Skip" + *: "Exempt Skip" </voice> </phrase> <phrase> @@ -13889,10 +13881,10 @@ *: "Disable Locked Reminders" </source> <dest> - *: "Disable Notify" + *: "Disable Locked Reminders" </dest> <voice> - *: "Disable Notify" + *: "Disable Locked Reminders" </voice> </phrase> <phrase> @@ -14307,16 +14299,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_TITLE - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Title]" + *: "" </source> <dest> - *: "[Title]" + *: "" </dest> <voice> - *: "Title" + *: "" </voice> </phrase> <phrase> @@ -14433,16 +14425,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_DURATION - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Duration]" + *: "" </source> <dest> - *: "[Duration]" + *: "" </dest> <voice> - *: "Duration" + *: "" </voice> </phrase> <phrase> @@ -14489,16 +14481,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_ARTIST - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Artist]" + *: "" </source> <dest> - *: "[Artist]" + *: "" </dest> <voice> - *: "Artist" + *: "" </voice> </phrase> <phrase> @@ -14545,16 +14537,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_ALBUM - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Album]" + *: "" </source> <dest> - *: "[Album]" + *: "" </dest> <voice> - *: "Album" + *: "" </voice> </phrase> <phrase> @@ -14615,16 +14607,16 @@ </phrase> <phrase> id: LANG_CLEAR_PLAYLIST - desc: in the pictureflow main menu + desc: deprecated user: core <source> - *: "Clear playlist" + *: "" </source> <dest> - *: "Clear playlist" + *: "" </dest> <voice> - *: "Clear playlist" + *: "" </voice> </phrase> <phrase> @@ -14921,7 +14913,7 @@ </phrase> <phrase> id: LANG_DIRECT - desc: in the pictureflow settings + desc: in the pictureflow settings, also a volume adjustment mode user: core <source> *: "Direct" @@ -15594,16 +15586,16 @@ </phrase> <phrase> id: LANG_CLEAR_LIST_AND_PLAY_NEXT - desc: in onplay menu. Replace current playlist with selected tracks + desc: deprecated user: core <source> - *: "Clear List & Play Next" + *: "" </source> <dest> - *: "Clear List & Play Next" + *: "" </dest> <voice> - *: "Clear List & Play Next" + *: "" </voice> </phrase> <phrase> @@ -15664,16 +15656,16 @@ </phrase> <phrase> id: LANG_CLEAR_LIST_AND_PLAY_SHUFFLED - desc: in onplay menu. Replace current playlist with selected tracks in random order. + desc: deprecated user: core <source> - *: "Clear List & Play Shuffled" + *: "" </source> <dest> - *: "Clear List & Play Shuffled" + *: "" </dest> <voice> - *: "Clear List & Play Shuffled" + *: "" </voice> </phrase> <phrase> @@ -15887,128 +15879,128 @@ </phrase> <phrase> id: LANG_PROPERTIES_ALBUMARTIST - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Album Artist]" + *: "" </source> <dest> - *: "[Album Artist]" + *: "" </dest> <voice> - *: "Album Artist" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_GENRE - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Genre]" + *: "" </source> <dest> - *: "[Genre]" + *: "" </dest> <voice> - *: "Genre" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_COMMENT - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Comment]" + *: "" </source> <dest> - *: "[Comment]" + *: "" </dest> <voice> - *: "Comment" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_COMPOSER - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Composer]" + *: "" </source> <dest> - *: "[Composer]" + *: "" </dest> <voice> - *: "Composer" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_YEAR - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Year]" + *: "" </source> <dest> - *: "[Year]" + *: "" </dest> <voice> - *: "Year" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_TRACKNUM - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Tracknum]" + *: "" </source> <dest> - *: "[Tracknum]" + *: "" </dest> <voice> - *: "Track number" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_DISCNUM - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Discnum]" + *: "" </source> <dest> - *: "[Discnum]" + *: "" </dest> <voice> - *: "Disc number" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_FREQUENCY - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Frequency]" + *: "" </source> <dest> - *: "[Frequency]" + *: "" </dest> <voice> - *: "Frequency" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_BITRATE - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Bitrate]" + *: "" </source> <dest> - *: "[Bitrate]" + *: "" </dest> <voice> - *: "Bit rate" + *: "" </voice> </phrase> <phrase> @@ -16109,3 +16101,472 @@ *: "Descending" </voice> </phrase> +<phrase> + id: LANG_ALBUM_ART + desc: in Settings + user: core + <source> + *: "Album Art" + </source> + <dest> + *: "Album Art" + </dest> + <voice> + *: "Album Art" + </voice> +</phrase> +<phrase> + id: LANG_PREFER_EMBEDDED + desc: in Settings + user: core + <source> + *: "Prefer Embedded" + </source> + <dest> + *: "Prefer Embedded" + </dest> + <voice> + *: "Prefer Embedded" + </voice> +</phrase> +<phrase> + id: LANG_PREFER_IMAGE_FILE + desc: in Settings + user: core + <source> + *: "Prefer Image File" + </source> + <dest> + *: "Prefer Image File" + </dest> + <voice> + *: "Prefer Image File" + </voice> +</phrase> +<phrase> + id: LANG_FM_SYNC_RDS_TIME + desc: in radio screen and Settings + user: core + <source> + *: none + rds: "Sync RDS Time" + </source> + <dest> + *: none + rds: "Sync RDS Time" + </dest> + <voice> + *: none + rds: "Sync RDS Time" + </voice> +</phrase> +<phrase> + id: LANG_SORT_ALBUMS_BY + desc: in Settings + user: core + <source> + *: "Sort albums by" + </source> + <dest> + *: "Sort albums by" + </dest> + <voice> + *: "Sort albums by" + </voice> +</phrase> +<phrase> + id: LANG_ARTIST_PLUS_NAME + desc: in Settings + user: core + <source> + *: "Artist + Name" + </source> + <dest> + *: "Artist + Name" + </dest> + <voice> + *: "Artist And Name" + </voice> +</phrase> +<phrase> + id: LANG_ARTIST_PLUS_YEAR + desc: in Settings + user: core + <source> + *: "Artist + Year" + </source> + <dest> + *: "Artist + Year" + </dest> + <voice> + *: "Artist And Year" + </voice> +</phrase> +<phrase> + id: LANG_YEAR_SORT_ORDER + desc: in Settings + user: core + <source> + *: "Year sort order" + </source> + <dest> + *: "Year sort order" + </dest> + <voice> + *: "Year sort order" + </voice> +</phrase> +<phrase> + id: LANG_SHOW_YEAR_IN_ALBUM_TITLE + desc: in Settings + user: core + <source> + *: "Show year in album title" + </source> + <dest> + *: "Show year in album title" + </dest> + <voice> + *: "Show year in album title" + </voice> +</phrase> +<phrase> + id: LANG_WAIT_FOR_CACHE + desc: in Settings + user: core + <source> + *: "Cache needs to finish updating first!" + </source> + <dest> + *: "Cache needs to finish updating first!" + </dest> + <voice> + *: "Cache needs to finish updating first!" + </voice> +</phrase> +<phrase> + id: LANG_TRACK_INFO + desc: Track Info Title + user: core + <source> + *: "Track Info" + </source> + <dest> + *: "Track Info" + </dest> + <voice> + *: "Track Info" + </voice> +</phrase> +<phrase> + id: LANG_PLAY + desc: play selected file/directory, in playlist context menu + user: core + <source> + *: "Play" + </source> + <dest> + *: "Play" + </dest> + <voice> + *: "Play" + </voice> +</phrase> +<phrase> + id: LANG_PLAY_SHUFFLED + desc: play selected files in shuffled order, in playlist context menu + user: core + <source> + *: "Play Shuffled" + </source> + <dest> + *: "Play Shuffled" + </dest> + <voice> + *: "Play Shuffled" + </voice> +</phrase> +<phrase> + id: LANG_KEEP_CURRENT_TRACK_ON_REPLACE + desc: used in the playlist settings menu + user: core + <source> + *: "Keep Current Track When Replacing Playlist" + </source> + <dest> + *: "Keep Current Track When Replacing Playlist" + </dest> + <voice> + *: "Keep Current Track When Replacing Playlist" + </voice> +</phrase> +<phrase> + id: LANG_CLEAR_SETTINGS_ON_HOLD + desc: in the system sub menu + user: core + <source> + *: none + clear_settings_on_hold,iriverh10: "Clear settings when reset button is held during startup" + ipod4g,ipodcolor,ipodmini1g,ipodmini2g,ipodnano1g,ipodvideo: "Clear settings when hold switch is on during startup" + </source> + <dest> + *: none + clear_settings_on_hold,iriverh10: "Clear settings when reset button is held during startup" + ipod4g,ipodcolor,ipodmini1g,ipodmini2g,ipodnano1g,ipodvideo: "Clear settings when hold switch is on during startup" + </dest> + <voice> + *: none + clear_settings_on_hold,iriverh10: "Clear settings when reset button is held during startup" + ipod4g,ipodcolor,ipodmini1g,ipodmini2g,ipodnano1g,ipodvideo: "Clear settings when hold switch is on during startup" + </voice> +</phrase> +<phrase> + id: LANG_REWIND_ACROSS_TRACKS + desc: in playback settings menu + user: core + <source> + *: "Rewind Across Tracks" + </source> + <dest> + *: "Rewind Across Tracks" + </dest> + <voice> + *: "Rewind across tracks" + </voice> +</phrase> +<phrase> + id: LANG_SET_AS + desc: used in the onplay menu + user: core + <source> + *: "Set As..." + </source> + <dest> + *: "Set As..." + </dest> + <voice> + *: "Set As..." + </voice> +</phrase> +<phrase> + id: LANG_PLAYLIST_DIR + desc: used in the onplay menu + user: core + <source> + *: "Playlist Directory" + </source> + <dest> + *: "Playlist Directory" + </dest> + <voice> + *: "Playlist Directory" + </voice> +</phrase> +<phrase> + id: LANG_START_DIR + desc: used in the onplay menu + user: core + <source> + *: "Start Directory" + </source> + <dest> + *: "Start Directory" + </dest> + <voice> + *: "Start Directory" + </voice> +</phrase> +<phrase> + id: LANG_RECORDING_DIR + desc: used in the onplay menu + user: core + <source> + *: none + recording: "Recording Directory" + </source> + <dest> + *: none + recording: "Recording Directory" + </dest> + <voice> + *: none + recording: "Recording Directory" + </voice> +</phrase> +<phrase> + id: LANG_ADD_TO_PL + desc: used in the onplay menu + user: core + <source> + *: "Add to Playlist..." + </source> + <dest> + *: "Add to Playlist..." + </dest> + <voice> + *: "Add to Playlist..." + </voice> +</phrase> +<phrase> + id: LANG_ADD_TO_EXISTING_PL + desc: used in the onplay menu + user: core + <source> + *: "Add to Existing Playlist" + </source> + <dest> + *: "Add to Existing Playlist" + </dest> + <voice> + *: "Add to Existing Playlist" + </voice> +</phrase> +<phrase> + id: LANG_PLAYING_NEXT + desc: used in the onplay menu + user: core + <source> + *: "Playing Next..." + </source> + <dest> + *: "Playing Next..." + </dest> + <voice> + *: "Playing Next..." + </voice> +</phrase> +<phrase> + id: LANG_PLAY_NEXT + desc: used in the onplay menu + user: core + <source> + *: "Play Next" + </source> + <dest> + *: "Play Next" + </dest> + <voice> + *: "Play Next" + </voice> +</phrase> +<phrase> + id: LANG_ADD_SHUFFLED + desc: used in the onplay menu + user: core + <source> + *: "Add Shuffled" + </source> + <dest> + *: "Add Shuffled" + </dest> + <voice> + *: "Add Shuffled" + </voice> +</phrase> +<phrase> + id: LANG_PLAY_LAST + desc: used in the onplay menu + user: core + <source> + *: "Play Last" + </source> + <dest> + *: "Play Last" + </dest> + <voice> + *: "Play Last" + </voice> +</phrase> +<phrase> + id: LANG_PLAY_LAST_SHUFFLED + desc: used in the onplay menu + user: core + <source> + *: "Play Last Shuffled" + </source> + <dest> + *: "Play Last Shuffled" + </dest> + <voice> + *: "Play Last Shuffled" + </voice> +</phrase> +<phrase> + id: LANG_VOLUME_ADJUST_MODE + desc: in system settings + user: core + <source> + *: none + perceptual_volume: "Volume Adjustment Mode" + </source> + <dest> + *: none + perceptual_volume: "Volume Adjustment Mode" + </dest> + <voice> + *: none + perceptual_volume: "Volume Adjustment Mode" + </voice> +</phrase> +<phrase> + id: LANG_VOLUME_ADJUST_NORM_STEPS + desc: in system settings + user: core + <source> + *: none + perceptual_volume: "Number of Volume Steps" + </source> + <dest> + *: none + perceptual_volume: "Number of Volume Steps" + </dest> + <voice> + *: none + perceptual_volume: "Number of Volume Steps" + </voice> +</phrase> +<phrase> + id: LANG_PERCEPTUAL + desc: in system settings -> volume adjustment mode + user: core + <source> + *: none + perceptual_volume: "Perceptual" + </source> + <dest> + *: none + perceptual_volume: "Perceptual" + </dest> + <voice> + *: none + perceptual_volume: "Perceptual" + </voice> +</phrase> +<phrase> + id: LANG_SHOW_TRACKS_WHILE_BROWSING + desc: in PictureFlow Main Menu + user: core + <source> + *: "Show Tracks While Browsing" + </source> + <dest> + *: "Show Tracks While Browsing" + </dest> + <voice> + *: "Show Tracks While Browsing" + </voice> +</phrase> +<phrase> + id: LANG_GOTO_LAST_ALBUM + desc: in PictureFlow Main Menu + user: core + <source> + *: "Go to Last Album" + </source> + <dest> + *: "Go to Last Album" + </dest> + <voice> + *: "Go to Last Album" + </voice> +</phrase> diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 3b505bb9a2..3773d138d4 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -2347,15 +2347,15 @@ desc: in lcd settings user: core <source> - *: none + *: "Backlight on Lock" hold_button: "Backlight on Hold" </source> <dest> - *: none + *: "Backlight on Lock" hold_button: "Backlight on Hold" </dest> <voice> - *: none + *: "Backlight on Lock" hold_button: "Backlight on hold" </voice> </phrase> @@ -3645,22 +3645,22 @@ user: core <source> *: none + rtc: "ON = Set" gigabeat*,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh10_5gb,mrobe100,sansac200*,sansaclip*,sansaconnect,sansae200*,sansafuze*: "SELECT = Set" gogearsa9200,samsungyh*: "PLAY = Set" iriverh100,iriverh120,iriverh300: "NAVI = Set" mpiohd300: "ENTER = Set" mrobe500: "HEART = Set" - rtc: "ON = Set" vibe500: "OK = Set" </source> <dest> *: none + rtc: "ON = Set" gigabeat*,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh10_5gb,mrobe100,sansac200*,sansaclip*,sansaconnect,sansae200*,sansafuze*: "SELECT = Set" gogearsa9200,samsungyh*: "PLAY = Set" iriverh100,iriverh120,iriverh300: "NAVI = Set" mpiohd300: "ENTER = Set" mrobe500: "HEART = Set" - rtc: "ON = Set" vibe500: "OK = Set" </dest> <voice> @@ -3674,6 +3674,7 @@ user: core <source> *: none + rtc: "OFF = Revert" gigabeatfx,mrobe500: "POWER = Revert" gigabeats,sansafuzeplus: "BACK = Revert" gogearsa9200: "LEFT = Revert" @@ -3682,12 +3683,12 @@ iriverh10,iriverh10_5gb,sansae200*,sansafuze*: "PREV = Revert" iriverh100,iriverh120,iriverh300: "STOP = Revert" mrobe100: "DISPLAY = Revert" - rtc: "OFF = Revert" samsungyh*: "REW = Revert" vibe500: "CANCEL = Revert" </source> <dest> *: none + rtc: "OFF = Revert" gigabeatfx,mrobe500: "POWER = Revert" gigabeats,sansafuzeplus: "BACK = Revert" gogearsa9200: "LEFT = Revert" @@ -3696,7 +3697,6 @@ iriverh10,iriverh10_5gb,sansae200*,sansafuze*: "PREV = Revert" iriverh100,iriverh120,iriverh300: "STOP = Revert" mrobe100: "DISPLAY = Revert" - rtc: "OFF = Revert" samsungyh*: "REW = Revert" vibe500: "CANCEL = Revert" </dest> @@ -5411,19 +5411,19 @@ </phrase> <phrase> id: LANG_SET_AS_REC_DIR - desc: used in the onplay menu to set a recording dir + desc: deprecated user: core <source> *: none - recording: "Set As Recording Directory" + recording: "" </source> <dest> *: none - recording: "Set As Recording Directory" + recording: "" </dest> <voice> *: none - recording: "Set As Recording Directory" + recording: "" </voice> </phrase> <phrase> @@ -6125,18 +6125,21 @@ user: core <source> *: none - multivolume: "HD1" + hibylinux: "USB:" + multivolume: "HD1:" sansac200*,sansaclipplus,sansae200*,sansafuze*: "mSD:" xduoox3: "mSD2:" </source> <dest> *: none - multivolume: "HD1" + hibylinux: "USB:" + multivolume: "HD1:" sansac200*,sansaclipplus,sansae200*,sansafuze*: "MSD:" xduoox3: "mSD2:" </dest> <voice> *: none + hibylinux: "U S B" multivolume: "H D 1" sansac200*,sansaclipplus,sansae200*,sansafuze*: "micro S D" xduoox3: "micro S D 2" @@ -6228,58 +6231,58 @@ </phrase> <phrase> id: LANG_INSERT - desc: in onplay menu. insert a track/playlist into dynamic playlist. + desc: deprecated user: core <source> - *: "Insert" + *: "" </source> <dest> - *: "Insert" + *: "" </dest> <voice> - *: "Insert" + *: "" </voice> </phrase> <phrase> id: LANG_INSERT_FIRST - desc: in onplay menu. insert a track/playlist into dynamic playlist. + desc: deprecated user: core <source> - *: "Insert Next" + *: "" </source> <dest> - *: "Insert Next" + *: "" </dest> <voice> - *: "Insert Next" + *: "" </voice> </phrase> <phrase> id: LANG_INSERT_LAST - desc: in onplay menu. append a track/playlist into dynamic playlist. + desc: deprecated user: core <source> - *: "Insert Last" + *: "" </source> <dest> - *: "Insert Last" + *: "" </dest> <voice> - *: "Insert Last" + *: "" </voice> </phrase> <phrase> id: LANG_INSERT_SHUFFLED - desc: in onplay menu. insert a track/playlist randomly into dynamic playlist + desc: deprecated user: core <source> - *: "Insert Shuffled" + *: "" </source> <dest> - *: "Insert Shuffled" + *: "" </dest> <voice> - *: "Insert Shuffled" + *: "" </voice> </phrase> <phrase> @@ -6452,16 +6455,16 @@ </phrase> <phrase> id: LANG_CATALOG_ADD_TO - desc: in onplay playlist catalogue submenu + desc: deprecated user: core <source> - *: "Add to Playlist" + *: "" </source> <dest> - *: "Add to Playlist" + *: "" </dest> <voice> - *: "Add to Playlist" + *: "" </voice> </phrase> <phrase> @@ -10980,16 +10983,16 @@ </phrase> <phrase> id: LANG_INSERT_LAST_SHUFFLED - desc: in onplay menu. insert a playlist randomly at end of dynamic playlist + desc: deprecated user: core <source> - *: "Insert Last Shuffled" + *: "" </source> <dest> - *: "Insert Last Shuffled" + *: "" </dest> <voice> - *: "Insert Last Shuffled" + *: "" </voice> </phrase> <phrase> @@ -11587,16 +11590,16 @@ </phrase> <phrase> id: LANG_SET_AS_START_DIR - desc: used in the onplay menu to set a starting browser dir + desc: deprecated user: core <source> - *: "Start File Browser Here" + *: "" </source> <dest> - *: "Start File Browser Here" + *: "" </dest> <voice> - *: "Start File Browser Here" + *: "" </voice> </phrase> <phrase> @@ -11702,16 +11705,16 @@ </phrase> <phrase> id: LANG_SET_AS_PLAYLISTCAT_DIR - desc: used in the onplay menu to set a playlist catalogue dir + desc: deprecated user: core <source> - *: "Set As Playlist Catalogue Directory" + *: "" </source> <dest> - *: "Set As Playlist Catalogue Directory" + *: "" </dest> <voice> - *: "Set As Playlist Catalogue Directory" + *: "" </voice> </phrase> <phrase> @@ -11792,16 +11795,16 @@ </phrase> <phrase> id: LANG_AUTOMATIC - desc: generic automatic + desc: deprecated user: core <source> - *: "Automatic" + *: "" </source> <dest> - *: "Automatic" + *: "" </dest> <voice> - *: "Automatic" + *: "" </voice> </phrase> <phrase> @@ -15107,16 +15110,16 @@ </phrase> <phrase> id: LANG_CLEAR_PLAYLIST - desc: in the pictureflow main menu + desc: deprecated user: core <source> - *: "Clear playlist" + *: "" </source> <dest> - *: "Clear playlist" + *: "" </dest> <voice> - *: "Clear playlist" + *: "" </voice> </phrase> <phrase> @@ -15163,7 +15166,7 @@ </phrase> <phrase> id: LANG_DIRECT - desc: in the pictureflow settings + desc: in the pictureflow settings, also a volume adjustment mode user: core <source> *: "Direct" @@ -16368,3 +16371,273 @@ *: "Keep Current Track When Replacing Playlist" </voice> </phrase> +<phrase> + id: LANG_CLEAR_SETTINGS_ON_HOLD + desc: in the system sub menu + user: core + <source> + *: none + ipodcolor,ipodnano1g,ipodvideo,ipod4g,ipodmini1g,ipodmini2g: "Clear settings when hold switch is on during startup" + clear_settings_on_hold, iriverh10: "Clear settings when reset button is held during startup" + </source> + <dest> + *: none + ipodcolor,ipodnano1g,ipodvideo,ipod4g,ipodmini1g,ipodmini2g: "Clear settings when hold switch is on during startup" + clear_settings_on_hold, iriverh10: "Clear settings when reset button is held during startup" + </dest> + <voice> + *: none + ipodcolor,ipodnano1g,ipodvideo,ipod4g,ipodmini1g,ipodmini2g: "Clear settings when hold switch is on during startup" + clear_settings_on_hold, iriverh10: "Clear settings when reset button is held during startup" + </voice> +</phrase> +<phrase> + id: LANG_REWIND_ACROSS_TRACKS + desc: in playback settings menu + user: core + <source> + *: "Rewind Across Tracks" + </source> + <dest> + *: "Rewind Across Tracks" + </dest> + <voice> + *: "Rewind across tracks" + </voice> +</phrase> +<phrase> + id: LANG_SET_AS + desc: used in the onplay menu + user: core + <source> + *: "Set As..." + </source> + <dest> + *: "Set As..." + </dest> + <voice> + *: "Set As..." + </voice> +</phrase> +<phrase> + id: LANG_PLAYLIST_DIR + desc: used in the onplay menu + user: core + <source> + *: "Playlist Directory" + </source> + <dest> + *: "Playlist Directory" + </dest> + <voice> + *: "Playlist Directory" + </voice> +</phrase> +<phrase> + id: LANG_START_DIR + desc: used in the onplay menu + user: core + <source> + *: "Start Directory" + </source> + <dest> + *: "Start Directory" + </dest> + <voice> + *: "Start Directory" + </voice> +</phrase> +<phrase> + id: LANG_RECORDING_DIR + desc: used in the onplay menu + user: core + <source> + *: none + recording: "Recording Directory" + </source> + <dest> + *: none + recording: "Recording Directory" + </dest> + <voice> + *: none + recording: "Recording Directory" + </voice> +</phrase> +<phrase> + id: LANG_ADD_TO_PL + desc: used in the onplay menu + user: core + <source> + *: "Add to Playlist..." + </source> + <dest> + *: "Add to Playlist..." + </dest> + <voice> + *: "Add to Playlist..." + </voice> +</phrase> +<phrase> + id: LANG_ADD_TO_EXISTING_PL + desc: used in the onplay menu + user: core + <source> + *: "Add to Existing Playlist" + </source> + <dest> + *: "Add to Existing Playlist" + </dest> + <voice> + *: "Add to Existing Playlist" + </voice> +</phrase> +<phrase> + id: LANG_PLAYING_NEXT + desc: used in the onplay menu + user: core + <source> + *: "Playing Next..." + </source> + <dest> + *: "Playing Next..." + </dest> + <voice> + *: "Playing Next..." + </voice> +</phrase> +<phrase> + id: LANG_PLAY_NEXT + desc: used in the onplay menu + user: core + <source> + *: "Play Next" + </source> + <dest> + *: "Play Next" + </dest> + <voice> + *: "Play Next" + </voice> +</phrase> +<phrase> + id: LANG_ADD_SHUFFLED + desc: used in the onplay menu + user: core + <source> + *: "Add Shuffled" + </source> + <dest> + *: "Add Shuffled" + </dest> + <voice> + *: "Add Shuffled" + </voice> +</phrase> +<phrase> + id: LANG_PLAY_LAST + desc: used in the onplay menu + user: core + <source> + *: "Play Last" + </source> + <dest> + *: "Play Last" + </dest> + <voice> + *: "Play Last" + </voice> +</phrase> +<phrase> + id: LANG_PLAY_LAST_SHUFFLED + desc: used in the onplay menu + user: core + <source> + *: "Play Last Shuffled" + </source> + <dest> + *: "Play Last Shuffled" + </dest> + <voice> + *: "Play Last Shuffled" + </voice> +</phrase> +<phrase> + id: LANG_VOLUME_ADJUST_MODE + desc: in system settings + user: core + <source> + *: none + perceptual_volume: "Volume Adjustment Mode" + </source> + <dest> + *: none + perceptual_volume: "Volume Adjustment Mode" + </dest> + <voice> + *: none + perceptual_volume: "Volume Adjustment Mode" + </voice> +</phrase> +<phrase> + id: LANG_VOLUME_ADJUST_NORM_STEPS + desc: in system settings + user: core + <source> + *: none + perceptual_volume: "Number of Volume Steps" + </source> + <dest> + *: none + perceptual_volume: "Number of Volume Steps" + </dest> + <voice> + *: none + perceptual_volume: "Number of Volume Steps" + </voice> +</phrase> +<phrase> + id: LANG_PERCEPTUAL + desc: in system settings -> volume adjustment mode + user: core + <source> + *: none + perceptual_volume: "Perceptual" + </source> + <dest> + *: none + perceptual_volume: "Perceptual" + </dest> + <voice> + *: none + perceptual_volume: "Perceptual" + </voice> +</phrase> +<phrase> + id: LANG_SHOW_TRACKS_WHILE_BROWSING + desc: in PictureFlow Main Menu + user: core + <source> + *: "Show Tracks While Browsing" + </source> + <dest> + *: "Show Tracks While Browsing" + </dest> + <voice> + *: "Show Tracks While Browsing" + </voice> +</phrase> +<phrase> + id: LANG_GOTO_LAST_ALBUM + desc: in PictureFlow Main Menu + user: core + <source> + *: "Go to Last Album" + </source> + <dest> + *: "Go to Last Album" + </dest> + <voice> + *: "Go to Last Album" + </voice> +</phrase> diff --git a/apps/lang/italiano.lang b/apps/lang/italiano.lang index 0688ca7846..b6b97df22f 100644 --- a/apps/lang/italiano.lang +++ b/apps/lang/italiano.lang @@ -5324,19 +5324,17 @@ </phrase> <phrase> id: LANG_SET_AS_REC_DIR - desc: used in the onplay menu to set a recording dir + desc: deprecated user: core <source> *: none - recording: "Set As Recording Directory" + recording: "" </source> <dest> - *: none - recording: "Imposta come cartella di registrazione" + *: "" </dest> <voice> - *: none - recording: "Imposta come cartella di registrazione" + *: "" </voice> </phrase> <phrase> @@ -6038,18 +6036,21 @@ user: core <source> *: none - multivolume: "HD1" + hibylinux: "USB:" + multivolume: "HD1:" sansac200*,sansaclipplus,sansae200*,sansafuze*: "mSD:" xduoox3: "mSD2:" </source> <dest> *: none + hibylinux: "USB:" multivolume: "HD1" sansac200*,sansaclipplus,sansae200*,sansafuze*: "MSD:" xduoox3: "MSD2:" </dest> <voice> *: none + hibylinux: "U S B" multivolume: "HD 1" sansac200*,sansaclipplus,sansae200*,sansafuze*: "Micro S D" xduoox3: "Micro SD 2" @@ -6141,58 +6142,58 @@ </phrase> <phrase> id: LANG_INSERT - desc: in onplay menu. insert a track/playlist into dynamic playlist. + desc: deprecated user: core <source> - *: "Insert" + *: "" </source> <dest> - *: "Inserisci" + *: "" </dest> <voice> - *: "Inserisci" + *: "" </voice> </phrase> <phrase> id: LANG_INSERT_FIRST - desc: in onplay menu. insert a track/playlist into dynamic playlist. + desc: deprecated user: core <source> - *: "Insert Next" + *: "" </source> <dest> - *: "Inserisci come prossima" + *: "" </dest> <voice> - *: "Inserisci come prossima" + *: "" </voice> </phrase> <phrase> id: LANG_INSERT_LAST - desc: in onplay menu. append a track/playlist into dynamic playlist. + desc: deprecated user: core <source> - *: "Insert Last" + *: "" </source> <dest> - *: "Inserisci Come Ultima" + *: "" </dest> <voice> - *: "Inserisci Come Ultima" + *: "" </voice> </phrase> <phrase> id: LANG_INSERT_SHUFFLED - desc: in onplay menu. insert a track/playlist randomly into dynamic playlist + desc: deprecated user: core <source> - *: "Insert Shuffled" + *: "" </source> <dest> - *: "Mescola E Inserisci" + *: "" </dest> <voice> - *: "Mescola E Inserisci" + *: "" </voice> </phrase> <phrase> @@ -6365,16 +6366,16 @@ </phrase> <phrase> id: LANG_CATALOG_ADD_TO - desc: in onplay playlist catalogue submenu + desc: deprecated user: core <source> - *: "Add to Playlist" + *: "" </source> <dest> - *: "Aggiungi alla playlist" + *: "" </dest> <voice> - *: "Aggiungi alla playlist" + *: "" </voice> </phrase> <phrase> @@ -6763,7 +6764,7 @@ *: "<No Info>" </source> <dest> - *: "<No Info>" + *: "<Nessuna0 Info>" </dest> <voice> *: "Nessuna Informazione" @@ -10848,16 +10849,16 @@ </phrase> <phrase> id: LANG_INSERT_LAST_SHUFFLED - desc: in onplay menu. insert a playlist randomly at end of dynamic playlist + desc: deprecated user: core <source> - *: "Insert Last Shuffled" + *: "" </source> <dest> - *: "Mescola E Inserisci Come Ultima" + *: "" </dest> <voice> - *: "Mescola E Inserisci Come Ultima" + *: "" </voice> </phrase> <phrase> @@ -11455,16 +11456,16 @@ </phrase> <phrase> id: LANG_SET_AS_START_DIR - desc: used in the onplay menu to set a starting browser dir + desc: deprecated user: core <source> - *: "Start File Browser Here" + *: "" </source> <dest> - *: "Avvia Sfoglia File Da Qui" + *: "" </dest> <voice> - *: "Avvia Sfoglia File Da Qui" + *: "" </voice> </phrase> <phrase> @@ -11570,16 +11571,16 @@ </phrase> <phrase> id: LANG_SET_AS_PLAYLISTCAT_DIR - desc: used in the onplay menu to set a playlist catalogue dir + desc: deprecated user: core <source> - *: "Set As Playlist Catalogue Directory" + *: "" </source> <dest> - *: "Imposta Come Cartella Catalogo Playlist" + *: "" </dest> <voice> - *: "Imposta Come Cartella Catalogo Playlist" + *: "" </voice> </phrase> <phrase> @@ -11660,16 +11661,16 @@ </phrase> <phrase> id: LANG_AUTOMATIC - desc: generic automatic + desc: deprecated user: core <source> - *: "Automatic" + *: "" </source> <dest> - *: "Automatico" + *: "" </dest> <voice> - *: "Automatico" + *: "" </voice> </phrase> <phrase> @@ -12510,7 +12511,7 @@ </phrase> <phrase> id: LANG_DIRECT - desc: in the pictureflow settings + desc: in the pictureflow settings, also a volume adjustment mode user: core <source> *: "Direct" @@ -13069,16 +13070,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_ALBUM - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Album]" + *: "" </source> <dest> - *: "[Album]" + *: "" </dest> <voice> - *: "Album" + *: "" </voice> </phrase> <phrase> @@ -13198,16 +13199,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_ARTIST - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Artist]" + *: "" </source> <dest> - *: "[Artista]" + *: "" </dest> <voice> - *: "Artista" + *: "" </voice> </phrase> <phrase> @@ -13257,16 +13258,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_TITLE - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Title]" + *: "" </source> <dest> - *: "[Titolo]" + *: "" </dest> <voice> - *: "Titolo" + *: "" </voice> </phrase> <phrase> @@ -13532,16 +13533,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_DURATION - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Duration]" + *: "" </source> <dest> - *: "[Durata]" + *: "" </dest> <voice> - *: "Durata" + *: "" </voice> </phrase> <phrase> @@ -14879,16 +14880,16 @@ </phrase> <phrase> id: LANG_CLEAR_PLAYLIST - desc: in the pictureflow main menu + desc: deprecated user: core <source> - *: "Clear playlist" + *: "" </source> <dest> - *: "Svuota playlist" + *: "" </dest> <voice> - *: "Svuota playlist" + *: "" </voice> </phrase> <phrase> @@ -15507,16 +15508,16 @@ </phrase> <phrase> id: LANG_CLEAR_LIST_AND_PLAY_NEXT - desc: in onplay menu. Replace current playlist with selected tracks + desc: deprecated user: core <source> - *: "Clear List & Play Next" + *: "" </source> <dest> - *: "Cancella Lista e Riproduci Successivo" + *: "" </dest> <voice> - *: "Cancella Lista e Riproduci Successivo" + *: "" </voice> </phrase> <phrase> @@ -15637,16 +15638,16 @@ </phrase> <phrase> id: LANG_CLEAR_LIST_AND_PLAY_SHUFFLED - desc: in onplay menu. Replace current playlist with selected tracks in random order. + desc: deprecated user: core <source> - *: "Clear List & Play Shuffled" + *: "" </source> <dest> - *: "Cancella Lista e Riproduci in Ordine Casuale" + *: "" </dest> <voice> - *: "Cancella Lista e Riproduci in Ordine Casuale" + *: "" </voice> </phrase> <phrase> @@ -15874,128 +15875,128 @@ </phrase> <phrase> id: LANG_PROPERTIES_ALBUMARTIST - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Album Artist]" + *: "" </source> <dest> - *: "[Artista Album]" + *: "" </dest> <voice> - *: "Artista Album" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_GENRE - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Genre]" + *: "" </source> <dest> - *: "[Genere]" + *: "" </dest> <voice> - *: "Genere" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_COMMENT - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Comment]" + *: "" </source> <dest> - *: "[Commento]" + *: "" </dest> <voice> - *: "Commento" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_COMPOSER - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Composer]" + *: "" </source> <dest> - *: "[Compositore]" + *: "" </dest> <voice> - *: "Compositore" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_YEAR - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Year]" + *: "" </source> <dest> - *: "[Anno]" + *: "" </dest> <voice> - *: "Anno" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_TRACKNUM - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Tracknum]" + *: "" </source> <dest> - *: "[Numtraccia]" + *: "" </dest> <voice> - *: "Numero traccia" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_DISCNUM - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Discnum]" + *: "" </source> <dest> - *: "[Numdisco]" + *: "" </dest> <voice> - *: "Numero disco" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_FREQUENCY - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Frequency]" + *: "" </source> <dest> - *: "[Frequenza]" + *: "" </dest> <voice> - *: "Frequenza" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_BITRATE - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Bitrate]" + *: "" </source> <dest> - *: "[Bitrate]" + *: "" </dest> <voice> - *: "Bitrate" + *: "" </voice> </phrase> <phrase> @@ -16239,3 +16240,329 @@ *: "La cache deve prima completare l'aggiornamento!" </voice> </phrase> +<phrase> + id: LANG_TRACK_INFO + desc: Track Info Title + user: core + <source> + *: "Track Info" + </source> + <dest> + *: "Info Traccia" + </dest> + <voice> + *: "Info Traccia" + </voice> +</phrase> +<phrase> + id: LANG_PLAY + desc: play selected file/directory, in playlist context menu + user: core + <source> + *: "Play" + </source> + <dest> + *: "Riproduci" + </dest> + <voice> + *: "Riproduci" + </voice> +</phrase> +<phrase> + id: LANG_PLAY_SHUFFLED + desc: play selected files in shuffled order, in playlist context menu + user: core + <source> + *: "Play Shuffled" + </source> + <dest> + *: "Riproduci Casualmente" + </dest> + <voice> + *: "Riproduci Casualmente" + </voice> +</phrase> +<phrase> + id: LANG_KEEP_CURRENT_TRACK_ON_REPLACE + desc: used in the playlist settings menu + user: core + <source> + *: "Keep Current Track When Replacing Playlist" + </source> + <dest> + *: "Mantieni La Traccia Corrente Quando Sostituisci La Playlist" + </dest> + <voice> + *: "Mantieni La Traccia Corrente Quando Sostituisci La Playlist" + </voice> +</phrase> +<phrase> + id: LANG_CLEAR_SETTINGS_ON_HOLD + desc: in the system sub menu + user: core + <source> + *: none + clear_settings_on_hold,iriverh10: "Clear settings when reset button is held during startup" + ipod4g,ipodcolor,ipodmini1g,ipodmini2g,ipodnano1g,ipodvideo: "Clear settings when hold switch is on during startup" + </source> + <dest> + *: none + clear_settings_on_hold,iriverh10: "Cancella le impostazioni quando si tiene premuto il pulsante reset durante l'avvio" + ipod4g,ipodcolor,ipodmini1g,ipodmini2g,ipodnano1g,ipodvideo: "Cancella le impostazioni quando l'interruttore di blocco è attivo durante l'avvio" + </dest> + <voice> + *: none + clear_settings_on_hold,iriverh10: "Cancella le impostazioni quando si tiene premuto il pulsante reset durante l'avvio" + ipod4g,ipodcolor,ipodmini1g,ipodmini2g,ipodnano1g,ipodvideo: "Cancella le impostazioni quando l'interruttore di blocco è attivo durante l'avvio" + </voice> +</phrase> +<phrase> + id: LANG_REWIND_ACROSS_TRACKS + desc: in playback settings menu + user: core + <source> + *: "Rewind Across Tracks" + </source> + <dest> + *: "Riavvolgi tra le tracce" + </dest> + <voice> + *: "Riavvolgi tra le tracce" + </voice> +</phrase> +<phrase> + id: LANG_SET_AS + desc: used in the onplay menu + user: core + <source> + *: "Set As..." + </source> + <dest> + *: "Imposta Come..." + </dest> + <voice> + *: "Imposta Come..." + </voice> +</phrase> +<phrase> + id: LANG_PLAYLIST_DIR + desc: used in the onplay menu + user: core + <source> + *: "Playlist Directory" + </source> + <dest> + *: "Cartella Playlist" + </dest> + <voice> + *: "Cartella Playlist" + </voice> +</phrase> +<phrase> + id: LANG_START_DIR + desc: used in the onplay menu + user: core + <source> + *: "Start Directory" + </source> + <dest> + *: "Cartella Iniziale" + </dest> + <voice> + *: "Cartella Iniziale" + </voice> +</phrase> +<phrase> + id: LANG_RECORDING_DIR + desc: used in the onplay menu + user: core + <source> + *: none + recording: "Recording Directory" + </source> + <dest> + *: none + recording: "Cartella Di Registrazione" + </dest> + <voice> + *: none + recording: "Cartella Di Registrazione" + </voice> +</phrase> +<phrase> + id: LANG_ADD_TO_PL + desc: used in the onplay menu + user: core + <source> + *: "Add to Playlist..." + </source> + <dest> + *: "Aggiungi alla Playlist..." + </dest> + <voice> + *: "Aggiungi alla Playlist..." + </voice> +</phrase> +<phrase> + id: LANG_ADD_TO_EXISTING_PL + desc: used in the onplay menu + user: core + <source> + *: "Add to Existing Playlist" + </source> + <dest> + *: "Aggiungi alla Playlist Esistente" + </dest> + <voice> + *: "Aggiungi alla Playlist Esistente" + </voice> +</phrase> +<phrase> + id: LANG_PLAYING_NEXT + desc: used in the onplay menu + user: core + <source> + *: "Playing Next..." + </source> + <dest> + *: "Riproduzione Brano Successivo..." + </dest> + <voice> + *: "Riproduzione Brano Successivo..." + </voice> +</phrase> +<phrase> + id: LANG_PLAY_NEXT + desc: used in the onplay menu + user: core + <source> + *: "Play Next" + </source> + <dest> + *: "Riproduci Successivo" + </dest> + <voice> + *: "Riproduci Successivo" + </voice> +</phrase> +<phrase> + id: LANG_ADD_SHUFFLED + desc: used in the onplay menu + user: core + <source> + *: "Add Shuffled" + </source> + <dest> + *: "Aggiungi Casualmente" + </dest> + <voice> + *: "Aggiungi Casualmente" + </voice> +</phrase> +<phrase> + id: LANG_PLAY_LAST + desc: used in the onplay menu + user: core + <source> + *: "Play Last" + </source> + <dest> + *: "Riproduci Ultimo" + </dest> + <voice> + *: "Riproduci Ultimo" + </voice> +</phrase> +<phrase> + id: LANG_PLAY_LAST_SHUFFLED + desc: used in the onplay menu + user: core + <source> + *: "Play Last Shuffled" + </source> + <dest> + *: "Riproduci Ultimo Casualmente" + </dest> + <voice> + *: "Riproduci Ultimo Casualmente" + </voice> +</phrase> +<phrase> + id: LANG_VOLUME_ADJUST_MODE + desc: in system settings + user: core + <source> + *: none + perceptual_volume: "Volume Adjustment Mode" + </source> + <dest> + *: none + perceptual_volume: "Modalità Aggiustamento Volume" + </dest> + <voice> + *: none + perceptual_volume: "Modalità Aggiustamento Volume" + </voice> +</phrase> +<phrase> + id: LANG_VOLUME_ADJUST_NORM_STEPS + desc: in system settings + user: core + <source> + *: none + perceptual_volume: "Number of Volume Steps" + </source> + <dest> + *: none + perceptual_volume: "Numero di Passi per il Volume" + </dest> + <voice> + *: none + perceptual_volume: "Numero di Passi per il Volume" + </voice> +</phrase> +<phrase> + id: LANG_PERCEPTUAL + desc: in system settings -> volume adjustment mode + user: core + <source> + *: none + perceptual_volume: "Perceptual" + </source> + <dest> + *: none + perceptual_volume: "Percettivo" + </dest> + <voice> + *: none + perceptual_volume: "Percettivo" + </voice> +</phrase> +<phrase> + id: LANG_SHOW_TRACKS_WHILE_BROWSING + desc: in PictureFlow Main Menu + user: core + <source> + *: "Show Tracks While Browsing" + </source> + <dest> + *: "Mostra tracce durante la navigazione" + </dest> + <voice> + *: "Mostra tracce durante la navigazione" + </voice> +</phrase> +<phrase> + id: LANG_GOTO_LAST_ALBUM + desc: in PictureFlow Main Menu + user: core + <source> + *: "Go to Last Album" + </source> + <dest> + *: "Vai all'Ultimo Album" + </dest> + <voice> + *: "Vai all'Ultimo Album" + </voice> +</phrase> diff --git a/apps/lang/nederlands.lang b/apps/lang/nederlands.lang index 5fbd93df81..83139cc6de 100644 --- a/apps/lang/nederlands.lang +++ b/apps/lang/nederlands.lang @@ -4250,31 +4250,16 @@ </phrase> <phrase> id: LANG_ALARM_MOD_KEYS - desc: Shown key functions in alarm menu (for the RTC alarm mod). + desc: deprecated user: core <source> - *: none - alarm: "PLAY=Set OFF=Cancel" - gigabeats: "SELECT=Set POWER=Cancel" - ipod*: "SELECT=Set MENU=Cancel" - iriverh10,iriverh10_5gb: "SELECT=Set PREV=Cancel" - mpiohd300: "ENTER=Set MENU=Cancel" - sansafuzeplus: "SELECT=Set BACK=Cancel" - vibe500: "OK=Set C=Cancel" + *: "" </source> <dest> - *: none - alarm: "PLAY=Instellen, OFF=Annuleren" - gigabeats: "SELECT=Instellen, POWER=Annuleren" - ipod*: "SELECT=Instellen, MENU=Annuleren" - iriverh10,iriverh10_5gb: "SELECT=Instellen, PREV=Annuleren" - mpiohd300: "ENTER=Instellen, MENU=Annuleren" - sansafuzeplus: "SELECT=Instellen, BACK=Annuleren" - vibe500: "OK=Instellen, C=Annuleren" + *: "" </dest> <voice> - *: none - alarm,ipod*: "" + *: "" </voice> </phrase> <phrase> @@ -7580,10 +7565,10 @@ </phrase> <phrase> id: LANG_AUDIOSCROBBLER - desc: "Last.fm Log" in the playback menu + desc: "Last.fm Logger" in Plugin/apps/scrobbler user: core <source> - *: "Last.fm Log" + *: "Last.fm Logger" </source> <dest> *: "Last.fm-logboek" @@ -14430,58 +14415,58 @@ </phrase> <phrase> id: LANG_PROPERTIES_ARTIST - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Artist]" + *: "" </source> <dest> - *: "[Artiest]" + *: "" </dest> <voice> - *: "Artiest" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_TITLE - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Title]" + *: "" </source> <dest> - *: "[Titel]" + *: "" </dest> <voice> - *: "Titel" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_ALBUM - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Album]" + *: "" </source> <dest> - *: "[Album]" + *: "" </dest> <voice> - *: "Album" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_DURATION - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Duration]" + *: "" </source> <dest> - *: "[Looptijd]" + *: "" </dest> <voice> - *: "Looptijd" + *: "" </voice> </phrase> <phrase> @@ -14683,7 +14668,7 @@ lowmem: none </dest> <voice> - *: "CPU Boost" + *: "CPU-boost" lowmem: none </voice> </phrase> @@ -15744,16 +15729,16 @@ </phrase> <phrase> id: LANG_CLEAR_LIST_AND_PLAY_NEXT - desc: in onplay menu. Replace current playlist with selected tracks + desc: deprecated user: core <source> - *: "Clear List & Play Next" + *: "" </source> <dest> - *: "Lijst Wissen en Volgende Afspelen" + *: "" </dest> <voice> - *: "Lijst Wissen en Volgende Afspelen" + *: "" </voice> </phrase> <phrase> @@ -15814,16 +15799,16 @@ </phrase> <phrase> id: LANG_CLEAR_LIST_AND_PLAY_SHUFFLED - desc: in onplay menu. Replace current playlist with selected tracks in random order. + desc: deprecated user: core <source> - *: "Clear List & Play Shuffled" + *: "" </source> <dest> - *: "Lijst Wissen en in Geschude Volgorde Afspelen" + *: "" </dest> <voice> - *: "Lijst Wissen en in Geschude Volgorde Afspelen" + *: "" </voice> </phrase> <phrase> @@ -15898,128 +15883,128 @@ </phrase> <phrase> id: LANG_PROPERTIES_ALBUMARTIST - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Album Artist]" + *: "" </source> <dest> - *: "[Album Artiest]" + *: "" </dest> <voice> - *: "Album Artiest" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_GENRE - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Genre]" + *: "" </source> <dest> - *: "[Genre]" + *: "" </dest> <voice> - *: "Genre" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_COMMENT - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Comment]" + *: "" </source> <dest> - *: "[Commentaar]" + *: "" </dest> <voice> - *: "Commentaar" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_COMPOSER - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Composer]" + *: "" </source> <dest> - *: "[Componist]" + *: "" </dest> <voice> - *: "Componist" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_YEAR - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Year]" + *: "" </source> <dest> - *: "[Jaar]" + *: "" </dest> <voice> - *: "Jaar" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_TRACKNUM - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Tracknum]" + *: "" </source> <dest> - *: "[Tracknum]" + *: "" </dest> <voice> - *: "Tracknummer" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_DISCNUM - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Discnum]" + *: "" </source> <dest> - *: "[Schijfnum]" + *: "" </dest> <voice> - *: "Schijfnummer" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_FREQUENCY - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Frequency]" + *: "" </source> <dest> - *: "[Frequentie]" + *: "" </dest> <voice> - *: "Frequentie" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_BITRATE - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Bitrate]" + *: "" </source> <dest> - *: "[Bitsnelheid]" + *: "" </dest> <voice> - *: "Bitsnelheid" + *: "" </voice> </phrase> <phrase> @@ -16120,3 +16105,222 @@ *: "Aflopend" </voice> </phrase> +<phrase> + id: LANG_ALBUM_ART + desc: in Settings + user: core + <source> + *: "Album Art" + </source> + <dest> + *: "Albumhoezen" + </dest> + <voice> + *: "Albumhoezen" + </voice> +</phrase> +<phrase> + id: LANG_PREFER_EMBEDDED + desc: in Settings + user: core + <source> + *: "Prefer Embedded" + </source> + <dest> + *: "Liever Ingesloten" + </dest> + <voice> + *: "Liever Ingesloten" + </voice> +</phrase> +<phrase> + id: LANG_PREFER_IMAGE_FILE + desc: in Settings + user: core + <source> + *: "Prefer Image File" + </source> + <dest> + *: "Liever Afbeeldingsbestand" + </dest> + <voice> + *: "Liever Afbeeldingsbestand" + </voice> +</phrase> +<phrase> + id: LANG_FM_SYNC_RDS_TIME + desc: in radio screen and Settings + user: core + <source> + *: none + rds: "Sync RDS Time" + </source> + <dest> + *: none + rds: "RDS-tijd Synchroniseren" + </dest> + <voice> + *: none + rds: "RDS Tijd Synchroniseren" + </voice> +</phrase> +<phrase> + id: LANG_SORT_ALBUMS_BY + desc: in Settings + user: core + <source> + *: "Sort albums by" + </source> + <dest> + *: "Sorteer albums op" + </dest> + <voice> + *: "Sorteer albums op" + </voice> +</phrase> +<phrase> + id: LANG_ARTIST_PLUS_NAME + desc: in Settings + user: core + <source> + *: "Artist + Name" + </source> + <dest> + *: "Artiest + Naam" + </dest> + <voice> + *: "Artiest En Naam" + </voice> +</phrase> +<phrase> + id: LANG_ARTIST_PLUS_YEAR + desc: in Settings + user: core + <source> + *: "Artist + Year" + </source> + <dest> + *: "Artiest + Jaar" + </dest> + <voice> + *: "Artiest En Jaar" + </voice> +</phrase> +<phrase> + id: LANG_YEAR_SORT_ORDER + desc: in Settings + user: core + <source> + *: "Year sort order" + </source> + <dest> + *: "Sorteervolgorde jaar" + </dest> + <voice> + *: "Sorteer volgorde jaar" + </voice> +</phrase> +<phrase> + id: LANG_SHOW_YEAR_IN_ALBUM_TITLE + desc: in Settings + user: core + <source> + *: "Show year in album title" + </source> + <dest> + *: "Jaar in albumtitel weergeven" + </dest> + <voice> + *: "Jaar in albumtitel weergeven" + </voice> +</phrase> +<phrase> + id: LANG_WAIT_FOR_CACHE + desc: in Settings + user: core + <source> + *: "Cache needs to finish updating first!" + </source> + <dest> + *: "Cache moet eerst de update voltooien!" + </dest> + <voice> + *: "Cache moet eerst de update voltooien!" + </voice> +</phrase> +<phrase> + id: LANG_TRACK_INFO + desc: Track Info Title + user: core + <source> + *: "Track Info" + </source> + <dest> + *: "Nummer Info" + </dest> + <voice> + *: "Nummer Info" + </voice> +</phrase> +<phrase> + id: LANG_PLAY + desc: play selected file/directory, in playlist context menu + user: core + <source> + *: "Play" + </source> + <dest> + *: "Speel" + </dest> + <voice> + *: "Speel" + </voice> +</phrase> +<phrase> + id: LANG_PLAY_SHUFFLED + desc: play selected files in shuffled order, in playlist context menu + user: core + <source> + *: "Play Shuffled" + </source> + <dest> + *: "Geschud Afspelen" + </dest> + <voice> + *: "Geschud Afspelen" + </voice> +</phrase> +<phrase> + id: LANG_KEEP_CURRENT_TRACK_ON_REPLACE + desc: used in the playlist settings menu + user: core + <source> + *: "Keep Current Track When Replacing Playlist" + </source> + <dest> + *: "Huidige Track Behouden bij het Vervangen van een Afspeellijst" + </dest> + <voice> + *: "Huidige Track Behouden bij het Vervangen van een Afspeellijst" + </voice> +</phrase> +<phrase> + id: LANG_CLEAR_SETTINGS_ON_HOLD + desc: in the system sub menu + user: core + <source> + *: none + clear_settings_on_hold,iriverh10: "Clear settings when reset button is held during startup" + ipod4g,ipodcolor,ipodmini1g,ipodmini2g,ipodnano1g,ipodvideo: "Clear settings when hold switch is on during startup" + </source> + <dest> + *: none + clear_settings_on_hold,iriverh10: "Instellingen wissen wanneer de resetknop wordt ingedrukt tijdens het opstarten" + ipod4g,ipodcolor,ipodmini1g,ipodmini2g,ipodnano1g,ipodvideo: "Instellingen wissen wanneer de houd-schakelaar aan staat tijdens het opstarten" + </dest> + <voice> + *: none + clear_settings_on_hold,iriverh10: "Instellingen wissen wanneer de resetknop wordt ingedrukt tijdens het opstarten" + ipod4g,ipodcolor,ipodmini1g,ipodmini2g,ipodnano1g,ipodvideo: "Instellingen wissen wanneer de houd schakelaar aan staat tijdens het opstarten" + </voice> +</phrase> diff --git a/apps/lang/polski.lang b/apps/lang/polski.lang index 91998e8eb1..849566d60d 100644 --- a/apps/lang/polski.lang +++ b/apps/lang/polski.lang @@ -4102,31 +4102,16 @@ </phrase> <phrase> id: LANG_ALARM_MOD_KEYS - desc: Shown key functions in alarm menu (for the RTC alarm mod). + desc: deprecated user: core <source> - *: none - alarm: "PLAY=Set OFF=Cancel" - gigabeats: "SELECT=Set POWER=Cancel" - ipod*: "SELECT=Set MENU=Cancel" - iriverh10,iriverh10_5gb: "SELECT=Set PREV=Cancel" - mpiohd300: "ENTER=Set MENU=Cancel" - sansafuzeplus: "SELECT=Set BACK=Cancel" - vibe500: "OK=Set C=Cancel" + *: "" </source> <dest> - *: none - alarm: "PLAY=Ustaw OFF=Anuluj" - gigabeats: "WYBIERZ=Ustaw POWER=Anuluj" - ipod*: "WYBIERZ=Ustaw MENU=Anuluj" - iriverh10,iriverh10_5gb: "WYBIERZ=Ustaw COFNIJ=Anuluj" - mpiohd300: "ENTER=Ustaw MENU=Anuluj" - sansafuzeplus: "SELECT=Ustaw BACK=Anuluj" - vibe500: "OK=Ustaw C=Anuluj" + *: "" </dest> <voice> - *: none - alarm,ipod*: "" + *: "" </voice> </phrase> <phrase> @@ -5345,19 +5330,17 @@ </phrase> <phrase> id: LANG_SET_AS_REC_DIR - desc: used in the onplay menu to set a recording dir + desc: deprecated user: core <source> *: none - recording: "Set As Recording Directory" + recording: "" </source> <dest> - *: none - recording: "Ustaw jako katalog nagrywania" + *: "" </dest> <voice> - *: none - recording: "Ustaw jako katalog nagrywania" + *: "" </voice> </phrase> <phrase> @@ -6059,18 +6042,21 @@ user: core <source> *: none - multivolume: "HD1" + hibylinux: "USB:" + multivolume: "HD1:" sansac200*,sansaclipplus,sansae200*,sansafuze*: "mSD:" xduoox3: "mSD2:" </source> <dest> *: none + hibylinux: "USB:" multivolume: "HD1" sansac200*,sansaclipplus,sansae200*,sansafuze*: "mSD:" xduoox3: "mSD2:" </dest> <voice> *: none + hibylinux: "U S B" multivolume: "ha de 1" sansac200*,sansaclipplus,sansae200*,sansafuze*: "mikro es de" xduoox3: "mikro es de 2" @@ -6162,58 +6148,58 @@ </phrase> <phrase> id: LANG_INSERT - desc: in onplay menu. insert a track/playlist into dynamic playlist. + desc: deprecated user: core <source> - *: "Insert" + *: "" </source> <dest> - *: "Wstaw" + *: "" </dest> <voice> - *: "Wstaw" + *: "" </voice> </phrase> <phrase> id: LANG_INSERT_FIRST - desc: in onplay menu. insert a track/playlist into dynamic playlist. + desc: deprecated user: core <source> - *: "Insert Next" + *: "" </source> <dest> - *: "Wstaw następne" + *: "" </dest> <voice> - *: "Wstaw następne" + *: "" </voice> </phrase> <phrase> id: LANG_INSERT_LAST - desc: in onplay menu. append a track/playlist into dynamic playlist. + desc: deprecated user: core <source> - *: "Insert Last" + *: "" </source> <dest> - *: "Wstaw ostatnie" + *: "" </dest> <voice> - *: "Wstaw ostatnie" + *: "" </voice> </phrase> <phrase> id: LANG_INSERT_SHUFFLED - desc: in onplay menu. insert a track/playlist randomly into dynamic playlist + desc: deprecated user: core <source> - *: "Insert Shuffled" + *: "" </source> <dest> - *: "Wstaw losowo" + *: "" </dest> <voice> - *: "Wstaw losowo" + *: "" </voice> </phrase> <phrase> @@ -6386,16 +6372,16 @@ </phrase> <phrase> id: LANG_CATALOG_ADD_TO - desc: in onplay playlist catalogue submenu + desc: deprecated user: core <source> - *: "Add to Playlist" + *: "" </source> <dest> - *: "Dołącz do listy" + *: "" </dest> <voice> - *: "Dołącz do listy odtwarzania" + *: "" </voice> </phrase> <phrase> @@ -10706,16 +10692,16 @@ </phrase> <phrase> id: LANG_INSERT_LAST_SHUFFLED - desc: in onplay menu. insert a playlist randomly at end of dynamic playlist + desc: deprecated user: core <source> - *: "Insert Last Shuffled" + *: "" </source> <dest> - *: "Wstaw losowo na koniec" + *: "" </dest> <voice> - *: "Wstaw losowo na koniec" + *: "" </voice> </phrase> <phrase> @@ -11490,16 +11476,16 @@ </phrase> <phrase> id: LANG_SET_AS_START_DIR - desc: used in the onplay menu to set a starting browser dir + desc: deprecated user: core <source> - *: "Start File Browser Here" + *: "" </source> <dest> - *: "Rozpocznij przeglądanie plików tutaj" + *: "" </dest> <voice> - *: "Rozpocznij przeglądanie plików tutaj" + *: "" </voice> </phrase> <phrase> @@ -11605,16 +11591,16 @@ </phrase> <phrase> id: LANG_SET_AS_PLAYLISTCAT_DIR - desc: used in the onplay menu to set a playlist catalogue dir + desc: deprecated user: core <source> - *: "Set As Playlist Catalogue Directory" + *: "" </source> <dest> - *: "Ustaw jako katalog list odtwarzania" + *: "" </dest> <voice> - *: "Ustaw jako katalog list odtwarzania" + *: "" </voice> </phrase> <phrase> @@ -13182,16 +13168,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_ALBUM - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Album]" + *: "" </source> <dest> - *: "[Album]" + *: "" </dest> <voice> - *: "Album" + *: "" </voice> </phrase> <phrase> @@ -13314,16 +13300,16 @@ </phrase> <phrase> id: LANG_CLEAR_PLAYLIST - desc: in the pictureflow main menu + desc: deprecated user: core <source> - *: "Clear playlist" + *: "" </source> <dest> - *: "Wyczyść listę odtwarzania" + *: "" </dest> <voice> - *: "Wyczyść listę odtwarzania" + *: "" </voice> </phrase> <phrase> @@ -13654,16 +13640,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_DURATION - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Duration]" + *: "" </source> <dest> - *: "[Czas trwania]" + *: "" </dest> <voice> - *: "Czas trwania" + *: "" </voice> </phrase> <phrase> @@ -14224,16 +14210,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_ARTIST - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Artist]" + *: "" </source> <dest> - *: "[Artysta]" + *: "" </dest> <voice> - *: "Artysta" + *: "" </voice> </phrase> <phrase> @@ -14900,30 +14886,30 @@ </phrase> <phrase> id: LANG_PROPERTIES_TITLE - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Title]" + *: "" </source> <dest> - *: "[Tytuł]" + *: "" </dest> <voice> - *: "Tytuł" + *: "" </voice> </phrase> <phrase> id: LANG_DIRECT - desc: in the pictureflow settings + desc: in the pictureflow settings, also a volume adjustment mode user: core <source> *: "Direct" </source> <dest> - *: "Bezpośrednie" + *: "Bezpośrednio" </dest> <voice> - *: "Bezpośrednie" + *: "Bezpośrednio" </voice> </phrase> <phrase> @@ -15528,16 +15514,16 @@ </phrase> <phrase> id: LANG_CLEAR_LIST_AND_PLAY_NEXT - desc: in onplay menu. Replace current playlist with selected tracks + desc: deprecated user: core <source> - *: "Clear List & Play Next" + *: "" </source> <dest> - *: "Wyczyść listę i odtwarzaj następne" + *: "" </dest> <voice> - *: "Wyczyść listę i odtwarzaj następne" + *: "" </voice> </phrase> <phrase> @@ -15598,16 +15584,16 @@ </phrase> <phrase> id: LANG_CLEAR_LIST_AND_PLAY_SHUFFLED - desc: in onplay menu. Replace current playlist with selected tracks in random order. + desc: deprecated user: core <source> - *: "Clear List & Play Shuffled" + *: "" </source> <dest> - *: "Wyczyść listę i odtwarzaj losowe" + *: "" </dest> <voice> - *: "Wyczyść listę i odtwarzaj losowe" + *: "" </voice> </phrase> <phrase> @@ -15881,128 +15867,128 @@ </phrase> <phrase> id: LANG_PROPERTIES_ALBUMARTIST - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Album Artist]" + *: "" </source> <dest> - *: "[Wykonawca albumu]" + *: "" </dest> <voice> - *: "Wykonawca albumu" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_GENRE - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Genre]" + *: "" </source> <dest> - *: "[Gatunek]" + *: "" </dest> <voice> - *: "Gatunek" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_COMMENT - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Comment]" + *: "" </source> <dest> - *: "[Komentarz]" + *: "" </dest> <voice> - *: "Komentarz" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_COMPOSER - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Composer]" + *: "" </source> <dest> - *: "[Kompozytor]" + *: "" </dest> <voice> - *: "Kompozytor" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_YEAR - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Year]" + *: "" </source> <dest> - *: "[Rok]" + *: "" </dest> <voice> - *: "Rok" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_TRACKNUM - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Tracknum]" + *: "" </source> <dest> - *: "[Nr utworu]" + *: "" </dest> <voice> - *: "Numer utworu" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_DISCNUM - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Discnum]" + *: "" </source> <dest> - *: "[Nr płyty]" + *: "" </dest> <voice> - *: "Numer płyty" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_FREQUENCY - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Frequency]" + *: "" </source> <dest> - *: "[Częstotliwość]" + *: "" </dest> <voice> - *: "Częstotliwość" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_BITRATE - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Bitrate]" + *: "" </source> <dest> - *: "[Prędkość transmisji]" + *: "" </dest> <voice> - *: "Prędkość transmisji" + *: "" </voice> </phrase> <phrase> @@ -16260,3 +16246,329 @@ *: "Pamięć podręczna musi najpierw zakończyć aktualizację!" </voice> </phrase> +<phrase> + id: LANG_TRACK_INFO + desc: Track Info Title + user: core + <source> + *: "Track Info" + </source> + <dest> + *: "Informacje o utworze" + </dest> + <voice> + *: "Informacje o utworze" + </voice> +</phrase> +<phrase> + id: LANG_PLAY + desc: play selected file/directory, in playlist context menu + user: core + <source> + *: "Play" + </source> + <dest> + *: "Odtwarzaj" + </dest> + <voice> + *: "Odtwarzaj" + </voice> +</phrase> +<phrase> + id: LANG_PLAY_SHUFFLED + desc: play selected files in shuffled order, in playlist context menu + user: core + <source> + *: "Play Shuffled" + </source> + <dest> + *: "Odtwarzaj losowe" + </dest> + <voice> + *: "Odtwarzaj losowe" + </voice> +</phrase> +<phrase> + id: LANG_KEEP_CURRENT_TRACK_ON_REPLACE + desc: used in the playlist settings menu + user: core + <source> + *: "Keep Current Track When Replacing Playlist" + </source> + <dest> + *: "Zachowaj bieżący utwór podczas zastępowania listy odtwarzania" + </dest> + <voice> + *: "Zachowaj bieżący utwór podczas zastępowania listy odtwarzania" + </voice> +</phrase> +<phrase> + id: LANG_CLEAR_SETTINGS_ON_HOLD + desc: in the system sub menu + user: core + <source> + *: none + clear_settings_on_hold,iriverh10: "Clear settings when reset button is held during startup" + ipod4g,ipodcolor,ipodmini1g,ipodmini2g,ipodnano1g,ipodvideo: "Clear settings when hold switch is on during startup" + </source> + <dest> + *: none + clear_settings_on_hold,iriverh10: "Wyczyść ustawienia, gdy przycisk resetowania będzie przytrzymany podczas uruchamiania" + ipod4g,ipodcolor,ipodmini1g,ipodmini2g,ipodnano1g,ipodvideo: "Wyczyść ustawienia, gdy przełącznik blokady będzie włączony podczas uruchamiania" + </dest> + <voice> + *: none + clear_settings_on_hold,iriverh10: "Wyczyść ustawienia, gdy przycisk resetowania będzie przytrzymany podczas uruchamiania" + ipod4g,ipodcolor,ipodmini1g,ipodmini2g,ipodnano1g,ipodvideo: "Wyczyść ustawienia, gdy przełącznik blokady będzie włączony podczas uruchamiania" + </voice> +</phrase> +<phrase> + id: LANG_REWIND_ACROSS_TRACKS + desc: in playback settings menu + user: core + <source> + *: "Rewind Across Tracks" + </source> + <dest> + *: "Przewiń poprzez utwory" + </dest> + <voice> + *: "Przewiń poprzez utwory" + </voice> +</phrase> +<phrase> + id: LANG_SET_AS + desc: used in the onplay menu + user: core + <source> + *: "Set As..." + </source> + <dest> + *: "Ustaw jako..." + </dest> + <voice> + *: "Ustaw jako..." + </voice> +</phrase> +<phrase> + id: LANG_PLAYLIST_DIR + desc: used in the onplay menu + user: core + <source> + *: "Playlist Directory" + </source> + <dest> + *: "Katalog list odtwarzania" + </dest> + <voice> + *: "Katalog list odtwarzania" + </voice> +</phrase> +<phrase> + id: LANG_START_DIR + desc: used in the onplay menu + user: core + <source> + *: "Start Directory" + </source> + <dest> + *: "Katalog startowy" + </dest> + <voice> + *: "Katalog startowy" + </voice> +</phrase> +<phrase> + id: LANG_RECORDING_DIR + desc: used in the onplay menu + user: core + <source> + *: none + recording: "Recording Directory" + </source> + <dest> + *: none + recording: "Katalog nagrywania" + </dest> + <voice> + *: none + recording: "Katalog nagrywania" + </voice> +</phrase> +<phrase> + id: LANG_ADD_TO_PL + desc: used in the onplay menu + user: core + <source> + *: "Add to Playlist..." + </source> + <dest> + *: "Dodaj do listy odtwarzania..." + </dest> + <voice> + *: "Dodaj do listy odtwarzania..." + </voice> +</phrase> +<phrase> + id: LANG_ADD_TO_EXISTING_PL + desc: used in the onplay menu + user: core + <source> + *: "Add to Existing Playlist" + </source> + <dest> + *: "Dodaj do istniejącej listy odtwarzania" + </dest> + <voice> + *: "Dodaj do istniejącej listy odtwarzania" + </voice> +</phrase> +<phrase> + id: LANG_PLAYING_NEXT + desc: used in the onplay menu + user: core + <source> + *: "Playing Next..." + </source> + <dest> + *: "Odtwarzanie następnego..." + </dest> + <voice> + *: "Odtwarzanie następnego..." + </voice> +</phrase> +<phrase> + id: LANG_PLAY_NEXT + desc: used in the onplay menu + user: core + <source> + *: "Play Next" + </source> + <dest> + *: "Odtwórz następny" + </dest> + <voice> + *: "Odtwórz następny" + </voice> +</phrase> +<phrase> + id: LANG_ADD_SHUFFLED + desc: used in the onplay menu + user: core + <source> + *: "Add Shuffled" + </source> + <dest> + *: "Dodaj losowy" + </dest> + <voice> + *: "Dodaj losowy" + </voice> +</phrase> +<phrase> + id: LANG_PLAY_LAST + desc: used in the onplay menu + user: core + <source> + *: "Play Last" + </source> + <dest> + *: "Odtwórz ostatni" + </dest> + <voice> + *: "Odtwórz ostatni" + </voice> +</phrase> +<phrase> + id: LANG_PLAY_LAST_SHUFFLED + desc: used in the onplay menu + user: core + <source> + *: "Play Last Shuffled" + </source> + <dest> + *: "Odtwórz ostatni losowy" + </dest> + <voice> + *: "Odtwórz ostatni losowy" + </voice> +</phrase> +<phrase> + id: LANG_VOLUME_ADJUST_MODE + desc: in system settings + user: core + <source> + *: none + perceptual_volume: "Volume Adjustment Mode" + </source> + <dest> + *: none + perceptual_volume: "Tryb regulacji głośności" + </dest> + <voice> + *: none + perceptual_volume: "Tryb regulacji głośności" + </voice> +</phrase> +<phrase> + id: LANG_VOLUME_ADJUST_NORM_STEPS + desc: in system settings + user: core + <source> + *: none + perceptual_volume: "Number of Volume Steps" + </source> + <dest> + *: none + perceptual_volume: "Liczba kroków głośności" + </dest> + <voice> + *: none + perceptual_volume: "Liczba kroków głośności" + </voice> +</phrase> +<phrase> + id: LANG_PERCEPTUAL + desc: in system settings -> volume adjustment mode + user: core + <source> + *: none + perceptual_volume: "Perceptual" + </source> + <dest> + *: none + perceptual_volume: "Percepcyjny" + </dest> + <voice> + *: none + perceptual_volume: "Percepcyjny" + </voice> +</phrase> +<phrase> + id: LANG_SHOW_TRACKS_WHILE_BROWSING + desc: in PictureFlow Main Menu + user: core + <source> + *: "Show Tracks While Browsing" + </source> + <dest> + *: "Pokazuj utwory podczas przeglądania" + </dest> + <voice> + *: "Pokazuj utwory podczas przeglądania" + </voice> +</phrase> +<phrase> + id: LANG_GOTO_LAST_ALBUM + desc: in PictureFlow Main Menu + user: core + <source> + *: "Go to Last Album" + </source> + <dest> + *: "Przejdź do ostatniego albumu" + </dest> + <voice> + *: "Przejdź do ostatniego albumu" + </voice> +</phrase> diff --git a/apps/lang/slovak.lang b/apps/lang/slovak.lang index f68b7e12f8..2efe3b7b35 100644 --- a/apps/lang/slovak.lang +++ b/apps/lang/slovak.lang @@ -1683,10 +1683,10 @@ </phrase> <phrase> id: LANG_AUDIOSCROBBLER - desc: "Last.fm Log" in the playback menu + desc: "Last.fm Logger" in Plugin/apps/scrobbler user: core <source> - *: "Last.fm Log" + *: "Last.fm Logger" </source> <dest> *: "Denník Last.fm" @@ -3576,7 +3576,7 @@ </dest> <voice> *: none - gigabeat*,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh10_5gb,mrobe100,sansac200*,sansae200*,gogearsa9200,samsungyh*,iriverh100,iriverh120,iriverh300,rtc: "" + gigabeat*,gogearsa9200,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh100,iriverh10_5gb,iriverh120,iriverh300,mrobe100,rtc,samsungyh*,sansac200*,sansae200*: "" </voice> </phrase> <phrase> @@ -3613,7 +3613,7 @@ </dest> <voice> *: none - gogearsa9200,iaudiom5,iaudiox5,ipod*,sansac200*,iriverh10,iriverh10_5gb,sansae200*,iriverh100,iriverh120,iriverh300,mrobe100,rtc,samsungyh*: "" + gigabeat*,gogearsa9200,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh100,iriverh10_5gb,iriverh120,iriverh300,mrobe100,rtc,samsungyh*,sansac200*,sansae200*: "" </voice> </phrase> <phrase> @@ -4094,31 +4094,16 @@ </phrase> <phrase> id: LANG_ALARM_MOD_KEYS - desc: Shown key functions in alarm menu (for the RTC alarm mod). + desc: deprecated user: core <source> - *: none - alarm: "PLAY=Set OFF=Cancel" - gigabeats: "SELECT=Set POWER=Cancel" - ipod*: "SELECT=Set MENU=Cancel" - iriverh10,iriverh10_5gb: "SELECT=Set PREV=Cancel" - mpiohd300: "ENTER=Set MENU=Cancel" - sansafuzeplus: "SELECT=Set BACK=Cancel" - vibe500: "OK=Set C=Cancel" + *: "" </source> <dest> - *: none - alarm: "PLAY=Nastaviť OFF=Zrušiť" - gigabeats: "SELECT=Nastaviť POWER=Zrušiť" - ipod*: "SELECT=Nastaviť MENU=Zrušiť" - iriverh10,iriverh10_5gb: "SELECT=Nastaviť PREV=Zrušiť" - mpiohd300: "ENTER=Nastaviť MENU=Zrušiť" - sansafuzeplus: "SELECT=Nastaviť BACK=Zrušiť" - vibe500: "OK=Nastaviť C=Zrušiť" + *: "" </dest> <voice> - *: none - alarm,ipod*: "" + *: "" </voice> </phrase> <phrase> @@ -7672,10 +7657,10 @@ *: "." </source> <dest> - *: "." + *: "," </dest> <voice> - *: "bodka" + *: "čiarka" </voice> </phrase> <phrase> @@ -12664,16 +12649,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_TITLE - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Title]" + *: "" </source> <dest> - *: "[Názov]" + *: "" </dest> <voice> - *: "Názov" + *: "" </voice> </phrase> <phrase> @@ -13419,16 +13404,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_DURATION - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Duration]" + *: "" </source> <dest> - *: "[Trvanie]" + *: "" </dest> <voice> - *: "Trvanie" + *: "" </voice> </phrase> <phrase> @@ -14267,16 +14252,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_ARTIST - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Artist]" + *: "" </source> <dest> - *: "[Interpret]" + *: "" </dest> <voice> - *: "Interpret" + *: "" </voice> </phrase> <phrase> @@ -14427,16 +14412,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_ALBUM - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Album]" + *: "" </source> <dest> - *: "[Album]" + *: "" </dest> <voice> - *: "Album" + *: "" </voice> </phrase> <phrase> @@ -15313,10 +15298,10 @@ *: "Single Mode" </source> <dest> - *: "Single Mode" + *: "Single režim" </dest> <voice> - *: "Single Mode" + *: "Single režim" </voice> </phrase> <phrase> @@ -15588,10 +15573,10 @@ *: "Open Plugin" </source> <dest> - *: "Open Plugin" + *: "Otvoriť plugin" </dest> <voice> - *: "Open Plugin" + *: "Otvoriť plugin" </voice> </phrase> <phrase> @@ -15750,16 +15735,16 @@ </phrase> <phrase> id: LANG_CLEAR_LIST_AND_PLAY_NEXT - desc: in onplay menu. Replace current playlist with selected tracks + desc: deprecated user: core <source> - *: "Clear List & Play Next" + *: "" </source> <dest> - *: "Vymazať zoznam a prehrať ako ďalšie" + *: "" </dest> <voice> - *: "Vymazať zoznam a prehrať ako ďalšie" + *: "" </voice> </phrase> <phrase> @@ -15770,10 +15755,10 @@ *: "Queue..." </source> <dest> - *: "Queue..." + *: "Poradovník..." </dest> <voice> - *: "Queue..." + *: "Poradovník..." </voice> </phrase> <phrase> @@ -15784,10 +15769,10 @@ *: "Show Queue Options" </source> <dest> - *: "Show Queue Options" + *: "Ukázať voľby poradovníka" </dest> <voice> - *: "Show Queue Options" + *: "Ukázať voľby poradovníka" </voice> </phrase> <phrase> @@ -15798,10 +15783,10 @@ *: "Show Shuffled Adding Options" </source> <dest> - *: "Show Shuffled Adding Options" + *: "Ukázať voľby pridávania zamiešane" </dest> <voice> - *: "Show Shuffled Adding Options" + *: "Ukázať voľby pridávania zamiešane" </voice> </phrase> <phrase> @@ -15820,16 +15805,16 @@ </phrase> <phrase> id: LANG_CLEAR_LIST_AND_PLAY_SHUFFLED - desc: in onplay menu. Replace current playlist with selected tracks in random order. + desc: deprecated user: core <source> - *: "Clear List & Play Shuffled" + *: "" </source> <dest> - *: "Vymazať zoznam a prehrať zamiešané" + *: "" </dest> <voice> - *: "Vymazať zoznam a prehrať zamiešané" + *: "" </voice> </phrase> <phrase> @@ -15890,128 +15875,128 @@ </phrase> <phrase> id: LANG_PROPERTIES_ALBUMARTIST - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Album Artist]" + *: "" </source> <dest> - *: "[Interpret albumu]" + *: "" </dest> <voice> - *: "Interpret albumu" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_GENRE - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Genre]" + *: "" </source> <dest> - *: "[Žáner]" + *: "" </dest> <voice> - *: "Žáner" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_COMMENT - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Comment]" + *: "" </source> <dest> - *: "[Komentár]" + *: "" </dest> <voice> - *: "Komentár" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_COMPOSER - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Composer]" + *: "" </source> <dest> - *: "[Skladateľ]" + *: "" </dest> <voice> - *: "Skladateľ" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_YEAR - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Year]" + *: "" </source> <dest> - *: "[Rok]" + *: "" </dest> <voice> - *: "Rok" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_TRACKNUM - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Tracknum]" + *: "" </source> <dest> - *: "[Čstopy]" + *: "" </dest> <voice> - *: "Č. stopy" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_DISCNUM - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Discnum]" + *: "" </source> <dest> - *: "[Čdisku]" + *: "" </dest> <voice> - *: "Č. disku" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_FREQUENCY - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Frequency]" + *: "" </source> <dest> - *: "[Frekvencia]" + *: "" </dest> <voice> - *: "Frekvencia" + *: "" </voice> </phrase> <phrase> id: LANG_PROPERTIES_BITRATE - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Bitrate]" + *: "" </source> <dest> - *: "[Početbitov]" + *: "" </dest> <voice> - *: "Počet bitov" + *: "" </voice> </phrase> <phrase> @@ -16050,10 +16035,10 @@ *: "List Wraparound" </source> <dest> - *: "List Wraparound" + *: "Otáčať zoznam" </dest> <voice> - *: "List Wraparound" + *: "Otáčať zoznam" </voice> </phrase> <phrase> @@ -16171,3 +16156,143 @@ rds: "Synchronizovať s časom RDS" </voice> </phrase> +<phrase> + id: LANG_SORT_ALBUMS_BY + desc: in Settings + user: core + <source> + *: "Sort albums by" + </source> + <dest> + *: "Triediť albumy podľa" + </dest> + <voice> + *: "Triediť albumy podľa" + </voice> +</phrase> +<phrase> + id: LANG_ARTIST_PLUS_NAME + desc: in Settings + user: core + <source> + *: "Artist + Name" + </source> + <dest> + *: "Interpret + názov" + </dest> + <voice> + *: "Interpret a názov" + </voice> +</phrase> +<phrase> + id: LANG_ARTIST_PLUS_YEAR + desc: in Settings + user: core + <source> + *: "Artist + Year" + </source> + <dest> + *: "Interpret + rok" + </dest> + <voice> + *: "Interpret a rok" + </voice> +</phrase> +<phrase> + id: LANG_YEAR_SORT_ORDER + desc: in Settings + user: core + <source> + *: "Year sort order" + </source> + <dest> + *: "Triediť podľa roku" + </dest> + <voice> + *: "Triediť podľa roku" + </voice> +</phrase> +<phrase> + id: LANG_SHOW_YEAR_IN_ALBUM_TITLE + desc: in Settings + user: core + <source> + *: "Show year in album title" + </source> + <dest> + *: "Ukázať rok v názve albumu" + </dest> + <voice> + *: "Ukázať rok v názve albumu" + </voice> +</phrase> +<phrase> + id: LANG_WAIT_FOR_CACHE + desc: in Settings + user: core + <source> + *: "Cache needs to finish updating first!" + </source> + <dest> + *: "Najprv sa musí dokončiť aktualizácia cache!" + </dest> + <voice> + *: "Najprv sa musí dokončiť aktualizácia cache!" + </voice> +</phrase> +<phrase> + id: LANG_TRACK_INFO + desc: Track Info Title + user: core + <source> + *: "Track Info" + </source> + <dest> + *: "Info o stope" + </dest> + <voice> + *: "Info o stope" + </voice> +</phrase> +<phrase> + id: LANG_PLAY + desc: play selected file/directory, in playlist context menu + user: core + <source> + *: "Play" + </source> + <dest> + *: "Prehrať" + </dest> + <voice> + *: "Prehrať" + </voice> +</phrase> +<phrase> + id: LANG_PLAY_SHUFFLED + desc: play selected files in shuffled order, in playlist context menu + user: core + <source> + *: "Play Shuffled" + </source> + <dest> + *: "Prehrať zamiešané" + </dest> + <voice> + *: "Prehrať zamiešané" + </voice> +</phrase> +<phrase> + id: LANG_KEEP_CURRENT_TRACK_ON_REPLACE + desc: used in the playlist settings menu + user: core + <source> + *: "Keep Current Track When Replacing Playlist" + </source> + <dest> + *: "Ponechať aktuálnu stopu pri nahradení playlistu" + </dest> + <voice> + *: "Ponechať aktuálnu stopu pri nahradení playlistu" + </voice> +</phrase> diff --git a/apps/lang/srpski.lang b/apps/lang/srpski.lang index cdd7f51321..e9b97e9777 100644 --- a/apps/lang/srpski.lang +++ b/apps/lang/srpski.lang @@ -247,8 +247,7 @@ <source> *: "PLAY = Yes" cowond2*: "MENU, or top-right = Yes" - creativezen*: "SELECT = Yes" - gigabeat*,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh10_5gb,mrobe100,sansac200*,sansaclip*,sansaconnect,sansae200*,sansafuze*: "SELECT = Yes" + creativezen*,gigabeat*,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh10_5gb,mrobe100,sansac200*,sansaclip*,sansaconnect,sansae200*,sansafuze*: "SELECT = Yes" iriverh100,iriverh120,iriverh300: "NAVI = Yes" mrobe500: "PLAY, POWER, or top-right = Yes" vibe500: "OK = Yes" @@ -256,8 +255,7 @@ <dest> *: "PLAY = Да" cowond2*: "MENU, или горе-десно = Да" - creativezen*: "SELECT = Да" - gigabeat*,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh10_5gb,mrobe100,sansac200*,sansaclip*,sansaconnect,sansae200*,sansafuze*: "SELECT = Да" + creativezen*,gigabeat*,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh10_5gb,mrobe100,sansac200*,sansaclip*,sansaconnect,sansae200*,sansafuze*: "SELECT = Да" iriverh100,iriverh120,iriverh300: "NAVI = Да" mrobe500: "PLAY, POWER, или горе-десно = Да" vibe500: "OK = Да" @@ -278,7 +276,6 @@ </dest> <voice> *: "" - archosplayer: none </voice> </phrase> <phrase> @@ -799,10 +796,10 @@ *: "Crossfeed" </source> <dest> - *: "Crossfeed" + *: "Кросфид" </dest> <voice> - *: "Crossfeed" + *: "Кросфид" </voice> </phrase> <phrase> @@ -981,7 +978,7 @@ *: "Edit mode: %s" </source> <dest> - *: "Мод подешавања: %s" + *: "Режим уређивања: %s" </dest> <voice> *: "" @@ -1292,10 +1289,10 @@ *: "Party Mode" </source> <dest> - *: "Мод за журке" + *: "Режим за журке" </dest> <voice> - *: "Мод за журке" + *: "Режим за журке" </voice> </phrase> <phrase> @@ -1308,11 +1305,11 @@ </source> <dest> *: none - crossfade: "Crossfade" + crossfade: "Претапање" </dest> <voice> *: none - crossfade: "Crossfade" + crossfade: "Претапање" </voice> </phrase> <phrase> @@ -1325,11 +1322,11 @@ </source> <dest> *: none - crossfade: "Укључи Crossfade" + crossfade: "Укључи претапање" </dest> <voice> *: none - crossfade: "Укључи Crossfade" + crossfade: "Укључи претапање" </voice> </phrase> <phrase> @@ -1444,11 +1441,11 @@ </source> <dest> *: none - crossfade: "Fade-Out мод" + crossfade: "Fade-Out режим" </dest> <voice> *: none - crossfade: "Fade-Out мод" + crossfade: "Fade-Out режим" </voice> </phrase> <phrase> @@ -1461,11 +1458,11 @@ </source> <dest> *: none - crossfade: "Mix" + crossfade: "Микс" </dest> <voice> *: none - crossfade: "Mix" + crossfade: "Микс" </voice> </phrase> <phrase> @@ -1479,7 +1476,7 @@ *: "Replaygain" </dest> <voice> - *: "Replaygain" + *: "Риплејгејн" </voice> </phrase> <phrase> @@ -1669,16 +1666,16 @@ </phrase> <phrase> id: LANG_AUDIOSCROBBLER - desc: "Last.fm Log" in the playback menu + desc: "Last.fm Logger" in Plugin/apps/scrobbler user: core <source> - *: "Last.fm Log" + *: "Last.fm Logger" </source> <dest> - *: "Last.fm дневник" + *: "Креатор Last.fm дневника" </dest> <voice> - *: "Last.fm дневник" + *: "Креатор Last.fm дневника" </voice> </phrase> <phrase> @@ -2376,11 +2373,11 @@ </source> <dest> *: none - lcd_invert,remote_lcd_invert: "LCD мод" + lcd_invert,remote_lcd_invert: "LCD режим" </dest> <voice> *: none - lcd_invert,remote_lcd_invert: "LCD мод" + lcd_invert,remote_lcd_invert: "LCD режим" </voice> </phrase> <phrase> @@ -3389,7 +3386,7 @@ <voice> *: none battery_types: "Алкална" - xduoox3: "Новија (2000 милиампер часова)" + xduoox3: "Новија двехиљаде милиампер часова" </voice> </phrase> <phrase> @@ -3409,7 +3406,7 @@ <voice> *: none battery_types: "Никл метал хидридна" - xduoox3: "Старија (1500 милиампер часова)" + xduoox3: "Старија хиљадупетсто милиампер часова" </voice> </phrase> <phrase> @@ -3599,7 +3596,7 @@ </dest> <voice> *: none - gigabeat*,gogearsa9200,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh100,iriverh10_5gb,iriverh120,iriverh300,mrobe100,rtc,sansac200*,sansae200*: "" + gigabeat*,gogearsa9200,iaudiom5,iaudiox5,ipod*,iriverh10,iriverh100,iriverh10_5gb,iriverh120,iriverh300,mrobe100,rtc,samsungyh*,sansac200*,sansae200*: "" </voice> </phrase> <phrase> @@ -3969,11 +3966,11 @@ </source> <dest> *: none - charging: "Мод за адаптер у аутомобилу" + charging: "Режим за адаптер у аутомобилу" </dest> <voice> *: none - charging: "Мод за адаптер у аутомобилу" + charging: "Режим за адаптер у аутомобилу" </voice> </phrase> <phrase> @@ -4080,31 +4077,16 @@ </phrase> <phrase> id: LANG_ALARM_MOD_KEYS - desc: Shown key functions in alarm menu (for the RTC alarm mod). + desc: deprecated user: core <source> - *: none - alarm: "PLAY=Set OFF=Cancel" - gigabeats: "SELECT=Set POWER=Cancel" - ipod*: "SELECT=Set MENU=Cancel" - iriverh10,iriverh10_5gb: "SELECT=Set PREV=Cancel" - mpiohd300: "ENTER=Set MENU=Cancel" - sansafuzeplus: "SELECT=Set BACK=Cancel" - vibe500: "OK=Set C=Cancel" + *: "" </source> <dest> - *: none - alarm: "PLAY=Постави OFF=Одустани" - gigabeats: "SELECT=Постави POWER=Одустани" - ipod*: "SELECT=Постави MENU=Одустани" - iriverh10,iriverh10_5gb: "SELECT=Постави PREV=Одустани" - mpiohd300: "ENTER=Постави MENU=Одустани" - sansafuzeplus: "SELECT=Постави BACK=Одустани" - vibe500: "OK=Постави C=Одустани" + *: "" </dest> <voice> - *: none - alarm,ipod*: "" + *: "" </voice> </phrase> <phrase> @@ -4958,7 +4940,7 @@ </dest> <voice> *: none - recording: "MPEG Layer 3" + recording: "Епмег лејер три" </voice> </phrase> <phrase> @@ -4975,7 +4957,7 @@ </dest> <voice> *: none - recording: "PCM Wave" + recording: "пи си ем вејв" </voice> </phrase> <phrase> @@ -4992,7 +4974,7 @@ </dest> <voice> *: none - recording: "WavPack" + recording: "вавпак" </voice> </phrase> <phrase> @@ -5009,7 +4991,7 @@ </dest> <voice> *: none - recording: "AIFF" + recording: "еј ај еф еф" </voice> </phrase> <phrase> @@ -5323,19 +5305,19 @@ </phrase> <phrase> id: LANG_SET_AS_REC_DIR - desc: used in the onplay menu to set a recording dir + desc: deprecated user: core <source> *: none - recording: "Set As Recording Directory" + recording: "" </source> <dest> *: none - recording: "Постави као директоријум за снимање" + recording: "" </dest> <voice> *: none - recording: "Постави као директоријум за снимање" + recording: "" </voice> </phrase> <phrase> @@ -5974,12 +5956,10 @@ <source> *: "Battery: %d%% %dh %dm" ipodmini1g,ipodmini2g,iriverh10: "Batt: %d%% %dh %dm" - iriverifp7xx: "%d%% %dh %dm" </source> <dest> *: "Батерија: %d%% %dч %dм" ipodmini1g,ipodmini2g,iriverh10: "Бат: %d%% %dч %dм" - iriverifp7xx: "%d%% %dч %dм" </dest> <voice> *: "Ниво батерије" @@ -6019,15 +5999,18 @@ user: core <source> *: "Int:" + hibylinux: "mSD:" xduoox3: "mSD1:" </source> <dest> *: "Инт:" + hibylinux: "mSD:" xduoox3: "mSD1:" </dest> <voice> *: "Интерни" - xduoox3: "мајкро Ес Де 1" + hibylinux: "мајкро Ес Де" + xduoox3: "мајкро Ес Де један" </voice> </phrase> <phrase> @@ -6048,9 +6031,9 @@ </dest> <voice> *: none - multivolume: "Ха Де 1" + multivolume: "Ха Де један" sansac200*,sansaclipplus,sansae200*,sansafuze*: "мајкро Ес Де" - xduoox3: "мајкро Ес Де 2" + xduoox3: "мајкро Ес Де два" </voice> </phrase> <phrase> @@ -6139,58 +6122,58 @@ </phrase> <phrase> id: LANG_INSERT - desc: in onplay menu. insert a track/playlist into dynamic playlist. + desc: deprecated user: core <source> - *: "Insert" + *: "" </source> <dest> - *: "Уметни" + *: "" </dest> <voice> - *: "Уметни" + *: "" </voice> </phrase> <phrase> id: LANG_INSERT_FIRST - desc: in onplay menu. insert a track/playlist into dynamic playlist. + desc: deprecated user: core <source> - *: "Insert Next" + *: "" </source> <dest> - *: "Уметни наредну" + *: "" </dest> <voice> - *: "Уметни наредну" + *: "" </voice> </phrase> <phrase> id: LANG_INSERT_LAST - desc: in onplay menu. append a track/playlist into dynamic playlist. + desc: deprecated user: core <source> - *: "Insert Last" + *: "" </source> <dest> - *: "Уметни последњу" + *: "" </dest> <voice> - *: "Уметни последњу" + *: "" </voice> </phrase> <phrase> id: LANG_INSERT_SHUFFLED - desc: in onplay menu. insert a track/playlist randomly into dynamic playlist + desc: deprecated user: core <source> - *: "Insert Shuffled" + *: "" </source> <dest> - *: "Уметни промешано" + *: "" </dest> <voice> - *: "Уметни промешано" + *: "" </voice> </phrase> <phrase> @@ -6251,16 +6234,16 @@ </phrase> <phrase> id: LANG_REPLACE - desc: in onplay menu. Replace the current playlist with a new one. + desc: deprecated user: core <source> - *: "Play Next" + *: "" </source> <dest> - *: "Репродукуј следећу" + *: "" </dest> <voice> - *: "Репродукуј следећу" + *: "" </voice> </phrase> <phrase> @@ -6363,16 +6346,16 @@ </phrase> <phrase> id: LANG_CATALOG_ADD_TO - desc: in onplay playlist catalogue submenu + desc: deprecated user: core <source> - *: "Add to Playlist" + *: "" </source> <dest> - *: "Додај у плејлисту" + *: "" </dest> <voice> - *: "Додај у плејлисту" + *: "" </voice> </phrase> <phrase> @@ -7241,10 +7224,10 @@ *: "Mode:" </source> <dest> - *: "Мод:" + *: "Режим:" </dest> <voice> - *: "Мод:" + *: "Режим:" </voice> </phrase> <phrase> @@ -7345,7 +7328,7 @@ </dest> <voice> *: none - iaudiom5,iaudiox5,iriverh100,iriverh120,iriverh300,recording,sansac200*,sansae200*: "" + iaudiom5,iaudiox5,iriverh100,iriverh120,iriverh300,recording,samsungyh*,sansac200*,sansae200*,vibe500: "" </voice> </phrase> <phrase> @@ -7483,7 +7466,7 @@ *: "Incompatible model" </source> <dest> - *: "Модел није одговарајући" + *: "Овај модел није подржан" </dest> <voice> *: "Неодговарајући модел" @@ -8304,7 +8287,7 @@ *: "" </dest> <voice> - *: "pixel" + *: "пиксела" </voice> </phrase> <phrase> @@ -8332,7 +8315,7 @@ *: "" </dest> <voice> - *: "херц" + *: "херца" </voice> </phrase> <phrase> @@ -8808,7 +8791,7 @@ *: "" </dest> <voice> - *: "while-playing-screen" + *: "екран-током-репродукције" </voice> </phrase> <phrase> @@ -8864,7 +8847,7 @@ *: "" </dest> <voice> - *: "firmware" + *: "фирмвер" </voice> </phrase> <phrase> @@ -8909,7 +8892,7 @@ *: "" </dest> <voice> - *: "cuesheet" + *: "кјулиста" </voice> </phrase> <phrase> @@ -9108,7 +9091,7 @@ *: "" </dest> <voice> - *: "units per tick" + *: "јединица по подеоку" </voice> </phrase> <phrase> @@ -9122,7 +9105,7 @@ *: "" </dest> <voice> - *: "o'clock" + *: "сати" </voice> </phrase> <phrase> @@ -9136,7 +9119,7 @@ *: "" </dest> <voice> - *: "P M" + *: "поподне" </voice> </phrase> <phrase> @@ -9150,7 +9133,7 @@ *: "" </dest> <voice> - *: "A M" + *: "преподне" </voice> </phrase> <phrase> @@ -9164,7 +9147,7 @@ *: "" </dest> <voice> - *: "oh" + *: "о" </voice> </phrase> <phrase> @@ -9342,7 +9325,7 @@ *: "" </dest> <voice> - *: "Edit" + *: "Уреди" </voice> </phrase> <phrase> @@ -9356,7 +9339,7 @@ *: "" </dest> <voice> - *: "Blank" + *: "Празно" </voice> </phrase> <phrase> @@ -9370,7 +9353,7 @@ *: "" </dest> <voice> - *: "Empty list" + *: "Празна листа" </voice> </phrase> <phrase> @@ -9536,7 +9519,7 @@ *: "" </dest> <voice> - *: "Quick screen" + *: "Брзи екран" </voice> </phrase> <phrase> @@ -9564,7 +9547,7 @@ *: "" </dest> <voice> - *: "OK" + *: "О Кеј" </voice> </phrase> <phrase> @@ -9598,7 +9581,7 @@ </dest> <voice> *: none - recording: "" + recording: "Величина" </voice> </phrase> <phrase> @@ -9691,7 +9674,7 @@ </dest> <voice> *: none - recording: "" + recording: "Време дељења" </voice> </phrase> <phrase> @@ -9722,7 +9705,7 @@ </dest> <voice> *: none - recording: "" + recording: "КЛИП" </voice> </phrase> <phrase> @@ -9752,11 +9735,11 @@ </source> <dest> *: none - recording: "Фајл:" + recording: "Име фајла:" </dest> <voice> *: none - recording: "" + recording: "Име фајла" </voice> </phrase> <phrase> @@ -9814,7 +9797,7 @@ </source> <dest> *: none - agc: "AGC" + agc: "АРП" </dest> <voice> *: none @@ -9831,11 +9814,11 @@ </source> <dest> *: none - agc: "AGC време клиповања" + agc: "АРП време клиповања" </dest> <voice> *: none - agc: "AGC време клиповања" + agc: "AРП време клиповања" </voice> </phrase> <phrase> @@ -9975,11 +9958,11 @@ </source> <dest> *: none - recording: "Моно мод" + recording: "Моно режим" </dest> <voice> *: none - recording: "Моно мод" + recording: "Моно режим" </voice> </phrase> <phrase> @@ -10201,11 +10184,11 @@ </source> <dest> *: none - touchscreen: "Тачскрин мод" + touchscreen: "Тачскрин режим" </dest> <voice> *: none - touchscreen: "Тачскрин мод" + touchscreen: "Тачскрин режим" </voice> </phrase> <phrase> @@ -10247,7 +10230,7 @@ *: "" </dest> <voice> - *: "statusbar skin" + *: "изглед статусне линије" </voice> </phrase> <phrase> @@ -10337,7 +10320,7 @@ </dest> <voice> *: none - remote: "remote statusbar skin" + remote: "изглед удаљене статусне линије" </voice> </phrase> <phrase> @@ -10348,10 +10331,10 @@ *: "Knee" </source> <dest> - *: "Knee" + *: "Колено" </dest> <voice> - *: "Ни" + *: "колено" </voice> </phrase> <phrase> @@ -10370,16 +10353,16 @@ </phrase> <phrase> id: LANG_INSERT_LAST_SHUFFLED - desc: in onplay menu. insert a playlist randomly at end of dynamic playlist + desc: deprecated user: core <source> - *: "Insert Last Shuffled" + *: "" </source> <dest> - *: "Уметни на крај промешану" + *: "" </dest> <voice> - *: "Уметни на крај промешану" + *: "" </voice> </phrase> <phrase> @@ -10390,10 +10373,10 @@ *: "Soft Knee" </source> <dest> - *: "Soft Knee" + *: "Меко колено" </dest> <voice> - *: "Софт ни" + *: "меко колено" </voice> </phrase> <phrase> @@ -10434,11 +10417,11 @@ </source> <dest> *: none - usb_hid: "Мод USB тастатуре" + usb_hid: "Режим USB тастатуре" </dest> <voice> *: none - usb_hid: "Мод USB тастатуре" + usb_hid: "режим у ес бе тастатуре" </voice> </phrase> <phrase> @@ -10449,10 +10432,10 @@ *: "Hard Knee" </source> <dest> - *: "Hard Knee" + *: "Тврдо колено" </dest> <voice> - *: "Хард ни" + *: "тврдо колено" </voice> </phrase> <phrase> @@ -10482,11 +10465,11 @@ </source> <dest> *: none - pitchscreen: "Rate" + pitchscreen: "Стопа" </dest> <voice> *: none - pitchscreen: "Рејт" + pitchscreen: "Стопа" </voice> </phrase> <phrase> @@ -10520,7 +10503,7 @@ </dest> <voice> *: none - usb_hid: "USB Human Interface Device" + usb_hid: "У ес бе хјуман интерфејс дивајс" </voice> </phrase> <phrase> @@ -10813,10 +10796,10 @@ *: "Timestretch" </source> <dest> - *: "Timestretch" + *: "Временско растезање" </dest> <voice> - *: "Timestretch" + *: "Временско растезање" </voice> </phrase> <phrase> @@ -10975,11 +10958,11 @@ </source> <dest> *: none - touchscreen: "OK" + touchscreen: "ОК" </dest> <voice> *: none - touchscreen: "OK" + touchscreen: "О Кеј" </voice> </phrase> <phrase> @@ -11112,7 +11095,7 @@ </dest> <voice> *: none - touchscreen: "Del" + touchscreen: "Дел" </voice> </phrase> <phrase> @@ -11484,16 +11467,16 @@ </phrase> <phrase> id: LANG_SET_AS_START_DIR - desc: used in the onplay menu to set a starting browser dir + desc: deprecated user: core <source> - *: "Start File Browser Here" + *: "" </source> <dest> - *: "Покрени прегледач фајлова у овом фолдеру" + *: "" </dest> <voice> - *: "Покрени прегледач фајлова у овом фолдеру" + *: "" </voice> </phrase> <phrase> @@ -11664,16 +11647,16 @@ </phrase> <phrase> id: LANG_SET_AS_PLAYLISTCAT_DIR - desc: used in the onplay menu to set a playlist catalogue dir + desc: deprecated user: core <source> - *: "Set As Playlist Catalogue Directory" + *: "" </source> <dest> - *: "Постави као директоријум каталога плејлисти" + *: "" </dest> <voice> - *: "Постави као директоријум каталога плејлисти" + *: "" </voice> </phrase> <phrase> @@ -11799,10 +11782,10 @@ *: "Simple (Meier)" </source> <dest> - *: "Једноставан (Meier)" + *: "Једноставан (Мајер)" </dest> <voice> - *: "Једноставан Мејеров" + *: "Једноставан Мајеров" </voice> </phrase> <phrase> @@ -11979,7 +11962,7 @@ *: "Q" </dest> <voice> - *: "Q" + *: "Ку фактор" </voice> </phrase> <phrase> @@ -12023,11 +12006,11 @@ </source> <dest> *: none - filter_roll_off: "Стрмина DAC филтра" + filter_roll_off: "Стрмина ДАК филтра" </dest> <voice> *: none - filter_roll_off: "Стрмина DAC филтра" + filter_roll_off: "Стрмина ДАК филтра" </voice> </phrase> <phrase> @@ -12038,10 +12021,10 @@ *: "Line Separator" </source> <dest> - *: "Сепаратор линија" + *: "Граничник линија" </dest> <voice> - *: "Сепаратор линија" + *: "Граничник линија" </voice> </phrase> <phrase> @@ -12066,10 +12049,10 @@ *: "Line Separator Colour" </source> <dest> - *: "Боја сепаратора линија" + *: "Боја граничника линија" </dest> <voice> - *: "Боја сепаратора линија" + *: "Боја граничника линија" </voice> </phrase> <phrase> @@ -12122,13 +12105,13 @@ desc: Selective Actions user: core <source> - *: "Play" + *: "Exempt Play" </source> <dest> - *: "Репродукуј" + *: "Изузми репродукцију" </dest> <voice> - *: "Репродукуј" + *: "Изузми репродукцију" </voice> </phrase> <phrase> @@ -12136,13 +12119,13 @@ desc: Softlock behaviour setting user: core <source> - *: "Disable Notify" + *: "Disable Locked Reminders" </source> <dest> - *: "Онемогући обавештење" + *: "Онемогући закључана обавештења" </dest> <voice> - *: "Онемогући обавештење" + *: "Онемогући закључана обавештења" </voice> </phrase> <phrase> @@ -12181,10 +12164,10 @@ *: "USB Mode" </source> <dest> - *: "USB Мод" + *: "USB режим" </dest> <voice> - *: "USB Мод" + *: "USB режим" </voice> </phrase> <phrase> @@ -12209,10 +12192,10 @@ *: "Android Debug Bridge" </source> <dest> - *: "Android Debug Bridge" + *: "Андроид дибаг мост" </dest> <voice> - *: "Android Debug Bridge" + *: "Андроид дибаг мост" </voice> </phrase> <phrase> @@ -12248,13 +12231,13 @@ desc: Selective Actions user: core <source> - *: "Skip" + *: "Exempt Skip" </source> <dest> - *: "Прескочи" + *: "Изузми прескакање" </dest> <voice> - *: "Прескочи" + *: "Изузми прескакање" </voice> </phrase> <phrase> @@ -12265,10 +12248,10 @@ *: "Haas Surround" </source> <dest> - *: "Haas Surround" + *: "Хас окружујући звук" </dest> <voice> - *: "Haas Surround" + *: "Хас окружујући звук" </voice> </phrase> <phrase> @@ -12276,13 +12259,13 @@ desc: Selective Actions user: core <source> - *: "Seek" + *: "Exempt Seek" </source> <dest> - *: "Премотај" + *: "Изузми премотавање" </dest> <voice> - *: "Премотај" + *: "Изузми премотавање" </voice> </phrase> <phrase> @@ -12916,7 +12899,7 @@ *: "Особине директоријума" </dest> <voice> - *: "" + *: "Особине директоријума" </voice> </phrase> <phrase> @@ -12946,7 +12929,7 @@ lowmem: none </dest> <voice> - *: "Постави време настављања" + *: "Постави време настављања у минутама" lowmem: none </voice> </phrase> @@ -13025,16 +13008,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_ALBUM - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Album]" + *: "" </source> <dest> - *: "[Албум]" + *: "" </dest> <voice> - *: "Албум" + *: "" </voice> </phrase> <phrase> @@ -13135,7 +13118,7 @@ *: "Редослед Rockbox главног менија" </dest> <voice> - *: "" + *: "Редослед Рокбокс главног менија" </voice> </phrase> <phrase> @@ -13149,7 +13132,7 @@ *: "Особине фајла" </dest> <voice> - *: "" + *: "Особине фајла" </voice> </phrase> <phrase> @@ -13202,10 +13185,10 @@ *: "Cache will be rebuilt on next restart" </source> <dest> - *: "Кеш ће да се изради при наредном поновном покретању" + *: "Кеш ће да се изгради при наредном поновном покретању" </dest> <voice> - *: "Кеш ће да се изради при наредном поновном покретању" + *: "Кеш ће да се изгради при наредном поновном покретању" </voice> </phrase> <phrase> @@ -13367,16 +13350,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_TITLE - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Title]" + *: "" </source> <dest> - *: "[Наслов]" + *: "" </dest> <voice> - *: "Наслов" + *: "" </voice> </phrase> <phrase> @@ -13782,16 +13765,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_ARTIST - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Artist]" + *: "" </source> <dest> - *: "[Уметник]" + *: "" </dest> <voice> - *: "Уметник" + *: "" </voice> </phrase> <phrase> @@ -13886,16 +13869,16 @@ </phrase> <phrase> id: LANG_PROPERTIES_DURATION - desc: in properties plugin + desc: deprecated user: core <source> - *: "[Duration]" + *: "" </source> <dest> - *: "[Трајање]" + *: "" </dest> <voice> - *: "Трајање" + *: "" </voice> </phrase> <phrase> @@ -14259,7 +14242,7 @@ </phrase> <phrase> id: LANG_DIRECT - desc: in the pictureflow settings + desc: in the pictureflow settings, also a volume adjustment mode user: core <source> *: "Direct" @@ -14299,7 +14282,7 @@ *: "" </dest> <voice> - *: "" + *: "Притисните репродукцију за покретање теста батерије или стоп за отказивање" </voice> </phrase> <phrase> @@ -14583,7 +14566,7 @@ *: "" </dest> <voice> - *: "" + *: "Обележено" </voice> </phrase> <phrase> @@ -14872,7 +14855,7 @@ *: "Играј Вормлет!" </dest> <voice> - *: "Играј Вормлет!!" + *: "Играј Вормлет!" </voice> </phrase> <phrase> @@ -15210,11 +15193,11 @@ lowmem: none </source> <dest> - *: "Учестаност узорковања" + *: "Учесталост узорковања" lowmem: none </dest> <voice> - *: "Учестаност узорковања" + *: "Учесталост узорковања" lowmem: none </voice> </phrase> @@ -15349,7 +15332,6 @@ mpiohd200: "Дупли тап REC за прекид." mpiohd300: "Дупли тап MENU за прекид." rx27generic: "Притисните VOLUME за прекид." - sonynwza860: "Мапе тастера нису комплетне." touchscreen: "Притисните Middle Left за прекид." vibe500: "Притисните PREV за прекид." xduoox20,xduoox3,xduoox3ii: "Дупли тап HOME за прекид." @@ -15459,3 +15441,1097 @@ hotkey: "Објављивање укључено" </voice> </phrase> +<phrase> + id: LANG_SINGLE_MODE + desc: single mode + user: core + <source> + *: "Single Mode" + </source> + <dest> + *: "Режим само једне" + </dest> + <voice> + *: "режим само једне" + </voice> +</phrase> +<phrase> + id: LANG_TALK_MIXER_LEVEL + desc: Relative volume of voice prompts + user: core + <source> + *: "Voice prompt volume" + </source> + <dest> + *: "Јачина гласа" + </dest> + <voice> + *: "јачина гласа" + </voice> +</phrase> +<phrase> + id: LANG_FILTER_SHORT_SHARP + desc: in sound settings + user: core + <source> + *: none + filter_roll_off: "Short Sharp" + </source> + <dest> + *: none + filter_roll_off: "Кратки оштар" + </dest> + <voice> + *: none + filter_roll_off: "кратки оштар" + </voice> +</phrase> +<phrase> + id: LANG_FILTER_SHORT_SLOW + desc: in sound settings + user: core + <source> + *: none + filter_roll_off: "Short Slow" + </source> + <dest> + *: none + filter_roll_off: "Кратки спори" + </dest> + <voice> + *: none + filter_roll_off: "Кратки спори" + </voice> +</phrase> +<phrase> + id: LANG_FILTER_SUPER_SLOW + desc: in sound settings + user: core + <source> + *: none + filter_roll_off: "Super Slow" + </source> + <dest> + *: none + filter_roll_off: "Супер спори" + </dest> + <voice> + *: none + filter_roll_off: "Супер спори" + </voice> +</phrase> +<phrase> + id: LANG_FILTER_LINEAR_FAST + desc: in sound settings + user: core + <source> + *: none + es9218: "Linear Fast" + </source> + <dest> + *: none + es9218: "Линеарни брзи" + </dest> + <voice> + *: none + es9218: "линеарни брзи" + </voice> +</phrase> +<phrase> + id: LANG_FILTER_LINEAR_SLOW + desc: in sound settings + user: core + <source> + *: none + es9218: "Linear Slow" + </source> + <dest> + *: none + es9218: "Линеарни спори" + </dest> + <voice> + *: none + es9218: "линеарни спори" + </voice> +</phrase> +<phrase> + id: LANG_FILTER_MINIMUM_FAST + desc: in sound settings + user: core + <source> + *: none + es9218: "Minimum Fast" + </source> + <dest> + *: none + es9218: "Минимални брзи" + </dest> + <voice> + *: none + es9218: "минимални брзи" + </voice> +</phrase> +<phrase> + id: LANG_FILTER_MINIMUM_SLOW + desc: in sound settings + user: core + <source> + *: none + es9218: "Minimum Slow" + </source> + <dest> + *: none + es9218: "Минимални спори" + </dest> + <voice> + *: none + es9218: "минимални спори" + </voice> +</phrase> +<phrase> + id: LANG_FILTER_APODIZING_1 + desc: in sound settings + user: core + <source> + *: none + es9218: "Apodizing type 1" + </source> + <dest> + *: none + es9218: "Аподизациони тип 1" + </dest> + <voice> + *: none + es9218: "Аподизациони тип 1" + </voice> +</phrase> +<phrase> + id: LANG_FILTER_APODIZING_2 + desc: in sound settings + user: core + <source> + *: none + es9218: "Apodizing type 2" + </source> + <dest> + *: none + es9218: "Аподизациони тип 2" + </dest> + <voice> + *: none + es9218: "Аподизациони тип 2" + </voice> +</phrase> +<phrase> + id: LANG_FILTER_HYBRID_FAST + desc: in sound settings + user: core + <source> + *: none + es9218: "Hybrid Fast" + </source> + <dest> + *: none + es9218: "Хибридни брзи" + </dest> + <voice> + *: none + es9218: "Хибридни брзи" + </voice> +</phrase> +<phrase> + id: LANG_FILTER_BRICK_WALL + desc: in sound settings + user: core + <source> + *: none + es9218: "Brick Wall" + </source> + <dest> + *: none + es9218: "Зид" + </dest> + <voice> + *: none + es9218: "Зид" + </voice> +</phrase> +<phrase> + id: LANG_DAC_POWER_MODE + desc: in sound settings + user: core + <source> + *: none + dac_power_mode: "DAC's power mode" + es9218: "DAC's output level" + </source> + <dest> + *: none + dac_power_mode: "Режим напајања ДАК" + es9218: "Излазни ниво ДАК" + </dest> + <voice> + *: none + dac_power_mode: "Режим напајања ДАК" + es9218: "Излазни ниво ДАК" + </voice> +</phrase> +<phrase> + id: LANG_DAC_POWER_HIGH + desc: in sound settings + user: core + <source> + *: none + dac_power_mode: "High performance" + es9218: "High Gain (2 Vrms)" + </source> + <dest> + *: none + dac_power_mode: "Високе перформансе" + es9218: "Високо појачање (2 Vrms)" + </dest> + <voice> + *: none + dac_power_mode: "Високе перформансе" + es9218: "Високо појачање два волта ефективно" + </voice> +</phrase> +<phrase> + id: LANG_DAC_POWER_LOW + desc: in sound settings + user: core + <source> + *: none + dac_power_mode: "Save battery" + es9218: "Low Gain (1 Vrms)" + </source> + <dest> + *: none + dac_power_mode: "Штедња батерије" + es9218: "Ниско појачање (1 Vrms)" + </dest> + <voice> + *: none + dac_power_mode: "Штедња батерије" + es9218: "Ниско појачање један волт ефективно" + </voice> +</phrase> +<phrase> + id: LANG_ENTER_USB_STORAGE_MODE_QUERY + desc: upon plugging in USB + user: core + <source> + *: "Enter USB mass storage mode?" + </source> + <dest> + *: "Да пређем у режим USB масовне меморије?" + </dest> + <voice> + *: "Да пређем у режим У Ес Бе масовне меморије?" + </voice> +</phrase> +<phrase> + id: LANG_CLEAR_LIST_AND_PLAY_NEXT + desc: deprecated + user: core + <source> + *: "" + </source> + <dest> + *: "" + </dest> + <voice> + *: "" + </voice> +</phrase> +<phrase> + id: LANG_QUEUE_MENU + desc: in onplay menu + user: core + <source> + *: "Queue..." + </source> + <dest> + *: "Ред..." + </dest> + <voice> + *: "ред..." + </voice> +</phrase> +<phrase> + id: LANG_SHOW_QUEUE_OPTIONS + desc: in Current Playlist settings + user: core + <source> + *: "Show Queue Options" + </source> + <dest> + *: "Прикажи опције реда" + </dest> + <voice> + *: "Прикажи опције реда" + </voice> +</phrase> +<phrase> + id: LANG_SHOW_SHUFFLED_ADDING_OPTIONS + desc: in Current Playlist settings + user: core + <source> + *: "Show Shuffled Adding Options" + </source> + <dest> + *: "Прикажи опције измешаног додавања" + </dest> + <voice> + *: "Прикажи опције измешаног додавања" + </voice> +</phrase> +<phrase> + id: LANG_IN_SUBMENU + desc: in Settings + user: core + <source> + *: "In Submenu" + </source> + <dest> + *: "У подменију" + </dest> + <voice> + *: "У подменију" + </voice> +</phrase> +<phrase> + id: LANG_CLEAR_LIST_AND_PLAY_SHUFFLED + desc: deprecated + user: core + <source> + *: "" + </source> + <dest> + *: "" + </dest> + <voice> + *: "" + </voice> +</phrase> +<phrase> + id: LANG_SOFTLOCK_DISABLE_ALL_NOTIFY + desc: disable all softlock notifications + user: core + <source> + *: "Disable All Lock Notifications" + </source> + <dest> + *: "Искључи сва закључана обавештења" + </dest> + <voice> + *: "Искључи сва закључана обавештења" + </voice> +</phrase> +<phrase> + id: LANG_ACTION_VOLUME + desc: exempt volume from softlock + user: core + <source> + *: "Exempt Volume" + </source> + <dest> + *: "Изузми јачину" + </dest> + <voice> + *: "Изузми јачину" + </voice> +</phrase> +<phrase> + id: LANG_ACTION_ALWAYSAUTOLOCK + desc: always prime autolock + user: core + <source> + *: "Always Autolock" + </source> + <dest> + *: "Увек аутоматски закључај" + </dest> + <voice> + *: "Увек аутоматски закључај" + </voice> +</phrase> +<phrase> + id: LANG_PLAYLIST_RELOAD_AFTER_SAVE + desc: reload playlist after saving + user: core + <source> + *: "Reload After Saving" + </source> + <dest> + *: "Поново учитај након чувања" + </dest> + <voice> + *: "Поново учитај након чувања" + </voice> +</phrase> +<phrase> + id: LANG_PROPERTIES_ALBUMARTIST + desc: deprecated + user: core + <source> + *: "" + </source> + <dest> + *: "" + </dest> + <voice> + *: "" + </voice> +</phrase> +<phrase> + id: LANG_PROPERTIES_GENRE + desc: deprecated + user: core + <source> + *: "" + </source> + <dest> + *: "" + </dest> + <voice> + *: "" + </voice> +</phrase> +<phrase> + id: LANG_PROPERTIES_COMMENT + desc: deprecated + user: core + <source> + *: "" + </source> + <dest> + *: "" + </dest> + <voice> + *: "" + </voice> +</phrase> +<phrase> + id: LANG_PROPERTIES_COMPOSER + desc: deprecated + user: core + <source> + *: "" + </source> + <dest> + *: "" + </dest> + <voice> + *: "" + </voice> +</phrase> +<phrase> + id: LANG_PROPERTIES_YEAR + desc: deprecated + user: core + <source> + *: "" + </source> + <dest> + *: "" + </dest> + <voice> + *: "" + </voice> +</phrase> +<phrase> + id: LANG_PROPERTIES_TRACKNUM + desc: deprecated + user: core + <source> + *: "" + </source> + <dest> + *: "" + </dest> + <voice> + *: "" + </voice> +</phrase> +<phrase> + id: LANG_PROPERTIES_DISCNUM + desc: deprecated + user: core + <source> + *: "" + </source> + <dest> + *: "" + </dest> + <voice> + *: "" + </voice> +</phrase> +<phrase> + id: LANG_PROPERTIES_FREQUENCY + desc: deprecated + user: core + <source> + *: "" + </source> + <dest> + *: "" + </dest> + <voice> + *: "" + </voice> +</phrase> +<phrase> + id: LANG_PROPERTIES_BITRATE + desc: deprecated + user: core + <source> + *: "" + </source> + <dest> + *: "" + </dest> + <voice> + *: "" + </voice> +</phrase> +<phrase> + id: VOICE_NUMERIC_TENS_SWAP_SEPARATOR + desc: voice only, for speaking numbers in languages that swap the tens and ones fields. Leave blank for languages that do not need it, such as English ("231" => "two hundred thirty one") but other languages may speak it as "two hundred one [AND] thirty" + user: core + <source> + *: "" + </source> + <dest> + *: "" + </dest> + <voice> + *: "" + </voice> +</phrase> +<phrase> + id: LANG_VOICED_DATE_FORMAT + desc: format string for how dates will be read back. Y == 4-digit year, A == month name, m == numeric month, d == numeric day. For example, "AdY" will read "January 21 2021" + user: core + <source> + *: "dAY" + </source> + <dest> + *: "dAY" + </dest> + <voice> + *: "" + </voice> +</phrase> +<phrase> + id: LANG_LIST_WRAPAROUND + desc: in Settings + user: core + <source> + *: "List Wraparound" + </source> + <dest> + *: "Обмотавање листе" + </dest> + <voice> + *: "Обмотавање листе" + </voice> +</phrase> +<phrase> + id: LANG_SHOW_SHUTDOWN_MESSAGE + desc: in Settings + user: core + <source> + *: "Show Shutdown Message" + </source> + <dest> + *: "Прикажи поруку искључивања" + </dest> + <voice> + *: "Прикажи поруку искључивања" + </voice> +</phrase> +<phrase> + id: LANG_LIST_ORDER + desc: in Settings + user: core + <source> + *: "List Order" + </source> + <dest> + *: "Редослед листе" + </dest> + <voice> + *: "Редослед листе" + </voice> +</phrase> +<phrase> + id: LANG_ASCENDING + desc: in Settings + user: core + <source> + *: "Ascending" + </source> + <dest> + *: "Растући" + </dest> + <voice> + *: "растући" + </voice> +</phrase> +<phrase> + id: LANG_DESCENDING + desc: in Settings + user: core + <source> + *: "Descending" + </source> + <dest> + *: "Опадајући" + </dest> + <voice> + *: "опадајући" + </voice> +</phrase> +<phrase> + id: LANG_ALBUM_ART + desc: in Settings + user: core + <source> + *: "Album Art" + </source> + <dest> + *: "Слика омота" + </dest> + <voice> + *: "слика омота" + </voice> +</phrase> +<phrase> + id: LANG_PREFER_EMBEDDED + desc: in Settings + user: core + <source> + *: "Prefer Embedded" + </source> + <dest> + *: "Предност има уграђена" + </dest> + <voice> + *: "Предност има уграђена" + </voice> +</phrase> +<phrase> + id: LANG_PREFER_IMAGE_FILE + desc: in Settings + user: core + <source> + *: "Prefer Image File" + </source> + <dest> + *: "Предност има фајл слике" + </dest> + <voice> + *: "Предност има фајл слике" + </voice> +</phrase> +<phrase> + id: LANG_FM_SYNC_RDS_TIME + desc: in radio screen and Settings + user: core + <source> + *: none + rds: "Sync RDS Time" + </source> + <dest> + *: none + rds: "Синхронизуј са RDS временом" + </dest> + <voice> + *: none + rds: "Синхронизуј са Ер де ес временом" + </voice> +</phrase> +<phrase> + id: LANG_SORT_ALBUMS_BY + desc: in Settings + user: core + <source> + *: "Sort albums by" + </source> + <dest> + *: "Сортирај албуме по" + </dest> + <voice> + *: "Сортирај албуме по" + </voice> +</phrase> +<phrase> + id: LANG_ARTIST_PLUS_NAME + desc: in Settings + user: core + <source> + *: "Artist + Name" + </source> + <dest> + *: "Уметник + Име" + </dest> + <voice> + *: "Уметник и име" + </voice> +</phrase> +<phrase> + id: LANG_ARTIST_PLUS_YEAR + desc: in Settings + user: core + <source> + *: "Artist + Year" + </source> + <dest> + *: "Уметник + Година" + </dest> + <voice> + *: "Ументик и година" + </voice> +</phrase> +<phrase> + id: LANG_YEAR_SORT_ORDER + desc: in Settings + user: core + <source> + *: "Year sort order" + </source> + <dest> + *: "Редослед сортирања године" + </dest> + <voice> + *: "Редослед сортирања године" + </voice> +</phrase> +<phrase> + id: LANG_SHOW_YEAR_IN_ALBUM_TITLE + desc: in Settings + user: core + <source> + *: "Show year in album title" + </source> + <dest> + *: "Приказуј годину у наслову албума" + </dest> + <voice> + *: "Приказуј годину у наслову албума" + </voice> +</phrase> +<phrase> + id: LANG_WAIT_FOR_CACHE + desc: in Settings + user: core + <source> + *: "Cache needs to finish updating first!" + </source> + <dest> + *: "Најпре мора да се освежи кеш!" + </dest> + <voice> + *: "Најпре мора да се освежи кеш!" + </voice> +</phrase> +<phrase> + id: LANG_TRACK_INFO + desc: Track Info Title + user: core + <source> + *: "Track Info" + </source> + <dest> + *: "Инфо о нумери" + </dest> + <voice> + *: "Инфо о нумери" + </voice> +</phrase> +<phrase> + id: LANG_PLAY + desc: play selected file/directory, in playlist context menu + user: core + <source> + *: "Play" + </source> + <dest> + *: "Пусти" + </dest> + <voice> + *: "Пусти" + </voice> +</phrase> +<phrase> + id: LANG_PLAY_SHUFFLED + desc: play selected files in shuffled order, in playlist context menu + user: core + <source> + *: "Play Shuffled" + </source> + <dest> + *: "Пусти измешано" + </dest> + <voice> + *: "Пусти измешано" + </voice> +</phrase> +<phrase> + id: LANG_KEEP_CURRENT_TRACK_ON_REPLACE + desc: used in the playlist settings menu + user: core + <source> + *: "Keep Current Track When Replacing Playlist" + </source> + <dest> + *: "Задржи текућу нумеру када се замењује плејлиста" + </dest> + <voice> + *: "Задржи текућу нумеру када се замењује плејлиста" + </voice> +</phrase> +<phrase> + id: LANG_CLEAR_SETTINGS_ON_HOLD + desc: in the system sub menu + user: core + <source> + *: none + clear_settings_on_hold,iriverh10: "Clear settings when reset button is held during startup" + ipod4g,ipodcolor,ipodmini1g,ipodmini2g,ipodnano1g,ipodvideo: "Clear settings when hold switch is on during startup" + </source> + <dest> + *: none + clear_settings_on_hold,iriverh10: "Обриши подешавања када се током покретања држи ресет тастер" + ipod4g,ipodcolor,ipodmini1g,ipodmini2g,ipodnano1g,ipodvideo: "Обриши подешавања када је током покретања укључен тастер hold" + </dest> + <voice> + *: none + clear_settings_on_hold,iriverh10: "Обриши подешавања када се током покретања држи ресет тастер" + ipod4g,ipodcolor,ipodmini1g,ipodmini2g,ipodnano1g,ipodvideo: "Обриши подешавања када је током покретања укључен тастер hold" + </voice> +</phrase> +<phrase> + id: LANG_REWIND_ACROSS_TRACKS + desc: in playback settings menu + user: core + <source> + *: "Rewind Across Tracks" + </source> + <dest> + *: "Премотавај преко нумера" + </dest> + <voice> + *: "Премотавај преко нумера" + </voice> +</phrase> +<phrase> + id: LANG_SET_AS + desc: used in the onplay menu + user: core + <source> + *: "Set As..." + </source> + <dest> + *: "Постави као..." + </dest> + <voice> + *: "Постави као..." + </voice> +</phrase> +<phrase> + id: LANG_PLAYLIST_DIR + desc: used in the onplay menu + user: core + <source> + *: "Playlist Directory" + </source> + <dest> + *: "Директоријум са плејлистама" + </dest> + <voice> + *: "Директоријум са плејлистама" + </voice> +</phrase> +<phrase> + id: LANG_START_DIR + desc: used in the onplay menu + user: core + <source> + *: "Start Directory" + </source> + <dest> + *: "Почетни директоријум" + </dest> + <voice> + *: "Почетни директоријум" + </voice> +</phrase> +<phrase> + id: LANG_RECORDING_DIR + desc: used in the onplay menu + user: core + <source> + *: none + recording: "Recording Directory" + </source> + <dest> + *: none + recording: "Директоријум за снимање" + </dest> + <voice> + *: none + recording: "Директоријум за снимање" + </voice> +</phrase> +<phrase> + id: LANG_ADD_TO_PL + desc: used in the onplay menu + user: core + <source> + *: "Add to Playlist..." + </source> + <dest> + *: "Додај у плејлисту..." + </dest> + <voice> + *: "Додај у плејлисту..." + </voice> +</phrase> +<phrase> + id: LANG_ADD_TO_EXISTING_PL + desc: used in the onplay menu + user: core + <source> + *: "Add to Existing Playlist" + </source> + <dest> + *: "Додај у постојећу плејлисту" + </dest> + <voice> + *: "Додај у постојећу плејлисту" + </voice> +</phrase> +<phrase> + id: LANG_PLAYING_NEXT + desc: used in the onplay menu + user: core + <source> + *: "Playing Next..." + </source> + <dest> + *: "Пушта се следеће..." + </dest> + <voice> + *: "Пушта се следеће..." + </voice> +</phrase> +<phrase> + id: LANG_PLAY_NEXT + desc: used in the onplay menu + user: core + <source> + *: "Play Next" + </source> + <dest> + *: "Пусти следећу" + </dest> + <voice> + *: "Пусти следећу" + </voice> +</phrase> +<phrase> + id: LANG_ADD_SHUFFLED + desc: used in the onplay menu + user: core + <source> + *: "Add Shuffled" + </source> + <dest> + *: "Додај промешано" + </dest> + <voice> + *: "Додај промешано" + </voice> +</phrase> +<phrase> + id: LANG_PLAY_LAST + desc: used in the onplay menu + user: core + <source> + *: "Play Last" + </source> + <dest> + *: "Пусти последње" + </dest> + <voice> + *: "Пусти последње" + </voice> +</phrase> +<phrase> + id: LANG_PLAY_LAST_SHUFFLED + desc: used in the onplay menu + user: core + <source> + *: "Play Last Shuffled" + </source> + <dest> + *: "Пусти последње промешано" + </dest> + <voice> + *: "Пусти последње промешано" + </voice> +</phrase> +<phrase> + id: LANG_VOLUME_ADJUST_MODE + desc: in system settings + user: core + <source> + *: none + perceptual_volume: "Volume Adjustment Mode" + </source> + <dest> + *: none + perceptual_volume: "Режим подешавања јачине" + </dest> + <voice> + *: none + perceptual_volume: "Режим подешавања јачине" + </voice> +</phrase> +<phrase> + id: LANG_VOLUME_ADJUST_NORM_STEPS + desc: in system settings + user: core + <source> + *: none + perceptual_volume: "Number of Volume Steps" + </source> + <dest> + *: none + perceptual_volume: "Број корака јачине" + </dest> + <voice> + *: none + perceptual_volume: "Број корака јачине" + </voice> +</phrase> +<phrase> + id: LANG_PERCEPTUAL + desc: in system settings -> volume adjustment mode + user: core + <source> + *: none + perceptual_volume: "Perceptual" + </source> + <dest> + *: none + perceptual_volume: "Перцептуално" + </dest> + <voice> + *: none + perceptual_volume: "Перцептуално" + </voice> +</phrase> diff --git a/apps/language.c b/apps/language.c index 1ad1d5c829..d177303d89 100644 --- a/apps/language.c +++ b/apps/language.c @@ -37,7 +37,9 @@ /* See tools/genlang (TODO: Use common include for both) */ #define LANGUAGE_COOKIE 0x1a #define LANGUAGE_VERSION 0x06 -#define LANGUAGE_FLAG_RTL 0x01 + +#define LANGUAGE_FLAG_RTL 0x01 +#define LANGUAGE_FLAG_UNITS_FIRST 0x02 #define HEADER_SIZE 4 #define SUBHEADER_SIZE 6 @@ -54,8 +56,8 @@ void lang_init(const unsigned char *builtin, unsigned char **dest, int count) } } -int lang_load(const char *filename, const unsigned char *builtin, - unsigned char **dest, unsigned char *buffer, +int lang_load(const char *filename, const unsigned char *builtin, + unsigned char **dest, unsigned char *buffer, unsigned int user_num, int max_lang_size, unsigned int max_id) { @@ -143,3 +145,8 @@ int lang_is_rtl(void) { return (lang_options & LANGUAGE_FLAG_RTL) != 0; } + +int lang_units_first(void) +{ + return (lang_options & LANGUAGE_FLAG_UNITS_FIRST) != 0; +} diff --git a/apps/language.h b/apps/language.h index cbfa7e2c1d..85fa7f6efa 100644 --- a/apps/language.h +++ b/apps/language.h @@ -37,4 +37,6 @@ int lang_english_to_id(const char *english); /* returns whether the loaded language is a right-to-left language */ int lang_is_rtl(void); +/* returns whether the loaded language needs units spoken before the value */ +int lang_units_first(void); #endif diff --git a/apps/logfdisp.c b/apps/logfdisp.c index b139f30ac7..efbfa192f5 100644 --- a/apps/logfdisp.c +++ b/apps/logfdisp.c @@ -35,7 +35,9 @@ #include "logfdisp.h" #include "action.h" #include "splash.h" - +#if CONFIG_RTC +#include "misc.h" +#endif /*CONFIG_RTC*/ int compute_nb_lines(int w, struct font* font) { int i, nb_lines; @@ -212,10 +214,6 @@ bool logfdisplay(void) bool logfdump(void) { int fd; -#if CONFIG_RTC - struct tm *nowtm; - char fname[MAX_PATH]; -#endif splashf(HZ, "Log File Dumped"); @@ -227,11 +225,12 @@ bool logfdump(void) logfenabled = false; #if CONFIG_RTC - nowtm = get_time(); - snprintf(fname, MAX_PATH, "%s/logf_%04d%02d%02d%02d%02d%02d.txt", ROCKBOX_DIR, + char fname[MAX_PATH]; + struct tm *nowtm = get_time(); + fd = open_pathfmt(fname, sizeof(fname), O_CREAT|O_WRONLY|O_TRUNC, + "%s/logf_%04d%02d%02d%02d%02d%02d.txt", ROCKBOX_DIR, nowtm->tm_year + 1900, nowtm->tm_mon + 1, nowtm->tm_mday, nowtm->tm_hour, nowtm->tm_min, nowtm->tm_sec); - fd = open(fname, O_CREAT|O_WRONLY|O_TRUNC); #else fd = open(ROCKBOX_DIR "/logf.txt", O_CREAT|O_WRONLY|O_TRUNC, 0666); #endif diff --git a/apps/main.c b/apps/main.c index dff9dc5778..1e012efb3c 100644 --- a/apps/main.c +++ b/apps/main.c @@ -21,6 +21,7 @@ #include "config.h" #include "system.h" +#include "version.h" #include "gcc_extensions.h" #include "storage.h" #include "disk.h" @@ -167,7 +168,7 @@ int main(void) screens[i].update(); } list_init(); - tree_gui_init(); + tree_init(); /* Keep the order of this 3 * Must be done before any code uses the multi-screen API */ #ifdef HAVE_USBSTACK @@ -208,6 +209,50 @@ int main(void) root_menu(); } +/* The disk isn't ready at boot, rblogo is stored in bin and erased after boot */ +int show_logo_boot( void ) INIT_ATTR; +int show_logo_boot( void ) +{ + unsigned char version[32]; + int font_h, ver_w; + snprintf(version, sizeof(version), "Ver. %s", rbversion); + ver_w = font_getstringsize(version, NULL, &font_h, FONT_SYSFIXED); + lcd_clear_display(); + lcd_setfont(FONT_SYSFIXED); +#if defined(SANSA_CLIP) || defined(SANSA_CLIPV2) || defined(SANSA_CLIPPLUS) + /* display the logo in the blue area of the screen (bottom 48 pixels) */ + if (ver_w > LCD_WIDTH) + lcd_putsxy(0, 0, rbversion); + else + lcd_putsxy((LCD_WIDTH/2) - (ver_w/2), 0, version); + lcd_bmp(&bm_rockboxlogo, (LCD_WIDTH - BMPWIDTH_rockboxlogo) / 2, 16); +#else + lcd_bmp(&bm_rockboxlogo, (LCD_WIDTH - BMPWIDTH_rockboxlogo) / 2, 10); + if (ver_w > LCD_WIDTH) + lcd_putsxy(0, LCD_HEIGHT-font_h, rbversion); + else + lcd_putsxy((LCD_WIDTH/2) - (ver_w/2), LCD_HEIGHT-font_h, version); +#endif + lcd_setfont(FONT_UI); + lcd_update(); +#ifdef HAVE_REMOTE_LCD + lcd_remote_clear_display(); + lcd_remote_bmp(&bm_remote_rockboxlogo, 0, 10); + lcd_remote_setfont(FONT_SYSFIXED); + if (ver_w > LCD_REMOTE_WIDTH) + lcd_remote_putsxy(0, LCD_REMOTE_HEIGHT-font_h, rbversion); + else + lcd_remote_putsxy((LCD_REMOTE_WIDTH/2) - (ver_w/2), + LCD_REMOTE_HEIGHT-font_h, version); + lcd_remote_setfont(FONT_UI); + lcd_remote_update(); +#endif +#ifdef SIMULATOR + sleep(HZ); /* sim is too fast to see logo */ +#endif + return 0; +} + #ifdef HAVE_DIRCACHE static int INIT_ATTR init_dircache(bool preinit) { @@ -241,7 +286,7 @@ static int INIT_ATTR init_dircache(bool preinit) splash(0, str(LANG_SCANNING_DISK)); dircache_wait(); backlight_on(); - show_logo(); + show_logo_boot(); } struct dircache_info info; @@ -288,13 +333,15 @@ static void init_tagcache(void) #endif if (lang_is_rtl()) { - splashf(0, "[%d/%d] %s", ret, tagcache_get_max_commit_step(), - str(LANG_TAGCACHE_INIT)); + splash_progress(ret, tagcache_get_max_commit_step(), + "[%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()); + splash_progress(ret, tagcache_get_max_commit_step(), + "%s [%d/%d]", str(LANG_TAGCACHE_INIT), ret, + tagcache_get_max_commit_step()); } clear = true; } @@ -305,7 +352,7 @@ static void init_tagcache(void) if (clear) { backlight_on(); - show_logo(); + show_logo_boot(); } } #endif /* HAVE_TAGCACHE */ @@ -328,7 +375,7 @@ static void init(void) FOR_NB_SCREENS(i) global_status.font_id[i] = FONT_SYSFIXED; font_init(); - show_logo(); + show_logo_boot(); button_init(); powermgmt_init(); backlight_init(); @@ -432,7 +479,7 @@ static void init(void) settings_reset(); CHART(">show_logo"); - show_logo(); + show_logo_boot(); CHART("<show_logo"); lang_init(core_language_builtin, language_strings, LANG_LAST_INDEX_IN_ARRAY); @@ -566,27 +613,28 @@ static void init(void) pcm_init(); dsp_init(); -#if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \ + CHART(">settings_load(ALL)"); + settings_load(SETTINGS_ALL); + CHART("<settings_load(ALL)"); + +#if defined(BUTTON_REC) || \ + (CONFIG_KEYPAD == GIGABEAT_PAD) || \ + (CONFIG_KEYPAD == IPOD_4G_PAD) || \ (CONFIG_KEYPAD == IRIVER_H10_PAD) + if (global_settings.clear_settings_on_hold && #ifdef SETTINGS_RESET /* Reset settings if holding the reset button. (Rec on Archos, A on Gigabeat) */ - if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET) + ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)) #else /* Reset settings if the hold button is turned on */ - if (button_hold()) + (button_hold())) #endif { splash(HZ*2, str(LANG_RESET_DONE_CLEAR)); settings_reset(); } - else #endif - { - CHART(">settings_load(ALL)"); - settings_load(SETTINGS_ALL); - CHART("<settings_load(ALL)"); - } #ifdef HAVE_DIRCACHE CHART(">init_dircache(true)"); @@ -594,7 +642,7 @@ static void init(void) CHART("<init_dircache(true)"); #ifdef HAVE_TAGCACHE if (rc < 0) - remove(TAGCACHE_STATEFILE); + tagcache_remove_statefile(); #endif /* HAVE_TAGCACHE */ #endif /* HAVE_DIRCACHE */ diff --git a/apps/menu.c b/apps/menu.c index ab5578dede..df2284be12 100644 --- a/apps/menu.c +++ b/apps/menu.c @@ -147,7 +147,7 @@ static const char* get_menu_item_name(int selected_item, type = (menu->flags&MENU_TYPE_MASK); if ((type == MT_SETTING) || (type == MT_SETTING_W_TEXT)) { - const struct settings_list *v = find_setting(menu->variable, NULL); + const struct settings_list *v = find_setting(menu->variable); if (v) return str(v->lang_id); else return "Not Done yet!"; @@ -260,7 +260,6 @@ static int init_menu_lists(const struct menu_item_ex *menu, if(global_settings.talk_menu) gui_synclist_set_voice_callback(lists, talk_menu_item); gui_synclist_set_nb_items(lists,current_subitems_count); - gui_synclist_limit_scroll(lists,true); gui_synclist_select_item(lists, find_menu_selection(selected)); get_menu_callback(menu,&menu_callback); @@ -334,10 +333,7 @@ void do_setting_screen(const struct settings_list *setting, const char * title, if (setting->flags&F_PADTITLE) { int i = 0, len; - if (setting->lang_id == -1) - title = (char*)setting->cfg_vals; - else - title = P2STR((unsigned char*)title); + title = P2STR((unsigned char*)title); len = strlen(title); while (i < MAX_PATH-1) { @@ -360,14 +356,12 @@ void do_setting_from_menu(const struct menu_item_ex *temp, struct viewport parent[NB_SCREENS]) { char *title; - int setting_id; if (!temp) { panicf("do_setting_from_menu, NULL pointer"); return; } - const struct settings_list *setting = - find_setting(temp->variable, &setting_id); + const struct settings_list *setting = find_setting(temp->variable); if ((temp->flags&MENU_TYPE_MASK) == MT_SETTING_W_TEXT) title = temp->callback_and_desc->desc; @@ -451,19 +445,27 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected, action = new_action; } - if (LIKELY(gui_synclist_do_button(&lists, &action, LIST_WRAP_UNLESS_HELD))) + if (LIKELY(gui_synclist_do_button(&lists, &action))) continue; #ifdef HAVE_QUICKSCREEN else if (action == ACTION_STD_QUICKSCREEN) { - if (global_settings.shortcuts_replaces_qs) + if (global_settings.shortcuts_replaces_qs || + quick_screen_quick(action) == QUICKSCREEN_GOTO_SHORTCUTS_MENU) { + int last_screen = global_status.last_screen; global_status.last_screen = GO_TO_SHORTCUTMENU; - ret = quick_screen_quick(action); - done = true; + int shortcut_ret = do_shortcut_menu(NULL); + if (shortcut_ret == GO_TO_PREVIOUS) + global_status.last_screen = last_screen; + else + { + ret = shortcut_ret; + done = true; + } } - else - quick_screen_quick(action); + if (!done) + init_menu_lists(menu, &lists, lists.selected_item, false, vps); redraw_lists = true; } #endif @@ -517,17 +519,17 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected, MENUITEM_STRINGLIST(notquickscreen_able_option, ID2P(LANG_ONPLAY_MENU_TITLE), NULL, ID2P(LANG_RESET_SETTING)); - const struct menu_item_ex *menu; + const struct menu_item_ex *context_menu; const struct settings_list *setting = - find_setting(temp->variable, NULL); + find_setting(temp->variable); #ifdef HAVE_QUICKSCREEN if (is_setting_quickscreenable(setting)) - menu = &quickscreen_able_option; + context_menu = &quickscreen_able_option; else #endif - menu = ¬quickscreen_able_option; + context_menu = ¬quickscreen_able_option; |