summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/action.c120
-rw-r--r--apps/action.h6
-rw-r--r--apps/bookmark.c1136
-rw-r--r--apps/bookmark.h8
-rw-r--r--apps/buffering.c1
-rw-r--r--apps/core_keymap.c134
-rw-r--r--apps/core_keymap.h7
-rw-r--r--apps/cuesheet.c34
-rw-r--r--apps/debug_menu.c97
-rw-r--r--apps/filetree.c101
-rw-r--r--apps/filetree.h3
-rw-r--r--apps/filetypes.c269
-rw-r--r--apps/filetypes.h4
-rw-r--r--apps/gui/bitmap/list-skinned.c3
-rw-r--r--apps/gui/bitmap/list.c13
-rw-r--r--apps/gui/color_picker.c26
-rw-r--r--apps/gui/folder_select.c8
-rw-r--r--apps/gui/icon.c16
-rw-r--r--apps/gui/line.c3
-rw-r--r--apps/gui/list.c171
-rw-r--r--apps/gui/list.h47
-rw-r--r--apps/gui/option_select.c17
-rw-r--r--apps/gui/quickscreen.c25
-rw-r--r--apps/gui/quickscreen.h7
-rw-r--r--apps/gui/skin_engine/skin_backdrops.c19
-rw-r--r--apps/gui/skin_engine/skin_display.c233
-rw-r--r--apps/gui/skin_engine/skin_display.h9
-rw-r--r--apps/gui/skin_engine/skin_engine.c61
-rw-r--r--apps/gui/skin_engine/skin_engine.h24
-rw-r--r--apps/gui/skin_engine/skin_parser.c73
-rw-r--r--apps/gui/skin_engine/skin_render.c44
-rw-r--r--apps/gui/skin_engine/skin_tokens.c51
-rw-r--r--apps/gui/skin_engine/skin_touchsupport.c11
-rw-r--r--apps/gui/skin_engine/wps_internals.h51
-rw-r--r--apps/gui/splash.c176
-rw-r--r--apps/gui/splash.h11
-rw-r--r--apps/gui/statusbar-skinned.c18
-rw-r--r--apps/gui/statusbar-skinned.h5
-rw-r--r--apps/gui/viewport.c40
-rw-r--r--apps/gui/viewport.h1
-rw-r--r--apps/gui/wps.c178
-rw-r--r--apps/gui/wps.h37
-rw-r--r--apps/gui/yesno.c5
-rw-r--r--apps/hosted/android/keyboard.c2
-rw-r--r--apps/hosted/android/notification.c1
-rw-r--r--apps/iap/iap-core.c2
-rw-r--r--apps/iap/iap-lingo4.c21
-rw-r--r--apps/keymaps/keymap-agptekrocker.c19
-rw-r--r--apps/keymaps/keymap-clip.c2
-rw-r--r--apps/keymaps/keymap-erosq.c1
-rw-r--r--apps/keymaps/keymap-fiiom3k.c3
-rw-r--r--apps/keymaps/keymap-fuzeplus.c3
-rw-r--r--apps/keymaps/keymap-ipod.c2
-rw-r--r--apps/keymaps/keymap-nwz.c3
-rw-r--r--apps/keymaps/keymap-nwza860.c3
-rw-r--r--apps/keymaps/keymap-zen.c3
-rw-r--r--apps/lang/english-us.lang54
-rw-r--r--apps/lang/english.lang22
-rw-r--r--apps/lang/italiano.lang196
-rw-r--r--apps/lang/nederlands.lang368
-rw-r--r--apps/lang/polski.lang20
-rw-r--r--apps/lang/srpski.lang256
-rw-r--r--apps/logfdisp.c15
-rw-r--r--apps/main.c10
-rw-r--r--apps/menu.c27
-rw-r--r--apps/menus/display_menu.c18
-rw-r--r--apps/menus/eq_menu.c40
-rw-r--r--apps/menus/main_menu.c6
-rw-r--r--apps/menus/playback_menu.c2
-rw-r--r--apps/menus/playlist_menu.c2
-rw-r--r--apps/menus/sound_menu.c18
-rw-r--r--apps/misc.c100
-rw-r--r--apps/misc.h6
-rw-r--r--apps/onplay.c91
-rw-r--r--apps/onplay.h3
-rw-r--r--apps/open_plugin.c36
-rw-r--r--apps/open_plugin.h5
-rw-r--r--apps/playback.c38
-rw-r--r--apps/playlist.c63
-rw-r--r--apps/playlist_catalog.c82
-rw-r--r--apps/playlist_catalog.h2
-rw-r--r--apps/playlist_viewer.c125
-rw-r--r--apps/playlist_viewer.h3
-rw-r--r--apps/plugin.c39
-rw-r--r--apps/plugin.h44
-rw-r--r--apps/plugins/2048.c5
-rw-r--r--apps/plugins/SOURCES3
-rw-r--r--apps/plugins/SUBDIRS3
-rw-r--r--apps/plugins/bitmaps/native/SOURCES3
-rw-r--r--apps/plugins/brickmania.c23
-rw-r--r--apps/plugins/calendar.c2
-rw-r--r--apps/plugins/chessbox/chessbox_pgn.c4
-rw-r--r--apps/plugins/chopper.c8
-rw-r--r--apps/plugins/credits.c8
-rw-r--r--apps/plugins/demystify.c12
-rw-r--r--apps/plugins/doom/i_video.c3
-rw-r--r--apps/plugins/doom/rockdoom.c8
-rw-r--r--apps/plugins/fft/fft.c6
-rw-r--r--apps/plugins/fire.c6
-rw-r--r--apps/plugins/fireworks.c8
-rw-r--r--apps/plugins/imageviewer/imageviewer.c4
-rw-r--r--apps/plugins/imageviewer/jpeg/yuv2rgb.c2
-rw-r--r--apps/plugins/imageviewer/ppm/ppm_decoder.c2
-rw-r--r--apps/plugins/invadrox.c2
-rw-r--r--apps/plugins/keybox.c3
-rw-r--r--apps/plugins/keyremap.c5
-rw-r--r--apps/plugins/lamp.c15
-rw-r--r--apps/plugins/lib/bmp_smooth_scale.c2
-rw-r--r--apps/plugins/lib/helper.c48
-rw-r--r--apps/plugins/lib/helper.h20
-rw-r--r--apps/plugins/lib/osd.c8
-rw-r--r--apps/plugins/lib/pluginlib_bmp.c2
-rw-r--r--apps/plugins/lib/printcell_helper.c2
-rw-r--r--apps/plugins/lib/xlcd_scroll.c4
-rw-r--r--apps/plugins/lrcplayer.c4
-rw-r--r--apps/plugins/lua/rocklib_events.c4
-rw-r--r--apps/plugins/lua/rocklib_img.c2
-rw-r--r--apps/plugins/main_menu_config.c2
-rw-r--r--apps/plugins/maze.c5
-rw-r--r--apps/plugins/mazezam.c5
-rw-r--r--apps/plugins/mpegplayer/mpegplayer.c5
-rw-r--r--apps/plugins/open_plugins.c36
-rw-r--r--apps/plugins/oscilloscope.c6
-rwxr-xr-xapps/plugins/pacbox/pacbox.c4
-rw-r--r--apps/plugins/pictureflow/pictureflow.c94
-rw-r--r--apps/plugins/plasma.c8
-rw-r--r--apps/plugins/pong.c7
-rw-r--r--apps/plugins/properties.c221
-rw-r--r--apps/plugins/puzzles/rockbox.c15
-rw-r--r--apps/plugins/random_folder_advance_config.c3
-rw-r--r--apps/plugins/rb_info.c5
-rw-r--r--apps/plugins/resistor.c18
-rw-r--r--apps/plugins/rockblox.c11
-rw-r--r--apps/plugins/rockboy/menu.c6
-rw-r--r--apps/plugins/rockboy/rockboy.c5
-rw-r--r--apps/plugins/rocklife.c6
-rw-r--r--apps/plugins/sdl/main.c7
-rw-r--r--apps/plugins/shopper.c3
-rw-r--r--apps/plugins/shortcuts/shortcuts_view.c8
-rw-r--r--apps/plugins/spacerocks.c11
-rw-r--r--apps/plugins/speedread.c7
-rw-r--r--apps/plugins/starfield.c8
-rw-r--r--apps/plugins/superdom.c1
-rw-r--r--apps/plugins/test_disk.c6
-rw-r--r--apps/plugins/test_fps.c8
-rw-r--r--apps/plugins/test_gfx.c8
-rw-r--r--apps/plugins/test_grey.c8
-rw-r--r--apps/plugins/test_viewports.c4
-rw-r--r--apps/plugins/text_editor.c3
-rw-r--r--apps/plugins/wormlet.c7
-rw-r--r--apps/plugins/xobox.c7
-rw-r--r--apps/plugins/xworld/sys.c18
-rw-r--r--apps/radio/presets.c7
-rw-r--r--apps/radio/radio.c5
-rw-r--r--apps/radio/radio_skin.c16
-rw-r--r--apps/radio/radioart.c2
-rw-r--r--apps/rbcodec_helpers.c5
-rw-r--r--apps/recorder/albumart.c80
-rw-r--r--apps/recorder/albumart.h6
-rw-r--r--apps/recorder/keyboard.c4
-rw-r--r--apps/recorder/pcm_record.c7
-rw-r--r--apps/recorder/recording.c2
-rw-r--r--apps/recorder/resize.c2
-rw-r--r--apps/root_menu.c31
-rw-r--r--apps/screen_access.c2
-rw-r--r--apps/screen_access.h1
-rw-r--r--apps/screens.c26
-rw-r--r--apps/settings.c59
-rw-r--r--apps/settings.h3
-rw-r--r--apps/settings_list.c34
-rw-r--r--apps/settings_list.h5
-rw-r--r--apps/shortcuts.c18
-rw-r--r--apps/status.h2
-rw-r--r--apps/tagcache.c71
-rw-r--r--apps/tagcache.h1
-rw-r--r--apps/tagtree.c271
-rw-r--r--apps/tagtree.h4
-rw-r--r--apps/talk.c316
-rw-r--r--apps/talk.h7
-rw-r--r--apps/tree.c120
-rw-r--r--apps/tree.h19
-rw-r--r--bootloader/x1000/main.c14
-rw-r--r--bootloader/x1000/x1000bootloader.h5
-rw-r--r--docs/CREDITS2
-rw-r--r--docs/PLUGIN_API8
-rw-r--r--firmware/SOURCES71
-rw-r--r--firmware/buflib.c677
-rw-r--r--firmware/common/dircache.c76
-rw-r--r--firmware/common/file_internal.c1
-rw-r--r--firmware/common/linked_list.c53
-rw-r--r--firmware/common/multiboot.c6
-rw-r--r--firmware/common/strlcat.c19
-rw-r--r--firmware/common/strlcpy.c64
-rw-r--r--firmware/common/strmemccpy.c38
-rw-r--r--firmware/common/strnatcmp.c16
-rw-r--r--firmware/common/strptokspn.c77
-rw-r--r--firmware/common/unicode.c29
-rw-r--r--firmware/common/zip.c23
-rw-r--r--firmware/core_alloc.c15
-rw-r--r--firmware/drivers/fat.c2
-rw-r--r--firmware/drivers/lcd-16bit-common.c245
-rw-r--r--firmware/drivers/lcd-16bit-vert.c214
-rw-r--r--firmware/drivers/lcd-16bit.c213
-rw-r--r--firmware/drivers/lcd-1bit-vert.c393
-rw-r--r--firmware/drivers/lcd-24bit.c436
-rw-r--r--firmware/drivers/lcd-2bit-horz.c441
-rw-r--r--firmware/drivers/lcd-2bit-vert.c447
-rw-r--r--firmware/drivers/lcd-2bit-vi.c449
-rw-r--r--firmware/drivers/lcd-bitmap-common.c344
-rw-r--r--firmware/drivers/lcd-color-common.c177
-rw-r--r--firmware/drivers/lcd-scroll.c8
-rw-r--r--firmware/drivers/usb-designware.c2
-rw-r--r--firmware/export/config.h25
-rw-r--r--firmware/export/config/mrobe500.h5
-rw-r--r--firmware/export/config/sansaconnect.h3
-rw-r--r--firmware/export/font.h2
-rw-r--r--firmware/export/lcd.h4
-rw-r--r--firmware/font.c45
-rw-r--r--firmware/general.c4
-rw-r--r--firmware/include/buflib.h44
-rw-r--r--firmware/include/core_alloc.h7
-rw-r--r--firmware/include/fs_defines.h12
-rw-r--r--firmware/include/linked_list.h38
-rw-r--r--firmware/include/string-extra.h1
-rw-r--r--firmware/include/strmemccpy.h32
-rw-r--r--firmware/include/strptokspn_r.h26
-rw-r--r--firmware/libc/include/string.h4
-rw-r--r--firmware/libc/memccpy.c119
-rw-r--r--firmware/libc/strcspn.c45
-rw-r--r--firmware/libc/strtok.c63
-rw-r--r--firmware/linuxboot.c3
-rw-r--r--firmware/panic.c6
-rw-r--r--firmware/scroll_engine.c8
-rw-r--r--firmware/target/arm/tms320dm320/mrobe-500/lcd-mr500.c4
-rw-r--r--firmware/target/hosted/sdl/lcd-sdl.c6
-rw-r--r--firmware/target/mips/exception-mips.S181
-rw-r--r--firmware/target/mips/ingenic_jz47xx/app.lds6
-rw-r--r--firmware/target/mips/ingenic_jz47xx/boot.lds6
-rw-r--r--firmware/target/mips/ingenic_jz47xx/crt0.S165
-rw-r--r--firmware/target/mips/ingenic_jz47xx/debug-jz4760.c8
-rw-r--r--firmware/target/mips/ingenic_jz47xx/system-jz4740.c74
-rw-r--r--firmware/target/mips/ingenic_jz47xx/system-jz4760.c40
-rw-r--r--firmware/target/mips/ingenic_jz47xx/system-target.h1
-rw-r--r--firmware/target/mips/ingenic_x1000/app.lds2
-rw-r--r--firmware/target/mips/ingenic_x1000/crt0.S147
-rw-r--r--firmware/target/mips/ingenic_x1000/installer-x1000.c19
-rw-r--r--firmware/target/mips/ingenic_x1000/installer-x1000.h1
-rw-r--r--firmware/target/mips/ingenic_x1000/nand-x1000.c149
-rw-r--r--firmware/target/mips/ingenic_x1000/nand-x1000.h38
-rw-r--r--firmware/target/mips/ingenic_x1000/spl-x1000.c7
-rw-r--r--firmware/target/mips/ingenic_x1000/system-target.h1
-rw-r--r--firmware/target/mips/ingenic_x1000/system-x1000.c47
-rw-r--r--firmware/target/mips/mmu-mips.h6
-rw-r--r--firmware/target/mips/system-mips.c175
-rw-r--r--firmware/target/mips/system-mips.h40
-rw-r--r--firmware/usb.c44
-rw-r--r--firmware/usbstack/usb_storage.c3
-rw-r--r--lib/rbcodec/codecs/aac.c10
-rw-r--r--lib/rbcodec/codecs/alac.c64
-rw-r--r--lib/rbcodec/codecs/mpa.c160
-rw-r--r--lib/rbcodec/metadata/replaygain.c2
-rw-r--r--lib/rbcodec/test/SOURCES1
-rw-r--r--lib/skin_parser/skin_parser.h15
-rw-r--r--lib/x1000-installer/src/xf_nandio.c5
-rw-r--r--lib/x1000-installer/src/xf_package.c5
-rw-r--r--manual/appendix/config_file_options.tex2
-rw-r--r--manual/configure_rockbox/playback_options.tex5
-rw-r--r--manual/main_menu/main.tex8
-rw-r--r--manual/plugins/pictureflow.tex23
-rw-r--r--tools/checkwps/SOURCES1
-rw-r--r--tools/database/SOURCES1
-rwxr-xr-xtools/rockboxdev.sh126
-rw-r--r--tools/toolchain-patches/crosstool-ng-1.13.2.diff13
-rw-r--r--wps/WPSLIST2
-rw-r--r--wps/cabbiev2.112x64x1.wps2
-rw-r--r--wps/cabbiev2.128x128x16.wps4
-rw-r--r--wps/cabbiev2.128x128x2.wps4
-rw-r--r--wps/cabbiev2.128x160x16.wps4
-rw-r--r--wps/cabbiev2.128x64x1.wps2
-rw-r--r--wps/cabbiev2.128x96x16.wps4
-rw-r--r--wps/cabbiev2.128x96x2.wps2
-rw-r--r--wps/cabbiev2.132x80x16.wps4
-rw-r--r--wps/cabbiev2.138x110x2.wps4
-rw-r--r--wps/cabbiev2.160x128x1.wps2
-rw-r--r--wps/cabbiev2.160x128x16.wps4
-rw-r--r--wps/cabbiev2.160x128x2.wps4
-rw-r--r--wps/cabbiev2.176x132x16.wps4
-rw-r--r--wps/cabbiev2.176x220x16.wps4
-rw-r--r--wps/cabbiev2.220x176x16.wps4
-rw-r--r--wps/cabbiev2.240x320x16.mini2440.wps4
-rw-r--r--wps/cabbiev2.240x320x16.wps16
-rw-r--r--wps/cabbiev2.240x400x16.wps4
-rw-r--r--wps/cabbiev2.320x240x16.mrobe500.wps2
-rw-r--r--wps/cabbiev2.320x240x16.wps4
-rw-r--r--wps/cabbiev2.320x480x16.wps4
-rw-r--r--wps/cabbiev2.360x400x16.wps8
-rw-r--r--wps/cabbiev2.400x240x16.wps4
-rw-r--r--wps/cabbiev2.480x800x16.wps4
-rw-r--r--wps/cabbiev2.800x480x16.wps4
-rw-r--r--wps/cabbiev2.96x96x16.wps6
300 files changed, 6381 insertions, 7397 deletions
diff --git a/apps/action.c b/apps/action.c
index 9ef10936f2..8c03ca4d65 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
@@ -601,9 +602,8 @@ 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)
@@ -611,7 +611,7 @@ static inline void action_code_lookup(action_last_t *last, action_cur_t *cur)
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 */
@@ -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", 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..444437edf8 100644
--- a/apps/action.h
+++ b/apps/action.h
@@ -419,7 +419,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 +449,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/bookmark.c b/apps/bookmark.c
index 70dbd8075d..f3c712240a 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,7 +69,8 @@ struct bookmark_list
#define BM_SPEED 0x02
/* bookmark values */
-static struct {
+static struct resume_info{
+ const struct mp3entry *id3;
int resume_index;
unsigned long resume_offset;
int resume_seed;
@@ -76,231 +80,188 @@ static struct {
/* 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);
+} resume_info;
-#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)
-{
- return write_bookmark(true, create_bookmark());
-}
-/* ----------------------------------------------------------------------- */
-/* 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_token(const char* s)
{
- char* bookmark;
- int ret = BOOKMARK_FAIL;
-
- push_current_activity(ACTIVITY_BOOKMARKSLIST);
+ while (*s && *s != ';')
+ {
+ s++;
+ }
- char* name = playlist_get_name(NULL, global_temp_buffer,
- sizeof(global_temp_buffer));
- if (generate_bookmark_file_name(name))
+ if (*s)
{
- ret = select_bookmark(global_bookmark_file_name, false, &bookmark);
- if (bookmark != NULL)
- {
- ret = play_bookmark(bookmark) ? BOOKMARK_SUCCESS : BOOKMARK_FAIL;
- }
+ s++;
}
- pop_current_activity();
- return ret;
+ return s;
}
-/* ----------------------------------------------------------------------- */
-/* 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 const char* int_token(const char* s, int* dest)
{
- char* bookmark;
- bool ret = false;
+ *dest = atoi(s);
+ return skip_token(s);
+}
- push_current_activity(ACTIVITY_BOOKMARKSLIST);
- select_bookmark(RECENT_BOOKMARK_FILE, false, &bookmark);
- if (bookmark != NULL)
- {
- ret = play_bookmark(bookmark);
- }
+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);
+}
- pop_current_activity();
- return ret;
+/*-------------------------------------------------------------------------*/
+/* 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(const char *bookmark,
+ char **pl_start,
+ char **pl_end,
+ char **track)
+{
+ *pl_start = strchr(bookmark,'/');
+ if (!(*pl_start))
+ return false;
+ *pl_end = strrchr(bookmark,';');
+ *track = *pl_end + 1;
+ 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,
+ const bool strip_dir)
{
- char* bookmark;
- bool update;
-
- if (!bookmark_is_bookmarkable_state())
- return false;
-
- audio_pause(); /* first pause playback */
- update = (global_settings.autoupdatebookmark && bookmark_exists());
- bookmark = create_bookmark();
+ const char* s = bookmark;
+ const char* end;
- if (update)
- return write_bookmark(true, 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)
- switch (global_settings.autocreatebookmark)
+ /* 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)
{
- case BOOKMARK_YES:
- return write_bookmark(true, bookmark);
+ s++;
+ GET_INT_TOKEN(opt_flags);
+ }
- case BOOKMARK_NO:
- return false;
+ /* extract all original bookmark tokens */
+ GET_INT_TOKEN(resume_info.resume_index);
+ GET_LONG_TOKEN(resume_info.resume_offset);
+ GET_INT_TOKEN(resume_info.resume_seed);
+ if (!new_format) /* skip deprecated token */
+ s = skip_token(s);
+ GET_LONG_TOKEN(resume_info.resume_time);
+ GET_INT_TOKEN(resume_info.repeat_mode);
+ GET_BOOL_TOKEN(resume_info.shuffle);
- 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};
+ /* extract all optional bookmark tokens */
+ if (opt_flags & BM_PITCH)
+ GET_INT_TOKEN(resume_info.pitch);
+ if (opt_flags & BM_SPEED)
+ GET_INT_TOKEN(resume_info.speed);
- if(prompt_ok && gui_syncyesno_run(&message, NULL, NULL)==YESNO_YES)
+ if (*s == 0)
{
- if (global_settings.autocreatebookmark == BOOKMARK_RECENT_ONLY_ASK)
- return write_bookmark(false, bookmark);
- else
- return write_bookmark(true, bookmark);
+ return false;
}
- 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;
+ end = strchr(s, ';');
- if (!bookmark)
- {
- ret = false; /* something didn't happen correctly, do nothing */
- }
- else
+ /* extract file names */
+ if(filenamebuf)
{
- if (global_settings.usemrb)
- ret = add_bookmark(RECENT_BOOKMARK_FILE, bookmark, true);
-
+ 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);
- /* writing the bookmark */
- if (create_bookmark_file)
+ 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;
+ /* 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;
+ 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;
/* 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(bookmark, &pl_start, &pl_end, &track))
{
comp_playlist = true;
pl_len = pl_end - pl_start;
@@ -308,35 +269,38 @@ static bool add_bookmark(const char* bookmark_file_name, const char* bookmark,
comp_track = true;
}
}
-
+ 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++;
/* 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, 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(global_temp_buffer,
+ &bm_pl_start, &bm_pl_end, &bm_track))
{
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_len == bm_pl_len) &&
+ !strncmp(pl_start, bm_pl_start, pl_len);
+
if (equal && comp_track)
equal = !strcmp(track, bm_track);
}
@@ -344,8 +308,9 @@ static bool add_bookmark(const char* bookmark_file_name, const char* bookmark,
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);
}
}
@@ -353,181 +318,222 @@ static bool add_bookmark(const char* bookmark_file_name, const char* bookmark,
}
close(temp_bookmark_file);
+ /* only retrieve the path*/
+ open_temp_bookmark(fnamebuf,
+ sizeof(fnamebuf),
+ O_PATH,
+ bookmark_file_name);
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 (!strcmp("/", bmarknamein))
+ strmemccpy(filenamebuf, "/root_dir.bmark", filenamebufsz);
+ else
+ {
+ size_t len = strlcpy(filenamebuf, bmarknamein,
+ MIN(filenamebufsz, bmarknamelen));
+ if(len >= filenamebufsz)
+ return false;
+#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';
+ len--;
+ }
+
+ 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)
{
- 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 bmsz = 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);
-
- /* checking to see if the bookmark is valid */
- if (parse_bookmark(global_bookmark, false, false))
- return global_bookmark;
- else
+ ); /*sprintf*/
+/* mandatory tokens */
+ if (bmsz >= bufsz) /* include NULL*/
return NULL;
-}
-#if __GNUC__ >= 7
-#pragma GCC diagnostic pop /* -Wformat-truncation */
-#endif
+ buf += bmsz;
+ bufsz -= bmsz;
-/* ----------------------------------------------------------------------- */
-/* 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)
-{
- char* bookmark;
+ /* create the bookmark */
+ playlist_get_name(NULL, buf, bmsz);
+ bmsz = strlen(buf);
- if(global_settings.autoloadbookmark == BOOKMARK_NO)
- return false;
+ if (bmsz == 0 || (bmsz + 1) >= bufsz) /* include the separator & NULL*/
+ return NULL;
- /*Checking to see if a bookmark file exists.*/
- if(!generate_bookmark_file_name(file))
- {
- return false;
- }
+ *name = buf; /* return the playlist name through the *pointer */
+ *namelen = bmsz; /* return the name length through the pointer */
- if(!file_exists(global_bookmark_file_name))
- return false;
+ /* 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(global_settings.autoloadbookmark == BOOKMARK_YES)
- {
- return bookmark_load(global_bookmark_file_name, true);
- }
- else
- {
- int ret = select_bookmark(global_bookmark_file_name, true, &bookmark);
+ if (buf[bmsz - 1] != '/')
+ file = resume_info.id3->path;
+ else file++;
- if (bookmark != NULL)
- {
- if (!play_bookmark(bookmark))
- {
- /* Selected bookmark not found. */
- splash(HZ*2, ID2P(LANG_NOTHING_TO_RESUME));
- }
+ buf += bmsz;
+ bufsz -= (bmsz + 1);
+ buf[0] = ';';
+ buf[1] = '\0';
- /* Act as if autoload was done even if it failed, since the
- * user did make an active selection.
- */
- return true;
- }
+ strlcat(buf, file, bufsz);
- return ret != BOOKMARK_SUCCESS;
- }
+ logf("%s [%s]", __func__, global_temp_buffer);
+ /* checking to see if the bookmark is valid */
+ if (parse_bookmark(NULL, 0, global_temp_buffer, false))
+ return global_temp_buffer;
+ else
+ return NULL;
}
+#if 0/* __GNUC__ >= 7*/
+#pragma GCC diagnostic pop /* -Wformat-truncation */
+#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;
+ char bm_filename[MAX_PATH];
+ bool ret=true;
- if(autoload)
+ char *name = NULL;
+ size_t namelen = 0;
+ char* bm;
+
+ if (bookmark_is_bookmarkable_state())
{
- fd = open(file, O_RDONLY);
- if(fd >= 0)
+ /* Get some basic resume information */
+ playlist_get_resume_info(&(resume_info.resume_index));
+ 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
+ /* 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);
+ 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);
+ 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 +543,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 +574,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 +588,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 +603,7 @@ static const char* get_bookmark_info(int list_index,
char *buffer,
size_t buffer_len)
{
+ char fnamebuf[MAX_PATH];
struct bookmark_list* bookmarks = (struct bookmark_list*) data;
int index = list_index / 2;
@@ -652,7 +659,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], true))
{
return list_index % 2 == 0 ? (char*) str(LANG_BOOKMARK_INVALID) : " ";
}
@@ -686,25 +694,72 @@ 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_time);
+ 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];
+ if (!parse_bookmark(fnamebuf, sizeof(fnamebuf), bookmark, 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_time / 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 +777,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 +836,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,8 +855,11 @@ 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),
@@ -793,8 +904,7 @@ static int select_bookmark(const char* bookmark_file_name, bool show_dont_resume
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 +953,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 +979,234 @@ 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. */
-/* ------------------------------------------------------------------------*/
-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 */
- 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 */
-
- /* 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_read_buffer,
- sizeof(global_read_buffer)) > 0)
- {
- if (bookmark_id != bookmark_count)
- {
- write(temp_bookmark_file, global_read_buffer,
- strlen(global_read_buffer));
- write(temp_bookmark_file, "\n", 1);
- }
- bookmark_count++;
- }
- close(bookmark_file);
- }
- close(temp_bookmark_file);
-
- remove(bookmark_file_name);
- rename(global_temp_buffer, bookmark_file_name);
-
- return true;
-}
-
-/* ----------------------------------------------------------------------- */
-/* 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)
-{
- if (!parse_bookmark(bookmark, true, 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(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);
-}
-
-/* ----------------------------------------------------------------------- */
/* This function parses a bookmark and then plays it. */
/* Returns true on successful bookmark play. */
/* ------------------------------------------------------------------------*/
static bool play_bookmark(const char* bookmark)
{
+ char fnamebuf[MAX_PATH];
#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();
+ resume_info.pitch = sound_get_pitch();
+ resume_info.speed = dsp_get_timestretch();
#endif
- if (parse_bookmark(bookmark, true, true))
+ if (parse_bookmark(fnamebuf, sizeof(fnamebuf), bookmark, true))
{
- global_settings.repeat_mode = bm.repeat_mode;
- global_settings.playlist_shuffle = bm.shuffle;
+ global_settings.repeat_mode = resume_info.repeat_mode;
+ global_settings.playlist_shuffle = resume_info.shuffle;
#if defined(HAVE_PITCHCONTROL)
- sound_set_pitch(bm.pitch);
- dsp_set_timestretch(bm.speed);
+ sound_set_pitch(resume_info.pitch);
+ dsp_set_timestretch(resume_info.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);
+ return bookmark_play(global_temp_buffer, resume_info.resume_index,
+ resume_info.resume_time, resume_info.resume_offset,
+ resume_info.resume_seed, fnamebuf);
}
return false;
}
-static const char* skip_token(const char* s)
+/*-------------------------------------------------------------------------*/
+/* PUBLIC INTERFACE -------------------------------------------------------*/
+/*-------------------------------------------------------------------------*/
+
+
+/* ----------------------------------------------------------------------- */
+/* This is an interface function from the context menu. */
+/* Returns true on successful bookmark creation. */
+/* ----------------------------------------------------------------------- */
+bool bookmark_create_menu(void)
{
- while (*s && *s != ';')
- {
- s++;
- }
+ 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;
- if (*s)
+ push_current_activity(ACTIVITY_BOOKMARKSLIST);
+
+ 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))
{
- s++;
+ ret = select_bookmark(bm_filename, false, &bookmark);
+ if (bookmark != NULL)
+ {
+ ret = play_bookmark(bookmark) ? BOOKMARK_SUCCESS : BOOKMARK_FAIL;
+ }
}
- return s;
+ pop_current_activity();
+ return ret;
}
-static const char* int_token(const char* s, int* dest)
+/* ----------------------------------------------------------------------- */
+/* 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()
{
- *dest = atoi(s);
- return skip_token(s);
-}
+ char* bookmark;
+ bool ret = false;
-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);
+ push_current_activity(ACTIVITY_BOOKMARKSLIST);
+ select_bookmark(RECENT_BOOKMARK_FILE, false, &bookmark);
+ if (bookmark != NULL)
+ {
+ ret = play_bookmark(bookmark);
+ }
+
+ pop_current_activity();
+ return ret;
}
/* ----------------------------------------------------------------------- */
-/* 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. */
+/* This function handles an autobookmark creation. This is an interface */
+/* function. */
+/* Returns true on successful bookmark creation. */
/* ----------------------------------------------------------------------- */
-static bool parse_bookmark(const char *bookmark, const bool parse_filenames, const bool strip_dir)
+bool bookmark_autobookmark(bool prompt_ok)
{
- const char* s = bookmark;
- const char* end;
+ bool update;
-#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 (!bookmark_is_bookmarkable_state())
+ return false;
- /* 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)
+ audio_pause(); /* first pause playback */
+ update = (global_settings.autoupdatebookmark && bookmark_exists());
+
+ if (update)
+ return write_bookmark(true);
+
+ switch (global_settings.autocreatebookmark)
{
- s++;
- GET_INT_TOKEN(opt_flags);
+ case BOOKMARK_YES:
+ return write_bookmark(true);
+
+ case BOOKMARK_NO:
+ return false;
+
+ case BOOKMARK_RECENT_ONLY_YES:
+ return write_bookmark(false);
}
+ const char *lines[]={ID2P(LANG_AUTO_BOOKMARK_QUERY)};
+ const struct text_message message={lines, 1};
- /* 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);
+ 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;
+}
- /* 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);
+/* ----------------------------------------------------------------------- */
+/* 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)
+{
+ char bm_filename[MAX_PATH];
+ char* bookmark;
- if (*s == 0)
+ if(global_settings.autoloadbookmark == BOOKMARK_NO)
+ return BOOKMARK_DONT_RESUME;
+
+ /*Checking to see if a bookmark file exists.*/
+ if(!generate_bookmark_file_name(bm_filename, sizeof(bm_filename), file, -1))
{
- return false;
+ return BOOKMARK_DONT_RESUME;
}
- end = strchr(s, ';');
+ if(!file_exists(bm_filename))
+ return BOOKMARK_DONT_RESUME;
- /* extract file names */
- if (parse_filenames)
+ if(global_settings.autoloadbookmark == BOOKMARK_YES)
{
- 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);
+ return (bookmark_load(bm_filename, true)
+ ? BOOKMARK_DO_RESUME : BOOKMARK_DONT_RESUME);
+ }
+ else
+ {
+ int ret = select_bookmark(bm_filename, true, &bookmark);
- if (end != NULL)
+ if (bookmark != NULL)
{
- end++;
- if (strip_dir)
+ if (!play_bookmark(bookmark))
{
- s = strrchr(end, '/');
- if (s)
- {
- end = s;
- end++;
- }
+ /* Selected bookmark not found. */
+ splash(HZ*2, ID2P(LANG_NOTHING_TO_RESUME));
}
- strlcpy(global_filename, end, MAX_PATH);
+
+ /* Act as if autoload was done even if it failed, since the
+ * user did make an active selection.
+ */
+ 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;
+ 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 +1218,14 @@ 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 (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;
}
@@ -1180,4 +1251,3 @@ bool bookmark_is_bookmarkable_state(void)
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..9743c9c319 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"
diff --git a/apps/core_keymap.c b/apps/core_keymap.c
index dbe7ae0072..9d54fcffac 100644
--- a/apps/core_keymap.c
+++ b/apps/core_keymap.c
@@ -27,119 +27,67 @@
#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("keyremap", bufsize);
+ if (handle > 0)
{
- *fsize = 0;
- *fd = open(filename, O_RDONLY);
- if (*fd)
- {
- *fsize = filesize(*fd);
-
- count = *fsize / sizeof(struct button_mapping);
-
- if (count * sizeof(struct button_mapping) != *fsize)
- {
- count = -10;
- logf("core_keymap: %d Size mismatch", count);
- break;
- }
+ core_pin(handle);
+ if (read(fd, core_get_data(handle), 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_unpin(handle);
}
+
+ 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..263fed154d 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) &&
@@ -535,7 +535,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 +565,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..71c0395e6e 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -23,7 +23,7 @@
#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"
@@ -227,7 +227,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 +340,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);
}
@@ -522,8 +520,7 @@ static int bf_action_cb(int action, struct gui_synclist* list)
/* 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;
}
@@ -568,7 +565,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 +866,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 +1243,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 +1274,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 +1627,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 +1719,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);
}
@@ -1775,7 +1772,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 +1840,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);
}
@@ -1902,7 +1897,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 +2169,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 */
@@ -2304,11 +2297,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 +2307,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 +2436,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 +2475,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 +2500,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 +2543,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) */
diff --git a/apps/filetree.c b/apps/filetree.c
index 1944713d13..107163add5 100644
--- a/apps/filetree.c
+++ b/apps/filetree.c
@@ -51,7 +51,23 @@
#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)
{
@@ -89,7 +105,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,22 +114,15 @@ 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)
@@ -198,7 +208,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 +243,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);
}
}
@@ -392,7 +384,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 +495,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 +531,7 @@ int ft_enter(struct tree_context* c)
play = true;
}
break;
-
+ }
#if CONFIG_TUNER
/* fmr preset file */
case FILE_ATTR_FMR:
@@ -674,7 +683,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));
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..ec9bd1a7ae 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) */
@@ -47,103 +48,142 @@
/* 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 },
+ { "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
};
@@ -153,6 +193,28 @@ void tree_get_filetypes(const struct filetype** types, int* count)
*count = sizeof(inbuilt_filetypes) / sizeof(*inbuilt_filetypes);
}
+long tree_get_filetype_voiceclip(int attr)
+{
+ 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"
struct file_type {
@@ -262,9 +324,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 +365,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))
@@ -399,15 +461,28 @@ static void rm_whitespaces(char* str)
static void read_builtin_types(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++;
}
}
@@ -618,7 +693,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..9013f81b02 100644
--- a/apps/filetypes.h
+++ b/apps/filetypes.h
@@ -53,10 +53,10 @@
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_ATTR;
/* init the filetypes structs.
uses audio buffer for storage, so call early in init... */
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..1c9b73a5fe 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,7 +326,6 @@ 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;
@@ -355,7 +351,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 +361,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..9deb1a0c65 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;
}
@@ -184,10 +182,9 @@ static void load_icons(const char* filename, enum Iconset iconset,
ic->handle = 0;
if (filename[0] && filename[0] != '-')
{
- char path[MAX_PATH];
-
- snprintf(path, sizeof(path), ICON_DIR "/%s.bmp", filename);
- fd = open(path, O_RDONLY);
+ char fname[MAX_PATH];
+ fd = open_pathfmt(fname, sizeof(fname), O_RDONLY,
+ ICON_DIR "/%s.bmp", filename);
if (fd < 0)
return;
buf_size = read_bmp_fd(fd, &ic->bmp, 0,
@@ -201,11 +198,10 @@ static void load_icons(const char* filename, enum Iconset iconset,
goto finished;
}
lseek(fd, 0, SEEK_SET);
+ core_pin(ic->handle);
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;
+ core_unpin(ic->handle);
if (size_read < 0)
{
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..d15948e97a 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;
@@ -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,16 +560,22 @@ 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;
}
@@ -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;
@@ -697,23 +646,14 @@ 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;
- };
+
+ /* Prevent list wraparound by repeating actions */
+ bool allow_wrap = lists->wraparound;
+ if (action == ACTION_STD_PREVREPEAT ||
+ action == ACTION_STD_NEXTREPEAT ||
+ action == ACTION_LISTTREE_PGUP ||
+ action == ACTION_LISTTREE_PGDOWN)
+ allow_wrap = false;
switch (action)
{
@@ -733,7 +673,7 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
#endif
case ACTION_STD_PREV:
case ACTION_STD_PREVREPEAT:
- gui_list_select_at_offset(lists, -next_item_modifier);
+ gui_list_select_at_offset(lists, -next_item_modifier, allow_wrap);
#ifndef HAVE_WHEEL_ACCELERATION
if (button_queue_count() < FRAMEDROP_TRIGGER)
#endif
@@ -744,7 +684,7 @@ bool gui_synclist_do_button(struct gui_synclist * lists,
case ACTION_STD_NEXT:
case ACTION_STD_NEXTREPEAT:
- gui_list_select_at_offset(lists, next_item_modifier);
+ gui_list_select_at_offset(lists, next_item_modifier, allow_wrap);
#ifndef HAVE_WHEEL_ACCELERATION
if (button_queue_count() < FRAMEDROP_TRIGGER)
#endif
@@ -795,7 +735,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, allow_wrap);
gui_synclist_draw(lists);
yield();
*actionptr = ACTION_STD_NEXT;
@@ -810,7 +750,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, allow_wrap);
gui_synclist_draw(lists);
yield();
*actionptr = ACTION_STD_PREV;
@@ -849,8 +789,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 +797,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 +857,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 +881,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 +899,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 +963,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..15ee1df736 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,11 +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,
@@ -232,13 +218,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 +227,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 +261,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 +270,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 +318,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..4687367fba 100644
--- a/apps/gui/option_select.c
+++ b/apps/gui/option_select.c
@@ -68,8 +68,8 @@ const char *option_get_valuestring(const struct settings_list *setting,
if ((setting->flags & F_BOOL_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)
@@ -121,7 +121,7 @@ const char *option_get_valuestring(const struct settings_list *setting,
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
{
@@ -133,7 +133,7 @@ const char *option_get_valuestring(const struct settings_list *setting,
{
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;
@@ -506,15 +506,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);
diff --git a/apps/gui/quickscreen.c b/apps/gui/quickscreen.c
index e403e13e6c..141eb1a16b 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],
@@ -389,6 +389,11 @@ static bool gui_syncquickscreen_run(struct gui_quickscreen * qs, int button_ente
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;
@@ -405,7 +410,8 @@ static bool gui_syncquickscreen_run(struct gui_quickscreen * qs, int button_ente
}
pop_current_activity();
- return changed;
+
+ return ret;
}
static const struct settings_list *get_setting(int gs_value,
@@ -427,9 +433,6 @@ int quick_screen_quick(int button_enter)
#endif
bool usb = false;
- if (global_settings.shortcuts_replaces_qs)
- return do_shortcut_menu(NULL);
-
qs.items[QUICKSCREEN_TOP] =
get_setting(global_settings.qs_items[QUICKSCREEN_TOP], NULL);
qs.items[QUICKSCREEN_LEFT] =
@@ -442,7 +445,8 @@ int quick_screen_quick(int button_enter)
get_setting(global_settings.qs_items[QUICKSCREEN_BOTTOM], 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 */
@@ -465,7 +469,10 @@ int quick_screen_quick(int button_enter)
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 */
diff --git a/apps/gui/quickscreen.h b/apps/gui/quickscreen.h
index 015928ee8a..6082b5a883 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];
diff --git a/apps/gui/skin_engine/skin_backdrops.c b/apps/gui/skin_engine/skin_backdrops.c
index 146dccb18a..8be40d1ce2 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;
@@ -182,16 +180,16 @@ bool skin_backdrops_preload(void)
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;
@@ -296,12 +293,12 @@ void skin_backdrop_load_setting(void)
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..43337049fd 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;
@@ -411,8 +413,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 +500,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 +606,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 +637,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)
{
- (void)screen;
- (void)data;
+ 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)
+{
+ 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..3e91536411 100644
--- a/apps/gui/skin_engine/skin_parser.c
+++ b/apps/gui/skin_engine/skin_parser.c
@@ -427,9 +427,6 @@ static int parse_image_load(struct skin_element *element,
img->is_9_segment = false;
img->loaded = false;
- /* save current viewport */
- img->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp);
-
if (token->type == SKIN_TOKEN_IMAGE_DISPLAY)
token->value.data = PTRTOSKINOFFSET(skin_buffer, img);
@@ -497,7 +494,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 +611,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 +711,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 +747,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)
{
@@ -942,7 +965,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;
@@ -1169,7 +1191,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 +1317,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 .. ! */
@@ -1828,9 +1848,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 +1889,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.
@@ -1891,14 +1907,6 @@ 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)
@@ -1945,12 +1953,12 @@ static int load_skin_bmp(struct wps_data *wps_data, struct bitmap *bitmap, char*
_stats->buflib_handles++;
_stats->images_size += buf_size;
lseek(fd, 0, SEEK_SET);
- lock_handle(handle);
+ core_pin(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();
+ core_unpin(handle);
close(fd);
if (ret > 0)
{
@@ -1998,7 +2006,7 @@ static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir)
strcpy(path, img->bm.data);
handle = load_skin_bmp(wps_data, &img->bm, bmpdir);
img->buflib_handle = handle;
- img->loaded = img->buflib_handle >= 0;
+ img->loaded = img->buflib_handle > 0;
if (img->loaded)
{
@@ -2396,13 +2404,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 +2564,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
{
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..874eff3809 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;
}
diff --git a/apps/gui/skin_engine/skin_touchsupport.c b/apps/gui/skin_engine/skin_touchsupport.c
index 045bc809c8..77ab30d675 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;
diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h
index bf368bc4f3..6a5d3c27f9 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.
@@ -81,7 +90,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 */
@@ -104,7 +112,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
@@ -189,7 +196,6 @@ struct skin_viewport {
#endif
};
struct viewport_colour {
- OFFSETTYPE(struct viewport *) vp;
unsigned colour;
};
@@ -236,7 +242,6 @@ struct touchregion_lastpress {
#endif
struct playlistviewer {
- OFFSETTYPE(struct viewport *) vp;
bool show_icons;
int start_offset;
OFFSETTYPE(struct skin_element *) line;
@@ -267,7 +272,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 +317,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 +387,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 +397,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, &region);
-
+
+ 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/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..430746cc8d 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,6 +62,7 @@
#include "playlist_viewer.h"
#include "wps.h"
#include "statusbar-skinned.h"
+#include "skin_engine/wps_internals.h"
#define RESTORE_WPS_INSTANTLY 0l
#define RESTORE_WPS_NEXT_SECOND ((long)(HZ+current_tick))
@@ -69,6 +71,8 @@
/* 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 +118,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 +135,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,8 +145,6 @@ 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)
@@ -156,11 +156,12 @@ static bool update_onvol_change(enum screen_type screen)
#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, &region);
+ 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,9 +183,9 @@ 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:
{
@@ -202,7 +203,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 +211,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 +223,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 +268,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 +276,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 +285,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 +307,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,10 +328,11 @@ 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)
button = ACTION_WPS_STOPSEEK;
}
}
@@ -330,7 +342,7 @@ bool ffwd_rew(int button)
#if defined(HAVE_BACKLIGHT) || defined(HAVE_REMOTE_LCD)
static void gwps_caption_backlight(struct wps_state *state)
{
- if (state && state->id3)
+ if (state->id3)
{
#ifdef HAVE_BACKLIGHT
if (global_settings.caption_backlight)
@@ -385,7 +397,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 +418,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 +435,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 +454,26 @@ 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);
+ prev_track(DEFAULT_SKIP_THRESH);
return;
}
else if (direction == 1 && step >= remaining)
@@ -506,12 +518,12 @@ static void gwps_leave_wps(void)
{
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();
#ifdef HAVE_BACKDROP_IMAGE
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)
@@ -536,7 +548,7 @@ static void gwps_enter_wps(void)
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);
+ viewportmanager_theme_enable(i, skin_has_sbs(gwps), NULL);
/* Update the values in the first (default) viewport - in case the user
has modified the statusbar or colour settings */
@@ -563,7 +575,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 +585,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 */
@@ -610,7 +622,7 @@ long gui_wps_show(void)
bool update = false;
bool vol_changed = false;
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();
@@ -644,7 +656,7 @@ 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
/* The iPods/X5/M5 use a single button for the A-B mode markers,
defined as ACTION_WPSAB_SINGLE in their config files. */
@@ -733,7 +745,7 @@ 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
@@ -752,9 +764,19 @@ long gui_wps_show(void)
{
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;
@@ -839,15 +861,24 @@ long gui_wps_show(void)
case ACTION_WPS_QUICKSCREEN:
{
gwps_leave_wps();
- if (global_settings.shortcuts_replaces_qs)
+ 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)
+ {
+ 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 */
@@ -917,7 +948,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:
@@ -1023,10 +1054,15 @@ long gui_wps_show(void)
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 +1078,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 +1108,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..c763753cd7 100644
--- a/apps/gui/yesno.c
+++ b/apps/gui/yesno.c
@@ -253,14 +253,15 @@ enum yesno_res gui_syncyesno_run(const struct text_message * main_message,
if(result_displayed)
sleep(HZ);
+ exit:
+ remove_event_ex(GUI_EVENT_NEED_UI_UPDATE, gui_yesno_ui_update, &yn[0]);
+
FOR_NB_SCREENS(i)
{
screens[i].scroll_stop_viewport(yn[i].vp);
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
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/iap/iap-core.c b/apps/iap/iap-core.c
index ae05806ae9..d2095b65bd 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"
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..d016b3b323 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 */
diff --git a/apps/keymaps/keymap-clip.c b/apps/keymaps/keymap-clip.c
index 3c92f03a07..917f769890 100644
--- a/apps/keymaps/keymap-clip.c
+++ b/apps/keymaps/keymap-clip.c
@@ -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 },
diff --git a/apps/keymaps/keymap-erosq.c b/apps/keymaps/keymap-erosq.c
index d486423a53..c69e4babdb 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 */
diff --git a/apps/keymaps/keymap-fiiom3k.c b/apps/keymaps/keymap-fiiom3k.c
index d0fbbb2e98..a9744b908b 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},
diff --git a/apps/keymaps/keymap-fuzeplus.c b/apps/keymaps/keymap-fuzeplus.c
index 6601316469..9ce5a79fc2 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 },
diff --git a/apps/keymaps/keymap-ipod.c b/apps/keymaps/keymap-ipod.c
index e3a17fffba..6d06bd0244 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 },
diff --git a/apps/keymaps/keymap-nwz.c b/apps/keymaps/keymap-nwz.c
index 028fbf1bfd..1fae8d3594 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 },
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-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/lang/english-us.lang b/apps/lang/english-us.lang
index bf5e9e93ce..4b35e2a82a 100644
--- a/apps/lang/english-us.lang
+++ b/apps/lang/english-us.lang
@@ -1694,12 +1694,6 @@
*: "Random"
</voice>
</phrase>
-### The 'desc' field for 'LANG_AUDIOSCROBBLER' differs from the english!
-### the previously used desc is commented below:
-### desc: "Last.fm Log" in the playback menu
-### The <source> section for 'LANG_AUDIOSCROBBLER:*' differs from the english!
-### the previously used one is commented below:
-### Last.fm Logger
<phrase>
id: LANG_AUDIOSCROBBLER
desc: "Last.fm Logger" in Plugin/apps/scrobbler
@@ -16099,7 +16093,6 @@
*: "Descending"
</voice>
</phrase>
-### This phrase is missing entirely, copying from english!
<phrase>
id: LANG_ALBUM_ART
desc: in Settings
@@ -16114,7 +16107,6 @@
*: "Album Art"
</voice>
</phrase>
-### This phrase is missing entirely, copying from english!
<phrase>
id: LANG_PREFER_EMBEDDED
desc: in Settings
@@ -16129,7 +16121,6 @@
*: "Prefer Embedded"
</voice>
</phrase>
-### This phrase is missing entirely, copying from english!
<phrase>
id: LANG_PREFER_IMAGE_FILE
desc: in Settings
@@ -16144,7 +16135,6 @@
*: "Prefer Image File"
</voice>
</phrase>
-### This phrase is missing entirely, copying from english!
<phrase>
id: LANG_FM_SYNC_RDS_TIME
desc: in radio screen and Settings
@@ -16162,7 +16152,6 @@
rds: "Sync RDS Time"
</voice>
</phrase>
-### This phrase is missing entirely, copying from english!
<phrase>
id: LANG_SORT_ALBUMS_BY
desc: in Settings
@@ -16177,7 +16166,6 @@
*: "Sort albums by"
</voice>
</phrase>
-### This phrase is missing entirely, copying from english!
<phrase>
id: LANG_ARTIST_PLUS_NAME
desc: in Settings
@@ -16192,7 +16180,6 @@
*: "Artist And Name"
</voice>
</phrase>
-### This phrase is missing entirely, copying from english!
<phrase>
id: LANG_ARTIST_PLUS_YEAR
desc: in Settings
@@ -16207,7 +16194,6 @@
*: "Artist And Year"
</voice>
</phrase>
-### This phrase is missing entirely, copying from english!
<phrase>
id: LANG_YEAR_SORT_ORDER
desc: in Settings
@@ -16222,7 +16208,6 @@
*: "Year sort order"
</voice>
</phrase>
-### This phrase is missing entirely, copying from english!
<phrase>
id: LANG_SHOW_YEAR_IN_ALBUM_TITLE
desc: in Settings
@@ -16237,7 +16222,6 @@
*: "Show year in album title"
</voice>
</phrase>
-### This phrase is missing entirely, copying from english!
<phrase>
id: LANG_WAIT_FOR_CACHE
desc: in Settings
@@ -16252,7 +16236,6 @@
*: "Cache needs to finish updating first!"
</voice>
</phrase>
-### This phrase is missing entirely, copying from english!
<phrase>
id: LANG_TRACK_INFO
desc: Track Info Title
@@ -16267,7 +16250,6 @@
*: "Track Info"
</voice>
</phrase>
-### This phrase is missing entirely, copying from english!
<phrase>
id: LANG_PLAY
desc: play selected file/directory, in playlist context menu
@@ -16282,7 +16264,6 @@
*: "Play"
</voice>
</phrase>
-### This phrase is missing entirely, copying from english!
<phrase>
id: LANG_PLAY_SHUFFLED
desc: play selected files in shuffled order, in playlist context menu
@@ -16297,7 +16278,6 @@
*: "Play Shuffled"
</voice>
</phrase>
-### This phrase is missing entirely, copying from english!
<phrase>
id: LANG_KEEP_CURRENT_TRACK_ON_REPLACE
desc: used in the playlist settings menu
@@ -16312,3 +16292,37 @@
*: "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>
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index e8d646b258..29a2527bec 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -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>
@@ -16388,3 +16388,17 @@
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>
diff --git a/apps/lang/italiano.lang b/apps/lang/italiano.lang
index 0688ca7846..1dc3319e85 100644
--- a/apps/lang/italiano.lang
+++ b/apps/lang/italiano.lang
@@ -13069,16 +13069,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 +13198,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 +13257,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 +13532,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>
@@ -15507,16 +15507,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 +15637,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 +15874,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 +16239,79 @@
*: "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>
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 4cef4ba59a..f9650475db 100644
--- a/apps/lang/polski.lang
+++ b/apps/lang/polski.lang
@@ -16301,3 +16301,23 @@
*: "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>
diff --git a/apps/lang/srpski.lang b/apps/lang/srpski.lang
index 8e64e3f938..dc7b3e3825 100644
--- a/apps/lang/srpski.lang
+++ b/apps/lang/srpski.lang
@@ -1473,10 +1473,10 @@
*: "Replaygain"
</source>
<dest>
- *: "Replaygain"
+ *: "Риплејгејн"
</dest>
<voice>
- *: "Replaygain"
+ *: "Риплејгејн"
</voice>
</phrase>
<phrase>
@@ -3400,13 +3400,13 @@
</source>
<dest>
*: none
- battery_types: "NiMH"
+ battery_types: "НиМХ"
xduoox3: "Старија (1500 mAh)"
</dest>
<voice>
*: none
battery_types: "Никл метал хидридна"
- xduoox3: "Старија (1500 милиампер часова)"
+ xduoox3: "Старија 1500 милиампер часова"
</voice>
</phrase>
<phrase>
@@ -4936,11 +4936,11 @@
</source>
<dest>
*: none
- recording: "MPEG Layer 3"
+ recording: "МПЕГ Слој 3"
</dest>
<voice>
*: none
- recording: "MPEG Layer 3"
+ recording: "МПЕГ Слој 3"
</voice>
</phrase>
<phrase>
@@ -4953,11 +4953,11 @@
</source>
<dest>
*: none
- recording: "PCM Wave"
+ recording: "ПЦМ Талас"
</dest>
<voice>
*: none
- recording: "PCM Wave"
+ recording: "ПЦМ Талас"
</voice>
</phrase>
<phrase>
@@ -6004,13 +6004,13 @@
</source>
<dest>
*: "Инт:"
- hibylinux: "mSD:"
- xduoox3: "mSD1:"
+ hibylinux: "мСД:"
+ xduoox3: "мСД1:"
</dest>
<voice>
*: "Интерни"
- hibylinux: "мајкро Ес Де"
- xduoox3: "мајкро Ес Де 1"
+ hibylinux: "микро Ес Де"
+ xduoox3: "микро Ес Де 1"
</voice>
</phrase>
<phrase>
@@ -6025,15 +6025,15 @@
</source>
<dest>
*: none
- multivolume: "HD1"
- sansac200*,sansaclipplus,sansae200*,sansafuze*: "mSD:"
- xduoox3: "mSD2:"
+ multivolume: "ХД1"
+ sansac200*,sansaclipplus,sansae200*,sansafuze*: "мСД:"
+ xduoox3: "мСД2:"
</dest>
<voice>
*: none
multivolume: "Ха Де 1"
- sansac200*,sansaclipplus,sansae200*,sansafuze*: "мајкро Ес Де"
- xduoox3: "мајкро Ес Де 2"
+ sansac200*,sansaclipplus,sansae200*,sansafuze*: "микро Ес Де"
+ xduoox3: "микро Ес Де 2"
</voice>
</phrase>
<phrase>
@@ -9581,7 +9581,7 @@
</dest>
<voice>
*: none
- recording: "величина"
+ recording: ""
</voice>
</phrase>
<phrase>
@@ -9674,7 +9674,7 @@
</dest>
<voice>
*: none
- recording: "време дељења"
+ recording: ""
</voice>
</phrase>
<phrase>
@@ -9705,7 +9705,7 @@
</dest>
<voice>
*: none
- recording: "клип"
+ recording: ""
</voice>
</phrase>
<phrase>
@@ -9735,11 +9735,11 @@
</source>
<dest>
*: none
- recording: "Фајл:"
+ recording: "Датотека:"
</dest>
<voice>
*: none
- recording: "фајл"
+ recording: ""
</voice>
</phrase>
<phrase>
@@ -9797,7 +9797,7 @@
</source>
<dest>
*: none
- agc: "AGC"
+ agc: "АРП"
</dest>
<voice>
*: none
@@ -10465,11 +10465,11 @@
</source>
<dest>
*: none
- pitchscreen: "Rate"
+ pitchscreen: "Рата"
</dest>
<voice>
*: none
- pitchscreen: "Рејт"
+ pitchscreen: "Рата"
</voice>
</phrase>
<phrase>
@@ -12192,10 +12192,10 @@
*: "Android Debug Bridge"
</source>
<dest>
- *: "Android Debug Bridge"
+ *: "Андроид Прегледни Мост"
</dest>
<voice>
- *: "Android Debug Bridge"
+ *: "Андроид Прегледни Мост"
</voice>
</phrase>
<phrase>
@@ -12248,10 +12248,10 @@
*: "Haas Surround"
</source>
<dest>
- *: "Haas Surround"
+ *: "Хаас Просторни Звук"
</dest>
<voice>
- *: "Haas Surround"
+ *: "Хаас Просторни Звук"
</voice>
</phrase>
<phrase>
@@ -13008,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>
@@ -13350,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>
@@ -13765,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>
@@ -13869,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>
@@ -15732,16 +15732,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>
- *: "Очисти листу & репродукуј наредну"
+ *: ""
</dest>
<voice>
- *: "Очисти листу и репродукуј наредну"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -15802,16 +15802,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>
- *: "Очисти листу & репродукуј измешано"
+ *: ""
</dest>
<voice>
- *: "Очисти листу & репродукуј измешано"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -15872,128 +15872,128 @@
</phrase>
<phrase>
id: LANG_PROPERTIES_ALBUMARTIST
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Album Artist]"
+ *: ""
</source>
<dest>
- *: "[Уметник албума]"
+ *: ""
</dest>
<voice>
- *: "Уметник албума"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_GENRE
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Genre]"
+ *: ""
</source>
<dest>
- *: "[Жанр]"
+ *: ""
</dest>
<voice>
- *: "Жанр"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_COMMENT
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Comment]"
+ *: ""
</source>
<dest>
- *: "[Коментар]"
+ *: ""
</dest>
<voice>
- *: "Коментар"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_COMPOSER
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Composer]"
+ *: ""
</source>
<dest>
- *: "[Композитор]"
+ *: ""
</dest>
<voice>
- *: "Композитор"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_YEAR
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Year]"
+ *: ""
</source>
<dest>
- *: "[Година]"
+ *: ""
</dest>
<voice>
- *: "Година"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_TRACKNUM
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Tracknum]"
+ *: ""
</source>
<dest>
- *: "[Брнумере]"
+ *: ""
</dest>
<voice>
- *: "Број нумере"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_DISCNUM
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Discnum]"
+ *: ""
</source>
<dest>
- *: "[Брдиска]"
+ *: ""
</dest>
<voice>
- *: "Број диска"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_FREQUENCY
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Frequency]"
+ *: ""
</source>
<dest>
- *: "[Фреквенција]"
+ *: ""
</dest>
<voice>
- *: "Фреквенција"
+ *: ""
</voice>
</phrase>
<phrase>
id: LANG_PROPERTIES_BITRATE
- desc: in properties plugin
+ desc: deprecated
user: core
<source>
- *: "[Bitrate]"
+ *: ""
</source>
<dest>
- *: "[Битски_проток]"
+ *: ""
</dest>
<voice>
- *: "Битски проток"
+ *: ""
</voice>
</phrase>
<phrase>
@@ -16018,7 +16018,7 @@
*: "dAY"
</source>
<dest>
- *: "dAY"
+ *: "dmY"
</dest>
<voice>
*: ""
@@ -16237,3 +16237,79 @@
*: "Најпре мора да се освежи кеш!"
</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: "Обришите подешавања када је прекидач за чекање укључен током покретања"
+ </dest>
+ <voice>
+ *: none
+ clear_settings_on_hold,iriverh10: "Обришите подешавања када се дугме за ресетовање држи током покретања"
+ ipod4g,ipodcolor,ipodmini1g,ipodmini2g,ipodnano1g,ipodvideo: "Обришите подешавања када је прекидач за чекање укључен током покретања"
+ </voice>
+</phrase>
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 59932d6185..6360267243 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -288,13 +288,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;
}
diff --git a/apps/menu.c b/apps/menu.c
index ab5578dede..1b2c21cef7 100644
--- a/apps/menu.c
+++ b/apps/menu.c
@@ -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);
@@ -451,19 +450,25 @@ 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);
redraw_lists = true;
}
#endif
@@ -517,17 +522,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);
#ifdef HAVE_QUICKSCREEN
if (is_setting_quickscreenable(setting))
- menu = &quickscreen_able_option;
+ context_menu = &quickscreen_able_option;
else
#endif
- menu = &notquickscreen_able_option;
+ context_menu = &notquickscreen_able_option;
- int msel = do_menu(menu, NULL, NULL, false);
+ int msel = do_menu(context_menu, NULL, NULL, false);
switch (msel)
{
diff --git a/apps/menus/display_menu.c b/apps/menus/display_menu.c
index 6ed0f34ab6..b228095bb3 100644
--- a/apps/menus/display_menu.c
+++ b/apps/menus/display_menu.c
@@ -332,22 +332,7 @@ MENUITEM_SETTING(list_accel_start_delay,
&global_settings.list_accel_start_delay, NULL);
MENUITEM_SETTING(list_accel_wait, &global_settings.list_accel_wait, NULL);
#endif /* HAVE_WHEEL_ACCELERATION */
-static int screenscroll_callback(int action,
- const struct menu_item_ex *this_item,
- struct gui_synclist *this_list)
-{
- (void)this_item;
- (void)this_list;
- switch (action)
- {
- case ACTION_EXIT_MENUITEM:
- gui_list_screen_scroll_out_of_view(global_settings.offset_out_of_view);
- break;
- }
- return action;
-}
-MENUITEM_SETTING(offset_out_of_view, &global_settings.offset_out_of_view,
- screenscroll_callback);
+MENUITEM_SETTING(offset_out_of_view, &global_settings.offset_out_of_view, NULL);
MENUITEM_SETTING(screen_scroll_step, &global_settings.screen_scroll_step, NULL);
MENUITEM_SETTING(scroll_paginated, &global_settings.scroll_paginated, NULL);
@@ -359,7 +344,6 @@ static int listwraparound_callback(int action,
switch (action)
{
case ACTION_EXIT_MENUITEM:
- gui_synclist_limit_scroll(this_list, !global_settings.list_wraparound);
gui_synclist_init_display_settings(this_list);
break;
}
diff --git a/apps/menus/eq_menu.c b/apps/menus/eq_menu.c
index 109c3c9ab7..c25d19e352 100644
--- a/apps/menus/eq_menu.c
+++ b/apps/menus/eq_menu.c
@@ -154,9 +154,9 @@ static int32_t get_dec_talkid(int value, int unit)
static const struct int_setting gain_int_setting = {
.option_callback = NULL,
.unit = UNIT_DB,
+ .step = EQ_GAIN_STEP,
.min = EQ_GAIN_MIN,
.max = EQ_GAIN_MAX,
- .step = EQ_GAIN_STEP,
.formatter = db_format,
.get_talk_id = get_dec_talkid,
};
@@ -164,9 +164,9 @@ static const struct int_setting gain_int_setting = {
static const struct int_setting q_int_setting = {
.option_callback = NULL,
.unit = UNIT_INT,
+ .step = EQ_Q_STEP,
.min = EQ_Q_MIN,
.max = EQ_Q_MAX,
- .step = EQ_Q_STEP,
.formatter = eq_q_format,
.get_talk_id = get_dec_talkid,
};
@@ -174,9 +174,9 @@ static const struct int_setting q_int_setting = {
static const struct int_setting cutoff_int_setting = {
.option_callback = NULL,
.unit = UNIT_HERTZ,
+ .step = EQ_CUTOFF_STEP,
.min = EQ_CUTOFF_MIN,
.max = EQ_CUTOFF_MAX,
- .step = EQ_CUTOFF_STEP,
.formatter = NULL,
.get_talk_id = NULL,
};
@@ -287,7 +287,7 @@ static char *advancedmenu_item_get_name(int selected_item, void *data, char *buf
buffer[0] = 0;
else {
buffer[0] = '\t';
- strlcpy(&buffer[1], str(lang), len - 1);
+ strmemccpy(&buffer[1], str(lang), len - 1);
}
return buffer;
@@ -480,17 +480,18 @@ static int draw_eq_slider(struct screen * screen, int x, int y,
/* Print out the band label */
if (band == 0) {
screen->putsxy(x1, y1, "LS: ");
- screen->getstringsize("LS:", &w, &h);
+ /*screen->getstringsize("LS:", &w, &h); UNUSED*/
} else if (band == EQ_NUM_BANDS - 1) {
screen->putsxy(x1, y1, "HS: ");
- screen->getstringsize("HS:", &w, &h);
+ /*screen->getstringsize("HS:", &w, &h); UNUSED*/
} else {
snprintf(buf, sizeof(buf), "PK%d:", band);
screen->putsxy(x1, y1, buf);
- screen->getstringsize(buf, &w, &h);
+ /*screen->getstringsize(buf, &w, &h); UNUSED*/
}
- screen->getstringsize("A", &w, &h);
+ w = screen->getstringsize("A", NULL, &h);
+
x1 += 5*w; /* 4 chars for label + 1 space = 5 */
/* Print out gain part of status line (left justify after label) */
@@ -503,7 +504,7 @@ static int draw_eq_slider(struct screen * screen, int x, int y,
abs_gain / EQ_USER_DIVISOR, abs_gain % EQ_USER_DIVISOR,
screen->lcdwidth >= 160 ? "dB" : "");
screen->putsxy(x1, y1, buf);
- screen->getstringsize(buf, &w, &h);
+ w = screen->getstringsize(buf, NULL, NULL);
x1 += w;
/* Print out Q part of status line (right justify) */
@@ -514,7 +515,7 @@ static int draw_eq_slider(struct screen * screen, int x, int y,
snprintf(buf, sizeof(buf), "%d.%d%s", q / EQ_USER_DIVISOR,
q % EQ_USER_DIVISOR, screen->lcdwidth >= 160 ? " Q" : "");
- screen->getstringsize(buf, &w, &h);
+ w = screen->getstringsize(buf, NULL, NULL);
x2 = x + width - w - 2;
screen->putsxy(x2, y1, buf);
@@ -526,7 +527,7 @@ static int draw_eq_slider(struct screen * screen, int x, int y,
snprintf(buf, sizeof(buf), "%5d%s", cutoff,
screen->lcdwidth >= 160 ? "Hz" : "");
- screen->getstringsize(buf, &w, &h);
+ w = screen->getstringsize(buf, NULL, NULL);
x1 = x1 + (x2 - x1 - w)/2;
screen->putsxy(x1, y1, buf);
@@ -589,8 +590,7 @@ int eq_menu_graphical(void)
int *setting;
int current_band, x, y, step, fast_step, min, max;
enum eq_slider_mode mode;
- char buf[24];
- int w, h, height, start_item, nb_eq_sliders[NB_SCREENS];
+ int h, height, start_item, nb_eq_sliders[NB_SCREENS];
FOR_NB_SCREENS(i)
viewportmanager_theme_enable(i, false, NULL);
@@ -601,7 +601,7 @@ int eq_menu_graphical(void)
screens[i].clear_display();
/* Figure out how many sliders can be drawn on the screen */
- screens[i].getstringsize("A", &w, &h);
+ h = screens[i].getcharheight();
/* Total height includes margins (1), text, slider, and line selector (1) */
height = 3 + h + 1 + SCROLLBAR_SIZE + 3;
@@ -637,10 +637,8 @@ int eq_menu_graphical(void)
min = EQ_GAIN_MIN;
max = EQ_GAIN_MAX;
- snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
+ screens[i].putsxyf(0, 0, str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
str(LANG_SYSFONT_GAIN), "(dB)");
-
- screens[i].putsxy(0, 0, buf);
} else if (mode == CUTOFF) {
/* cutoff */
setting = &global_settings.eq_band_settings[current_band].cutoff;
@@ -650,10 +648,8 @@ int eq_menu_graphical(void)
min = EQ_CUTOFF_MIN;
max = EQ_CUTOFF_MAX;
- snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
+ screens[i].putsxyf(0, 0, str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
str(LANG_SYSFONT_EQUALIZER_BAND_CUTOFF), "(Hz)");
-
- screens[i].putsxy(0, 0, buf);
} else {
/* Q */
setting = &global_settings.eq_band_settings[current_band].q;
@@ -663,10 +659,8 @@ int eq_menu_graphical(void)
min = EQ_Q_MIN;
max = EQ_Q_MAX;
- snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
+ screens[i].putsxyf(0, 0, str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
str(LANG_SYSFONT_EQUALIZER_BAND_Q), "");
-
- screens[i].putsxy(0, 0, buf);
}
/* Draw scrollbar if needed */
diff --git a/apps/menus/main_menu.c b/apps/menus/main_menu.c
index 321f2cdec4..03873faac9 100644
--- a/apps/menus/main_menu.c
+++ b/apps/menus/main_menu.c
@@ -441,8 +441,7 @@ static int info_action_callback(int action, struct gui_synclist *lists)
else if (action == ACTION_NONE)
{
static int last_redraw = 0;
- if (gui_synclist_item_is_onscreen(lists, 0, INFO_TIME)
- && TIME_AFTER(current_tick, last_redraw + HZ*5))
+ if (TIME_AFTER(current_tick, last_redraw + HZ*5))
{
last_redraw = current_tick;
return ACTION_REDRAW;
@@ -458,9 +457,6 @@ static int show_info(void)
struct simplelist_info info;
int count = INFO_COUNT + refresh_data(&data) - 1;
simplelist_info_init(&info, str(LANG_ROCKBOX_INFO), count, (void*)&data);
- info.hide_selection = !global_settings.talk_menu;
- if (info.hide_selection)
- info.scroll_all = true;
info.get_name = info_getname;
if(global_settings.talk_menu)
info.get_talk = info_speak_item;
diff --git a/apps/menus/playback_menu.c b/apps/menus/playback_menu.c
index 881a4b5a99..e4945be0b5 100644
--- a/apps/menus/playback_menu.c
+++ b/apps/menus/playback_menu.c
@@ -174,6 +174,7 @@ MAKE_MENU(unplug_menu, ID2P(LANG_HEADPHONE_UNPLUG), 0, Icon_NOICON,
MENUITEM_SETTING(skip_length, &global_settings.skip_length, NULL);
MENUITEM_SETTING(prevent_skip, &global_settings.prevent_skip, NULL);
+MENUITEM_SETTING(rewind_across_tracks, &global_settings.rewind_across_tracks, NULL);
MENUITEM_SETTING(resume_rewind, &global_settings.resume_rewind, NULL);
MENUITEM_SETTING(pause_rewind, &global_settings.pause_rewind, NULL);
#ifdef HAVE_PLAY_FREQ
@@ -226,6 +227,7 @@ MAKE_MENU(playback_settings,ID2P(LANG_PLAYBACK),0,
,&unplug_menu
#endif
,&skip_length, &prevent_skip
+ ,&rewind_across_tracks
,&resume_rewind
,&pause_rewind
diff --git a/apps/menus/playlist_menu.c b/apps/menus/playlist_menu.c
index e1e83d4311..357efe6b29 100644
--- a/apps/menus/playlist_menu.c
+++ b/apps/menus/playlist_menu.c
@@ -137,7 +137,7 @@ int save_playlist_screen(struct playlist_info* playlist)
static int playlist_view_(void)
{
- playlist_viewer_ex(NULL);
+ playlist_viewer_ex(NULL, NULL);
return 0;
}
MENUITEM_FUNCTION(create_playlist_item, 0, ID2P(LANG_CREATE_PLAYLIST),
diff --git a/apps/menus/sound_menu.c b/apps/menus/sound_menu.c
index 6d7ef270cb..d72e3c7fa7 100644
--- a/apps/menus/sound_menu.c
+++ b/apps/menus/sound_menu.c
@@ -54,13 +54,17 @@ static int volume_limit_callback(int action,
(void)this_list;
static struct int_setting volume_limit_int_setting;
- volume_limit_int_setting.option_callback = NULL;
- volume_limit_int_setting.unit = UNIT_DB;
- volume_limit_int_setting.min = sound_min(SOUND_VOLUME);
- volume_limit_int_setting.max = sound_max(SOUND_VOLUME);
- volume_limit_int_setting.step = sound_steps(SOUND_VOLUME);
- volume_limit_int_setting.formatter = vol_limit_format;
- volume_limit_int_setting.get_talk_id = NULL;
+
+ volume_limit_int_setting = (struct int_setting)
+ {
+ .option_callback = NULL,
+ .unit = UNIT_DB,
+ .step = sound_steps(SOUND_VOLUME),
+ .min = sound_min(SOUND_VOLUME),
+ .max = sound_max(SOUND_VOLUME),
+ .formatter = vol_limit_format,
+ .get_talk_id = NULL
+ };
struct settings_list setting;
setting.flags = F_BANFROMQS|F_INT_SETTING|F_T_INT|F_NO_WRAP;
diff --git a/apps/misc.c b/apps/misc.c
index 63aa3589b2..3e93cc9649 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -465,7 +465,7 @@ static void car_adapter_mode_processing(bool inserted)
if ((audio_status() & AUDIO_STATUS_PLAY) &&
!(audio_status() & AUDIO_STATUS_PAUSE))
{
- pause_action(true, true);
+ pause_action(true);
paused_on_unplugged = true;
}
else if (!waiting_to_resume_play)
@@ -513,14 +513,14 @@ static void hp_unplug_change(bool inserted)
if ((audio_stat & AUDIO_STATUS_PLAY) &&
headphone_caused_pause &&
global_settings.unplug_mode > 1 )
- unpause_action(true, true);
+ unpause_action(true);
headphone_caused_pause = false;
} else {
if ((audio_stat & AUDIO_STATUS_PLAY) &&
!(audio_stat & AUDIO_STATUS_PAUSE))
{
headphone_caused_pause = true;
- pause_action(false, false);
+ pause_action(false);
}
}
}
@@ -552,14 +552,14 @@ static void lo_unplug_change(bool inserted)
if ((audio_stat & AUDIO_STATUS_PLAY) &&
lineout_caused_pause &&
global_settings.unplug_mode > 1 )
- unpause_action(true, true);
+ unpause_action(true);
lineout_caused_pause = false;
} else {
if ((audio_stat & AUDIO_STATUS_PLAY) &&
!(audio_stat & AUDIO_STATUS_PAUSE))
{
lineout_caused_pause = true;
- pause_action(false, false);
+ pause_action(false);
}
}
}
@@ -629,7 +629,7 @@ long default_event_handler_ex(long event, void (*callback)(void *), void *parame
return SYS_CHARGER_DISCONNECTED;
case SYS_CAR_ADAPTER_RESUME:
- unpause_action(true, true);
+ unpause_action(true);
return SYS_CAR_ADAPTER_RESUME;
#endif
#ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
@@ -710,9 +710,9 @@ long default_event_handler_ex(long event, void (*callback)(void *), void *parame
if (status & AUDIO_STATUS_PLAY)
{
if (status & AUDIO_STATUS_PAUSE)
- unpause_action(true, true);
+ unpause_action(true);
else
- pause_action(true, true);
+ pause_action(true);
}
else
if (playlist_resume() != -1)
@@ -748,25 +748,32 @@ long default_event_handler(long event)
int show_logo( void )
{
- char version[32];
- int font_h, font_w;
+ 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) */
- lcd_setfont(FONT_SYSFIXED);
- lcd_getstringsize((unsigned char *)"A", &font_w, &font_h);
- lcd_putsxy((LCD_WIDTH/2) - ((strlen(version)*font_w)/2),
- 0, (unsigned char *)version);
+ 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);
- lcd_setfont(FONT_SYSFIXED);
- lcd_getstringsize((unsigned char *)"A", &font_w, &font_h);
- lcd_putsxy((LCD_WIDTH/2) - ((strlen(version)*font_w)/2),
- LCD_HEIGHT-font_h, (unsigned char *)version);
+
+ 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);
@@ -776,9 +783,13 @@ int show_logo( void )
lcd_remote_clear_display();
lcd_remote_bmp(&bm_remote_rockboxlogo, 0, 10);
lcd_remote_setfont(FONT_SYSFIXED);
- lcd_remote_getstringsize((unsigned char *)"A", &font_w, &font_h);
- lcd_remote_putsxy((LCD_REMOTE_WIDTH/2) - ((strlen(version)*font_w)/2),
- LCD_REMOTE_HEIGHT-font_h, (unsigned char *)version);
+
+ 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
@@ -885,7 +896,7 @@ char *strip_extension(char* buffer, int buffer_size, const char *filename)
/* no match on filename beginning with '.' or beyond buffer_size */
if(dotpos > 1 && dotpos < buffer_size)
buffer_size = dotpos;
- strlcpy(buffer, filename, buffer_size);
+ strmemccpy(buffer, filename, buffer_size);
return buffer;
}
@@ -1122,7 +1133,6 @@ int read_line(int fd, char* buffer, int buffer_size)
return rdbufend >= 0 ? num_read : -1;
}
-
char* skip_whitespace(char* const str)
{
char *s = str;
@@ -1134,6 +1144,16 @@ char* skip_whitespace(char* const str)
}
#if !defined(CHECKWPS) && !defined(DBTOOL)
+
+int confirm_delete_yesno(const char *name)
+{
+ const char *lines[] = { ID2P(LANG_REALLY_DELETE), name };
+ const char *yes_lines[] = { ID2P(LANG_DELETING), name };
+ const struct text_message message = { lines, 2 };
+ const struct text_message yes_message = { yes_lines, 2 };
+ return gui_syncyesno_run(&message, &yes_message, NULL);
+}
+
/* time_split_units()
split time values depending on base unit
unit_idx: UNIT_HOUR, UNIT_MIN, UNIT_SEC, UNIT_MS
@@ -1324,12 +1344,12 @@ const char *format_time_auto(char *buffer, int buf_len, long value,
if (!supress_unit)
{
- strlcpy(buffer, unit_strings_core[units[max_idx]], buf_len);
+ strmemccpy(buffer, unit_strings_core[units[max_idx]], buf_len);
left_offset += strlcat(buffer, " ", buf_len);
strlcat(buffer, &timebuf[offsets[base_idx]], buf_len);
}
else
- strlcpy(buffer, &timebuf[offsets[base_idx]], buf_len);
+ strmemccpy(buffer, &timebuf[offsets[base_idx]], buf_len);
strlcat(buffer, sign, buf_len);
}
@@ -1373,20 +1393,16 @@ void format_time(char* buf, int buf_size, long t)
int split_string(char *str, const char split_char, char *vector[], const int vector_length)
{
int i;
- char *p = str;
-
- /* skip leading splitters */
- while(*p == split_char) p++;
+ char sep[2] = {split_char, '\0'};
+ char *e, *p = strtok_r(str, sep, &e);
- /* *p in the condition takes care of trailing splitters */
- for(i = 0; p && *p && i < vector_length; i++)
+ /* strtok takes care of leading & trailing splitters */
+ for(i = 0; i < vector_length; i++)
{
vector[i] = p;
- if ((p = strchr(p, split_char)))
- {
- *p++ = '\0';
- while(*p == split_char) p++; /* skip successive splitters */
- }
+ if (!p)
+ break;
+ p = strtok_r(NULL, sep, &e);
}
return i;
@@ -1411,6 +1427,18 @@ int string_option(const char *option, const char *const oplist[], bool ignore_ca
return -1;
}
+/* open but with a builtin printf for assembling the path */
+int open_pathfmt(char *buf, size_t size, int oflag, const char *pathfmt, ...)
+{
+ va_list ap;
+ va_start(ap, pathfmt);
+ vsnprintf(buf, size, pathfmt, ap);
+ va_end(ap);
+ if ((oflag & O_PATH) == O_PATH)
+ return -1;
+ return open(buf, oflag, 0666);
+}
+
/** Open a UTF-8 file and set file descriptor to first byte after BOM.
* If no BOM is present this behaves like open().
* If the file is opened for writing and O_TRUNC is set, write a BOM to
diff --git a/apps/misc.h b/apps/misc.h
index ed40de3e1f..af520a7fd1 100644
--- a/apps/misc.h
+++ b/apps/misc.h
@@ -122,6 +122,10 @@ extern int show_logo(void);
#define BOM_UTF_16_SIZE 2
int split_string(char *str, const char needle, char *vector[], int vector_length);
+#ifndef O_PATH
+#define O_PATH 0x2000
+#endif
+int open_pathfmt(char *buf, size_t size, int oflag, const char *pathfmt, ...);
int open_utf8(const char* pathname, int flags);
int string_option(const char *option, const char *const oplist[], bool ignore_case);
@@ -139,6 +143,8 @@ void setvol(void);
int hex_to_rgb(const char* hex, int* color);
#endif
+int confirm_delete_yesno(const char *name);
+
char* strrsplt(char* str, int c);
char* skip_whitespace(char* const str);
diff --git a/apps/onplay.c b/apps/onplay.c
index e44e81ee5d..f2dbf8b3bf 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -63,6 +63,7 @@
#include "viewport.h"
#include "pathfuncs.h"
#include "shortcuts.h"
+#include "misc.h"
static int context;
static const char *selected_file = NULL;
@@ -126,8 +127,8 @@ static bool clipboard_clip(struct clipboard *clip, const char *path,
unsigned int attr, unsigned int flags)
{
/* if it fits it clips */
- if (strlcpy(clip->path, path, sizeof (clip->path))
- < sizeof (clip->path)) {
+ if (strmemccpy(clip->path, path, sizeof (clip->path)) != NULL)
+ {
clip->attr = attr;
clip->flags = flags;
return true;
@@ -382,8 +383,9 @@ static bool playing_time(void)
although playback continues forward. */
for (i = 0; i < pti.nb_tracks; i++) {
/* Show a splash while we are loading. */
- splashf(0, str(LANG_LOADING_PERCENT),
- i*100/pti.nb_tracks, str(LANG_OFF_ABORT));
+ splash_progress(i, pti.nb_tracks,
+ "%s (%s)", str(LANG_WAIT), str(LANG_OFF_ABORT));
+
/* Voice equivalent */
if (TIME_AFTER(current_tick, talked_tick+5*HZ)) {
talked_tick = current_tick;
@@ -429,8 +431,7 @@ static bool playing_time(void)
gui_synclist_draw(&pt_lists);
gui_synclist_speak_item(&pt_lists);
while (true) {
- if (list_do_action(CONTEXT_LIST, HZ/2,
- &pt_lists, &key, LIST_WRAP_UNLESS_HELD) == 0
+ if (list_do_action(CONTEXT_LIST, HZ/2, &pt_lists, &key) == 0
&& key!=ACTION_NONE && key!=ACTION_UNKNOWN)
{
talk_force_shutup();
@@ -588,12 +589,11 @@ static int add_to_playlist(void* arg)
static bool view_playlist(void)
{
- bool was_playing = audio_status() & AUDIO_STATUS_PLAY;
bool result;
- result = playlist_viewer_ex(selected_file);
+ result = playlist_viewer_ex(selected_file, NULL);
- if (!was_playing && (audio_status() & AUDIO_STATUS_PLAY) &&
+ if (result == PLAYLIST_VIEWER_OK &&
onplay_result == ONPLAY_OK)
/* playlist was started from viewer */
onplay_result = ONPLAY_START_PLAY;
@@ -899,15 +899,6 @@ static int confirm_overwrite(void)
return gui_syncyesno_run(&message, NULL, NULL);
}
-static int confirm_delete(const char *file)
-{
- const char *lines[] = { ID2P(LANG_REALLY_DELETE), file };
- const char *yes_lines[] = { ID2P(LANG_DELETING), file };
- const struct text_message message = { lines, 2 };
- const struct text_message yes_message = { yes_lines, 2 };
- return gui_syncyesno_run(&message, &yes_message, NULL);
-}
-
static bool check_new_name(const char *basename)
{
/* at least prevent escapes out of the base directory from keyboard-
@@ -1002,7 +993,7 @@ static int delete_file_dir(void)
{
const char *to_delete=selected_file;
const int to_delete_attr=selected_file_attr;
- if (confirm_delete(to_delete) != YESNO_YES) {
+ if (confirm_delete_yesno(to_delete) != YESNO_YES) {
return 1;
}
@@ -1048,7 +1039,7 @@ static int rename_file(void)
size_t pathlen = oldbase - selection;
char *newbase = newname + pathlen;
- if (strlcpy(newname, selection, sizeof (newname)) >= sizeof (newname)) {
+ if (strmemccpy(newname, selection, sizeof (newname)) == NULL) {
/* Too long */
} else if (kbd_input(newbase, sizeof (newname) - pathlen, NULL) < 0) {
rc = OPRC_CANCELLED;
@@ -1559,6 +1550,8 @@ static bool onplay_load_plugin(void *param)
onplay_result = ONPLAY_RELOAD_DIR;
else if (ret == PLUGIN_GOTO_PLUGIN)
onplay_result = ONPLAY_PLUGIN;
+ else if (ret == PLUGIN_GOTO_WPS)
+ onplay_result = ONPLAY_START_PLAY;
return false;
}
@@ -1587,7 +1580,7 @@ MENUITEM_FUNCTION(add_to_faves_item, 0, ID2P(LANG_ADD_TO_FAVES),
#if LCD_DEPTH > 1
static bool set_backdrop(void)
{
- strlcpy(global_settings.backdrop_file, selected_file,
+ strmemccpy(global_settings.backdrop_file, selected_file,
sizeof(global_settings.backdrop_file));
settings_save();
skin_backdrop_load_setting();
@@ -1600,7 +1593,7 @@ MENUITEM_FUNCTION(set_backdrop_item, 0, ID2P(LANG_SET_AS_BACKDROP),
#ifdef HAVE_RECORDING
static bool set_recdir(void)
{
- strlcpy(global_settings.rec_directory, selected_file,
+ strmemccpy(global_settings.rec_directory, selected_file,
sizeof(global_settings.rec_directory));
settings_save();
return false;
@@ -1784,7 +1777,7 @@ static int onplaymenu_callback(int action,
#ifdef HAVE_HOTKEY
/* direct function calls, no need for menu callbacks */
-static bool delete_item(void)
+static bool hotkey_delete_item(void)
{
#ifdef HAVE_MULTIVOLUME
/* no delete for volumes */
@@ -1794,7 +1787,7 @@ static bool delete_item(void)
return delete_file_dir();
}
-static bool open_with(void)
+static bool hotkey_open_with(void)
{
/* only open files */
if (selected_file_attr & ATTR_DIRECTORY)
@@ -1806,30 +1799,37 @@ static bool open_with(void)
return list_viewers();
}
-static int playlist_insert_shuffled(void)
+static int hotkey_tree_pl_insert_shuffled(void)
{
if ((audio_status() & AUDIO_STATUS_PLAY) ||
(selected_file_attr & ATTR_DIRECTORY) ||
((selected_file_attr & FILE_ATTR_MASK) == FILE_ATTR_M3U))
{
add_to_playlist(&addtopl_insert_shuf);
- return ONPLAY_START_PLAY;
}
+ return ONPLAY_RELOAD_DIR;
+}
+
+static int hotkey_tree_run_plugin(void *param)
+{
+ if (filetype_load_plugin((const char*)param, selected_file) == PLUGIN_GOTO_WPS)
+ return ONPLAY_START_PLAY;
return ONPLAY_RELOAD_DIR;
}
-static void hotkey_run_plugin(void)
+static int hotkey_wps_run_plugin(void)
{
open_plugin_run(ID2P(LANG_HOTKEY_WPS));
+ return ONPLAY_OK;
}
struct hotkey_assignment {
int action; /* hotkey_action */
int lang_id; /* Language ID */
struct menu_func func; /* Function to run if this entry is selected */
- int return_code; /* What to return after the function is run */
-};
+ int return_code; /* What to return after the function is run. */
+}; /* (Pick ONPLAY_FUNC_RETURN to use function's return value) */
#define HOTKEY_FUNC(func, param) {{(void *)func}, param}
@@ -1849,30 +1849,30 @@ static struct hotkey_assignment hotkey_items[] = {
ONPLAY_RELOAD_DIR },
#endif
{ HOTKEY_OPEN_WITH, LANG_ONPLAY_OPEN_WITH,
- HOTKEY_FUNC(open_with, NULL),
+ HOTKEY_FUNC(hotkey_open_with, NULL),
ONPLAY_RELOAD_DIR },
{ HOTKEY_DELETE, LANG_DELETE,
- HOTKEY_FUNC(delete_item, NULL),
+ HOTKEY_FUNC(hotkey_delete_item, NULL),
ONPLAY_RELOAD_DIR },
{ HOTKEY_INSERT, LANG_INSERT,
HOTKEY_FUNC(add_to_playlist, (intptr_t*)&addtopl_insert),
ONPLAY_RELOAD_DIR },
{ HOTKEY_INSERT_SHUFFLED, LANG_INSERT_SHUFFLED,
- HOTKEY_FUNC(playlist_insert_shuffled, NULL),
- ONPLAY_RELOAD_DIR },
+ HOTKEY_FUNC(hotkey_tree_pl_insert_shuffled, NULL),
+ ONPLAY_FUNC_RETURN },
{ HOTKEY_PLUGIN, LANG_OPEN_PLUGIN,
- HOTKEY_FUNC(hotkey_run_plugin, NULL),
- ONPLAY_OK },
+ HOTKEY_FUNC(hotkey_wps_run_plugin, NULL),
+ ONPLAY_FUNC_RETURN },
{ HOTKEY_BOOKMARK, LANG_BOOKMARK_MENU_CREATE,
HOTKEY_FUNC(bookmark_create_menu, NULL),
ONPLAY_OK },
{ HOTKEY_PROPERTIES, LANG_PROPERTIES,
- HOTKEY_FUNC(onplay_load_plugin, (void *)"properties"),
- ONPLAY_RELOAD_DIR },
+ HOTKEY_FUNC(hotkey_tree_run_plugin, (void *)"properties"),
+ ONPLAY_FUNC_RETURN },
#ifdef HAVE_TAGCACHE
{ HOTKEY_PICTUREFLOW, LANG_ONPLAY_PICTUREFLOW,
- HOTKEY_FUNC(onplay_load_plugin, (void *)"pictureflow"),
- ONPLAY_RELOAD_DIR },
+ HOTKEY_FUNC(hotkey_tree_run_plugin, (void *)"pictureflow"),
+ ONPLAY_FUNC_RETURN },
#endif
};
@@ -1895,7 +1895,7 @@ static int execute_hotkey(bool is_wps)
int i = ARRAYLEN(hotkey_items);
struct hotkey_assignment *this_item;
const int action = (is_wps ? global_settings.hotkey_wps :
- global_settings.hotkey_tree);
+ global_settings.hotkey_tree);
/* search assignment struct for a match for the hotkey setting */
while (i--)
@@ -1913,12 +1913,11 @@ static int execute_hotkey(bool is_wps)
else
func_return = (*func.function)();
}
- /* return with the associated code */
const int return_code = this_item->return_code;
- /* ONPLAY_OK here means to use the function return code */
- if (return_code == ONPLAY_OK)
- return func_return;
- return return_code;
+
+ if (return_code == ONPLAY_FUNC_RETURN)
+ return func_return; /* Use value returned by function */
+ return return_code; /* or return the associated value */
}
}
@@ -1937,7 +1936,7 @@ int onplay(char* file, int attr, int from, bool hotkey)
selected_file = NULL;
else
{
- strlcpy(selected_file_path, file, MAX_PATH);
+ strmemccpy(selected_file_path, file, MAX_PATH);
selected_file = selected_file_path;
}
selected_file_attr = attr;
diff --git a/apps/onplay.h b/apps/onplay.h
index 3121c918ac..80e0371eaf 100644
--- a/apps/onplay.h
+++ b/apps/onplay.h
@@ -31,6 +31,9 @@ enum {
ONPLAY_START_PLAY,
ONPLAY_PLAYLIST,
ONPLAY_PLUGIN,
+#ifdef HAVE_HOTKEY
+ ONPLAY_FUNC_RETURN, /* for use in hotkey_assignment only */
+#endif
};
#ifdef HAVE_HOTKEY
diff --git a/apps/open_plugin.c b/apps/open_plugin.c
index fad528e215..45dd7cdd2c 100644
--- a/apps/open_plugin.c
+++ b/apps/open_plugin.c
@@ -28,7 +28,7 @@
#include "lang.h"
/* Define LOGF_ENABLE to enable logf output in this file */
-//#define LOGF_ENABLE
+/*#define LOGF_ENABLE*/
#include "logf.h"
#define ROCK_EXT "rock"
@@ -60,8 +60,12 @@ static inline void op_clear_entry(struct open_plugin_entry_t *entry)
static int op_entry_checksum(struct open_plugin_entry_t *entry)
{
- if (entry == NULL || entry->checksum != open_plugin_csum)
+ if (entry == NULL || entry->checksum != open_plugin_csum +
+ (entry->lang_id <= OPEN_PLUGIN_LANG_INVALID ? 0 : LANG_LAST_INDEX_IN_ARRAY))
+ {
+ logf("OP entry bad checksum");
return 0;
+ }
return 1;
}
@@ -81,6 +85,14 @@ static int op_find_entry(int fd, struct open_plugin_entry_t *entry,
if (entry->lang_id == lang_id || entry->hash == hash ||
(lang_id == OPEN_PLUGIN_LANG_IGNOREALL))/* return first entry found */
{
+#if (CONFIG_STORAGE & STORAGE_ATA)
+ /* may have invalid entries but we append the file so continue looking*/
+ if (op_entry_checksum(entry) <= 0)
+ {
+ ret = OPEN_PLUGIN_INVALID_ENTRY;
+ continue;
+ }
+#endif
ret = record;
/* NULL terminate fields NOTE -- all are actually +1 larger */
entry->name[OPEN_PLUGIN_NAMESZ] = '\0';
@@ -98,7 +110,12 @@ static int op_find_entry(int fd, struct open_plugin_entry_t *entry,
}
/* sanity check */
- if (ret > OPEN_PLUGIN_NOT_FOUND && op_entry_checksum(entry) <= 0)
+#if (CONFIG_STORAGE & STORAGE_ATA)
+ if (ret == OPEN_PLUGIN_INVALID_ENTRY ||
+#else
+ if(
+#endif
+ (ret > OPEN_PLUGIN_NOT_FOUND && op_entry_checksum(entry) <= 0))
{
splash(HZ * 2, "OpenPlugin Invalid entry");
ret = OPEN_PLUGIN_NOT_FOUND;
@@ -144,7 +161,7 @@ static int op_update_dat(struct open_plugin_entry_t *entry, bool clear)
hash_langid_csum[2] == open_plugin_csum)
{
logf("OP update *Entry Exists* hash: %x langid: %d",
- hash_langid_csum[0], (int32_t)hash_langid[1]);
+ hash_langid_csum[0], (int32_t)hash_langid_csum[1]);
lseek(fd, 0-hlc_sz, SEEK_CUR);/* back to the start of record */
break;
}
@@ -261,7 +278,8 @@ uint32_t open_plugin_add_path(const char *key, const char *plugin, const char *p
{
open_plugin_entry.hash = hash;
open_plugin_entry.lang_id = lang_id;
- open_plugin_entry.checksum = open_plugin_csum;
+ open_plugin_entry.checksum = open_plugin_csum +
+ (lang_id <= OPEN_PLUGIN_LANG_INVALID ? 0 : LANG_LAST_INDEX_IN_ARRAY);
/* name */
if (path_basename(plugin, (const char **)&pos) == 0)
pos = "\0";
@@ -270,11 +288,11 @@ uint32_t open_plugin_add_path(const char *key, const char *plugin, const char *p
if (len > ROCK_LEN && strcasecmp(&(pos[len-ROCK_LEN]), "." ROCK_EXT) == 0)
{
/* path */
- strlcpy(open_plugin_entry.path, plugin, OPEN_PLUGIN_BUFSZ);
+ strmemccpy(open_plugin_entry.path, plugin, OPEN_PLUGIN_BUFSZ);
if(!parameter)
parameter = "";
- strlcpy(open_plugin_entry.param, parameter, OPEN_PLUGIN_BUFSZ);
+ strmemccpy(open_plugin_entry.param, parameter, OPEN_PLUGIN_BUFSZ);
goto retnhash;
}
else if (len > OP_LEN && strcasecmp(&(pos[len-OP_LEN]), "." OP_EXT) == 0)
@@ -337,7 +355,7 @@ int open_plugin_get_entry(const char *key, struct open_plugin_entry_t *entry)
opret = op_get_entry(hash, lang_id, entry, OPEN_PLUGIN_DAT);
logf("OP entry hash: %x lang id: %d ret: %d key: %s", hash, lang_id, opret, skey);
- if (opret == OPEN_PLUGIN_NOT_FOUND && lang_id > OPEN_PLUGIN_LANG_INVALID)
+ if (opret == OPEN_PLUGIN_NOT_FOUND && lang_id > OPEN_PLUGIN_LANG_INVALID)
{ /* try rb defaults */
opret = op_get_entry(hash, lang_id, entry, OPEN_RBPLUGIN_DAT);
logf("OP rb_entry hash: %x lang id: %d ret: %d key: %s", hash, lang_id, opret, skey);
@@ -364,6 +382,8 @@ int open_plugin_run(const char *key)
if (param[0] == '\0')
param = NULL;
+ if (path[0] == '\0' && key)
+ path = P2STR((unsigned char *)key);
ret = plugin_load(path, param);
diff --git a/apps/open_plugin.h b/apps/open_plugin.h
index d16be2052c..62e3662849 100644
--- a/apps/open_plugin.h
+++ b/apps/open_plugin.h
@@ -40,8 +40,9 @@ enum {
OPEN_PLUGIN_LANG_INVALID = (-1),
OPEN_PLUGIN_LANG_IGNORE = (-2),
OPEN_PLUGIN_LANG_IGNOREALL = (-3),
- OPEN_PLUGIN_NOT_FOUND = (-1),
- OPEN_PLUGIN_NEEDS_FLUSHED = (-2),
+ OPEN_PLUGIN_INVALID_ENTRY = (-1),
+ OPEN_PLUGIN_NOT_FOUND = (-2),
+ OPEN_PLUGIN_NEEDS_FLUSHED = (-3),
};
struct open_plugin_entry_t
diff --git a/apps/playback.c b/apps/playback.c
index 7fdb302d71..7eaa149f2c 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -1483,7 +1483,7 @@ static bool audio_init_codec(struct track_info *track_infop,
enum { AUTORESUMABLE_UNKNOWN = 0, AUTORESUMABLE_TRUE, AUTORESUMABLE_FALSE };
static bool autoresumable(struct mp3entry *id3)
{
- char *endp, *path;
+ char *path;
size_t len;
bool is_resumable;
@@ -1501,13 +1501,7 @@ static bool autoresumable(struct mp3entry *id3)
if (*path == ':') /* Skip empty search patterns */
continue;
- /* FIXME: As soon as strcspn or strchrnul are made available in
- the core, the following can be made more efficient. */
- endp = strchr(path, ':');
- if (endp)
- len = endp - path;
- else
- len = strlen(path);
+ len = strcspn(path, ":");
/* Note: At this point, len is always > 0 */
@@ -2097,23 +2091,11 @@ static int audio_finish_load_track(struct track_info *infop)
/** Finally, load the audio **/
off_t file_offset = 0;
- if (track_id3->elapsed > track_id3->length)
- track_id3->elapsed = 0;
-
- if ((off_t)track_id3->offset >= buf_filesize(infop->audio_hid))
- track_id3->offset = 0;
-
- logf("%s: set offset for %s to %lu\n", __func__,
- track_id3->title, track_id3->offset);
-
/* Adjust for resume rewind so we know what to buffer - starting the codec
calls it again, so we don't save it (and they shouldn't accumulate) */
unsigned long elapsed, offset;
resume_rewind_adjust_progress(track_id3, &elapsed, &offset);
- logf("%s: Set resume for %s to %lu %lu", __func__,
- track_id3->title, elapsed, offset);
-
enum data_type audiotype = rbcodec_format_is_atomic(track_id3->codectype) ?
TYPE_ATOMIC_AUDIO : TYPE_PACKET_AUDIO;
@@ -2145,6 +2127,19 @@ static int audio_finish_load_track(struct track_info *infop)
if (hid >= 0)
{
infop->audio_hid = hid;
+
+ /*
+ * Fix up elapsed time and offset if past the end
+ */
+ if (track_id3->elapsed > track_id3->length)
+ track_id3->elapsed = 0;
+
+ if ((off_t)track_id3->offset >= buf_filesize(infop->audio_hid))
+ track_id3->offset = 0;
+
+ logf("%s: set resume for %s to %lu %lX", __func__,
+ track_id3->title, track_id3->elapsed, track_id3->offset);
+
if (infop->self_hid == cur_info.self_hid)
{
/* This is the current track to decode - should be started now */
@@ -3683,8 +3678,7 @@ void audio_hard_stop(void)
#ifdef PLAYBACK_VOICE
voice_stop();
#endif
- if (audiobuf_handle > 0)
- audiobuf_handle = core_free(audiobuf_handle);
+ audiobuf_handle = core_free(audiobuf_handle);
}
/* Resume playback if paused */
diff --git a/apps/playlist.c b/apps/playlist.c
index b1d5d5a4be..f3a7bd2c9f 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -124,8 +124,8 @@
//NOTEF
#endif
-
-
+/* default load buffer size (should be at least 1 KiB) */
+#define PLAYLIST_LOAD_BUFLEN (32*1024)
#define PLAYLIST_CONTROL_FILE_VERSION 2
@@ -1400,7 +1400,7 @@ static int get_filename(struct playlist_info* playlist, int index, int seek,
if (playlist->in_ram && !control_file && max < 0)
{
- max = strlcpy(tmp_buf, (char*)&playlist->buffer[seek], sizeof(tmp_buf));
+ strmemccpy(tmp_buf, (char*)&playlist->buffer[seek], sizeof(tmp_buf));
}
else if (max < 0)
{
@@ -1457,7 +1457,7 @@ static int get_filename(struct playlist_info* playlist, int index, int seek,
}
}
- strlcpy(dir_buf, playlist->filename, playlist->dirlen);
+ strmemccpy(dir_buf, playlist->filename, playlist->dirlen);
return format_track_path(buf, tmp_buf, buf_length, dir_buf);
@@ -1551,7 +1551,7 @@ static int get_next_dir(char *dir, bool is_forward)
/* if the current file is within our base dir, use its dir instead */
if (base_len == 0 || !strncmp(playlist->filename, dir, base_len))
- strlcpy(dir, playlist->filename, playlist->dirlen);
+ strmemccpy(dir, playlist->filename, playlist->dirlen);
/* use the tree browser dircache to load files */
*(tc->dirfilter) = SHOW_ALL;
@@ -1999,6 +1999,23 @@ static int rotate_index(const struct playlist_info* playlist, int index)
}
/*
+ * Allocate a temporary buffer for loading playlists
+ */
+static int alloc_tempbuf(size_t* buflen)
+{
+ /* request a reasonable size first */
+ int handle = core_alloc_ex(NULL, PLAYLIST_LOAD_BUFLEN, &buflib_ops_locked);
+ if (handle > 0)
+ {
+ *buflen = PLAYLIST_LOAD_BUFLEN;
+ return handle;
+ }
+
+ /* otherwise, try being unreasonable */
+ return core_alloc_maximum(NULL, buflen, &buflib_ops_locked);
+}
+
+/*
* Need no movement protection since all 3 allocations are not passed to
* other functions which can yield().
*/
@@ -2034,7 +2051,7 @@ void playlist_init(void)
mutex_init(&created_playlist_mutex);
playlist->current = true;
- strlcpy(playlist->control_filename, PLAYLIST_CONTROL_FILE,
+ strmemccpy(playlist->control_filename, PLAYLIST_CONTROL_FILE,
sizeof(playlist->control_filename));
playlist->fd = -1;
playlist->control_fd = -1;
@@ -2097,14 +2114,17 @@ int playlist_create(const char *dir, const char *file)
if (file)
{
- int handle;
size_t buflen;
- /* use mp3 buffer for maximum load speed */
- handle = core_alloc_maximum("temp", &buflen, &buflib_ops_locked);
+ int handle = alloc_tempbuf(&buflen);
if (handle > 0)
{
+ /* align for faster load times */
+ void* buf = core_get_data(handle);
+ STORAGE_ALIGN_BUFFER(buf, buflen);
+ buflen = ALIGN_DOWN(buflen, 512); /* to avoid partial sector I/O */
+
/* load the playlist file */
- add_indices_to_playlist(playlist, core_get_data(handle), buflen);
+ add_indices_to_playlist(playlist, buf, buflen);
core_free(handle);
}
else
@@ -2145,15 +2165,19 @@ int playlist_resume(void)
dircache_wait(); /* we need the dircache to use the files in the playlist */
#endif
- /* use mp3 buffer for maximum load speed */
- handle = core_alloc_maximum("temp", &buflen, &buflib_ops_locked);
+ handle = alloc_tempbuf(&buflen);
if (handle < 0)
{
splashf(HZ * 2, "%s(): OOM", __func__);
return -1;
}
+
+ /* align buffer for faster load times */
buffer = core_get_data(handle);
+ STORAGE_ALIGN_BUFFER(buffer, buflen);
+ buflen = ALIGN_DOWN(buflen, 512); /* to avoid partial sector I/O */
+ playlist_shutdown(); /* flush any cached control commands to disk */
empty_playlist(playlist, true);
playlist->control_fd = open(playlist->control_filename, O_RDWR);
@@ -2196,16 +2220,16 @@ int playlist_resume(void)
char *str2 = NULL;
char *str3 = NULL;
unsigned long last_tick = current_tick;
+ splash_progress_set_delay(HZ / 2); /* wait 1/2 sec before progress */
bool useraborted = false;
for(count=0; count<nread && !exit_loop && !useraborted; count++,p++)
{
- /* So a splash while we are loading. */
+ /* Show a splash while we are loading. */
+ splash_progress((total_read + count), control_file_size,
+ "%s (%s)", str(LANG_WAIT), str(LANG_OFF_ABORT));
if (TIME_AFTER(current_tick, last_tick + HZ/4))
{
- splashf(0, str(LANG_LOADING_PERCENT),
- (total_read+count)*100/control_file_size,
- str(LANG_OFF_ABORT));
if (action_userabort(TIMEOUT_NOBLOCK))
{
useraborted = true;
@@ -2213,7 +2237,6 @@ int playlist_resume(void)
}
last_tick = current_tick;
}
-
/* Are we on a new line? */
if((*p == '\n') || (*p == '\r'))
{
@@ -2955,7 +2978,7 @@ int playlist_set_current(struct playlist_info* playlist)
empty_playlist(&current_playlist, false);
- strlcpy(current_playlist.filename, playlist->filename,
+ strmemccpy(current_playlist.filename, playlist->filename,
sizeof(current_playlist.filename));
current_playlist.utf8 = playlist->utf8;
@@ -3517,7 +3540,7 @@ char *playlist_name(const struct playlist_info* playlist, char *buf,
if (!playlist)
playlist = &current_playlist;
- strlcpy(buf, playlist->filename+playlist->dirlen, buf_size);
+ strmemccpy(buf, playlist->filename+playlist->dirlen, buf_size);
if (!buf[0])
return NULL;
@@ -3537,7 +3560,7 @@ char *playlist_get_name(const struct playlist_info* playlist, char *buf,
if (!playlist)
playlist = &current_playlist;
- strlcpy(buf, playlist->filename, buf_size);
+ strmemccpy(buf, playlist->filename, buf_size);
if (!buf[0])
return NULL;
diff --git a/apps/playlist_catalog.c b/apps/playlist_catalog.c
index ba12ff6d98..619293377c 100644
--- a/apps/playlist_catalog.c
+++ b/apps/playlist_catalog.c
@@ -46,6 +46,7 @@
#include "talk.h"
#include "playlist_viewer.h"
#include "bookmark.h"
+#include "root_menu.h"
/* Use for recursive directory search */
struct add_track_context {
@@ -128,8 +129,8 @@ void catalog_set_directory(const char* directory)
}
else
{
- strlcpy(global_settings.playlist_catalog_dir,
- directory, sizeof(global_settings.playlist_catalog_dir));
+ strmemccpy(global_settings.playlist_catalog_dir,
+ directory, sizeof(global_settings.playlist_catalog_dir));
}
initialized = false;
initialize_catalog();
@@ -146,6 +147,8 @@ const char* catalog_get_directory(void)
If "view" mode is set then we're not adding anything into playlist. */
static int display_playlists(char* playlist, bool view)
{
+ static bool reopen_last_playlist = false;
+ static int most_recent_selection = 0;
struct browse_context browse;
char selected_playlist[MAX_PATH];
int result = -1;
@@ -153,34 +156,75 @@ static int display_playlists(char* playlist, bool view)
browse_context_init(&browse, SHOW_M3U,
BROWSE_SELECTONLY|(view? 0: BROWSE_NO_CONTEXT_MENU),
str(LANG_CATALOG), NOICON,
- playlist_dir, most_recent_playlist);
+ playlist_dir, playlist_dir_length + 1 + most_recent_playlist);
browse.buf = selected_playlist;
browse.bufsize = sizeof(selected_playlist);
restart:
browse.flags &= ~BROWSE_SELECTED;
- rockbox_browse(&browse);
- if (browse.flags & BROWSE_SELECTED)
+ if (view && reopen_last_playlist)
{
- strlcpy(most_recent_playlist, selected_playlist+playlist_dir_length+1,
- sizeof(most_recent_playlist));
+ switch (playlist_viewer_ex(most_recent_playlist, &most_recent_selection))
+ {
+ case PLAYLIST_VIEWER_OK:
+ result = 0;
+ break;
+ case PLAYLIST_VIEWER_CANCEL:
+ reopen_last_playlist = false;
+ goto restart;
+ case PLAYLIST_VIEWER_USB:
+ case PLAYLIST_VIEWER_MAINMENU:
+ default:
+ break;
+ }
+ }
+ else /* browse playlist dir */
+ {
+ int browse_ret = rockbox_browse(&browse);
+ if (browse_ret == GO_TO_WPS
+ || (view && browse_ret == GO_TO_PREVIOUS_MUSIC))
+ result = 0;
+ }
+
+ if (browse.flags & BROWSE_SELECTED) /* User picked a playlist */
+ {
+ if (strcmp(most_recent_playlist, selected_playlist)) /* isn't most recent one */
+ {
+ strmemccpy(most_recent_playlist, selected_playlist,
+ sizeof(most_recent_playlist));
+ most_recent_selection = 0;
+ reopen_last_playlist = false;
+ }
- if (view)
+ if (view) /* display playlist contents or resume bookmark */
{
-
- if (!bookmark_autoload(selected_playlist))
+
+ int res = bookmark_autoload(selected_playlist);
+ if (res == BOOKMARK_DO_RESUME)
+ result = 0;
+ else
{
- if (playlist_viewer_ex(selected_playlist) == PLAYLIST_VIEWER_CANCEL)
- goto restart;
+ switch (playlist_viewer_ex(selected_playlist, &most_recent_selection)) {
+ case PLAYLIST_VIEWER_OK:
+ reopen_last_playlist = true;
+ result = 0;
+ break;
+ case PLAYLIST_VIEWER_CANCEL:
+ goto restart;
+ case PLAYLIST_VIEWER_USB:
+ case PLAYLIST_VIEWER_MAINMENU:
+ default:
+ reopen_last_playlist = true;
+ break;
+ }
}
- result = 0;
}
- else
+ else /* we're just adding something to a playlist */
{
result = 0;
- strlcpy(playlist, selected_playlist, MAX_PATH);
+ strmemccpy(playlist, selected_playlist, MAX_PATH);
}
}
@@ -192,7 +236,7 @@ restart:
static void display_insert_count(int count)
{
static long talked_tick = 0;
- if(global_settings.talk_menu && count &&
+ if(global_settings.talk_menu && count &&
(talked_tick == 0 || TIME_AFTER(current_tick, talked_tick+5*HZ)))
{
talked_tick = current_tick;
@@ -233,8 +277,10 @@ static int add_to_playlist(const char* playlist, bool new_playlist,
fd = open(playlist, O_CREAT|O_WRONLY|O_APPEND, 0666);
if(fd < 0)
+ {
+ splash(HZ*2, ID2P(LANG_FAILED));
return result;
-
+ }
/* In case we're in the playlist directory */
reload_directory();
@@ -358,7 +404,7 @@ bool catalog_add_to_a_playlist(const char* sel, int sel_attr,
(name!=NULL && (sel_attr & ATTR_DIRECTORY))?name+1:"");
}
else
- strlcpy(playlist, m3u8name, MAX_PATH);
+ strmemccpy(playlist, m3u8name, MAX_PATH);
if (kbd_input(playlist, MAX_PATH, NULL))
return false;
diff --git a/apps/playlist_catalog.h b/apps/playlist_catalog.h
index 2e317128b7..17efd0ea7e 100644
--- a/apps/playlist_catalog.h
+++ b/apps/playlist_catalog.h
@@ -29,7 +29,7 @@ void catalog_set_directory(const char* directory);
/*
* View list of playlists in catalog.
- * ret : true if no error
+ * ret : true if item was selected
*/
bool catalog_view_playlists(void);
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c
index 7e50c42bdc..8f1c5d961d 100644
--- a/apps/playlist_viewer.c
+++ b/apps/playlist_viewer.c
@@ -76,6 +76,7 @@ enum direction
enum pv_onplay_result {
PV_ONPLAY_USB,
PV_ONPLAY_USB_CLOSED,
+ PV_ONPLAY_WPS_CLOSED,
PV_ONPLAY_CLOSED,
PV_ONPLAY_ITEM_REMOVED,
PV_ONPLAY_CHANGED,
@@ -101,8 +102,10 @@ struct playlist_buffer
/* Global playlist viewer settings */
struct playlist_viewer {
- struct playlist_info* playlist; /* playlist being viewed */
+ const char *title; /* Playlist Viewer list title */
+ struct playlist_info* playlist; /* Playlist being viewed */
int num_tracks; /* Number of tracks in playlist */
+ int *initial_selection; /* The initially selected track */
int current_playing_track; /* Index of current playing track */
int selected_track; /* The selected track, relative (first is 0) */
int moving_track; /* The track to move, relative (first is 0)
@@ -130,7 +133,8 @@ static struct playlist_entry * playlist_buffer_get_track(struct playlist_buffer
int index);
static bool playlist_viewer_init(struct playlist_viewer * viewer,
- const char* filename, bool reload);
+ const char* filename, bool reload,
+ int *most_recent_selection);
static void format_name(char* dest, const char* src);
static void format_line(const struct playlist_entry* track, char* str,
@@ -319,7 +323,8 @@ static struct playlist_entry * playlist_buffer_get_track(struct playlist_buffer
/* Initialize the playlist viewer. */
static bool playlist_viewer_init(struct playlist_viewer * viewer,
- const char* filename, bool reload)
+ const char* filename, bool reload,
+ int *most_recent_selection)
{
char* buffer;
size_t buffer_size;
@@ -348,7 +353,10 @@ static bool playlist_viewer_init(struct playlist_viewer * viewer,
return false;
if (!filename)
+ {
viewer->playlist = NULL;
+ viewer->title = (char *) str(LANG_PLAYLIST);
+ }
else
{
/* Viewing playlist on disk */
@@ -372,6 +380,7 @@ static bool playlist_viewer_init(struct playlist_viewer * viewer,
dir = "/";
file = filename+1;
}
+ viewer->title = file;
if (is_playing)
{
@@ -400,11 +409,12 @@ static bool playlist_viewer_init(struct playlist_viewer * viewer,
viewer->moving_track = -1;
viewer->moving_playlist_index = -1;
+ viewer->initial_selection = most_recent_selection;
if (!reload)
{
if (viewer->playlist)
- viewer->selected_track = 0;
+ viewer->selected_track = most_recent_selection ? *most_recent_selection : 0;
else
viewer->selected_track = playlist_get_display_index() - 1;
}
@@ -511,25 +521,47 @@ static enum pv_onplay_result show_track_info(const struct playlist_entry *curren
}
+#ifdef HAVE_HOTKEY
static enum pv_onplay_result open_with(const struct playlist_entry *current_track)
{
char selected_track[MAX_PATH];
close_playlist_viewer();
- snprintf(selected_track, sizeof(selected_track), "%s", current_track->name);
- return (filetype_list_viewers(selected_track) ==
- PLUGIN_USB_CONNECTED ? PV_ONPLAY_USB_CLOSED : PV_ONPLAY_CLOSED);
+ strmemccpy(selected_track, current_track->name, sizeof(selected_track));
+
+ int plugin_return = filetype_list_viewers(selected_track);
+
+ switch (plugin_return)
+ {
+ case PLUGIN_USB_CONNECTED:
+ return PV_ONPLAY_USB_CLOSED;
+ case PLUGIN_GOTO_WPS:
+ return PV_ONPLAY_WPS_CLOSED;
+ default:
+ return PV_ONPLAY_CLOSED;
+ }
}
+#endif /* HAVE_HOTKEY */
#ifdef HAVE_TAGCACHE
static enum pv_onplay_result open_pictureflow(const struct playlist_entry *current_track)
{
char selected_track[MAX_PATH];
close_playlist_viewer();
- snprintf(selected_track, sizeof(selected_track), "%s", current_track->name);
- return (filetype_load_plugin((void *)"pictureflow", selected_track) ==
- PLUGIN_USB_CONNECTED ? PV_ONPLAY_USB_CLOSED : PV_ONPLAY_CLOSED);
+ strmemccpy(selected_track, current_track->name, sizeof(selected_track));
+
+ int plugin_return = filetype_load_plugin((void *)"pictureflow", selected_track);
+
+ switch (plugin_return)
+ {
+ case PLUGIN_USB_CONNECTED:
+ return PV_ONPLAY_USB_CLOSED;
+ case PLUGIN_GOTO_WPS:
+ return PV_ONPLAY_WPS_CLOSED;
+ default:
+ return PV_ONPLAY_CLOSED;
+ }
}
#endif
@@ -640,7 +672,7 @@ static enum pv_onplay_result onplay_menu(int index)
/* View current playlist */
enum playlist_viewer_result playlist_viewer(void)
{
- return playlist_viewer_ex(NULL);
+ return playlist_viewer_ex(NULL, NULL);
}
static int get_track_num(struct playlist_viewer *local_viewer,
@@ -748,7 +780,7 @@ static void update_lists(struct gui_synclist * playlist_lists)
gui_synclist_set_icon_callback(playlist_lists,
global_settings.playlist_viewer_icons?
&playlist_callback_icons:NULL);
- gui_synclist_set_title(playlist_lists, str(LANG_PLAYLIST), Icon_Playlist);
+ gui_synclist_set_title(playlist_lists, viewer.title, Icon_Playlist);
gui_synclist_draw(playlist_lists);
gui_synclist_speak_item(playlist_lists);
}
@@ -785,7 +817,7 @@ static void prepare_lists(struct gui_synclist * playlist_lists)
global_settings.playlist_viewer_icons ?
&playlist_callback_icons : NULL);
gui_synclist_set_nb_items(playlist_lists, viewer.num_tracks);
- gui_synclist_set_title(playlist_lists, str(LANG_PLAYLIST), Icon_Playlist);
+ gui_synclist_set_title(playlist_lists, viewer.title, Icon_Playlist);
gui_synclist_select_item(playlist_lists, viewer.selected_track);
gui_synclist_draw(playlist_lists);
gui_synclist_speak_item(playlist_lists);
@@ -793,11 +825,11 @@ static void prepare_lists(struct gui_synclist * playlist_lists)
static bool open_playlist_viewer(const char* filename,
struct gui_synclist *playlist_lists,
- bool reload)
+ bool reload, int *most_recent_selection)
{
push_current_activity(ACTIVITY_PLAYLISTVIEWER);
- if (!playlist_viewer_init(&viewer, filename, reload))
+ if (!playlist_viewer_init(&viewer, filename, reload, most_recent_selection))
return false;
prepare_lists(playlist_lists);
@@ -807,15 +839,19 @@ static bool open_playlist_viewer(const char* filename,
/* Main viewer function. Filename identifies playlist to be viewed. If NULL,
view current playlist. */
-enum playlist_viewer_result playlist_viewer_ex(const char* filename)
+enum playlist_viewer_result playlist_viewer_ex(const char* filename,
+ int* most_recent_selection)
{
enum playlist_viewer_result ret = PLAYLIST_VIEWER_OK;
bool exit = false; /* exit viewer */
int button;
struct gui_synclist playlist_lists;
- if (!open_playlist_viewer(filename, &playlist_lists, false))
+ if (!open_playlist_viewer(filename, &playlist_lists, false, most_recent_selection))
+ {
+ ret = PLAYLIST_VIEWER_CANCEL;
goto exit;
+ }
while (!exit)
{
@@ -842,8 +878,7 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename)
}
/* Timeout so we can determine if play status has changed */
- bool res = list_do_action(CONTEXT_TREE, HZ/2,
- &playlist_lists, &button, LIST_WRAP_UNLESS_HELD);
+ bool res = list_do_action(CONTEXT_TREE, HZ/2, &playlist_lists, &button);
/* during moving, another redraw is going to be needed,
* since viewer.selected_track is updated too late (after the first draw)
* drawing the moving item needs it */
@@ -876,7 +911,8 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename)
else
{
exit = true;
- ret = PLAYLIST_VIEWER_CANCEL;
+ ret = button == ACTION_TREE_WPS ?
+ PLAYLIST_VIEWER_OK : PLAYLIST_VIEWER_CANCEL;
}
break;
}
@@ -930,8 +966,11 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename)
start_index = playlist_shuffle(current_tick, start_index);
playlist_start(start_index, 0, 0);
+ if (viewer.initial_selection)
+ *(viewer.initial_selection) = viewer.selected_track;
+
/* Our playlist is now the current list */
- if (!playlist_viewer_init(&viewer, NULL, true))
+ if (!playlist_viewer_init(&viewer, NULL, true, NULL))
goto exit;
exit = true;
}
@@ -951,13 +990,22 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename)
}
else if (pv_onplay_result == PV_ONPLAY_USB_CLOSED)
return PLAYLIST_VIEWER_USB;
+ else if (pv_onplay_result == PV_ONPLAY_WPS_CLOSED)
+ return PLAYLIST_VIEWER_OK;
else if (pv_onplay_result == PV_ONPLAY_CLOSED)
{
- if (!open_playlist_viewer(filename, &playlist_lists, true))
+ if (!open_playlist_viewer(filename, &playlist_lists, true, NULL))
+ {
+ ret = PLAYLIST_VIEWER_CANCEL;
goto exit;
+ }
break;
}
- exit = update_viewer_with_changes(&playlist_lists, pv_onplay_result);
+ if (update_viewer_with_changes(&playlist_lists, pv_onplay_result))
+ {
+ exit = true;
+ ret = PLAYLIST_VIEWER_CANCEL;
+ }
break;
}
case ACTION_STD_MENU:
@@ -970,8 +1018,8 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename)
quick_screen_quick(button);
update_playlist(true);
update_lists(&playlist_lists);
- break;
}
+ break;
#endif
#ifdef HAVE_HOTKEY
case ACTION_TREE_HOTKEY:
@@ -989,10 +1037,17 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename)
if (do_plugin != NULL)
{
- if (do_plugin(current_track) == PV_ONPLAY_USB_CLOSED)
+ int plugin_result = do_plugin(current_track);
+
+ if (plugin_result == PV_ONPLAY_USB_CLOSED)
return PLAYLIST_VIEWER_USB;
- else if (!open_playlist_viewer(filename, &playlist_lists, true))
+ else if (plugin_result == PV_ONPLAY_WPS_CLOSED)
+ return PLAYLIST_VIEWER_OK;
+ else if (!open_playlist_viewer(filename, &playlist_lists, true, NULL))
+ {
+ ret = PLAYLIST_VIEWER_CANCEL;
goto exit;
+ }
}
else if (global_settings.hotkey_tree == HOTKEY_PROPERTIES)
{
@@ -1004,10 +1059,16 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename)
update_lists(&playlist_lists);
}
else if (global_settings.hotkey_tree == HOTKEY_DELETE)
- exit = update_viewer_with_changes(&playlist_lists,
+ {
+ if (update_viewer_with_changes(&playlist_lists,
delete_track(current_track->index,
viewer.selected_track,
- (current_track->index == viewer.current_playing_track)));
+ (current_track->index == viewer.current_playing_track))))
+ {
+ ret = PLAYLIST_VIEWER_CANCEL;
+ exit = true;
+ }
+ }
else
onplay(current_track->name, FILE_ATTR_AUDIO, CONTEXT_STD, true);
break;
@@ -1034,6 +1095,9 @@ static void close_playlist_viewer(void)
pop_current_activity();
if (viewer.playlist)
{
+ if (viewer.initial_selection)
+ *(viewer.initial_selection) = viewer.selected_track;
+
if(dirty && yesno_pop(ID2P(LANG_SAVE_CHANGES)))
save_playlist_screen(viewer.playlist);
playlist_close(viewer.playlist);
@@ -1074,7 +1138,7 @@ bool search_playlist(void)
struct gui_synclist playlist_lists;
struct playlist_track_info track;
- if (!playlist_viewer_init(&viewer, 0, false))
+ if (!playlist_viewer_init(&viewer, 0, false, NULL))
return ret;
if (kbd_input(search_str, sizeof(search_str), NULL) < 0)
return ret;
@@ -1129,8 +1193,7 @@ bool search_playlist(void)
gui_synclist_speak_item(&playlist_lists);
while (!exit)
{
- if (list_do_action(CONTEXT_LIST, HZ/4,
- &playlist_lists, &button, LIST_WRAP_UNLESS_HELD))
+ if (list_do_action(CONTEXT_LIST, HZ/4, &playlist_lists, &button))
continue;
switch (button)
{
diff --git a/apps/playlist_viewer.h b/apps/playlist_viewer.h
index 0a54c1b2cd..2bb1336f4f 100644
--- a/apps/playlist_viewer.h
+++ b/apps/playlist_viewer.h
@@ -24,7 +24,8 @@
#define _PLAYLIST_VIEWER_H_
enum playlist_viewer_result playlist_viewer(void);
-enum playlist_viewer_result playlist_viewer_ex(const char* filename);
+enum playlist_viewer_result playlist_viewer_ex(const char* filename,
+ int* most_recent_selection);
bool search_playlist(void);
enum playlist_viewer_result {
diff --git a/apps/plugin.c b/apps/plugin.c
index eb76eb7753..128b52ea2d 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -341,7 +341,6 @@ static const struct plugin_api rockbox_api = {
gui_synclist_select_item,
gui_synclist_add_item,
gui_synclist_del_item,
- gui_synclist_limit_scroll,
gui_synclist_do_button,
gui_synclist_set_title,
gui_syncyesno_run,
@@ -357,6 +356,7 @@ static const struct plugin_api rockbox_api = {
action_get_touchscreen_press_in_vp,
#endif
action_userabort,
+ core_set_keyremap,
/* button */
button_get,
@@ -436,6 +436,8 @@ static const struct plugin_api rockbox_api = {
tree_get_entry_at,
set_current_file,
set_dirfilter,
+ onplay_show_playlist_menu,
+ browse_id3,
/* talking */
talk_id,
@@ -519,6 +521,7 @@ static const struct plugin_api rockbox_api = {
queue_wait,
queue_send,
queue_reply,
+ queue_remove_from_head,
#ifdef RB_PROFILE
profile_thread,
@@ -688,7 +691,9 @@ static const struct plugin_api rockbox_api = {
playlist_create,
playlist_insert_track,
playlist_insert_directory,
+ playlist_insert_playlist,
playlist_shuffle,
+ warn_on_pl_erase,
audio_play,
audio_stop,
audio_pause,
@@ -731,6 +736,7 @@ static const struct plugin_api rockbox_api = {
battery_level_safe,
battery_time,
battery_voltage,
+ battery_current,
#if CONFIG_CHARGING
charger_inserted,
# if CONFIG_CHARGING >= CHARGING_MONITOR
@@ -801,21 +807,24 @@ static const struct plugin_api rockbox_api = {
plugin_release_audio_buffer, /* defined in plugin.c */
plugin_tsr, /* defined in plugin.c */
plugin_get_current_filename,
- /* new stuff at the end, sort into place next time
- the API gets incompatible */
- warn_on_pl_erase,
- playlist_insert_playlist,
- battery_current,
- onplay_show_playlist_menu,
- queue_remove_from_head,
- core_set_keyremap,
plugin_reserve_buffer,
+
+ /* reboot and poweroff */
+ sys_poweroff,
+ sys_reboot,
+
+ /* pathfuncs */
#ifdef HAVE_MULTIVOLUME
path_strip_volume,
#endif
- sys_poweroff,
- sys_reboot,
- browse_id3,
+
+ /* new stuff at the end, sort into place next time
+ the API gets incompatible */
+#ifdef HAVE_TAGCACHE
+#ifdef HAVE_TC_RAMCACHE
+ tagcache_is_in_ram,
+#endif
+#endif
};
static int plugin_buffer_handle;
@@ -835,8 +844,7 @@ int plugin_load(const char* plugin, const void* parameter)
}
lc_close(current_plugin_handle);
current_plugin_handle = pfn_tsr_exit = NULL;
- if (plugin_buffer_handle > 0)
- plugin_buffer_handle = core_free(plugin_buffer_handle);
+ plugin_buffer_handle = core_free(plugin_buffer_handle);
}
splash(0, ID2P(LANG_WAIT));
@@ -917,8 +925,7 @@ int plugin_load(const char* plugin, const void* parameter)
{ /* close handle if plugin is no tsr one */
lc_close(current_plugin_handle);
current_plugin_handle = NULL;
- if (plugin_buffer_handle > 0)
- plugin_buffer_handle = core_free(plugin_buffer_handle);
+ plugin_buffer_handle = core_free(plugin_buffer_handle);
}
talk_buffer_set_policy(TALK_BUFFER_DEFAULT);
diff --git a/apps/plugin.h b/apps/plugin.h
index a487f64168..e2a821bb57 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -157,12 +157,12 @@ int plugin_open(const char *plugin, const char *parameter);
#define PLUGIN_MAGIC 0x526F634B /* RocK */
/* increase this every time the api struct changes */
-#define PLUGIN_API_VERSION 251
+#define PLUGIN_API_VERSION 256
/* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any
new function which are "waiting" at the end of the function table) */
-#define PLUGIN_MIN_API_VERSION 245
+#define PLUGIN_MIN_API_VERSION 255
/* 239 Marks the removal of ARCHOS HWCODEC and CHARCELL */
@@ -384,10 +384,8 @@ struct plugin_api {
int item_number);
void (*gui_synclist_add_item)(struct gui_synclist * lists);
void (*gui_synclist_del_item)(struct gui_synclist * lists);
- void (*gui_synclist_limit_scroll)(struct gui_synclist * lists, bool scroll);
- bool (*gui_synclist_do_button)(struct gui_synclist * lists,
- int *action, enum list_wrap wrap);
- void (*gui_synclist_set_title)(struct gui_synclist *lists, char* title,
+ bool (*gui_synclist_do_button)(struct gui_synclist * lists, int *action);
+ void (*gui_synclist_set_title)(struct gui_synclist *lists, const char* title,
enum themable_icons icon);
enum yesno_res (*gui_syncyesno_run)(const struct text_message * main_message,
const struct text_message * yes_message,
@@ -406,6 +404,7 @@ struct plugin_api {
int (*action_get_touchscreen_press_in_vp)(short *x1, short *y1, struct viewport *vp);
#endif
bool (*action_userabort)(int timeout);
+ int (*core_set_keyremap)(struct button_mapping* core_keymap, int count);
/* button */
long (*button_get)(bool block);
@@ -492,6 +491,10 @@ struct plugin_api {
void (*set_current_file)(const char* path);
void (*set_dirfilter)(int l_dirfilter);
+ void (*onplay_show_playlist_menu)(const char* path, void (*playlist_insert_cb));
+ bool (*browse_id3)(struct mp3entry *id3,
+ int playlist_display_index, int playlist_amount);
+
/* talking */
int (*talk_id)(int32_t id, bool enqueue);
int (*talk_file)(const char *root, const char *dir, const char *file,
@@ -588,6 +591,7 @@ struct plugin_api {
intptr_t (*queue_send)(struct event_queue *q, long id,
intptr_t data);
void (*queue_reply)(struct event_queue *q, intptr_t retval);
+ void (*queue_remove_from_head)(struct event_queue *q, long id);
#ifdef RB_PROFILE
void (*profile_thread)(void);
@@ -790,7 +794,10 @@ struct plugin_api {
int (*playlist_insert_directory)(struct playlist_info* playlist,
const char *dirname, int position, bool queue,
bool recurse);
+ int (*playlist_insert_playlist)(struct playlist_info* playlist,
+ const char *filename, int position, bool queue);
int (*playlist_shuffle)(int random_seed, int start_index);
+ bool (*warn_on_pl_erase)(void);
void (*audio_play)(unsigned long elapsed, unsigned long offset);
void (*audio_stop)(void);
void (*audio_pause)(void);
@@ -850,6 +857,7 @@ struct plugin_api {
bool (*battery_level_safe)(void);
int (*battery_time)(void);
int (*battery_voltage)(void);
+ int (*battery_current)(void);
#if CONFIG_CHARGING
bool (*charger_inserted)(void);
# if CONFIG_CHARGING >= CHARGING_MONITOR
@@ -928,23 +936,21 @@ struct plugin_api {
void (*plugin_release_audio_buffer)(void);
void (*plugin_tsr)(bool (*exit_callback)(bool reenter));
char* (*plugin_get_current_filename)(void);
- /* new stuff at the end, sort into place next time
- the API gets incompatible */
- bool (*warn_on_pl_erase)(void);
- int (*playlist_insert_playlist)(struct playlist_info* playlist,
- const char *filename, int position, bool queue);
- int (*battery_current)(void);
- void (*onplay_show_playlist_menu)(const char* path, void (*playlist_insert_cb));
- void (*queue_remove_from_head)(struct event_queue *q, long id);
- int (*core_set_keyremap)(struct button_mapping* core_keymap, int count);
size_t (*plugin_reserve_buffer)(size_t buffer_size);
+ /* reboot and poweroff */
+ void (*sys_poweroff)(void);
+ void (*sys_reboot)(void);
+ /* pathfuncs */
#ifdef HAVE_MULTIVOLUME
int (*path_strip_volume)(const char *name, const char **nameptr, bool greedy);
#endif
- void (*sys_poweroff)(void);
- void (*sys_reboot)(void);
- bool (*browse_id3)(struct mp3entry *id3,
- int playlist_display_index, int playlist_amount);
+ /* new stuff at the end, sort into place next time
+ the API gets incompatible */
+#ifdef HAVE_TAGCACHE
+#ifdef HAVE_TC_RAMCACHE
+ bool (*tagcache_is_in_ram)(void);
+#endif
+#endif
};
/* plugin header */
diff --git a/apps/plugins/2048.c b/apps/plugins/2048.c
index 2633753071..456f973aef 100644
--- a/apps/plugins/2048.c
+++ b/apps/plugins/2048.c
@@ -148,9 +148,7 @@ static inline int rand_range(int min, int max)
/* prepares for exit */
static void cleanup(void)
{
-#ifdef HAVE_BACKLIGHT
backlight_use_settings();
-#endif
}
/* returns 2 or 4 */
@@ -700,9 +698,8 @@ static void init_game(bool newgame)
max_numeral_width = rb->font_get_width(rb->font_get(WHAT_FONT), '0');
#endif
-#ifdef HAVE_BACKLIGHT
backlight_ignore_timeout();
-#endif
+
draw();
}
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index 942f9a5b20..85227d80d7 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -82,8 +82,7 @@ crypt_firmware.c
/* Overlays loaders */
-#if defined(HAVE_LCD_COLOR) && \
- (!defined(LCD_STRIDEFORMAT) || (LCD_STRIDEFORMAT != VERTICAL_STRIDE))
+#if defined(HAVE_LCD_COLOR) && (LCD_STRIDEFORMAT == HORIZONTAL_STRIDE)
#if (PLUGIN_BUFFER_SIZE > 0x14000) && (CONFIG_PLATFORM & (PLATFORM_NATIVE |PLATFORM_HOSTED)) && (defined(CPU_ARM) || defined(CPU_MIPS))
duke3d.c
quake.c
diff --git a/apps/plugins/SUBDIRS b/apps/plugins/SUBDIRS
index 8479e4b3dd..4cb57edb1b 100644
--- a/apps/plugins/SUBDIRS
+++ b/apps/plugins/SUBDIRS
@@ -9,8 +9,7 @@ clock
#endif
/* color horizontal-stride LCDs */
-#if defined(HAVE_LCD_COLOR) && \
- (!defined(LCD_STRIDEFORMAT) || (LCD_STRIDEFORMAT != VERTICAL_STRIDE))
+#if defined(HAVE_LCD_COLOR) && (LCD_STRIDEFORMAT == HORIZONTAL_STRIDE)
xworld
/* for duke3d, wolf3d and quake */
diff --git a/apps/plugins/bitmaps/native/SOURCES b/apps/plugins/bitmaps/native/SOURCES
index f207f358b2..d0cc853f5b 100644
--- a/apps/plugins/bitmaps/native/SOURCES
+++ b/apps/plugins/bitmaps/native/SOURCES
@@ -548,8 +548,7 @@ pegbox_pieces.9x7x1.bmp
#endif
/* Puzzles */
-#if defined(HAVE_LCD_COLOR) && \
- (!defined(LCD_STRIDEFORMAT) || (LCD_STRIDEFORMAT != VERTICAL_STRIDE))
+#if defined(HAVE_LCD_COLOR) && (LCD_STRIDEFORMAT == HORIZONTAL_STRIDE)
puzzles_cursor.11x16x24.bmp
#endif
diff --git a/apps/plugins/brickmania.c b/apps/plugins/brickmania.c
index 4983d5a417..de65ce69e1 100644
--- a/apps/plugins/brickmania.c
+++ b/apps/plugins/brickmania.c
@@ -111,8 +111,7 @@
#elif CONFIG_KEYPAD == SANSA_C200_PAD || \
CONFIG_KEYPAD == SANSA_CLIP_PAD || \
-CONFIG_KEYPAD == SANSA_M200_PAD || \
-CONFIG_KEYPAD == SANSA_CONNECT_PAD
+CONFIG_KEYPAD == SANSA_M200_PAD
#define QUIT BUTTON_POWER
#define LEFT BUTTON_LEFT
#define RIGHT BUTTON_RIGHT
@@ -122,6 +121,18 @@ CONFIG_KEYPAD == SANSA_CONNECT_PAD
#define UP BUTTON_UP
#define DOWN BUTTON_DOWN
+#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD
+#define QUIT BUTTON_POWER
+#define LEFT BUTTON_LEFT
+#define RIGHT BUTTON_RIGHT
+#define SELECT BUTTON_SELECT
+#define UP BUTTON_UP
+#define DOWN BUTTON_DOWN
+
+#define SCROLL_FWD(x) ((x) & BUTTON_SCROLL_FWD)
+#define SCROLL_BACK(x) ((x) & BUTTON_SCROLL_BACK)
+
+
#elif CONFIG_KEYPAD == IRIVER_H10_PAD
#define QUIT BUTTON_POWER
#define LEFT BUTTON_LEFT
@@ -2522,10 +2533,10 @@ enum plugin_status plugin_start(const void* parameter)
#if LCD_DEPTH > 1
rb->lcd_set_backdrop(NULL);
#endif
-#ifdef HAVE_BACKLIGHT
+
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
+
/* now go ahead and have fun! */
rb->srand( *rb->current_tick );
brickmania_loadgame();
@@ -2554,9 +2565,9 @@ enum plugin_status plugin_start(const void* parameter)
configfile_save(CONFIG_FILE_NAME,config,1,0);
/* Restore user's original backlight setting */
rb->lcd_setfont(FONT_UI);
-#ifdef HAVE_BACKLIGHT
+
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings();
-#endif
+
return PLUGIN_OK;
}
diff --git a/apps/plugins/calendar.c b/apps/plugins/calendar.c
index 3299a81273..a70f47c34b 100644
--- a/apps/plugins/calendar.c
+++ b/apps/plugins/calendar.c
@@ -964,7 +964,7 @@ static bool view_events(int selected, struct shown *shown)
while (!exit)
{
button = rb->get_action(CONTEXT_LIST, TIMEOUT_BLOCK);
- rb->gui_synclist_do_button(&gui_memos, &button, LIST_WRAP_UNLESS_HELD);
+ rb->gui_synclist_do_button(&gui_memos, &button);
switch (button)
{
diff --git a/apps/plugins/chessbox/chessbox_pgn.c b/apps/plugins/chessbox/chessbox_pgn.c
index 0d9da441b1..bb35bec726 100644
--- a/apps/plugins/chessbox/chessbox_pgn.c
+++ b/apps/plugins/chessbox/chessbox_pgn.c
@@ -678,7 +678,6 @@ struct pgn_game_node* pgn_show_game_list(struct pgn_game_node* first_game){
if (rb->global_settings->talk_menu)
rb->gui_synclist_set_voice_callback(&games_list, speak_game_selection);
rb->gui_synclist_set_nb_items(&games_list, i);
- rb->gui_synclist_limit_scroll(&games_list, true);
rb->gui_synclist_select_item(&games_list, 0);
rb->gui_synclist_draw(&games_list);
@@ -687,9 +686,8 @@ struct pgn_game_node* pgn_show_game_list(struct pgn_game_node* first_game){
while (true) {
curr_selection = rb->gui_synclist_get_sel_pos(&games_list);
button = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
- if (rb->gui_synclist_do_button(&games_list,&button,LIST_WRAP_OFF)){
+ if (rb->gui_synclist_do_button(&games_list, &button))
continue;
- }
switch (button) {
case ACTION_STD_OK:
return get_game_info(curr_selection, first_game);
diff --git a/apps/plugins/chopper.c b/apps/plugins/chopper.c
index 392b840317..5c87e74e50 100644
--- a/apps/plugins/chopper.c
+++ b/apps/plugins/chopper.c
@@ -1083,10 +1083,10 @@ enum plugin_status plugin_start(const void* parameter)
rb->lcd_set_foreground(LCD_WHITE);
#endif
-#ifdef HAVE_BACKLIGHT
+
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
+
rb->srand( *rb->current_tick );
@@ -1098,10 +1098,10 @@ enum plugin_status plugin_start(const void* parameter)
configfile_save(CFG_FILE, config, 1, 0);
rb->lcd_setfont(FONT_UI);
-#ifdef HAVE_BACKLIGHT
+
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings();
-#endif
+
return ret;
}
diff --git a/apps/plugins/credits.c b/apps/plugins/credits.c
index 9e43aab2a7..efdcf42df1 100644
--- a/apps/plugins/credits.c
+++ b/apps/plugins/credits.c
@@ -303,10 +303,10 @@ enum plugin_status plugin_start(const void* parameter)
{
(void)parameter;
-#ifdef HAVE_BACKLIGHT
+
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
+
#if LCD_DEPTH>=16
rb->lcd_set_foreground (LCD_WHITE);
@@ -318,10 +318,10 @@ enum plugin_status plugin_start(const void* parameter)
if(!rb->action_userabort(3*HZ))
roll_credits();
-#ifdef HAVE_BACKLIGHT
+
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings();
-#endif
+
return PLUGIN_OK;
}
diff --git a/apps/plugins/demystify.c b/apps/plugins/demystify.c
index 74537e94f8..1a1505ff96 100644
--- a/apps/plugins/demystify.c
+++ b/apps/plugins/demystify.c
@@ -262,12 +262,10 @@ static void polygons_draw(struct polygon_fifo * polygons, struct screen * displa
static void cleanup(void)
{
-#ifdef HAVE_BACKLIGHT
+
backlight_use_settings();
-#ifdef HAVE_REMOTE_LCD
remote_backlight_use_settings();
-#endif
-#endif
+
}
#ifdef HAVE_LCD_COLOR
@@ -438,12 +436,10 @@ enum plugin_status plugin_start(const void* parameter)
#if LCD_DEPTH > 1
rb->lcd_set_backdrop(NULL);
#endif
-#ifdef HAVE_BACKLIGHT
+
backlight_ignore_timeout();
-#ifdef HAVE_REMOTE_LCD
remote_backlight_ignore_timeout();
-#endif
-#endif
+
ret = plugin_main();
return ret;
diff --git a/apps/plugins/doom/i_video.c b/apps/plugins/doom/i_video.c
index f5d07a8354..79f3212467 100644
--- a/apps/plugins/doom/i_video.c
+++ b/apps/plugins/doom/i_video.c
@@ -453,6 +453,9 @@ void I_ShutdownGraphics(void)
#define DOOMBUTTON_MAP BUTTON_BOTTOMRIGHT
#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD
+#define DOOMBUTTON_SCROLLWHEEL
+#define DOOMBUTTON_SCROLLWHEEL_CC BUTTON_SCROLL_BACK
+#define DOOMBUTTON_SCROLLWHEEL_CW BUTTON_SCROLL_FWD
#define DOOMBUTTON_UP BUTTON_UP
#define DOOMBUTTON_DOWN BUTTON_DOWN
#define DOOMBUTTON_LEFT BUTTON_LEFT
diff --git a/apps/plugins/doom/rockdoom.c b/apps/plugins/doom/rockdoom.c
index 6594859c08..b68107f8aa 100644
--- a/apps/plugins/doom/rockdoom.c
+++ b/apps/plugins/doom/rockdoom.c
@@ -722,9 +722,9 @@ enum plugin_status plugin_start(const void* parameter)
systemvol= rb->global_settings->volume-rb->global_settings->volume%mod;
general_translucency = default_translucency; // phares
-#ifdef HAVE_BACKLIGHT
+
backlight_ignore_timeout();
-#endif
+
#ifdef RB_PROFILE
rb->profile_thread();
#endif
@@ -738,9 +738,9 @@ enum plugin_status plugin_start(const void* parameter)
#ifdef RB_PROFILE
rb->profstop();
#endif
-#ifdef HAVE_BACKLIGHT
+
backlight_use_settings();
-#endif
+
M_SaveDefaults ();
I_Quit(); // Make SURE everything was closed out right
diff --git a/apps/plugins/fft/fft.c b/apps/plugins/fft/fft.c
index 35498227bf..f612a0ea35 100644
--- a/apps/plugins/fft/fft.c
+++ b/apps/plugins/fft/fft.c
@@ -1184,9 +1184,8 @@ static void fft_cleanup(void)
#ifndef HAVE_LCD_COLOR
grey_release();
#endif
-#ifdef HAVE_BACKLIGHT
+
backlight_use_settings();
-#endif
/* save settings if changed */
if (rb->memcmp(&fft, &fft_disk, sizeof(fft)))
@@ -1237,9 +1236,8 @@ static bool fft_setup(void)
mylcd_clear_display();
myosd_lcd_update();
#endif
-#ifdef HAVE_BACKLIGHT
+
backlight_ignore_timeout();
-#endif
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->trigger_cpu_boost();
diff --git a/apps/plugins/fire.c b/apps/plugins/fire.c
index f3e6fb35e4..43d10bf920 100644
--- a/apps/plugins/fire.c
+++ b/apps/plugins/fire.c
@@ -279,10 +279,9 @@ static void cleanup(void *parameter)
#ifndef HAVE_LCD_COLOR
grey_release();
#endif
-#ifdef HAVE_BACKLIGHT
+
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings();
-#endif
}
@@ -371,10 +370,9 @@ enum plugin_status plugin_start(const void* parameter)
#if LCD_DEPTH > 1
rb->lcd_set_backdrop(NULL);
#endif
-#ifdef HAVE_BACKLIGHT
+
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
rb->lcd_set_mode(LCD_MODE_PAL256);
diff --git a/apps/plugins/fireworks.c b/apps/plugins/fireworks.c
index b7dad0d8ba..febd093e3f 100644
--- a/apps/plugins/fireworks.c
+++ b/apps/plugins/fireworks.c
@@ -358,9 +358,9 @@ enum plugin_status plugin_start(const void* parameter)
/* set everything up.. no BL timeout, no backdrop,
white-text-on-black-background. */
-#ifdef HAVE_BACKLIGHT
+
backlight_ignore_timeout();
-#endif
+
#if LCD_DEPTH > 1
rb->lcd_set_backdrop(NULL);
rb->lcd_set_background(LCD_BLACK);
@@ -524,10 +524,10 @@ enum plugin_status plugin_start(const void* parameter)
break;
}
}
-#ifdef HAVE_BACKLIGHT
+
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings();
-#endif
+
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(false);
#endif
diff --git a/apps/plugins/imageviewer/imageviewer.c b/apps/plugins/imageviewer/imageviewer.c
index e30a98ef68..a8ef3efc97 100644
--- a/apps/plugins/imageviewer/imageviewer.c
+++ b/apps/plugins/imageviewer/imageviewer.c
@@ -1064,10 +1064,8 @@ enum plugin_status plugin_start(const void* parameter)
ARRAYLEN(config), IMGVIEW_SETTINGS_MINVERSION);
rb->memcpy(&old_settings, &settings, sizeof (settings));
-#ifdef HAVE_BACKLIGHT
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
#if LCD_DEPTH > 1
rb->lcd_set_backdrop(NULL);
@@ -1094,10 +1092,8 @@ enum plugin_status plugin_start(const void* parameter)
rb->storage_spindown(rb->global_settings->disk_spindown);
#endif
-#ifdef HAVE_BACKLIGHT
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings();
-#endif
#ifdef USEGSLIB
grey_release(); /* deinitialize */
diff --git a/apps/plugins/imageviewer/jpeg/yuv2rgb.c b/apps/plugins/imageviewer/jpeg/yuv2rgb.c
index 61d7fd6487..3e7f08d8bc 100644
--- a/apps/plugins/imageviewer/jpeg/yuv2rgb.c
+++ b/apps/plugins/imageviewer/jpeg/yuv2rgb.c
@@ -238,7 +238,7 @@ static fb_data (* const pixel_funcs[COLOUR_NUM_MODES][DITHER_NUM_MODES])(void) =
};
/* These defines are used fornormal horizontal strides and vertical strides. */
-#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
#define LCDADDR(x, y) (lcd_fb + LCD_HEIGHT*(x) + (y))
#define ROWENDOFFSET (width*LCD_HEIGHT)
#define ROWOFFSET (1)
diff --git a/apps/plugins/imageviewer/ppm/ppm_decoder.c b/apps/plugins/imageviewer/ppm/ppm_decoder.c
index 4a86be1a3a..ccb208b80b 100644
--- a/apps/plugins/imageviewer/ppm/ppm_decoder.c
+++ b/apps/plugins/imageviewer/ppm/ppm_decoder.c
@@ -177,7 +177,7 @@ static int read_ppm_row(int fd, struct ppm_info *ppm, int row)
int col;
int r, g, b;
#ifdef HAVE_LCD_COLOR
-#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
fb_data *dst = (fb_data *) ppm->buf + row;
const int stride = ppm->x;
#else
diff --git a/apps/plugins/invadrox.c b/apps/plugins/invadrox.c
index a164b95cf0..d130ab6108 100644
--- a/apps/plugins/invadrox.c
+++ b/apps/plugins/invadrox.c
@@ -785,7 +785,7 @@ static fb_data *lcd_fb;
/* No standard get_pixel function yet, use this hack instead */
#if (LCD_DEPTH >= 8)
-#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
static inline fb_data get_pixel(int x, int y)
{
return lcd_fb[x*LCD_HEIGHT+y];
diff --git a/apps/plugins/keybox.c b/apps/plugins/keybox.c
index f8c6800a4d..cb2e23a94a 100644
--- a/apps/plugins/keybox.c
+++ b/apps/plugins/keybox.c
@@ -567,7 +567,7 @@ static int keybox(void)
{
rb->gui_synclist_draw(&kb_list);
button = rb->get_action(CONTEXT_LIST, TIMEOUT_BLOCK);
- if (rb->gui_synclist_do_button(&kb_list, &button, LIST_WRAP_UNLESS_HELD))
+ if (rb->gui_synclist_do_button(&kb_list, &button))
continue;
switch (button)
@@ -659,7 +659,6 @@ enum plugin_status plugin_start(const void *parameter)
rb->gui_synclist_set_title(&kb_list, "Keybox", NOICON);
rb->gui_synclist_set_icon_callback(&kb_list, NULL);
rb->gui_synclist_set_nb_items(&kb_list, 0);
- rb->gui_synclist_limit_scroll(&kb_list, false);
rb->gui_synclist_select_item(&kb_list, 0);
init_ll();
diff --git a/apps/plugins/keyremap.c b/apps/plugins/keyremap.c
index a4ce1c48e6..4fd792646e 100644
--- a/apps/plugins/keyremap.c
+++ b/apps/plugins/keyremap.c
@@ -391,7 +391,7 @@ static struct button_mapping *keyremap_create_temp(int *entries)
size_t keymap_bytes = (entry_count) * sizeof(struct button_mapping);
*entries = entry_count;
logf("keyremap create temp entry count: %d", entry_count);
- logf("keyremap bytes: %ld, avail: %ld", keymap_bytes,
+ logf("keyremap bytes: %zu, avail: %zu", keymap_bytes,
(keyremap_buffer.end - keyremap_buffer.front));
if (keyremap_buffer.front + keymap_bytes < keyremap_buffer.end)
{
@@ -1950,7 +1950,6 @@ static void synclist_set(int id, int selected_item, int items, int sel_size)
rb->gui_synclist_set_icon_callback(&lists,NULL);
rb->gui_synclist_set_voice_callback(&lists, list_voice_cb);
rb->gui_synclist_set_nb_items(&lists,items);
- rb->gui_synclist_limit_scroll(&lists,true);
rb->gui_synclist_select_item(&lists, selected_item);
printcell_enable(&lists, false, false);
@@ -2055,7 +2054,7 @@ enum plugin_status plugin_start(const void* parameter)
redraw = true;
ret = menu_action_cb(&action, selected_item, &exit, &lists);
- if (rb->gui_synclist_do_button(&lists,&action,LIST_WRAP_UNLESS_HELD))
+ if (rb->gui_synclist_do_button(&lists, &action))
continue;
selected_item = rb->gui_synclist_get_sel_pos(&lists);
diff --git a/apps/plugins/lamp.c b/apps/plugins/lamp.c
index 6c9ae6626d..42a2353b2a 100644
--- a/apps/plugins/lamp.c
+++ b/apps/plugins/lamp.c
@@ -103,9 +103,8 @@ enum plugin_status plugin_start(const void* parameter)
int current_brightness = MAX_BRIGHTNESS_SETTING;
backlight_brightness_set(MAX_BRIGHTNESS_SETTING);
#endif /* HAVE_BACKLIGHT_BRIGHTNESS */
-#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
+
buttonlight_brightness_set(MAX_BRIGHTNESS_SETTING);
-#endif /* HAVE_BUTTONLIGHT_BRIGHTNESS */
#ifdef HAVE_LCD_INVERT
#ifdef HAVE_NEGATIVE_LCD
@@ -116,9 +115,8 @@ enum plugin_status plugin_start(const void* parameter)
#endif /* HAVE_LCD_INVERT */
backlight_force_on();
-#ifdef HAVE_BUTTON_LIGHT
buttonlight_force_on();
-#endif /* HAVE_BUTTON_LIGHT */
+
rb->lcd_clear_display();
rb->lcd_update();
@@ -207,20 +205,17 @@ enum plugin_status plugin_start(const void* parameter)
/* restore */
backlight_use_settings();
-#ifdef HAVE_BUTTON_LIGHT
+
buttonlight_use_settings();
-#endif /* HAVE_BUTTON_LIGHT */
#ifdef HAVE_LCD_INVERT
rb->lcd_set_invert_display(rb->global_settings->invert);
#endif /* HAVE_LCD_INVERT */
-#ifdef HAVE_BACKLIGHT_BRIGHTNESS
+
backlight_brightness_use_setting();
-#endif /* HAVE_BACKLIGHT_BRIGHTNESS */
-#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
+
buttonlight_brightness_use_setting();
-#endif /* HAVE_BUTTONLIGHT_BRIGHTNESS */
#if LCD_DEPTH > 1
rb->lcd_set_background(bg_color);
diff --git a/apps/plugins/lib/bmp_smooth_scale.c b/apps/plugins/lib/bmp_smooth_scale.c
index c5f258cdbf..378ff96448 100644
--- a/apps/plugins/lib/bmp_smooth_scale.c
+++ b/apps/plugins/lib/bmp_smooth_scale.c
@@ -78,7 +78,7 @@ void smooth_resize_bitmap(struct bitmap *src_bmp, struct bitmap *dest_bmp)
fb_data *sptr, *dptr;
int x, y, end;
int val_y = 0, val_x;
-#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
const int sw = src_bmp->height;
const int sh = src_bmp->width;
const int dw = dest_bmp->height;
diff --git a/apps/plugins/lib/helper.c b/apps/plugins/lib/helper.c
index 018c1616c8..92d9ec905e 100644
--- a/apps/plugins/lib/helper.c
+++ b/apps/plugins/lib/helper.c
@@ -58,7 +58,12 @@ void backlight_use_settings(void)
backlight_timeout_plugged);
#endif /* CONFIG_CHARGING */
}
-#endif /* HAVE_BACKLIGHT */
+#else /* HAVE_BACKLIGHT */
+/* DUMMY FUNCTIONS */
+void backlight_force_on(void){}
+void backlight_ignore_timeout(void){}
+void backlight_use_settings(void){}
+#endif /* !HAVE_BACKLIGHT */
#ifdef HAVE_SW_POWEROFF
static bool original_sw_poweroff_state = true;
@@ -73,7 +78,11 @@ void sw_poweroff_restore(void)
{
rb->button_set_sw_poweroff_state(original_sw_poweroff_state);
}
-#endif
+#else /* HAVE_SW_POWEROFF */
+/* DUMMY FUNCTIONS */
+void sw_poweroff_disable(void){}
+void sw_poweroff_restore(void){}
+#endif /* !HAVE_SW_POWEROFF */
#ifdef HAVE_REMOTE_LCD
/* Force the backlight on */
@@ -106,7 +115,12 @@ void remote_backlight_use_settings(void)
remote_backlight_timeout_plugged);
#endif /* CONFIG_CHARGING */
}
-#endif /* HAVE_REMOTE_LCD */
+#else /* HAVE_REMOTE_LCD */
+/* DUMMY FUNCTIONS */
+void remote_backlight_force_on(void){}
+void remote_backlight_ignore_timeout(void){}
+void remote_backlight_use_settings(void){}
+#endif /* !HAVE_REMOTE_LCD */
#ifdef HAVE_BUTTON_LIGHT
/* Force the buttonlight on */
@@ -133,7 +147,13 @@ void buttonlight_use_settings(void)
{
rb->buttonlight_set_timeout(rb->global_settings->buttonlight_timeout);
}
-#endif /* HAVE_BUTTON_LIGHT */
+#else /* HAVE_BUTTON_LIGHT */
+/* DUMMY FUNCTIONS */
+void buttonlight_force_on(void){}
+void buttonlight_force_off(void){}
+void buttonlight_ignore_timeout(void){}
+void buttonlight_use_settings(void){}
+#endif /* !HAVE_BUTTON_LIGHT */
#ifdef HAVE_BACKLIGHT_BRIGHTNESS
void backlight_brightness_set(int brightness)
@@ -145,7 +165,15 @@ void backlight_brightness_use_setting(void)
{
rb->backlight_set_brightness(rb->global_settings->brightness);
}
-#endif /* HAVE_BACKLIGHT_BRIGHTNESS */
+#else /* HAVE_BACKLIGHT_BRIGHTNESS */
+/* DUMMY FUNCTIONS */
+void backlight_brightness_set(int brightness)
+{
+ (void)brightness;
+}
+void backlight_brightness_use_setting(void){}
+
+#endif /* !HAVE_BACKLIGHT_BRIGHTNESS */
#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
void buttonlight_brightness_set(int brightness)
@@ -157,4 +185,12 @@ void buttonlight_brightness_use_setting(void)
{
rb->buttonlight_set_brightness(rb->global_settings->buttonlight_brightness);
}
-#endif /* HAVE_BUTTONLIGHT_BRIGHTNESS */
+#else /* HAVE_BUTTONLIGHT_BRIGHTNESS */
+/* DUMMY FUNCTIONS */
+void buttonlight_brightness_set(int brightness)
+{
+ (void)brightness;
+}
+
+void buttonlight_brightness_use_setting(void){}
+#endif /* !HAVE_BUTTONLIGHT_BRIGHTNESS */
diff --git a/apps/plugins/lib/helper.h b/apps/plugins/lib/helper.h
index 00ad8ac087..6aee4dc581 100644
--- a/apps/plugins/lib/helper.h
+++ b/apps/plugins/lib/helper.h
@@ -23,6 +23,16 @@
#include "plugin.h"
+#ifndef MAX_BRIGHTNESS_SETTING
+#define MAX_BRIGHTNESS_SETTING 0
+#endif
+#ifndef MIN_BRIGHTNESS_SETTING
+#define MIN_BRIGHTNESS_SETTING 0
+#endif
+#ifndef DEFAULT_BRIGHTNESS_SETTING
+#define DEFAULT_BRIGHTNESS_SETTING 0
+#endif
+
int talk_val(long n, int unit, bool enqueue);
/**
@@ -32,39 +42,29 @@ void backlight_force_on(void);
void backlight_ignore_timeout(void);
void backlight_use_settings(void);
-#ifdef HAVE_SW_POWEROFF
/**
* Disable and restore software poweroff (i.e. holding PLAY on iPods).
* Only call _restore() if _disable() was called earlier!
*/
void sw_poweroff_disable(void);
void sw_poweroff_restore(void);
-#endif
-#ifdef HAVE_REMOTE_LCD
void remote_backlight_force_on(void);
void remote_backlight_ignore_timeout(void);
void remote_backlight_use_settings(void);
-#endif
-#ifdef HAVE_BUTTON_LIGHT
void buttonlight_force_on(void);
void buttonlight_force_off(void);
void buttonlight_ignore_timeout(void);
void buttonlight_use_settings(void);
-#endif
/**
* Backlight brightness adjustment settings
*/
-#ifdef HAVE_BACKLIGHT_BRIGHTNESS
void backlight_brightness_set(int brightness);
void backlight_brightness_use_setting(void);
-#endif
-#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
void buttonlight_brightness_set(int brightness);
void buttonlight_brightness_use_setting(void);
-#endif /* HAVE_BUTTONLIGHT_BRIGHTNESS */
#endif /* _LIB_HELPER_H_ */
diff --git a/apps/plugins/lib/osd.c b/apps/plugins/lib/osd.c
index 7d6e10a410..99f77da7dc 100644
--- a/apps/plugins/lib/osd.c
+++ b/apps/plugins/lib/osd.c
@@ -106,10 +106,10 @@ static struct osd grey_osd;
# error Unknown 2-bit format; please define macros
# endif /* LCD_PIXELFORMAT */
#elif LCD_DEPTH == 16
-# if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
+# if LCD_STRIDEFORMAT == VERTICAL_STRIDE
# define _OSD_HEIGHT2BYTES(h) ((h)*2)
# define _OSD_BYTES2HEIGHT(b) ((b)/2)
-# else /* !defined(LCD_STRIDEFORMAT) || LCD_STRIDEFORMAT != VERTICAL_STRIDE */
+# else /* LCD_STRIDEFORMAT != VERTICAL_STRIDE */
# define _OSD_WIDTH2BYTES(w) ((w)*2)
# define _OSD_BYTES2WIDTH(b) ((b)/2)
# endif /* end stride type selection */
@@ -160,7 +160,7 @@ static void * _osd_lcd_init_buffers(struct osd *osd, unsigned flags,
rb->viewport_set_fullscreen(&osd->vp, SCREEN_MAIN);
-#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
int colbytes = _OSD_HEIGHT2BYTES(LCD_HEIGHT);
int bytecols = *bufsize / colbytes;
int w = _OSD_BYTES2WIDTH(bytecols);
@@ -193,7 +193,7 @@ static void * _osd_lcd_init_buffers(struct osd *osd, unsigned flags,
w = _OSD_BYTES2WIDTH(_OSD_WIDTH2BYTES(w));
osd->lcd_bitmap_stride = _OSD_BYTES2HEIGHT(_OSD_HEIGHT2BYTES(LCD_HEIGHT));
osd->back_bitmap_stride = h;
-#else /* !defined(LCD_STRIDEFORMAT) || LCD_STRIDEFORMAT != VERTICAL_STRIDE */
+#else /* LCD_STRIDEFORMAT != VERTICAL_STRIDE */
int rowbytes = _OSD_WIDTH2BYTES(LCD_WIDTH);
int byterows = *bufsize / rowbytes;
int w = _OSD_BYTES2WIDTH(rowbytes);
diff --git a/apps/plugins/lib/pluginlib_bmp.c b/apps/plugins/lib/pluginlib_bmp.c
index f3edfbf425..82f84b05af 100644
--- a/apps/plugins/lib/pluginlib_bmp.c
+++ b/apps/plugins/lib/pluginlib_bmp.c
@@ -94,7 +94,7 @@ int save_bmp_file( char* filename, struct bitmap *bm )
*/
void simple_resize_bitmap(struct bitmap *src, struct bitmap *dst)
{
-#if defined(LCD_STRIDEFORMAT) && (LCD_STRIDEFORMAT == VERTICAL_STRIDE)
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
const int srcw = src->height;
const int srch = src->width;
const int dstw = dst->height;
diff --git a/apps/plugins/lib/printcell_helper.c b/apps/plugins/lib/printcell_helper.c
index 328f74e318..f34636585e 100644
--- a/apps/plugins/lib/printcell_helper.c
+++ b/apps/plugins/lib/printcell_helper.c
@@ -234,7 +234,7 @@ static void printcell_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;
struct viewport *vp = list_info->vp;
int line = list_info->line;
diff --git a/apps/plugins/lib/xlcd_scroll.c b/apps/plugins/lib/xlcd_scroll.c
index 5ac4a366e8..906f4eaae1 100644
--- a/apps/plugins/lib/xlcd_scroll.c
+++ b/apps/plugins/lib/xlcd_scroll.c
@@ -30,7 +30,7 @@
static const unsigned short patterns[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000};
#endif
-#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
void xlcd_scroll_left(int count)
{
/*size_t dst_stride;*/
@@ -668,4 +668,4 @@ void xlcd_scroll_down(int count)
}
#endif /* LCD_PIXELFORMAT, LCD_DEPTH */
-#endif /* defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE */
+#endif /* LCD_STRIDEFORMAT == VERTICAL_STRIDE */
diff --git a/apps/plugins/lrcplayer.c b/apps/plugins/lrcplayer.c
index f42b96b5b3..32d001add9 100644
--- a/apps/plugins/lrcplayer.c
+++ b/apps/plugins/lrcplayer.c
@@ -2078,8 +2078,7 @@ static int timetag_editor(void)
while (!exit)
{
button = rb->get_action(CONTEXT_TREE, TIMEOUT_BLOCK);
- if (rb->gui_synclist_do_button(&gui_editor, &button,
- LIST_WRAP_UNLESS_HELD))
+ if (rb->gui_synclist_do_button(&gui_editor, &button))
continue;
switch (button)
@@ -2437,7 +2436,6 @@ static bool lrc_debug_menu(void)
{
struct simplelist_info info;
rb->simplelist_info_init(&info, "Debug Menu", 6, NULL);
- info.hide_selection = true;
info.scroll_all = true;
info.get_name = lrc_debug_data;
return rb->simplelist_show_list(&info);
diff --git a/apps/plugins/lua/rocklib_events.c b/apps/plugins/lua/rocklib_events.c
index 1c13a6758f..0cdec20213 100644
--- a/apps/plugins/lua/rocklib_events.c
+++ b/apps/plugins/lua/rocklib_events.c
@@ -253,7 +253,9 @@ static int lua_rev_callback(lua_State *L, struct cb_data *evt)
lua_pushlightuserdata(L, evt->data);
lua_status = lua_resume(L, 2); /* call the saved function */
- if (lua_status == LUA_YIELD) /* coroutine.yield() disallowed */
+ if (lua_status == LUA_SUCCESS)
+ lua_settop(L, 0); /* eat any value(s) returned */
+ else if (lua_status == LUA_YIELD) /* coroutine.yield() disallowed */
luaL_where(L, 1); /* push error string on stack */
return lua_status;
diff --git a/apps/plugins/lua/rocklib_img.c b/apps/plugins/lua/rocklib_img.c
index b0ca769ca4..68e5325ce0 100644
--- a/apps/plugins/lua/rocklib_img.c
+++ b/apps/plugins/lua/rocklib_img.c
@@ -380,7 +380,7 @@ static inline fb_data* rli_get_element(struct rocklua_image* img, int x, int y)
pixel_to_native(x, y, &x, &y);
-#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
/* column major address */
size_t data_address = (stride * (x - 1)) + (y - 1);
diff --git a/apps/plugins/main_menu_config.c b/apps/plugins/main_menu_config.c
index 9f651094b1..a5488ed2c0 100644
--- a/apps/plugins/main_menu_config.c
+++ b/apps/plugins/main_menu_config.c
@@ -188,7 +188,7 @@ enum plugin_status plugin_start(const void* parameter)
{
cur_sel = rb->gui_synclist_get_sel_pos(&list);
action = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
- if (rb->gui_synclist_do_button(&list,&action,LIST_WRAP_UNLESS_HELD))
+ if (rb->gui_synclist_do_button(&list, &action))
continue;
switch (action)
diff --git a/apps/plugins/maze.c b/apps/plugins/maze.c
index 20d5c82495..8c951ebdcc 100644
--- a/apps/plugins/maze.c
+++ b/apps/plugins/maze.c
@@ -498,10 +498,8 @@ enum plugin_status plugin_start(const void* parameter)
struct maze maze;
(void)parameter;
-#ifdef HAVE_BACKLIGHT
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
/* Seed the RNG */
rb->srand(*rb->current_tick);
@@ -591,8 +589,7 @@ enum plugin_status plugin_start(const void* parameter)
#endif
}
/* Turn on backlight timeout (revert to settings) */
-#ifdef HAVE_BACKLIGHT
backlight_use_settings();
-#endif
+
return ((quit == 1) ? PLUGIN_OK : PLUGIN_USB_CONNECTED);
}
diff --git a/apps/plugins/mazezam.c b/apps/plugins/mazezam.c
index cd7b6e22a8..423b09288d 100644
--- a/apps/plugins/mazezam.c
+++ b/apps/plugins/mazezam.c
@@ -256,9 +256,7 @@ static void store_lcd_settings(void)
******************************************************************************/
static void restore_lcd_settings(void) {
/* Turn on backlight timeout (revert to settings) */
-#ifdef HAVE_BACKLIGHT
backlight_use_settings();
-#endif
/* Restore the old settings */
#if LCD_DEPTH > 1
@@ -272,10 +270,9 @@ static void restore_lcd_settings(void) {
* Adjust the LCD settings to suit MazezaM levels
******************************************************************************/
static void plugin_lcd_settings(void) {
-#ifdef HAVE_BACKLIGHT
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
+
/* Set the new settings */
#ifdef HAVE_LCD_COLOR
rb->lcd_set_background(MAZEZAM_BG_COLOR);
diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c
index e66b4df146..654a348959 100644
--- a/apps/plugins/mpegplayer/mpegplayer.c
+++ b/apps/plugins/mpegplayer/mpegplayer.c
@@ -1215,10 +1215,9 @@ static void osd_lcd_enable_hook(unsigned short id, void* param)
static void osdbacklight_hw_on_video_mode(bool video_on)
{
if (video_on) {
-#ifdef HAVE_BACKLIGHT
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
+
#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
rb->remove_event(LCD_EVENT_ACTIVATION, osd_lcd_enable_hook);
#endif
@@ -1226,10 +1225,8 @@ static void osdbacklight_hw_on_video_mode(bool video_on)
#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
rb->add_event(LCD_EVENT_ACTIVATION, osd_lcd_enable_hook);
#endif
-#ifdef HAVE_BACKLIGHT
/* Revert to user's backlight settings */
backlight_use_settings();
-#endif
}
}
diff --git a/apps/plugins/open_plugins.c b/apps/plugins/open_plugins.c
index 3a0c34d8d6..6deaf80f7d 100644
--- a/apps/plugins/open_plugins.c
+++ b/apps/plugins/open_plugins.c
@@ -87,6 +87,15 @@ static size_t pathbasename(const char *name, const char **nameptr)
*nameptr = q;
return r - q;
}
+static int op_entry_checksum(void)
+{
+ if (op_entry.checksum != open_plugin_csum +
+ (op_entry.lang_id <= OPEN_PLUGIN_LANG_INVALID ? 0 : LANG_LAST_INDEX_IN_ARRAY))
+ {
+ return 0;
+ }
+ return 1;
+}
static bool op_entry_read(int fd, int selected_item, off_t data_sz)
{
@@ -94,7 +103,7 @@ static bool op_entry_read(int fd, int selected_item, off_t data_sz)
op_entry.lang_id = -1;
return ((selected_item >= 0) &&
(rb->lseek(fd, selected_item * op_entry_sz, SEEK_SET) >= 0) &&
- (rb->read(fd, &op_entry, data_sz) == data_sz));
+ (rb->read(fd, &op_entry, data_sz) == data_sz) && op_entry_checksum() > 0);
}
static bool op_entry_read_name(int fd, int selected_item)
@@ -102,15 +111,6 @@ static bool op_entry_read_name(int fd, int selected_item)
return op_entry_read(fd, selected_item, op_name_sz);
}
-static int op_entry_checksum(void)
-{
- if (op_entry.checksum != open_plugin_csum)
- {
- return 0;
- }
- return 1;
-}
-
static int op_entry_read_opx(const char *path)
{
int ret = -1;
@@ -174,7 +174,8 @@ failure:
static void op_entry_set_checksum(void)
{
- op_entry.checksum = open_plugin_csum;
+ op_entry.checksum = open_plugin_csum +
+ (op_entry.lang_id <= OPEN_PLUGIN_LANG_INVALID ? 0 : LANG_LAST_INDEX_IN_ARRAY);
}
static void op_entry_set_name(void)
@@ -466,7 +467,7 @@ static void op_entry_remove_empty(void)
while (resave == false &&
rb->read(fd_dat, &op_entry, op_entry_sz) == op_entry_sz)
{
- if (op_entry.hash == 0)
+ if (op_entry.hash == 0 || !op_entry_checksum())
resave = true;
}
}
@@ -623,7 +624,6 @@ static void synclist_set(char* menu_id, int selection, int items, int sel_size)
rb->gui_synclist_set_icon_callback(&lists,NULL);
rb->gui_synclist_set_voice_callback(&lists, list_voice_cb);
rb->gui_synclist_set_nb_items(&lists,items);
- rb->gui_synclist_limit_scroll(&lists,true);
rb->gui_synclist_select_item(&lists, selection);
list_voice_cb(selection, menu_id);
}
@@ -682,7 +682,7 @@ static void edit_menu(int selection)
{
action = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
- if (rb->gui_synclist_do_button(&lists,&action,LIST_WRAP_UNLESS_HELD))
+ if (rb->gui_synclist_do_button(&lists, &action))
continue;
selected_item = rb->gui_synclist_get_sel_pos(&lists);
switch (action)
@@ -840,6 +840,12 @@ reopen_datfile:
}/* OP_EXT */
}
+ for (int i = items - 1; i > 0 && !exit; i--)
+ {
+ if (!op_entry_read(fd_dat, i, op_entry_sz))
+ items--;
+ }
+
if (items < 1 && !exit)
{
char* cur_filename = rb->plugin_get_current_filename();
@@ -865,7 +871,7 @@ reopen_datfile:
{
action = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
- if (rb->gui_synclist_do_button(&lists,&action,LIST_WRAP_UNLESS_HELD))
+ if (rb->gui_synclist_do_button(&lists, &action))
continue;
selection = rb->gui_synclist_get_sel_pos(&lists);
switch (action)
diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c
index ae84e14f7f..ef9e6b8a98 100644
--- a/apps/plugins/oscilloscope.c
+++ b/apps/plugins/oscilloscope.c
@@ -1939,10 +1939,9 @@ static void osc_cleanup(void)
rb->lcd_set_foreground(LCD_DEFAULT_FG);
rb->lcd_set_background(LCD_DEFAULT_BG);
#endif
-#ifdef HAVE_BACKLIGHT
+
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings();
-#endif
/* save settings if changed */
if (rb->memcmp(&osc, &osc_disk, sizeof(osc)))
@@ -1975,10 +1974,9 @@ static void osc_setup(void)
mixer_sampr = rb->mixer_get_frequency();
#endif
-#ifdef HAVE_BACKLIGHT
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
+
graphmode_setup();
}
diff --git a/apps/plugins/pacbox/pacbox.c b/apps/plugins/pacbox/pacbox.c
index 71c9751cad..9434aed743 100755
--- a/apps/plugins/pacbox/pacbox.c
+++ b/apps/plugins/pacbox/pacbox.c
@@ -809,8 +809,8 @@ enum plugin_status plugin_start(const void* parameter)
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(false);
#endif
-#ifdef HAVE_BACKLIGHT
+
backlight_use_settings();
-#endif
+
return PLUGIN_OK;
}
diff --git a/apps/plugins/pictureflow/pictureflow.c b/apps/plugins/pictureflow/pictureflow.c
index 2f075a7e61..7670ef01df 100644
--- a/apps/plugins/pictureflow/pictureflow.c
+++ b/apps/plugins/pictureflow/pictureflow.c
@@ -151,8 +151,11 @@ const struct button_mapping pf_context_buttons[] =
{PF_QUIT, BUTTON_POWER, BUTTON_NONE},
#elif (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
|| (CONFIG_KEYPAD == IPOD_3G_PAD) \
- || (CONFIG_KEYPAD == IPOD_4G_PAD) \
- || (CONFIG_KEYPAD == MPIO_HD300_PAD)
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+ {PF_QUIT, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU},
+ {PF_SORTING_NEXT, BUTTON_SELECT|BUTTON_MENU, BUTTON_NONE},
+ {PF_SORTING_PREV, BUTTON_SELECT|BUTTON_PLAY, BUTTON_NONE},
+#elif CONFIG_KEYPAD == MPIO_HD300_PAD
{PF_QUIT, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU},
#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
{PF_QUIT, BUTTON_RC_REC, BUTTON_NONE},
@@ -689,7 +692,7 @@ static void config_set_defaults(struct pf_config_t *cfg)
cfg->resize = true;
cfg->cache_version = CACHE_REBUILD;
cfg->show_album_name = (LCD_HEIGHT > 100)
- ? ALBUM_NAME_TOP : ALBUM_NAME_BOTTOM;
+ ? ALBUM_AND_ARTIST_BOTTOM : ALBUM_NAME_BOTTOM;
cfg->sort_albums_by = SORT_BY_ARTIST_AND_NAME;
cfg->year_sort_order = ASCENDING;
cfg->show_year = false;
@@ -963,6 +966,9 @@ const struct custom_format format_transposed = {
static const struct button_mapping* get_context_map(int context)
{
+#ifdef HAVE_LOCKED_ACTIONS
+ context &= ~CONTEXT_LOCKED;
+#endif
return pf_contexts[context & ~CONTEXT_PLUGIN];
}
@@ -2318,6 +2324,8 @@ aa_success:
configfile_save(CONFIG_FILE, config, CONFIG_NUM_ITEMS,
CONFIG_VERSION);
free_all_slide_prio(0);
+ if (pf_state == pf_idle)
+ rb->queue_post(&thread_q, EV_WAKEUP, 0);
}
if(verbose)/* direct interaction with user */
@@ -3098,7 +3106,7 @@ static void render_slide(struct slide_data *slide, const int alpha)
const pix_t *ptr = &src[column * bmp->height];
-#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
#define PIXELSTEP_Y 1
#define LCDADDR(x, y) (&buffer[BUFFER_HEIGHT*(x) + (y)])
#else
@@ -3227,6 +3235,12 @@ static bool sort_albums(int new_sorting, bool from_settings)
{
#ifdef USEGSLIB
grey_show(false);
+#if LCD_DEPTH > 1
+ rb->lcd_set_background(N_BRIGHT(0));
+ rb->lcd_set_foreground(N_BRIGHT(255));
+#endif
+ rb->lcd_clear_display();
+ rb->lcd_update();
#endif
rb->splash(HZ, sort_options[pf_cfg.sort_albums_by]);
#ifdef USEGSLIB
@@ -3479,16 +3493,29 @@ static void cleanup(void)
rb->cpu_boost(false);
#endif
end_pf_thread();
-#ifdef HAVE_BACKLIGHT
+
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings();
-#endif
#ifdef USEGSLIB
grey_release();
#endif
}
+static void interrupt_cover_in_animation(void);
+static void adjust_album_display_for_setting(int old_val, int new_val)
+{
+ if (old_val == new_val)
+ return;
+
+ reset_track_list();
+ recalc_offsets();
+ reset_slides();
+
+ if (pf_state == pf_show_tracks)
+ interrupt_cover_in_animation();
+}
+
/**
Shows the settings menu
*/
@@ -3544,11 +3571,10 @@ static int settings_menu(void)
selection=rb->do_menu(&settings_menu,&selection, NULL, false);
switch(selection) {
case 0:
+ old_val = pf_cfg.show_album_name;
rb->set_option(rb->str(LANG_SHOW_ALBUM_TITLE),
&pf_cfg.show_album_name, INT, album_name_options, 5, NULL);
- reset_track_list();
- recalc_offsets();
- reset_slides();
+ adjust_album_display_for_setting(old_val, pf_cfg.show_album_name);
break;
case 1:
rb->set_bool(rb->str(LANG_SHOW_YEAR_IN_ALBUM_TITLE), &pf_cfg.show_year);
@@ -3570,38 +3596,40 @@ static int settings_menu(void)
pf_cfg.year_sort_order = old_val;
break;
case 4:
+ old_val = pf_cfg.show_fps;
rb->set_bool(rb->str(LANG_DISPLAY_FPS), &pf_cfg.show_fps);
- reset_track_list();
+ if (old_val != pf_cfg.show_fps)
+ reset_track_list();
break;
case 5:
+ old_val = pf_cfg.slide_spacing;
rb->set_int(rb->str(LANG_SPACING), "", 1,
&pf_cfg.slide_spacing,
NULL, 1, 0, 100, NULL );
- recalc_offsets();
- reset_slides();
+ adjust_album_display_for_setting(old_val, pf_cfg.slide_spacing);
break;
case 6:
+ old_val = pf_cfg.center_margin;
rb->set_int(rb->str(LANG_CENTRE_MARGIN), "", 1,
&pf_cfg.center_margin,
NULL, 1, 0, 80, NULL );
- recalc_offsets();
- reset_slides();
+ adjust_album_display_for_setting(old_val, pf_cfg.center_margin);
break;
case 7:
+ old_val = pf_cfg.num_slides;
rb->set_int(rb->str(LANG_NUMBER_OF_SLIDES), "", 1,
&pf_cfg.num_slides, NULL, 1, 1, MAX_SLIDES_COUNT, NULL );
- recalc_offsets();
- reset_slides();
+ adjust_album_display_for_setting(old_val, pf_cfg.num_slides);
break;
case 8:
+ old_val = pf_cfg.zoom;
rb->set_int(rb->str(LANG_ZOOM), "", 1, &pf_cfg.zoom,
NULL, 1, 10, 300, NULL );
- recalc_offsets();
- reset_slides();
+ adjust_album_display_for_setting(old_val, pf_cfg.zoom);
break;
case 9:
@@ -3892,7 +3920,10 @@ static void show_track_list(void)
{
mylcd_clear_display();
if ( center_slide.slide_index != pf_tracks.cur_idx ) {
- show_track_list_loading();
+#ifdef HAVE_TC_RAMCACHE
+ if (!rb->tagcache_is_in_ram())
+#endif
+ show_track_list_loading();
create_track_index(center_slide.slide_index);
if (pf_tracks.count == 0)
{
@@ -4016,7 +4047,10 @@ static bool track_list_ready(void)
{
if (pf_state != pf_show_tracks)
{
- rb->splash(0, ID2P(LANG_WAIT));
+#ifdef HAVE_TC_RAMCACHE
+ if (!rb->tagcache_is_in_ram())
+#endif
+ rb->splash(0, ID2P(LANG_WAIT));
create_track_index(center_slide.slide_index);
if (pf_tracks.count == 0)
{
@@ -4214,7 +4248,7 @@ static void set_initial_slide(const char* selected_file)
pf_cfg.last_album);
else
{
- struct mp3entry id3;
+ static struct mp3entry id3;
#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
if (rb->tagcache_fill_tags(&id3, selected_file))
set_current_slide(id3_get_index(&id3));
@@ -4268,14 +4302,11 @@ static int pictureflow_main(const char* selected_file)
config_set_defaults(&pf_cfg);
configfile_load(CONFIG_FILE, config, CONFIG_NUM_ITEMS, CONFIG_VERSION);
- if(pf_cfg.auto_wps == 0)
- draw_splashscreen(pf_idx.buf, pf_idx.buf_sz);
- if(pf_cfg.backlight_mode == 0) {
- /* Turn off backlight timeout */
+
#ifdef HAVE_BACKLIGHT
+ if(pf_cfg.backlight_mode == 0)
backlight_ignore_timeout();
#endif
- }
rb->mutex_init(&buf_ctx_mutex);
@@ -4451,7 +4482,8 @@ static int pictureflow_main(const char* selected_file)
rb->snprintf(fpstxt, sizeof(fpstxt), "%d %%", progress_pct);
}
- if (pf_cfg.show_album_name == ALBUM_NAME_TOP)
+ if (pf_cfg.show_album_name == ALBUM_NAME_TOP ||
+ pf_cfg.show_album_name == ALBUM_AND_ARTIST_TOP)
fpstxt_y = LCD_HEIGHT -
rb->screens[SCREEN_MAIN]->getcharheight();
else
@@ -4569,15 +4601,15 @@ static int pictureflow_main(const char* selected_file)
break;
#if PF_PLAYBACK_CAPABLE
case PF_CONTEXT:
- if (pf_cfg.auto_wps != 0 &&
- (pf_state == pf_idle || pf_state == pf_scrolling ||
- pf_state == pf_show_tracks || pf_state == pf_cover_out)) {
+ if (pf_state == pf_idle || pf_state == pf_scrolling ||
+ pf_state == pf_show_tracks || pf_state == pf_cover_out) {
if ( pf_state == pf_scrolling)
{
set_current_slide(target);
pf_state = pf_idle;
- } else if (pf_state == pf_cover_out)
+ }
+ else if (pf_state == pf_cover_out)
interrupt_cover_out_animation();
show_current_playlist_menu();
diff --git a/apps/plugins/plasma.c b/apps/plugins/plasma.c
index f944d3d775..8da53874e1 100644
--- a/apps/plugins/plasma.c
+++ b/apps/plugins/plasma.c
@@ -140,10 +140,10 @@ static void cleanup(void)
#ifndef HAVE_LCD_COLOR
grey_release();
#endif
-#ifdef HAVE_BACKLIGHT
+
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings();
-#endif
+
#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
rb->lcd_set_mode(LCD_MODE_RGB565);
#endif
@@ -321,10 +321,10 @@ enum plugin_status plugin_start(const void* parameter)
#if LCD_DEPTH > 1
rb->lcd_set_backdrop(NULL);
#endif
-#ifdef HAVE_BACKLIGHT
+
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
+
#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
rb->lcd_set_mode(LCD_MODE_PAL256);
#endif
diff --git a/apps/plugins/pong.c b/apps/plugins/pong.c
index b49fec2459..17e6e6ed73 100644
--- a/apps/plugins/pong.c
+++ b/apps/plugins/pong.c
@@ -750,10 +750,9 @@ enum plugin_status plugin_start(const void* parameter)
this to avoid the compiler warning about it */
(void)parameter;
-#ifdef HAVE_BACKLIGHT
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
+
/* Clear screen */
rb->lcd_clear_display();
@@ -792,9 +791,9 @@ enum plugin_status plugin_start(const void* parameter)
rb->lcd_clear_display();
}
}
-#ifdef HAVE_BACKLIGHT
+
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings();
-#endif
+
return (game == 0) ? PLUGIN_OK : PLUGIN_USB_CONNECTED;
}
diff --git a/apps/plugins/properties.c b/apps/plugins/properties.c
index c4378a0356..73ad841c0c 100644
--- a/apps/plugins/properties.c
+++ b/apps/plugins/properties.c
@@ -24,6 +24,14 @@
#define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
#endif
+struct dir_stats {
+ char dirname[MAX_PATH];
+ int len;
+ unsigned int dir_count;
+ unsigned int file_count;
+ unsigned long long byte_count;
+};
+
enum props_types {
PROPS_FILE = 0,
PROPS_ID3,
@@ -34,18 +42,17 @@ static int props_type = PROPS_FILE;
static struct mp3entry id3;
-char str_filename[MAX_PATH];
-char str_dirname[MAX_PATH];
-char str_size[64];
-char str_dircount[64];
-char str_filecount[64];
-char str_date[64];
-char str_time[64];
+static char str_filename[MAX_PATH];
+static char str_dirname[MAX_PATH];
+static char str_size[64];
+static char str_dircount[64];
+static char str_filecount[64];
+static char str_date[64];
+static char str_time[64];
-unsigned nseconds;
-unsigned long nsize;
-int32_t size_unit;
-struct tm tm;
+static unsigned long nsize;
+static int32_t size_unit;
+static struct tm tm;
#define NUM_FILE_PROPERTIES 5
static const unsigned char* const props_file[] =
@@ -128,15 +135,7 @@ static bool file_properties(const char* selected_file)
return found;
}
-typedef struct {
- char dirname[MAX_PATH];
- int len;
- unsigned int dc;
- unsigned int fc;
- unsigned long long bc;
-} DPS;
-
-static bool _dir_properties(DPS *dps)
+static bool _dir_properties(struct dir_stats *stats)
{
/* recursively scan directories in search of files
and informs the user of the progress */
@@ -147,11 +146,11 @@ static bool _dir_properties(DPS *dps)
struct dirent* entry;
result = true;
- dirlen = rb->strlen(dps->dirname);
- dir = rb->opendir(dps->dirname);
+ dirlen = rb->strlen(stats->dirname);
+ dir = rb->opendir(stats->dirname);
if (!dir)
{
- rb->splashf(HZ*2, "%s", dps->dirname);
+ rb->splashf(HZ*2, "%s", stats->dirname);
return false; /* open error */
}
@@ -160,7 +159,7 @@ static bool _dir_properties(DPS *dps)
{
struct dirinfo info = rb->dir_get_info(dir, entry);
/* append name to current directory */
- rb->snprintf(dps->dirname+dirlen, dps->len-dirlen, "/%s",
+ rb->snprintf(stats->dirname+dirlen, stats->len-dirlen, "/%s",
entry->d_name);
if (info.attribute & ATTR_DIRECTORY)
@@ -169,29 +168,30 @@ static bool _dir_properties(DPS *dps)
!rb->strcmp((char *)entry->d_name, ".."))
continue; /* skip these */
- dps->dc++; /* new directory */
+ stats->dir_count++; /* new directory */
if (*rb->current_tick - lasttick > (HZ/8))
{
unsigned log;
lasttick = *rb->current_tick;
rb->lcd_clear_display();
rb->lcd_puts(0,0,"SCANNING...");
- rb->lcd_puts(0,1,dps->dirname);
- rb->lcd_putsf(0,2,"Directories: %d", dps->dc);
- rb->lcd_putsf(0,3,"Files: %d", dps->fc);
- log = human_size_log(dps->bc);
- rb->lcd_putsf(0,4,"Size: %lu %cB", (unsigned long)(dps->bc >> (10*log)),
+ rb->lcd_puts(0,1,stats->dirname);
+ rb->lcd_putsf(0,2,"Directories: %d", stats->dir_count);
+ rb->lcd_putsf(0,3,"Files: %d", stats->file_count);
+ log = human_size_log(stats->byte_count);
+ rb->lcd_putsf(0,4,"Size: %lu %s",
+ (unsigned long)(stats->byte_count >> (10*log)),
rb->str(units[log]));
rb->lcd_update();
}
/* recursion */
- result = _dir_properties(dps);
+ result = _dir_properties(stats);
}
else
{
- dps->fc++; /* new file */
- dps->bc += info.size;
+ stats->file_count++; /* new file */
+ stats->byte_count += info.size;
}
if(ACTION_STD_CANCEL == rb->get_action(CONTEXT_STD,TIMEOUT_NOBLOCK))
result = false;
@@ -201,17 +201,17 @@ static bool _dir_properties(DPS *dps)
return result;
}
-static bool dir_properties(const char* selected_file, DPS *dps)
+static bool dir_properties(const char* selected_file, struct dir_stats *stats)
{
unsigned log;
- rb->strlcpy(dps->dirname, selected_file, MAX_PATH);
+ rb->strlcpy(stats->dirname, selected_file, MAX_PATH);
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(true);
#endif
- if (!_dir_properties(dps))
+ if (!_dir_properties(stats))
{
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(false);
@@ -224,10 +224,10 @@ static bool dir_properties(const char* selected_file, DPS *dps)
#endif
rb->strlcpy(str_dirname, selected_file, MAX_PATH);
- rb->snprintf(str_dircount, sizeof str_dircount, "%d", dps->dc);
- rb->snprintf(str_filecount, sizeof str_filecount, "%d", dps->fc);
- log = human_size_log(dps->bc);
- nsize = (long) (dps->bc >> (log*10));
+ rb->snprintf(str_dircount, sizeof str_dircount, "%d", stats->dir_count);
+ rb->snprintf(str_filecount, sizeof str_filecount, "%d", stats->file_count);
+ log = human_size_log(stats->byte_count);
+ nsize = (long) (stats->byte_count >> (log*10));
size_unit = units[log];
rb->snprintf(str_size, sizeof str_size, "%ld %s", nsize, rb->str(size_unit));
return true;
@@ -255,7 +255,7 @@ static const char * get_props(int selected_item, void* data,
static int speak_property_selection(int selected_item, void *data)
{
- DPS *dps = data;
+ struct dir_stats *stats = data;
int32_t id = P2ID((props_type == PROPS_DIR ? props_dir : props_file)[selected_item]);
rb->talk_id(id, false);
switch (id)
@@ -295,10 +295,10 @@ static int speak_property_selection(int selected_item, void *data)
rb->talk_time(&tm, true);
break;
case LANG_PROPERTIES_SUBDIRS:
- rb->talk_number(dps->dc, true);
+ rb->talk_number(stats->dir_count, true);
break;
case LANG_PROPERTIES_FILES:
- rb->talk_number(dps->fc, true);
+ rb->talk_number(stats->file_count, true);
break;
default:
rb->talk_spell(props_file[selected_item + 1], true);
@@ -307,34 +307,49 @@ static int speak_property_selection(int selected_item, void *data)
return 0;
}
-enum plugin_status plugin_start(const void* parameter)
+static int browse_file_or_dir(struct dir_stats *stats)
{
struct gui_synclist properties_lists;
int button;
- bool quit = false, usb = false;
- const char *file = parameter;
- if(!parameter || (file[0] != '/')) return PLUGIN_ERROR;
-
-#ifdef HAVE_TOUCHSCREEN
- rb->touchscreen_set_mode(rb->global_settings->touch_mode);
-#endif
- static DPS dps = {
- .len = MAX_PATH,
- .dc = 0,
- .fc = 0,
- .bc = 0,
- };
+ rb->gui_synclist_init(&properties_lists, &get_props, stats, false, 2, NULL);
+ rb->gui_synclist_set_title(&properties_lists,
+ rb->str(props_type == PROPS_DIR ?
+ LANG_PROPERTIES_DIRECTORY_PROPERTIES :
+ LANG_PROPERTIES_FILE_PROPERTIES),
+ NOICON);
+ rb->gui_synclist_set_icon_callback(&properties_lists, NULL);
+ if (rb->global_settings->talk_menu)
+ rb->gui_synclist_set_voice_callback(&properties_lists, speak_property_selection);
+ rb->gui_synclist_set_nb_items(&properties_lists,
+ 2 * (props_type == PROPS_FILE ? NUM_FILE_PROPERTIES :
+ NUM_DIR_PROPERTIES));
+ rb->gui_synclist_select_item(&properties_lists, 0);
+ rb->gui_synclist_draw(&properties_lists);
+ rb->gui_synclist_speak_item(&properties_lists);
+
+ while(true)
+ {
+ button = rb->get_action(CONTEXT_LIST, HZ);
+ /* HZ so the status bar redraws corectly */
+ if (rb->gui_synclist_do_button(&properties_lists,&button))
+ continue;
+ switch(button)
+ {
+ case ACTION_STD_CANCEL:
+ return false;
+ default:
+ if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
+ return true;
+ break;
+ }
+ }
+}
- /* determine if it's a file or a directory */
- bool found = false;
+static bool determine_file_or_dir(void)
+{
DIR* dir;
struct dirent* entry;
- char* ptr = rb->strrchr(file, '/') + 1;
- int dirlen = (ptr - file);
-
- rb->strlcpy(str_dirname, file, dirlen + 1);
- rb->snprintf(str_filename, sizeof str_filename, "%s", file+dirlen);
dir = rb->opendir(str_dirname);
if (dir)
@@ -345,15 +360,39 @@ enum plugin_status plugin_start(const void* parameter)
{
struct dirinfo info = rb->dir_get_info(dir, entry);
props_type = info.attribute & ATTR_DIRECTORY ? PROPS_DIR : PROPS_FILE;
- found = true;
- break;
+ rb->closedir(dir);
+ return true;
}
}
rb->closedir(dir);
}
- /* now we know if it's a file or a dir or maybe something failed */
+ return false;
+}
+
+enum plugin_status plugin_start(const void* parameter)
+{
+ static struct dir_stats stats =
+ {
+ .len = MAX_PATH,
+ .dir_count = 0,
+ .file_count = 0,
+ .byte_count = 0,
+ };
+
+ const char *file = parameter;
+ if(!parameter || (file[0] != '/')) return PLUGIN_ERROR;
+
+#ifdef HAVE_TOUCHSCREEN
+ rb->touchscreen_set_mode(rb->global_settings->touch_mode);
+#endif
+
+ const char* file_name = rb->strrchr(file, '/') + 1;
+ int dirlen = (file_name - file);
+
+ rb->strlcpy(str_dirname, file, dirlen + 1);
+ rb->snprintf(str_filename, sizeof str_filename, "%s", file+dirlen);
- if(!found)
+ if(!determine_file_or_dir())
{
/* weird: we couldn't find the entry. This Should Never Happen (TM) */
rb->splashf(0, "File/Dir not found: %s", file);
@@ -362,7 +401,7 @@ enum plugin_status plugin_start(const void* parameter)
}
/* get the info depending on its_a_dir */
- if(!(props_type == PROPS_DIR ? dir_properties(file, &dps) : file_properties(file)))
+ if(!(props_type == PROPS_DIR ? dir_properties(file, &stats) : file_properties(file)))
{
/* something went wrong (to do: tell user what it was (nesting,...) */
rb->splash(0, ID2P(LANG_PROPERTIES_FAIL));
@@ -373,48 +412,8 @@ enum plugin_status plugin_start(const void* parameter)
FOR_NB_SCREENS(i)
rb->viewportmanager_theme_enable(i, true, NULL);
- if (props_type == PROPS_ID3)
- usb = rb->browse_id3(&id3, 0, 0);
- else
- {
- rb->gui_synclist_init(&properties_lists, &get_props, &dps, false, 2, NULL);
- rb->gui_synclist_set_title(&properties_lists,
- rb->str(props_type == PROPS_DIR ?
- LANG_PROPERTIES_DIRECTORY_PROPERTIES :
- LANG_PROPERTIES_FILE_PROPERTIES),
- NOICON);
- rb->gui_synclist_set_icon_callback(&properties_lists, NULL);
- if (rb->global_settings->talk_menu)
- rb->gui_synclist_set_voice_callback(&properties_lists, speak_property_selection);
- rb->gui_synclist_set_nb_items(&properties_lists,
- 2 * (props_type == PROPS_FILE ? NUM_FILE_PROPERTIES :
- NUM_DIR_PROPERTIES));
- rb->gui_synclist_limit_scroll(&properties_lists, true);
- rb->gui_synclist_select_item(&properties_lists, 0);
- rb->gui_synclist_draw(&properties_lists);
- rb->gui_synclist_speak_item(&properties_lists);
-
- while(!quit)
- {
- button = rb->get_action(CONTEXT_LIST, HZ);
- /* HZ so the status bar redraws corectly */
- if (rb->gui_synclist_do_button(&properties_lists,&button,LIST_WRAP_UNLESS_HELD))
- continue;
- switch(button)
- {
- case ACTION_STD_CANCEL:
- quit = true;
- break;
- default:
- if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
- {
- quit = true;
- usb = true;
- }
- break;
- }
- }
- }
+ bool usb = props_type == PROPS_ID3 ? rb->browse_id3(&id3, 0, 0) :
+ browse_file_or_dir(&stats);
FOR_NB_SCREENS(i)
rb->viewportmanager_theme_undo(i, false);
diff --git a/apps/plugins/puzzles/rockbox.c b/apps/plugins/puzzles/rockbox.c
index 6e34adb1db..e175429075 100644
--- a/apps/plugins/puzzles/rockbox.c
+++ b/apps/plugins/puzzles/rockbox.c
@@ -1465,7 +1465,7 @@ static void rb_blitter_free(void *handle, blitter *bl)
static void rb_blitter_save(void *handle, blitter *bl, int x, int y)
{
/* no viewport offset */
-#if defined(LCD_STRIDEFORMAT) && (LCD_STRIDEFORMAT == VERTICAL_STRIDE)
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
#error no vertical stride
#else
if(bl && bl->bmp.data)
@@ -2450,7 +2450,6 @@ static int list_choose(const char *list_str, const char *title, int sel)
rb->gui_synclist_init(&list, &config_choices_formatter, (void*)list_str, false, 1, NULL);
rb->gui_synclist_set_icon_callback(&list, NULL);
rb->gui_synclist_set_nb_items(&list, n);
- rb->gui_synclist_limit_scroll(&list, false);
rb->gui_synclist_select_item(&list, sel);
@@ -2459,7 +2458,7 @@ static int list_choose(const char *list_str, const char *title, int sel)
{
rb->gui_synclist_draw(&list);
int button = rb->get_action(CONTEXT_LIST, TIMEOUT_BLOCK);
- if(rb->gui_synclist_do_button(&list, &button, LIST_WRAP_UNLESS_HELD))
+ if(rb->gui_synclist_do_button(&list, &button))
continue;
switch(button)
{
@@ -2664,7 +2663,6 @@ static bool config_menu(void)
rb->gui_synclist_init(&list, &config_formatter, config, false, 1, NULL);
rb->gui_synclist_set_icon_callback(&list, NULL);
rb->gui_synclist_set_nb_items(&list, n);
- rb->gui_synclist_limit_scroll(&list, false);
rb->gui_synclist_select_item(&list, 0);
@@ -2674,7 +2672,7 @@ static bool config_menu(void)
{
rb->gui_synclist_draw(&list);
int button = rb->get_action(CONTEXT_LIST, TIMEOUT_BLOCK);
- if(rb->gui_synclist_do_button(&list, &button, LIST_WRAP_UNLESS_HELD))
+ if(rb->gui_synclist_do_button(&list, &button))
continue;
switch(button)
{
@@ -2750,7 +2748,6 @@ static int do_preset_menu(struct preset_menu *menu, char *title, int selected)
rb->gui_synclist_init(&list, &preset_formatter, menu, false, 1, NULL);
rb->gui_synclist_set_icon_callback(&list, NULL);
rb->gui_synclist_set_nb_items(&list, menu->n_entries);
- rb->gui_synclist_limit_scroll(&list, false);
rb->gui_synclist_select_item(&list, selected);
@@ -2760,7 +2757,7 @@ static int do_preset_menu(struct preset_menu *menu, char *title, int selected)
{
rb->gui_synclist_draw(&list);
int button = rb->get_action(CONTEXT_LIST, TIMEOUT_BLOCK);
- if(rb->gui_synclist_do_button(&list, &button, LIST_WRAP_UNLESS_HELD))
+ if(rb->gui_synclist_do_button(&list, &button))
continue;
switch(button)
{
@@ -3393,9 +3390,7 @@ static void shutdown_tlsf(void)
static void exit_handler(void)
{
-#ifdef HAVE_SW_POWEROFF
sw_poweroff_restore();
-#endif
unload_fonts();
shutdown_tlsf();
@@ -3655,9 +3650,7 @@ static void puzzles_main(void)
{
rb_atexit(exit_handler);
-#ifdef HAVE_SW_POWEROFF
sw_poweroff_disable();
-#endif
init_default_settings();
init_fonttab();
diff --git a/apps/plugins/random_folder_advance_config.c b/apps/plugins/random_folder_advance_config.c
index 2c9fb411ac..5688ff93d3 100644
--- a/apps/plugins/random_folder_advance_config.c
+++ b/apps/plugins/random_folder_advance_config.c
@@ -311,14 +311,13 @@ static int edit_list(void)
rb->gui_synclist_init(&lists,list_get_name_cb,0, false, 1, NULL);
rb->gui_synclist_set_icon_callback(&lists,NULL);
rb->gui_synclist_set_nb_items(&lists,list->count);
- rb->gui_synclist_limit_scroll(&lists,true);
rb->gui_synclist_select_item(&lists, 0);
while (!exit)
{
rb->gui_synclist_draw(&lists);
button = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
- if (rb->gui_synclist_do_button(&lists,&button,LIST_WRAP_UNLESS_HELD))
+ if (rb->gui_synclist_do_button(&lists, &button))
continue;
selection = rb->gui_synclist_get_sel_pos(&lists);
switch (button)
diff --git a/apps/plugins/rb_info.c b/apps/plugins/rb_info.c
index e0ec117dfb..f123a623d2 100644
--- a/apps/plugins/rb_info.c
+++ b/apps/plugins/rb_info.c
@@ -428,7 +428,6 @@ int menu_action_cb(int *action, int selected_item, bool* exit, struct gui_syncli
if (cur->menuid == MENU_ID(M_TESTPUT))
{
- //rb->gui_list_screen_scroll_out_of_view(true);
synclist_set(cur->menuid, 0, cur->items, 1);
#if LCD_DEPTH > 1
/* If line sep is set to automatic then outline cells */
@@ -473,7 +472,6 @@ int menu_action_cb(int *action, int selected_item, bool* exit, struct gui_syncli
{
if (lists->data == MENU_ID(M_TESTPUT))
{
- //rb->gui_list_screen_scroll_out_of_view(false);
//lists->callback_draw_item = NULL;
printcell_enable(lists, false, false);
}
@@ -516,7 +514,6 @@ static void synclist_set(char* menu_id, int selected_item, int items, int sel_si
rb->gui_synclist_set_icon_callback(&lists,NULL);
rb->gui_synclist_set_voice_callback(&lists, list_voice_cb);
rb->gui_synclist_set_nb_items(&lists,items);
- rb->gui_synclist_limit_scroll(&lists,true);
rb->gui_synclist_select_item(&lists, selected_item);
}
@@ -560,7 +557,7 @@ enum plugin_status plugin_start(const void* parameter)
else
redraw = true;
ret = menu_action_cb(&action, selected_item, &exit, &lists);
- if (rb->gui_synclist_do_button(&lists,&action,LIST_WRAP_UNLESS_HELD))
+ if (rb->gui_synclist_do_button(&lists, &action))
continue;
selected_item = rb->gui_synclist_get_sel_pos(&lists);
}
diff --git a/apps/plugins/resistor.c b/apps/plugins/resistor.c
index d32ac3fad9..4461dc0dea 100644
--- a/apps/plugins/resistor.c
+++ b/apps/plugins/resistor.c
@@ -574,9 +574,8 @@ static void display_helpfile(void)
static void led_resistance_calc(void)
{
-#ifdef HAVE_BACKLIGHT
backlight_ignore_timeout();
-#endif
+
int voltage_menu_selection, button_press, j, k, l, foreward_current = 0;
int fwd_current_selection = 0;
bool quit = false;
@@ -769,9 +768,8 @@ static void led_resistance_calc(void)
default:
quit = true;
-#ifdef HAVE_BACKLIGHT
backlight_use_settings();
-#endif
+
break;
}
}
@@ -784,9 +782,8 @@ static void led_resistance_calc(void)
static void resistance_to_color(void)
{
-#ifdef HAVE_BACKLIGHT
backlight_ignore_timeout();
-#endif
+
int menu_selection;
int menu_selection_tol;
int button_press;
@@ -910,9 +907,9 @@ static void resistance_to_color(void)
break;
default:
quit = true;
-#ifdef HAVE_BACKLIGHT
+
backlight_use_settings();
-#endif
+
break;
}
}
@@ -924,9 +921,8 @@ static void resistance_to_color(void)
static void color_to_resistance(void)
{
-#ifdef HAVE_BACKLIGHT
backlight_ignore_timeout();
-#endif
+
bool quit = false;
int button_input = 0;
@@ -995,9 +991,7 @@ static void color_to_resistance(void)
case PLA_SELECT:
default:
quit = true;
-#ifdef HAVE_BACKLIGHT
backlight_use_settings();
-#endif
break;
}
}
diff --git a/apps/plugins/rockblox.c b/apps/plugins/rockblox.c
index 927710b37b..cc719e5067 100644
--- a/apps/plugins/rockblox.c
+++ b/apps/plugins/rockblox.c
@@ -1498,16 +1498,13 @@ static int rockblox_loop (void)
#ifdef HAS_BUTTON_HOLD
if (rb->button_hold ()) {
/* Turn on backlight timeout (revert to settings) */
-#ifdef HAVE_BACKLIGHT
backlight_use_settings();
-#endif
rb->splash(0, "Paused");
while (rb->button_hold ())
rb->sleep(HZ/10);
-#ifdef HAVE_BACKLIGHT
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
+
/* get rid of the splash text */
rb->lcd_bitmap (rockblox_background, 0, 0, LCD_WIDTH, LCD_HEIGHT);
show_details ();
@@ -1677,10 +1674,9 @@ enum plugin_status plugin_start (const void *parameter)
rb->lcd_setfont (FONT_SYSFIXED);
-#ifdef HAVE_BACKLIGHT
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
+
load_game();
resume_file = resume;
@@ -1728,9 +1724,8 @@ enum plugin_status plugin_start (const void *parameter)
/* Save user's HighScore */
highscore_save(SCORE_FILE, highscores, NUM_SCORES);
-#ifdef HAVE_BACKLIGNT
+
backlight_use_settings();
-#endif
return PLUGIN_OK;
}
diff --git a/apps/plugins/rockboy/menu.c b/apps/plugins/rockboy/menu.c
index 6fafdc11a6..caa8d499cb 100644
--- a/apps/plugins/rockboy/menu.c
+++ b/apps/plugins/rockboy/menu.c
@@ -83,9 +83,8 @@ int do_user_menu(void) {
rb->lcd_set_mode(LCD_MODE_RGB565);
#endif
-#ifdef HAVE_BACKLIGHT
backlight_use_settings();
-#endif
+
/* Clean out the button Queue */
while (rb->button_get(false) != BUTTON_NONE)
rb->yield();
@@ -139,10 +138,9 @@ int do_user_menu(void) {
rb->lcd_set_mode(LCD_MODE_PAL256);
#endif
-#ifdef HAVE_BACKLIGHT
/* ignore backlight time out */
backlight_ignore_timeout();
-#endif
+
return ret;
}
diff --git a/apps/plugins/rockboy/rockboy.c b/apps/plugins/rockboy/rockboy.c
index 2c5c6e4dbf..2d0c349507 100644
--- a/apps/plugins/rockboy/rockboy.c
+++ b/apps/plugins/rockboy/rockboy.c
@@ -602,10 +602,9 @@ enum plugin_status plugin_start(const void* parameter)
rb->lcd_set_mode(LCD_MODE_PAL256);
#endif
-#ifdef HAVE_BACKLIGHT
/* ignore backlight time out */
backlight_ignore_timeout();
-#endif
+
gnuboy_main(parameter);
#ifdef HAVE_WHEEL_POSITION
@@ -616,9 +615,7 @@ enum plugin_status plugin_start(const void* parameter)
rb->lcd_set_mode(LCD_MODE_RGB565);
#endif
-#ifdef HAVE_BACKLIGHT
backlight_use_settings();
-#endif
if(!rb->audio_status())
rockboy_pcm_close();
diff --git a/apps/plugins/rocklife.c b/apps/plugins/rocklife.c
index 99297abd0f..bed947cc71 100644
--- a/apps/plugins/rocklife.c
+++ b/apps/plugins/rocklife.c
@@ -474,9 +474,8 @@ enum plugin_status plugin_start(const void* parameter)
char *ptemp;
(void)(parameter);
-#ifdef HAVE_BACKLIGHT
backlight_ignore_timeout();
-#endif
+
#if LCD_DEPTH > 1
rb->lcd_set_backdrop(NULL);
#ifdef HAVE_LCD_COLOR
@@ -580,8 +579,7 @@ enum plugin_status plugin_start(const void* parameter)
rb->yield();
}
-#ifdef HAVE_BACKLIGHT
backlight_use_settings();
-#endif
+
return usb? PLUGIN_USB_CONNECTED: PLUGIN_OK;
}
diff --git a/apps/plugins/sdl/main.c b/apps/plugins/sdl/main.c
index 6efb072faf..7220c7cfd9 100644
--- a/apps/plugins/sdl/main.c
+++ b/apps/plugins/sdl/main.c
@@ -64,9 +64,8 @@ void cleanup(void)
if(audiobuf)
memset(audiobuf, 0, 4); /* clear */
-#ifdef HAVE_BACKLIGHT
backlight_use_settings();
-#endif
+
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(false);
#endif
@@ -219,9 +218,9 @@ enum plugin_status plugin_start(const void *param)
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(true);
#endif
-#ifdef HAVE_BACKLIGHT
+
backlight_ignore_timeout();
-#endif
+
/* set the real exit handler */
#undef rb_atexit
rb_atexit(cleanup);
diff --git a/apps/plugins/shopper.c b/apps/plugins/shopper.c
index 7129291c10..25a484a31e 100644
--- a/apps/plugins/shopper.c
+++ b/apps/plugins/shopper.c
@@ -304,7 +304,6 @@ enum plugin_status plugin_start(const void* parameter)
/* now dump it in the list */
rb->gui_synclist_init(&lists,list_get_name_cb,0, false, 1, NULL);
rb->gui_synclist_set_icon_callback(&lists, list_get_icon_cb);
- rb->gui_synclist_limit_scroll(&lists,true);
create_view(&lists);
rb->gui_synclist_set_nb_items(&lists,view_item_count);
rb->gui_synclist_select_item(&lists, 0);
@@ -316,7 +315,7 @@ enum plugin_status plugin_start(const void* parameter)
rb->gui_synclist_draw(&lists);
cur_sel = rb->gui_synclist_get_sel_pos(&lists);
button = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
- if (rb->gui_synclist_do_button(&lists,&button,LIST_WRAP_UNLESS_HELD))
+ if (rb->gui_synclist_do_button(&lists, &button))
continue;
switch (button)
{
diff --git a/apps/plugins/shortcuts/shortcuts_view.c b/apps/plugins/shortcuts/shortcuts_view.c
index f4c4b58bc1..2a7970bebe 100644
--- a/apps/plugins/shortcuts/shortcuts_view.c
+++ b/apps/plugins/shortcuts/shortcuts_view.c
@@ -59,13 +59,8 @@ enum sc_list_action_type draw_sc_list(struct gui_synclist *gui_sc)
/* user input */
button = rb->get_action(CONTEXT_LIST, HZ);
/* HZ so the status bar redraws corectly */
- if (rb->gui_synclist_do_button(gui_sc, &button,
- LIST_WRAP_UNLESS_HELD)) {
- /* automatic handling of user input.
- * _UNLESS_HELD can be _ON or _OFF also
- * selection changed, so redraw */
+ if (rb->gui_synclist_do_button(gui_sc, &button))
continue;
- }
switch (button) { /* process the user input */
case ACTION_STD_OK:
return SCLA_SELECT;
@@ -115,7 +110,6 @@ int list_sc(void)
rb->gui_synclist_set_title(&gui_sc,
(user_file?"Shortcuts (sealed)":"Shortcuts (editable)"), NOICON);
rb->gui_synclist_set_nb_items(&gui_sc, sc_file.entry_cnt);
- rb->gui_synclist_limit_scroll(&gui_sc, false);
rb->gui_synclist_select_item(&gui_sc, 0);
/* Draw the prepared widget to the LCD now */
diff --git a/apps/plugins/spacerocks.c b/apps/plugins/spacerocks.c
index 8203fad612..85beccb1c2 100644
--- a/apps/plugins/spacerocks.c
+++ b/apps/plugins/spacerocks.c
@@ -259,8 +259,8 @@
#define AST_QUIT BUTTON_POWER
#define AST_THRUST BUTTON_UP
#define AST_HYPERSPACE BUTTON_DOWN
-#define AST_LEFT BUTTON_LEFT
-#define AST_RIGHT BUTTON_RIGHT
+#define AST_LEFT BUTTON_SCROLL_BACK
+#define AST_RIGHT BUTTON_SCROLL_FWD
#define AST_FIRE BUTTON_SELECT
#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD)
@@ -2128,10 +2128,10 @@ enum plugin_status plugin_start(const void* parameter)
#endif
/* universal font */
rb->lcd_setfont(FONT_SYSFIXED);
-#ifdef HAVE_BACKLIGHT
+
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
+
highscore_load(SCORE_FILE, highscores, NUM_SCORES);
rb->srand(*rb->current_tick);
@@ -2143,10 +2143,9 @@ enum plugin_status plugin_start(const void* parameter)
rb->lcd_setfont(FONT_UI);
highscore_save(SCORE_FILE, highscores, NUM_SCORES);
-#ifdef HAVE_BACKLIGHT
+
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings();
-#endif
return ret;
}
diff --git a/apps/plugins/speedread.c b/apps/plugins/speedread.c
index 42634fb536..55d8fd58e5 100644
--- a/apps/plugins/speedread.c
+++ b/apps/plugins/speedread.c
@@ -141,9 +141,9 @@ static void cleanup(void)
{
if(custom_font != FONT_UI)
rb->font_unload(custom_font);
-#ifdef HAVE_BACKLIGHT
+
backlight_use_settings();
-#endif
+
}
/* returns height of drawn area */
@@ -302,9 +302,8 @@ static void begin_anim(void)
static void init_drawing(void)
{
-#ifdef HAVE_BACKLIGHT
backlight_ignore_timeout();
-#endif
+
atexit(cleanup);
rb->lcd_set_background(OUTSIDE_COLOR);
diff --git a/apps/plugins/starfield.c b/apps/plugins/starfield.c
index 7fc400d0ee..39ed8a8171 100644
--- a/apps/plugins/starfield.c
+++ b/apps/plugins/starfield.c
@@ -324,14 +324,14 @@ enum plugin_status plugin_start(const void* parameter)
int ret;
(void)parameter;
-#ifdef HAVE_BACKLIGHT
+
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
+
ret = plugin_main();
-#ifdef HAVE_BACKLIGHT
+
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings();
-#endif
+
return ret;
}
diff --git a/apps/plugins/superdom.c b/apps/plugins/superdom.c
index 50027a30c6..6969f76165 100644
--- a/apps/plugins/superdom.c
+++ b/apps/plugins/superdom.c
@@ -1450,7 +1450,6 @@ static int show_inventory(void)
{
struct simplelist_info info;
rb->simplelist_info_init(&info, "Inventory", 9, NULL);
- info.hide_selection = true;
info.get_name = inventory_data;
if(rb->simplelist_show_list(&info))
{
diff --git a/apps/plugins/test_disk.c b/apps/plugins/test_disk.c
index 1429668556..fee6c4d0b0 100644
--- a/apps/plugins/test_disk.c
+++ b/apps/plugins/test_disk.c
@@ -467,10 +467,9 @@ enum plugin_status plugin_start(const void* parameter)
rb->srand(*rb->current_tick);
-#ifdef HAVE_BACKLIGHT
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
+
while(!quit)
{
@@ -489,9 +488,8 @@ enum plugin_status plugin_start(const void* parameter)
}
/* Turn on backlight timeout (revert to settings) */
-#ifdef HAVE_BACKLIGHT
backlight_use_settings();
-#endif
+
rb->rmdir(testbasedir);
return PLUGIN_OK;
diff --git a/apps/plugins/test_fps.c b/apps/plugins/test_fps.c
index ddf938ac25..2f4e9bb13e 100644
--- a/apps/plugins/test_fps.c
+++ b/apps/plugins/test_fps.c
@@ -401,9 +401,9 @@ enum plugin_status plugin_start(const void* parameter)
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
cpu_freq = *rb->cpu_frequency; /* remember CPU frequency */
#endif
-#ifdef HAVE_BACKLIGHT
+
backlight_ignore_timeout();
-#endif
+
time_main_update();
rb->sleep(HZ);
#if defined(HAVE_LCD_COLOR) && (MEMORYSIZE > 2)
@@ -424,9 +424,9 @@ enum plugin_status plugin_start(const void* parameter)
(cpu_freq + 500000) / 1000000);
log_text(str);
#endif
-#ifdef HAVE_BACKLIGHT
+
backlight_use_settings();
-#endif
+
/* wait until user closes plugin */
plugin_quit();
diff --git a/apps/plugins/test_gfx.c b/apps/plugins/test_gfx.c
index 7734179159..60e2836463 100644
--- a/apps/plugins/test_gfx.c
+++ b/apps/plugins/test_gfx.c
@@ -495,9 +495,9 @@ enum plugin_status plugin_start(const void* parameter)
rb->lcd_set_backdrop(NULL);
rb->lcd_clear_display();
#endif
-#ifdef HAVE_BACKLIGHT
+
backlight_ignore_timeout();
-#endif
+
rb->splashf(0, "LCD driver performance test, please wait %d sec",
7*4*DURATION/HZ);
init_rand_table();
@@ -522,9 +522,9 @@ enum plugin_status plugin_start(const void* parameter)
(cpu_freq + 500000) / 1000000);
#endif
rb->close(log_fd);
-#ifdef HAVE_BACKLIGHT
+
backlight_use_settings();
-#endif
+
#ifdef TEST_GREYLIB
grey_release();
#endif
diff --git a/apps/plugins/test_grey.c b/apps/plugins/test_grey.c
index 121cbad051..07fda1b9c6 100644
--- a/apps/plugins/test_grey.c
+++ b/apps/plugins/test_grey.c
@@ -123,9 +123,9 @@ enum plugin_status plugin_start(const void* parameter)
}
for (i = 0; i <= STEPS; i++)
input_levels[i] = lcd_levels[i] = (255 * i + (STEPS/2)) / STEPS;
-#ifdef HAVE_BACKLIGHT
+
backlight_ignore_timeout();
-#endif
+
grey_set_background(0); /* set background to black */
grey_clear_display();
grey_show(true);
@@ -221,8 +221,8 @@ enum plugin_status plugin_start(const void* parameter)
}
grey_release();
-#ifdef HAVE_BACKLIGHT
+
backlight_use_settings();
-#endif
+
return PLUGIN_OK;
}
diff --git a/apps/plugins/test_viewports.c b/apps/plugins/test_viewports.c
index 2bada01f79..6eff0249a2 100644
--- a/apps/plugins/test_viewports.c
+++ b/apps/plugins/test_viewports.c
@@ -130,7 +130,7 @@ static void *test_address_fn(int x, int y)
struct frame_buffer_t *fb = vp0.buffer;
/* LCD_STRIDEFORMAT & LCD_NATIVE_STRIDE macros allow Horiz screens to work with RB */
-#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
size_t element = (x * LCD_NATIVE_STRIDE(fb->stride)) + y;
#else
size_t element = (y * LCD_NATIVE_STRIDE(fb->stride)) + x;
@@ -249,9 +249,11 @@ enum plugin_status plugin_start(const void* parameter)
rb->button_get(true);
+ rb->screens[SCREEN_MAIN]->scroll_stop();
/* Restore the default viewport */
rb->screens[SCREEN_MAIN]->set_viewport(NULL);
#ifdef HAVE_REMOTE_LCD
+ rb->screens[SCREEN_REMOTE]->scroll_stop();
rb->screens[SCREEN_REMOTE]->set_viewport(NULL);
#endif
diff --git a/apps/plugins/text_editor.c b/apps/plugins/text_editor.c
index 0cbb61c774..8740606c58 100644
--- a/apps/plugins/text_editor.c
+++ b/apps/plugins/text_editor.c
@@ -214,7 +214,6 @@ static void setup_lists(struct gui_synclist *lists, int sel)
rb->gui_synclist_init(lists,list_get_name_cb,0, false, 1, NULL);
rb->gui_synclist_set_icon_callback(lists,NULL);
rb->gui_synclist_set_nb_items(lists,line_count);
- rb->gui_synclist_limit_scroll(lists,true);
rb->gui_synclist_select_item(lists, sel);
rb->gui_synclist_draw(lists);
}
@@ -395,7 +394,7 @@ enum plugin_status plugin_start(const void* parameter)
rb->gui_synclist_draw(&lists);
cur_sel = rb->gui_synclist_get_sel_pos(&lists);
button = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
- if (rb->gui_synclist_do_button(&lists,&button,LIST_WRAP_UNLESS_HELD))
+ if (rb->gui_synclist_do_button(&lists, &button))
continue;
switch (button)
{
diff --git a/apps/plugins/wormlet.c b/apps/plugins/wormlet.c
index 162cea6208..c09ef48bdc 100644
--- a/apps/plugins/wormlet.c
+++ b/apps/plugins/wormlet.c
@@ -2428,10 +2428,9 @@ static bool launch_wormlet(void)
rb->lcd_clear_display();
-#ifdef HAVE_BACKLIGHT
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
+
/* start the game */
while (game_result == 1)
game_result = run();
@@ -2439,10 +2438,10 @@ static bool launch_wormlet(void)
switch (game_result)
{
case 2:
-#ifdef HAVE_BACKLIGHT
+
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings();
-#endif
+
return false;
break;
}
diff --git a/apps/plugins/xobox.c b/apps/plugins/xobox.c
index b8b1964db4..c7499fed7a 100644
--- a/apps/plugins/xobox.c
+++ b/apps/plugins/xobox.c
@@ -1297,10 +1297,9 @@ enum plugin_status plugin_start (const void *parameter)
rb->lcd_set_backdrop(NULL);
#endif
-#ifdef HAVE_BACKLIGHT
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
+
highscore_load(SCORE_FILE, highscores, NUM_SCORES);
if (!load_game()) {
@@ -1310,10 +1309,10 @@ enum plugin_status plugin_start (const void *parameter)
randomize ();
ret = xobox_loop ();
-#ifdef HAVE_BACKLIGHT
+
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings();
-#endif
+
rb->lcd_setfont (FONT_UI);
highscore_save(SCORE_FILE, highscores, NUM_SCORES);
diff --git a/apps/plugins/xworld/sys.c b/apps/plugins/xworld/sys.c
index c57da9456b..ece9d87b66 100644
--- a/apps/plugins/xworld/sys.c
+++ b/apps/plugins/xworld/sys.c
@@ -122,9 +122,8 @@ void exit_handler(void)
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost(false);
#endif
-#ifdef HAVE_BACKLIGHT
+
backlight_use_settings();
-#endif
}
static bool sys_do_help(void)
@@ -428,9 +427,8 @@ void sys_menu(struct System* sys)
void sys_init(struct System* sys, const char* title)
{
(void) title;
-#ifdef HAVE_BACKLIGHT
+
backlight_ignore_timeout();
-#endif
rb_atexit(exit_handler);
save_sys = sys;
rb->memset(&sys->input, 0, sizeof(sys->input));
@@ -496,7 +494,7 @@ void sys_copyRect(struct System* sys, uint16_t x, uint16_t y, uint16_t w, uint16
for (int i = 0; i < w / 2; ++i) {
uint8_t pix1 = *(buf + i) >> 4;
uint8_t pix2 = *(buf + i) & 0xF;
-#if defined(LCD_STRIDEFORMAT) && (LCD_STRIDEFORMAT == VERTICAL_STRIDE)
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
framebuffer[( (h * 2) ) * 320 + i] = sys->palette[pix1];
framebuffer[( (h * 2) + 1) * 320 + i] = sys->palette[pix2];
#else
@@ -515,7 +513,7 @@ void sys_copyRect(struct System* sys, uint16_t x, uint16_t y, uint16_t w, uint16
for (int i = 0; i < w / 2; ++i) {
uint8_t pix1 = *(buf + i) >> 4;
uint8_t pix2 = *(buf + i) & 0xF;
-#if defined(LCD_STRIDEFORMAT) && (LCD_STRIDEFORMAT == VERTICAL_STRIDE)
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
framebuffer[(200 - h * 2 ) * 320 + ( 320 - i )] = sys->palette[pix1];
framebuffer[(200 - h * 2 - 1) * 320 + ( 320 - i )] = sys->palette[pix2];
#else
@@ -531,7 +529,7 @@ void sys_copyRect(struct System* sys, uint16_t x, uint16_t y, uint16_t w, uint16
else
{
int next = 0;
-#if defined(LCD_STRIDEFORMAT) && (LCD_STRIDEFORMAT == VERTICAL_STRIDE)
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
for(int x = 0; x < w / 2; ++x)
{
for(int y = 0; y < h; ++y)
@@ -565,7 +563,7 @@ void sys_copyRect(struct System* sys, uint16_t x, uint16_t y, uint16_t w, uint16
struct bitmap in_bmp;
if(sys->settings.rotation_option)
{
-#if defined(LCD_STRIDEFORMAT) && (LCD_STRIDEFORMAT == VERTICAL_STRIDE)
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
in_bmp.width = 320;
in_bmp.height = 200;
#else
@@ -575,7 +573,7 @@ void sys_copyRect(struct System* sys, uint16_t x, uint16_t y, uint16_t w, uint16
}
else
{
-#if defined(LCD_STRIDEFORMAT) && (LCD_STRIDEFORMAT == VERTICAL_STRIDE)
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
in_bmp.width = 200;
in_bmp.height = 320;
#else
@@ -600,7 +598,7 @@ void sys_copyRect(struct System* sys, uint16_t x, uint16_t y, uint16_t w, uint16
}
else
{
-#if defined(LCD_STRIDEFORMAT) && (LCD_STRIDEFORMAT == VERTICAL_STRIDE)
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
for(int x = 0; x < 320; ++x)
{
for(int y = 0; y < 200; ++y)
diff --git a/apps/radio/presets.c b/apps/radio/presets.c
index 51bdabdfce..1cd85637e8 100644
--- a/apps/radio/presets.c
+++ b/apps/radio/presets.c
@@ -225,7 +225,7 @@ void radio_load_presets(char *filename)
}
/* Temporary preset, loaded until player shuts down. */
else if(filename[0] == '/')
- strlcpy(filepreset, filename, sizeof(filepreset));
+ strmemccpy(filepreset, filename, sizeof(filepreset));
/* Preset from default directory. */
else
snprintf(filepreset, sizeof(filepreset), "%s/%s.fmr",
@@ -246,7 +246,7 @@ void radio_load_presets(char *filename)
{
struct fmstation * const fms = &presets[num_presets];
fms->frequency = f;
- strlcpy(fms->name, name, MAX_FMPRESET_LEN+1);
+ strmemccpy(fms->name, name, MAX_FMPRESET_LEN+1);
num_presets++;
}
}
@@ -490,8 +490,7 @@ int handle_radio_presets(void)
while (result == 0)
{
gui_synclist_draw(&lists);
- list_do_action(CONTEXT_STD, TIMEOUT_BLOCK,
- &lists, &action, LIST_WRAP_UNLESS_HELD);
+ list_do_action(CONTEXT_STD, TIMEOUT_BLOCK, &lists, &action);
switch (action)
{
case ACTION_STD_MENU:
diff --git a/apps/radio/radio.c b/apps/radio/radio.c
index b74371413e..bf8ad865dd 100644
--- a/apps/radio/radio.c
+++ b/apps/radio/radio.c
@@ -56,6 +56,7 @@
#include "statusbar-skinned.h"
#include "playback.h"
#include "presets.h"
+#include "wps.h" /* for wps_state... */
#if CONFIG_TUNER
@@ -363,7 +364,9 @@ void radio_screen(void)
{
radio_load_presets(global_settings.fmr_file);
}
- skin_get_global_state()->id3 = NULL;
+ /* TODO: Can this be moved somewhere else? */
+ get_wps_state()->id3 = NULL;
+ get_wps_state()->nid3 = NULL;
#ifdef HAVE_ALBUMART
radioart_init(true);
#endif
diff --git a/apps/radio/radio_skin.c b/apps/radio/radio_skin.c
index 4d90c4e241..dc38faa31a 100644
--- a/apps/radio/radio_skin.c
+++ b/apps/radio/radio_skin.c
@@ -36,6 +36,7 @@
#include "sound.h"
#include "misc.h"
#endif
+#include "skin_engine/wps_internals.h"
char* default_radio_skin(enum screen_type screen)
@@ -62,12 +63,12 @@ void fms_fix_displays(enum fms_exiting toggle_state)
{
FOR_NB_SCREENS(i)
{
- struct wps_data *data = skin_get_gwps(FM_SCREEN, i)->data;
+ struct gui_wps *gwps = skin_get_gwps(FM_SCREEN, i);
if (toggle_state == FMS_ENTER)
{
- viewportmanager_theme_enable(i, skin_has_sbs(i, data), NULL);
+ viewportmanager_theme_enable(i, skin_has_sbs(gwps), NULL);
#ifdef HAVE_BACKDROP_IMAGE
- skin_backdrop_show(data->backdrop_id);
+ skin_backdrop_show(gwps->data->backdrop_id);
#endif
screens[i].clear_display();
/* force statusbar/skin update since we just cleared the whole screen */
@@ -79,10 +80,10 @@ void fms_fix_displays(enum fms_exiting toggle_state)
#ifdef HAVE_BACKDROP_IMAGE
skin_backdrop_show(sb_get_backdrop(i));
#endif
- viewportmanager_theme_undo(i, skin_has_sbs(i, data));
+ viewportmanager_theme_undo(i, skin_has_sbs(gwps));
}
#ifdef HAVE_TOUCHSCREEN
- if (i==SCREEN_MAIN && !data->touchregions)
+ if (i==SCREEN_MAIN && !gwps->data->touchregions)
touchscreen_set_mode(toggle_state == FMS_ENTER ?
TOUCHSCREEN_BUTTON : global_settings.touch_mode);
#endif
@@ -95,11 +96,10 @@ int fms_do_button_loop(bool update_screen)
int button = skin_wait_for_action(FM_SCREEN, CONTEXT_FM|ALLOW_SOFTLOCK,
update_screen ? TIMEOUT_NOBLOCK : HZ/5);
#ifdef HAVE_TOUCHSCREEN
- struct touchregion *region;
+ struct gui_wps *gwps = skin_get_gwps(FM_SCREEN, SCREEN_MAIN);
int offset;
if (button == ACTION_TOUCHSCREEN)
- button = skin_get_touchaction(skin_get_gwps(FM_SCREEN, SCREEN_MAIN)->data,
- &offset, &region);
+ button = skin_get_touchaction(gwps, &offset);
switch (button)
{
case ACTION_WPS_STOP:
diff --git a/apps/radio/radioart.c b/apps/radio/radioart.c
index 34efdea0da..230948c051 100644
--- a/apps/radio/radioart.c
+++ b/apps/radio/radioart.c
@@ -82,7 +82,7 @@ static int load_radioart_image(struct radioart *ra, const char* preset_name,
#endif
return -1;
}
- strlcpy(ra->name, preset_name, MAX_FMPRESET_LEN+1);
+ strmemccpy(ra->name, preset_name, MAX_FMPRESET_LEN+1);
ra->dim.height = dim->height;
ra->dim.width = dim->width;
ra->last_tick = current_tick;
diff --git a/apps/rbcodec_helpers.c b/apps/rbcodec_helpers.c
index 78e068ded7..b856d7355d 100644
--- a/apps/rbcodec_helpers.c
+++ b/apps/rbcodec_helpers.c
@@ -87,10 +87,7 @@ void tdspeed_free_buffers(int32_t **buffers, int nbuf)
{
for (int i = 0; i < nbuf; i++)
{
- if (handles[i] > 0)
- core_free(handles[i]);
-
- handles[i] = 0;
+ handles[i] = core_free(handles[i]);
buffers[i] = NULL;
}
}
diff --git a/apps/recorder/albumart.c b/apps/recorder/albumart.c
index 9ff9c72f80..c0d9e6d86f 100644
--- a/apps/recorder/albumart.c
+++ b/apps/recorder/albumart.c
@@ -39,6 +39,12 @@
#define USE_JPEG_COVER
#endif
+#ifdef PLUGIN
+ #define strmemccpy strlcpy
+ /* Note we don't use the return value so this works */
+ /* FIXME if strmemccpy gets added to the rb->plugin struct */
+#endif
+
/* Strip filename from a full path
*
* buf - buffer to extract directory to.
@@ -67,7 +73,7 @@ static char* strip_filename(char* buf, int buf_size, const char* fullpath)
}
len = MIN(sep - fullpath + 1, buf_size - 1);
- strlcpy(buf, fullpath, len + 1);
+ strmemccpy(buf, fullpath, len + 1);
return (sep + 1);
}
@@ -266,7 +272,7 @@ bool search_albumart_files(const struct mp3entry *id3, const char *size_string,
if (!found)
return false;
- strlcpy(buf, path, buflen);
+ strmemccpy(buf, path, buflen);
logf("Album art found: %s", path);
return true;
}
@@ -297,74 +303,4 @@ bool find_albumart(const struct mp3entry *id3, char *buf, int buflen,
return search_albumart_files(id3, size_string, buf, buflen);
}
-/* 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 /* PLUGIN */
diff --git a/apps/recorder/albumart.h b/apps/recorder/albumart.h
index 80cacaf5f0..0d663d3d92 100644
--- a/apps/recorder/albumart.h
+++ b/apps/recorder/albumart.h
@@ -35,12 +35,6 @@
bool find_albumart(const struct mp3entry *id3, char *buf, int buflen,
const struct dim *dim);
-#ifndef PLUGIN
-/* 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
-
bool search_albumart_files(const struct mp3entry *id3, const char *size_string,
char *buf, int buflen);
diff --git a/apps/recorder/keyboard.c b/apps/recorder/keyboard.c
index b6b5affb6a..f64061d303 100644
--- a/apps/recorder/keyboard.c
+++ b/apps/recorder/keyboard.c
@@ -549,8 +549,8 @@ int kbd_input(char* text, int buflen, unsigned short *kbd)
{
/* declare scoped pointers inside screen loops - hide the
declarations from previous block level */
- struct keyboard_parameters *pm = &param[l];
struct screen *sc = &screens[l];
+ pm = &param[l];
sc->clear_display();
kbd_draw_picker(pm, sc, &state);
kbd_draw_edit_line(pm, sc, &state);
@@ -1063,7 +1063,7 @@ static void kbd_draw_edit_line(struct keyboard_parameters *pm,
while (*utf8 && i < pm->max_chars_text)
{
j = utf8seek(utf8, 1);
- strlcpy(outline, utf8, j+1);
+ strmemccpy(outline, utf8, j+1);
sc->getstringsize(outline, &w, NULL);
sc->putsxy(text_margin + i*pm->text_w + (pm->text_w-w)/2,
y, outline);
diff --git a/apps/recorder/pcm_record.c b/apps/recorder/pcm_record.c
index 0f6e8469ec..f7f4c77928 100644
--- a/apps/recorder/pcm_record.c
+++ b/apps/recorder/pcm_record.c
@@ -1352,7 +1352,7 @@ static void mark_stream(const char *path, enum mark_stream_action action)
file->hdr.type = CHUNK_T_STREAM_START;
file->hdr.size = count;
- strlcpy(file->path, path, MAX_PATH);
+ strmemccpy(file->path, path, MAX_PATH);
}
}
@@ -1437,8 +1437,7 @@ static void on_close_recording(void)
audio_set_output_source(AUDIO_SRC_PLAYBACK);
pcm_apply_settings();
- if (pcmrec_handle > 0)
- pcmrec_handle = core_free(pcmrec_handle);
+ pcmrec_handle = core_free(pcmrec_handle);
talk_buffer_set_policy(TALK_BUFFER_DEFAULT);
send_event(RECORDING_EVENT_STOP, NULL);
@@ -1583,7 +1582,7 @@ static void on_record(const char *filename)
/* Copy path and let caller go */
char path[MAX_PATH];
- strlcpy(path, filename, MAX_PATH);
+ strmemccpy(path, filename, MAX_PATH);
queue_reply(&audio_queue, 0);
diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c
index 0a3c7af494..6c52adf5d3 100644
--- a/apps/recorder/recording.c
+++ b/apps/recorder/recording.c
@@ -1265,7 +1265,7 @@ bool recording_screen(bool no_source)
}
/* let list handle the button */
- gui_synclist_do_button(&lists, &button, LIST_WRAP_UNLESS_HELD);
+ gui_synclist_do_button(&lists, &button);
switch(button)
diff --git a/apps/recorder/resize.c b/apps/recorder/resize.c
index 6f561039c3..c16cec9dc9 100644
--- a/apps/recorder/resize.c
+++ b/apps/recorder/resize.c
@@ -593,7 +593,7 @@ static inline bool scale_v_linear(struct rowset *rset,
static void output_row_32_native_fromyuv(uint32_t row, void * row_in,
struct scaler_context *ctx)
{
-#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
+#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
#define DEST_STEP (ctx->bm->height)
#define Y_STEP (1)
#else
diff --git a/apps/root_menu.c b/apps/root_menu.c
index 80a84d9d49..80b5be1d36 100644
--- a/apps/root_menu.c
+++ b/apps/root_menu.c
@@ -107,7 +107,7 @@ static void rootmenu_track_changed_callback(unsigned short id, void* param)
{
(void)id;
struct mp3entry *id3 = ((struct track_event *)param)->id3;
- strlcpy(current_track_path, id3->path, MAX_PATH);
+ strmemccpy(current_track_path, id3->path, MAX_PATH);
}
static int browser(void* param)
{
@@ -122,7 +122,7 @@ static int browser(void* param)
static char last_folder[MAX_PATH] = "/";
/* and stuff for the database browser */
#ifdef HAVE_TAGCACHE
- static int last_db_dirlevel = 0, last_db_selection = 0;
+ static int last_db_dirlevel = 0, last_db_selection = 0, last_ft_dirlevel = 0;
#endif
switch ((intptr_t)param)
@@ -241,15 +241,19 @@ static int browser(void* param)
{
if (lang_is_rtl())
{
- splashf(0, "[%d/%d] %s", stat->commit_step,
- tagcache_get_max_commit_step(),
- str(LANG_TAGCACHE_INIT));
+ splash_progress(stat->commit_step,
+ tagcache_get_max_commit_step(),
+ "[%d/%d] %s", stat->commit_step,
+ tagcache_get_max_commit_step(),
+ str(LANG_TAGCACHE_INIT));
}
else
{
- splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT),
- stat->commit_step,
- tagcache_get_max_commit_step());
+ splash_progress(stat->commit_step,
+ tagcache_get_max_commit_step(),
+ "%s [%d/%d]", str(LANG_TAGCACHE_INIT),
+ stat->commit_step,
+ tagcache_get_max_commit_step());
}
}
else
@@ -262,6 +266,7 @@ static int browser(void* param)
if (!tagcache_is_usable())
return GO_TO_PREVIOUS;
filter = SHOW_ID3DB;
+ last_ft_dirlevel = tc->dirlevel;
tc->dirlevel = last_db_dirlevel;
tc->selected_item = last_db_selection;
push_current_activity(ACTIVITY_DATABASEBROWSER);
@@ -287,6 +292,7 @@ static int browser(void* param)
case GO_TO_DBBROWSER:
last_db_dirlevel = tc->dirlevel;
last_db_selection = tc->selected_item;
+ tc->dirlevel = last_ft_dirlevel;
break;
#endif
}
@@ -351,6 +357,7 @@ static int miscscrn(void * param)
case GO_TO_PLUGIN:
case GO_TO_PLAYLIST_VIEWER:
case GO_TO_WPS:
+ case GO_TO_PREVIOUS_MUSIC:
return result;
default:
return GO_TO_ROOT;
@@ -360,13 +367,11 @@ static int miscscrn(void * param)
static int playlist_view_catalog(void * param)
{
- /* kludge untill catalog_view_playlists() returns something useful */
- int old_playstatus = audio_status();
(void)param;
push_current_activity(ACTIVITY_PLAYLISTBROWSER);
- catalog_view_playlists();
+ bool item_was_selected = catalog_view_playlists();
pop_current_activity();
- if (!old_playstatus && audio_status())
+ if (item_was_selected)
return GO_TO_WPS;
return GO_TO_PREVIOUS;
}
@@ -724,6 +729,8 @@ static int load_plugin_screen(char *key)
char *param = open_plugin_entry.param;
if (param[0] == '\0')
param = NULL;
+ if (path[0] == '\0' && key)
+ path = P2STR((unsigned char *)key);
int ret = plugin_load(path, param);
diff --git a/apps/screen_access.c b/apps/screen_access.c
index a7b902918c..1909ef277c 100644
--- a/apps/screen_access.c
+++ b/apps/screen_access.c
@@ -217,6 +217,7 @@ struct screen screens[NB_SCREENS] =
.putsxy=&lcd_putsxy,
.puts=&lcd_puts,
.putsf=&lcd_putsf,
+ .putsxyf=&lcd_putsxyf,
.puts_scroll=&lcd_puts_scroll,
.putsxy_scroll_func=&lcd_putsxy_scroll_func,
.scroll_speed=&lcd_scroll_speed,
@@ -305,6 +306,7 @@ struct screen screens[NB_SCREENS] =
.putsxy=&lcd_remote_putsxy,
.puts=&lcd_remote_puts,
.putsf=&lcd_remote_putsf,
+ .putsxyf=&lcd_remote_putsxyf,
.puts_scroll=&lcd_remote_puts_scroll,
.putsxy_scroll_func=&lcd_remote_putsxy_scroll_func,
.scroll_speed=&lcd_remote_scroll_speed,
diff --git a/apps/screen_access.h b/apps/screen_access.h
index 94c0a19670..3e24306636 100644
--- a/apps/screen_access.h
+++ b/apps/screen_access.h
@@ -109,6 +109,7 @@ struct screen
void (*putsxy)(int x, int y, const unsigned char *str);
void (*puts)(int x, int y, const unsigned char *str);
void (*putsf)(int x, int y, const unsigned char *str, ...);
+ void (*putsxyf)(int x, int y, const unsigned char *fmt, ...);
bool (*puts_scroll)(int x, int y, const unsigned char *string);
bool (*putsxy_scroll_func)(int x, int y, const unsigned char *string,
void (*scroll_func)(struct scrollinfo *),
diff --git a/apps/screens.c b/apps/screens.c
index 24d1fed915..db24e534c1 100644
--- a/apps/screens.c
+++ b/apps/screens.c
@@ -20,7 +20,7 @@
****************************************************************************/
#include <stdbool.h>
-#include <string.h>
+#include <string-extra.h>
#include <stdio.h>
#include <stdlib.h>
#include "backlight.h"
@@ -233,12 +233,10 @@ bool set_time_screen(const char* title, struct tm *tm, bool set_date)
else
prev_line_height = 0;
- screen->getstringsize(SEPARATOR, &separator_width, NULL);
-
/* weekday */
- screen->getstringsize(str(LANG_WEEKDAY_SUNDAY + tm->tm_wday),
- &weekday_width, NULL);
- screen->getstringsize(" ", &separator_width, NULL);
+ weekday_width = screen->getstringsize(str(LANG_WEEKDAY_SUNDAY + tm->tm_wday),
+ NULL, NULL);
+ separator_width = screen->getstringsize(SEPARATOR, NULL, NULL);
for(i=0, j=0; i < 6; i++)
{
@@ -247,7 +245,7 @@ bool set_time_screen(const char* title, struct tm *tm, bool set_date)
j = weekday_width + separator_width;
prev_line_height *= 2;
}
- screen->getstringsize(ptr[i], &width, NULL);
+ width = screen->getstringsize(ptr[i], NULL, NULL);
cursor[i][INDEX_Y] = prev_line_height;
cursor[i][INDEX_X] = j;
j += width + separator_width;
@@ -563,7 +561,9 @@ static const char * id3_get_or_speak_info(int selected_item, void* data,
case LANG_ID3_COMMENT:
if (!id3->comment)
return NULL;
- snprintf(buffer, buffer_len, "%s", id3->comment);
+
+ strmemccpy(buffer, id3->comment, buffer_len);
+
val=buffer;
if(say_it && val)
talk_spell(val, true);
@@ -610,7 +610,9 @@ static const char * id3_get_or_speak_info(int selected_item, void* data,
case LANG_FORMAT:
if (id3->codectype >= AFMT_NUM_CODECS)
return NULL;
- snprintf(buffer, buffer_len, "%s", audio_formats[id3->codectype].label);
+
+ strmemccpy(buffer, audio_formats[id3->codectype].label, buffer_len);
+
val=buffer;
if(say_it)
talk_spell(val, true);
@@ -714,8 +716,7 @@ bool browse_id3(struct mp3entry *id3, int playlist_display_index, int playlist_a
gui_synclist_draw(&id3_lists);
gui_synclist_speak_item(&id3_lists);
while (true) {
- if(!list_do_action(CONTEXT_LIST,HZ/2,
- &id3_lists, &key,LIST_WRAP_UNLESS_HELD)
+ if(!list_do_action(CONTEXT_LIST,HZ/2, &id3_lists, &key)
&& key!=ACTION_NONE && key!=ACTION_UNKNOWN)
{
if (key == ACTION_STD_OK || key == ACTION_STD_CANCEL)
@@ -793,8 +794,7 @@ int view_runtime(void)
say_runtime = false;
}
gui_synclist_draw(&lists);
- list_do_action(CONTEXT_STD, HZ,
- &lists, &action, LIST_WRAP_UNLESS_HELD);
+ list_do_action(CONTEXT_STD, HZ, &lists, &action);
if(action == ACTION_STD_CANCEL)
break;
if(action == ACTION_STD_OK) {
diff --git a/apps/settings.c b/apps/settings.c
index 566573ae68..3d2c463cdd 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -35,8 +35,7 @@
#include "backlight.h"
#include "audio.h"
#include "talk.h"
-#include "strlcpy.h"
-#include "strcasestr.h"
+#include "string-extra.h"
#include "rtc.h"
#include "power.h"
#include "ata_idle_notify.h"
@@ -251,7 +250,7 @@ bool cfg_string_to_int(int setting_id, int* out, const char* str)
}
else return false;
}
- strlcpy(temp, start, end-start+1);
+ strmemccpy(temp, start, end-start+1);
if (!strcmp(str, temp))
{
*out = count;
@@ -343,18 +342,22 @@ bool settings_load_config(const char* file, bool apply)
size_t len = strlen(dir);
if (!strncasecmp(value, dir, len))
{
- strlcpy(storage, &value[len], MAX_PATH);
+ strmemccpy(storage, &value[len], MAX_PATH);
}
- else strlcpy(storage, value, MAX_PATH);
+ else
+ strmemccpy(storage, value, MAX_PATH);
+
}
- else strlcpy(storage, value, MAX_PATH);
+ else
+ strmemccpy(storage, value, MAX_PATH);
+
if (settings[i].filename_setting->suffix)
{
char *s = strcasestr(storage,settings[i].filename_setting->suffix);
if (s) *s = '\0';
}
- strlcpy((char*)settings[i].setting, storage,
- settings[i].filename_setting->max_len);
+ strmemccpy((char*)settings[i].setting, storage,
+ settings[i].filename_setting->max_len);
break;
}
}
@@ -393,11 +396,11 @@ bool cfg_int_to_string(int setting_id, int val, char* buf, int buf_len)
if (value[count] == val)
{
if (end == NULL)
- strlcpy(buf, start, buf_len);
+ strmemccpy(buf, start, buf_len);
else
{
int len = MIN(buf_len, (end-start) + 1);
- strlcpy(buf, start, len);
+ strmemccpy(buf, start, len);
}
return true;
}
@@ -421,11 +424,11 @@ bool cfg_int_to_string(int setting_id, int val, char* buf, int buf_len)
}
end = strchr(start,',');
if (end == NULL)
- strlcpy(buf, start, buf_len);
+ strmemccpy(buf, start, buf_len);
else
{
int len = MIN(buf_len, (end-start) + 1);
- strlcpy(buf, start, len);
+ strmemccpy(buf, start, len);
}
return true;
}
@@ -491,7 +494,7 @@ bool cfg_to_string(int i/*setting_id*/, char* buf, int buf_len)
else
{
int len = MIN(buf_len, settings[i].filename_setting->max_len);
- strlcpy(buf,(char*)settings[i].setting,len);
+ strmemccpy(buf,(char*)settings[i].setting,len);
}
break;
} /* switch () */
@@ -940,8 +943,6 @@ void settings_apply(bool read_disk)
#endif
lcd_scroll_step(global_settings.scroll_step);
- gui_list_screen_scroll_step(global_settings.screen_scroll_step);
- gui_list_screen_scroll_out_of_view(global_settings.offset_out_of_view);
lcd_bidir_scroll(global_settings.bidir_limit);
lcd_scroll_delay(global_settings.scroll_delay);
@@ -1073,8 +1074,8 @@ void reset_setting(const struct settings_list *setting, void *var)
break;
case F_T_CHARPTR:
case F_T_UCHARPTR:
- strlcpy((char*)var, setting->default_val.charptr,
- setting->filename_setting->max_len);
+ strmemccpy((char*)var, setting->default_val.charptr,
+ setting->filename_setting->max_len);
break;
}
}
@@ -1179,9 +1180,14 @@ bool set_int_ex(const unsigned char* string,
{
(void)unit;
struct settings_list item;
- struct int_setting data = {
- function, voice_unit, min, max, step,
- formatter, get_talk_id
+ const struct int_setting data = {
+ .option_callback = function,
+ .unit = voice_unit,
+ .step = step,
+ .min = min,
+ .max = max,
+ .formatter = formatter,
+ .get_talk_id = get_talk_id,
};
item.int_setting = &data;
item.flags = F_INT_SETTING|F_T_INT;
@@ -1211,9 +1217,14 @@ bool set_option(const char* string, const void* variable, enum optiontype type,
{
int temp;
struct settings_list item;
- struct int_setting data = {
- function, UNIT_INT, 0, numoptions-1, 1,
- set_option_formatter, set_option_get_talk_id
+ const struct int_setting data = {
+ .option_callback = function,
+ .unit = UNIT_INT,
+ .step = 1,
+ .min = 0,
+ .max = numoptions-1,
+ .formatter = set_option_formatter,
+ .get_talk_id = set_option_get_talk_id
};
memset(&item, 0, sizeof(struct settings_list));
set_option_options = options;
@@ -1267,6 +1278,6 @@ void set_file(const char* filename, char* setting, const int maxlen)
if (len > maxlen)
return;
- strlcpy(setting, fptr, len);
+ strmemccpy(setting, fptr, len);
settings_save();
}
diff --git a/apps/settings.h b/apps/settings.h
index 092c04a76b..37e546f6fc 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -613,7 +613,8 @@ struct user_settings
#ifdef HAVE_ALBUMART
int album_art; /* switch off album art display or choose preferred source */
#endif
-
+ bool rewind_across_tracks;
+
/* playlist viewer settings */
bool playlist_viewer_icons; /* display icons on viewer */
bool playlist_viewer_indices; /* display playlist indices on viewer */
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 5fd7e0459b..8e6271dd41 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -167,19 +167,19 @@
{flags|F_INT_SETTING|F_T_INT, &global_settings.var, \
lang_id, INT(default), name, cfg_vals, \
{.int_setting = (struct int_setting[]){ \
- {cb, unit, min, max, step, formatter, get_talk_id}}}}
+ {cb, unit, step, min, max, formatter, get_talk_id}}}}
#define INT_SETTING(flags, var, lang_id, default, name, \
unit, min, max, step, formatter, get_talk_id, cb) \
{flags|F_INT_SETTING|F_T_INT, &global_settings.var, \
lang_id, INT(default), name, NULL, \
{.int_setting = (struct int_setting[]){ \
- {cb, unit, min, max, step, formatter, get_talk_id}}}}
+ {cb, unit, step, min, max, formatter, get_talk_id}}}}
#define INT_SETTING_NOWRAP(flags, var, lang_id, default, name, \
unit, min, max, step, formatter, get_talk_id, cb) \
{flags|F_INT_SETTING|F_T_INT|F_NO_WRAP, &global_settings.var, \
lang_id, INT(default), name, NULL, \
{.int_setting = (struct int_setting[]){ \
- {cb, unit, min, max, step, formatter, get_talk_id}}}}
+ {cb, unit, step, min, max, formatter, get_talk_id}}}}
#define TABLE_SETTING(flags, var, lang_id, default, name, cfg_vals, \
unit, formatter, get_talk_id, cb, count, ...) \
@@ -240,8 +240,10 @@ static const char graphic_numeric[] = "graphic,numeric";
#define DEFAULT_FONTNAME "08-Rockfont"
#elif LCD_HEIGHT <= 220
#define DEFAULT_FONT_HEIGHT 12
-#elif LCD_HEIGHT <= 320
+#elif LCD_HEIGHT <= 240
#define DEFAULT_FONT_HEIGHT 15
+#elif LCD_HEIGHT <= 320
+ #define DEFAULT_FONT_HEIGHT 18
#elif defined(SHANLING_Q1)
/* 16pt font looks pretty aliased & ugly */
#define DEFAULT_FONT_HEIGHT 18
@@ -622,11 +624,11 @@ static char* qs_write_to_cfg(void* setting, char*buf, int buf_len)
int index = *(int*)setting;
if (index < 0 || index >= nb_settings)
{
- strlcpy(buf, "-", buf_len);
+ strmemccpy(buf, "-", buf_len);
return buf;
}
const struct settings_list *var = &settings[index];
- strlcpy(buf, var->cfg_name, buf_len);
+ strmemccpy(buf, var->cfg_name, buf_len);
return buf;
}
static bool qs_is_changed(void* setting, void* defaultval)
@@ -943,8 +945,10 @@ const struct settings_list settings[] = {
{ F_T_INT|F_DEF_ISFUNC|F_INT_SETTING, &global_settings.contrast,
LANG_CONTRAST, FUNCTYPE(lcd_default_contrast), "contrast", NULL , {
.int_setting = (struct int_setting[]) {
- { lcd_set_contrast, UNIT_INT, MIN_CONTRAST_SETTING,
- MAX_CONTRAST_SETTING, 1, NULL, NULL }}}},
+ { .option_callback = lcd_set_contrast,
+ .unit = UNIT_INT, .step = 1,
+ .min = MIN_CONTRAST_SETTING, .max = MAX_CONTRAST_SETTING,
+ .formatter = NULL, .get_talk_id = NULL }}}},
#endif
#ifdef HAVE_BACKLIGHT
TABLE_SETTING_LIST(F_TIME_SETTING | F_ALLOW_ARBITRARY_VALS,
@@ -1060,8 +1064,10 @@ const struct settings_list settings[] = {
LANG_BATTERY_CAPACITY, FUNCTYPE(battery_default_capacity),
"battery capacity", NULL , {
.int_setting = (struct int_setting[]) {
- { set_battery_capacity, UNIT_MAH, BATTERY_CAPACITY_MIN,
- BATTERY_CAPACITY_MAX, BATTERY_CAPACITY_INC, NULL, NULL }}}},
+ { .option_callback = set_battery_capacity,
+ .unit = UNIT_MAH, .step = BATTERY_CAPACITY_INC,
+ .min = BATTERY_CAPACITY_MIN, .max = BATTERY_CAPACITY_MAX,
+ .formatter = NULL, .get_talk_id = NULL }}}},
#else /* IPOD_VIDEO */
INT_SETTING(0, battery_capacity, LANG_BATTERY_CAPACITY,
BATTERY_CAPACITY_DEFAULT, "battery capacity", UNIT_MAH,
@@ -1225,13 +1231,11 @@ const struct settings_list settings[] = {
lcd_remote_bidir_scroll),
#endif
OFFON_SETTING(0, offset_out_of_view, LANG_SCREEN_SCROLL_VIEW,
- false, "Screen Scrolls Out Of View",
- gui_list_screen_scroll_out_of_view),
+ false, "Screen Scrolls Out Of View", NULL),
INT_SETTING(F_PADTITLE, scroll_step, LANG_SCROLL_STEP, 6, "scroll step",
UNIT_PIXEL, 1, LCD_WIDTH, 1, NULL, NULL, lcd_scroll_step),
INT_SETTING(F_PADTITLE, screen_scroll_step, LANG_SCREEN_SCROLL_STEP, 16,
- "screen scroll step", UNIT_PIXEL, 1, LCD_WIDTH, 1, NULL, NULL,
- gui_list_screen_scroll_step),
+ "screen scroll step", UNIT_PIXEL, 1, LCD_WIDTH, 1, NULL, NULL, NULL),
OFFON_SETTING(0,scroll_paginated,LANG_SCROLL_PAGINATED,
false,"scroll paginated",NULL),
OFFON_SETTING(0,list_wraparound,LANG_LIST_WRAPAROUND,
@@ -2061,7 +2065,7 @@ const struct settings_list settings[] = {
tsc_is_changed, tsc_set_default),
#endif
OFFON_SETTING(0, prevent_skip, LANG_PREVENT_SKIPPING, false, "prevent track skip", NULL),
-
+ OFFON_SETTING(0, rewind_across_tracks, LANG_REWIND_ACROSS_TRACKS, false, "rewind across tracks", NULL),
#ifdef HAVE_PITCHCONTROL
OFFON_SETTING(0, pitch_mode_semitone, LANG_SEMITONE, false,
"Semitone pitch change", NULL),
diff --git a/apps/settings_list.h b/apps/settings_list.h
index 36c4d8062f..d4862874d5 100644
--- a/apps/settings_list.h
+++ b/apps/settings_list.h
@@ -69,10 +69,11 @@ struct filename_setting {
struct int_setting {
void (*option_callback)(int);
- int unit;
+ int16_t unit;
+ int16_t step;
int min;
int max;
- int step;
+
const char* (*formatter)(char*, size_t, int, const char*);
int32_t (*get_talk_id)(int, int);
};
diff --git a/apps/shortcuts.c b/apps/shortcuts.c
index 2b032f1fd4..e52e38eb06 100644
--- a/apps/shortcuts.c
+++ b/apps/shortcuts.c
@@ -51,7 +51,7 @@
#include "playback.h"
#endif
-#define MAX_SHORTCUT_NAME 32
+#define MAX_SHORTCUT_NAME 64
#define SHORTCUTS_FILENAME ROCKBOX_DIR "/shortcuts.txt"
static const char * const type_strings[SHORTCUT_TYPE_COUNT] = {
[SHORTCUT_SETTING] = "setting",
@@ -80,7 +80,7 @@ struct shortcut {
} timedata;
} u;
};
-#define SHORTCUTS_PER_HANDLE 32
+#define SHORTCUTS_PER_HANDLE 4
struct shortcut_handle {
struct shortcut shortcuts[SHORTCUTS_PER_HANDLE];
int next_handle;
@@ -284,7 +284,7 @@ void shortcuts_add(enum shortcut_type type, const char* value)
if (type == SHORTCUT_SETTING)
sc->u.setting = (void*)value;
else
- strlcpy(sc->u.path, value, MAX_PATH);
+ strmemccpy(sc->u.path, value, MAX_PATH);
if (first_idx_to_writeback < 0)
first_idx_to_writeback = shortcut_count - 1;
@@ -325,7 +325,7 @@ static int readline_cb(int n, char *buf, void *parameters)
}
else if (nm_op == 1) /*name*/
{
- strlcpy(sc->name, value, MAX_SHORTCUT_NAME);
+ strmemccpy(sc->name, value, MAX_SHORTCUT_NAME);
}
else if (nm_op == 2) /*data*/
{
@@ -339,7 +339,7 @@ static int readline_cb(int n, char *buf, void *parameters)
case SHORTCUT_FILE:
case SHORTCUT_DEBUGITEM:
case SHORTCUT_PLAYLISTMENU:
- strlcpy(sc->u.path, value, MAX_PATH);
+ strmemccpy(sc->u.path, value, MAX_PATH);
break;
case SHORTCUT_SETTING:
sc->u.setting = find_setting_by_cfgname(value, NULL);
@@ -374,7 +374,7 @@ static int readline_cb(int n, char *buf, void *parameters)
}
else if (nm_op == 4) /*talkclip*/
{
- strlcpy(sc->talk_clip, value, MAX_PATH);
+ strmemccpy(sc->talk_clip, value, MAX_PATH);
}
}
return 0;
@@ -446,7 +446,7 @@ static const char * shortcut_menu_get_name(int selected_item, void * data,
static int shortcut_menu_get_action(int action, struct gui_synclist *lists)
{
(void)lists;
- if (action == ACTION_STD_OK)
+ if (action == ACTION_STD_OK || action == ACTION_STD_MENU)
return ACTION_STD_CANCEL;
else if (action == ACTION_STD_QUICKSCREEN && action != ACTION_STD_CONTEXT)
return ACTION_STD_CANCEL;
@@ -454,7 +454,7 @@ static int shortcut_menu_get_action(int action, struct gui_synclist *lists)
{
int selection = gui_synclist_get_sel_pos(lists);
- if (!yesno_pop(ID2P(LANG_REALLY_DELETE)))
+ if (confirm_delete_yesno("") != YESNO_YES)
{
gui_synclist_set_title(lists, lists->title, lists->title_icon);
return ACTION_REDRAW;
@@ -534,7 +534,7 @@ static int shortcut_menu_speak_item(int selected_item, void * data)
if (*filename != '\0')
{
int dirlen = (filename - sc->u.path);
- strlcpy(path, sc->u.path, dirlen + 1);
+ strmemccpy(path, sc->u.path, dirlen + 1);
dir = opendir(path);
if (dir)
{
diff --git a/apps/status.h b/apps/status.h
index 1add203a0c..c038b793af 100644
--- a/apps/status.h
+++ b/apps/status.h
@@ -21,6 +21,8 @@
#ifndef _STATUS_H
#define _STATUS_H
+/* Do not reorder these, inbuilt statusbar icons and the
+ * skin engine %mp tag depend on this ordering. */
enum playmode
{
STATUS_PLAY,
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 436d85812b..a66f9658ae 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -277,17 +277,16 @@ static struct tcramcache
{
struct ramcache_header *hdr; /* allocated ramcache_header */
int handle; /* buffer handle */
- int move_lock;
} tcramcache;
static inline void tcrc_buffer_lock(void)
{
- tcramcache.move_lock++;
+ core_pin(tcramcache.handle);
}
static inline void tcrc_buffer_unlock(void)
{
- tcramcache.move_lock--;
+ core_unpin(tcramcache.handle);
}
#else /* ndef HAVE_TC_RAMCACHE */
@@ -423,19 +422,19 @@ static ssize_t ecwrite_index_entry(int fd, struct index_entry *buf)
static int open_tag_fd(struct tagcache_header *hdr, int tag, bool write)
{
int fd;
- char buf[MAX_PATH];
- const int bufsz = sizeof(buf);
int rc;
+ char fname[MAX_PATH];
if (TAGCACHE_IS_NUMERIC(tag) || tag < 0 || tag >= TAG_COUNT)
return -1;
- snprintf(buf, bufsz, TAGCACHE_FILE_INDEX, tag);
+ fd = open_pathfmt(fname, sizeof(fname),
+ write ? O_RDWR : O_RDONLY, TAGCACHE_FILE_INDEX, tag);
- fd = open(buf, write ? O_RDWR : O_RDONLY);
if (fd < 0)
{
- logf("tag file open failed: tag=%d write=%d file=%s", tag, write, buf);
+ logf("tag file open failed: tag=%d write=%d file= " TAGCACHE_FILE_INDEX,
+ tag, write, tag);
tc_stat.ready = false;
return fd;
}
@@ -806,10 +805,9 @@ static bool open_files(struct tagcache_search *tcs, int tag)
{
if (tcs->idxfd[tag] < 0)
{
- char fn[MAX_PATH];
-
- snprintf(fn, sizeof fn, TAGCACHE_FILE_INDEX, tag);
- tcs->idxfd[tag] = open(fn, O_RDONLY);
+ char fname[MAX_PATH];
+ tcs->idxfd[tag] = open_pathfmt(fname, sizeof(fname),
+ O_RDONLY, TAGCACHE_FILE_INDEX, tag);
}
if (tcs->idxfd[tag] < 0)
@@ -854,7 +852,7 @@ static bool retrieve(struct tagcache_search *tcs, IF_DIRCACHE(int idx_id,)
{
struct tagfile_entry *ep =
(struct tagfile_entry *)&tcramcache.hdr->tags[tag][seek];
- strlcpy(buf, ep->tag_data, bufsz);
+ strmemccpy(buf, ep->tag_data, bufsz);
return true;
}
@@ -1590,11 +1588,9 @@ bool tagcache_search_add_clause(struct tagcache_search *tcs,
if (!TAGCACHE_IS_NUMERIC(clause->tag) && tcs->idxfd[clause->tag] < 0)
{
- char buf[MAX_PATH];
- const int bufsz = sizeof(buf);
-
- snprintf(buf, bufsz, TAGCACHE_FILE_INDEX, clause->tag);
- tcs->idxfd[clause->tag] = open(buf, O_RDONLY);
+ char fname[MAX_PATH];
+ tcs->idxfd[clause->tag] = open_pathfmt(fname, sizeof(fname), O_RDONLY,
+ TAGCACHE_FILE_INDEX, clause->tag);
}
}
@@ -2752,11 +2748,11 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
* Creating new index file to store the tags. No need to preload
* anything whether the index type is sorted or not.
*/
- snprintf(buf, bufsz, TAGCACHE_FILE_INDEX, index_type);
- fd = open(buf, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ fd = open_pathfmt(buf, bufsz, O_WRONLY | O_CREAT | O_TRUNC,
+ TAGCACHE_FILE_INDEX, index_type);
if (fd < 0)
{
- logf("%s open fail", buf);
+ logf(TAGCACHE_FILE_INDEX " open fail", index_type);
return -2;
}
@@ -3470,7 +3466,7 @@ static bool write_tag(int fd, const char *tagstr, const char *datastr)
}
str_setlen(buf, bufsz - 1);
- strlcpy(&buf[i], "\" ", (bufsz - i - 1));
+ strmemccpy(&buf[i], "\" ", (bufsz - i - 1));
write(fd, buf, i + 2);
@@ -3861,10 +3857,9 @@ static bool delete_entry(long idx_id)
struct tagfile_entry *tfe;
int32_t *seek = &tcramcache.hdr->indices[idx_id].tag_seek[tag];
+ /* crc_32 is assumed not to yield (why would it...?) */
tfe = (struct tagfile_entry *)&tcramcache.hdr->tags[tag][*seek];
- tcrc_buffer_lock(); /* protect tfe and seek if crc_32() yield()s */
*seek = crc_32(tfe->tag_data, strlen(tfe->tag_data), 0xffffffff);
- tcrc_buffer_unlock();
myidx.tag_seek[tag] = *seek;
}
else
@@ -4005,9 +4000,6 @@ static void fix_ramcache(void* old_addr, void* new_addr)
static int move_cb(int handle, void* current, void* new)
{
(void)handle;
- if (tcramcache.move_lock > 0)
- return BUFLIB_CB_CANNOT_MOVE;
-
fix_ramcache(current, new);
tcramcache.hdr = new;
return BUFLIB_CB_OK;
@@ -4092,8 +4084,8 @@ static bool tagcache_dumpload(void)
return false;
}
- tcrc_buffer_lock();
tcramcache.handle = handle;
+ tcrc_buffer_lock();
tcramcache.hdr = core_get_data(handle);
rc = read(fd, tcramcache.hdr, shdr.tc_stat.ramcache_allocated);
tcrc_buffer_unlock();
@@ -4338,11 +4330,11 @@ static bool load_tagcache(void)
unsigned int searchflag = auto_update ? DCS_STORAGE_PATH :
DCS_CACHED_PATH;
- int rc = dircache_search(searchflag | DCS_UPDATE_FILEREF,
- &tcrc_dcfrefs[idx_id], filename);
- if (rc > 0) /* in cache and we have fileref */
+ int rc_cache = dircache_search(searchflag | DCS_UPDATE_FILEREF,
+ &tcrc_dcfrefs[idx_id], filename);
+ if (rc_cache > 0) /* in cache and we have fileref */
idx->flag |= FLAG_DIRCACHE;
- else if (rc == 0) /* not in cache but okay */
+ else if (rc_cache == 0) /* not in cache but okay */
;
else if (auto_update)
#else /* ndef HAVE_DIRCACHE */
@@ -4413,12 +4405,11 @@ static bool check_deleted_files(void)
struct tagfile_entry tfe;
logf("reverse scan...");
- snprintf(buf, bufsz, TAGCACHE_FILE_INDEX, tag_filename);
- fd = open(buf, O_RDONLY);
+ fd = open_pathfmt(buf, bufsz, O_RDONLY, TAGCACHE_FILE_INDEX, tag_filename);
if (fd < 0)
{
- logf("%s open fail", buf);
+ logf(TAGCACHE_FILE_INDEX " open fail", tag_filename);
return false;
}
@@ -4742,7 +4733,7 @@ void do_tagcache_build(const char *path[])
/* check_dir might add new roots */
for(this = &roots_ll[0]; this; this = this->next)
{
- strlcpy(curpath, this->path, sizeof(curpath));
+ strmemccpy(curpath, this->path, sizeof(curpath));
ret = ret && check_dir(this->path, true);
}
free_search_roots(&roots_ll[0]);
@@ -4797,7 +4788,7 @@ void tagcache_build(void)
{
char *vect[MAX_STATIC_ROOTS + 1]; /* +1 to ensure NULL sentinel */
char str[sizeof(global_settings.tagcache_scan_paths)];
- strlcpy(str, global_settings.tagcache_scan_paths, sizeof(str));
+ strmemccpy(str, global_settings.tagcache_scan_paths, sizeof(str));
int res = split_string(str, ':', vect, MAX_STATIC_ROOTS);
vect[res] = NULL;
@@ -5084,6 +5075,12 @@ bool tagcache_is_usable(void)
{
return tc_stat.initialized && tc_stat.ready;
}
+#ifdef HAVE_TC_RAMCACHE
+bool tagcache_is_in_ram(void)
+{
+ return tc_stat.ramcache;
+}
+#endif
int tagcache_get_commit_step(void)
{
return tc_stat.commit_step;
diff --git a/apps/tagcache.h b/apps/tagcache.h
index 1218e42b42..690506b308 100644
--- a/apps/tagcache.h
+++ b/apps/tagcache.h
@@ -246,6 +246,7 @@ void tagcache_screensync_event(void);
void tagcache_screensync_enable(bool state);
#ifdef HAVE_TC_RAMCACHE
+bool tagcache_is_in_ram(void);
#ifdef HAVE_DIRCACHE
bool tagcache_fill_tags(struct mp3entry *id3, const char *filename);
#endif
diff --git a/apps/tagtree.c b/apps/tagtree.c
index 45d2bb991b..8e7b868dbc 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -117,7 +117,23 @@ static uint32_t uniqbuf[UNIQBUF_SIZE / sizeof(uint32_t)];
#define MAX_MENU_ID_SIZE 32
#define RELOAD_TAGTREE (-1024)
-static bool sort_inverse;
+
+static int(*qsort_fn)(const char*, const char*, size_t);
+/* dummmy functions to allow compatibility strncasecmp */
+static int strnatcasecmp_n(const char *a, const char *b, size_t n)
+{
+ (void)n;
+ return strnatcasecmp(a, b);
+}
+static int strnatcasecmp_n_inv(const char *a, const char *b, size_t n)
+{
+ (void)n;
+ return strnatcasecmp(b, a);
+}
+static int strncasecmp_inv(const char *a, const char *b, size_t n)
+{
+ return strncasecmp(b, a, n);
+}
/*
* "%3d. %s" autoscore title %sort = "inverse" %limit = "100"
@@ -191,8 +207,13 @@ static int current_entry_count;
static struct tree_context *tc;
+static int max_history_level; /* depth of menu levels with applicable history */
+static int selected_item_history[MAX_DIR_LEVELS];
+static int table_history[MAX_DIR_LEVELS];
+static int extra_history[MAX_DIR_LEVELS];
+
/* a few memory alloc helper */
-static int tagtree_handle, lock_count;
+static int tagtree_handle;
static size_t tagtree_bufsize, tagtree_buf_used;
#define UPDATE(x, y) { x = (typeof(x))((char*)(x) + (y)); }
@@ -201,9 +222,6 @@ static int move_callback(int handle, void* current, void* new)
(void)handle; (void)current; (void)new;
ptrdiff_t diff = new - current;
- if (lock_count > 0)
- return BUFLIB_CB_CANNOT_MOVE;
-
if (menu)
UPDATE(menu, diff);
@@ -213,11 +231,11 @@ static int move_callback(int handle, void* current, void* new)
/* loop over menus */
for(int i = 0; i < menu_count; i++)
{
- struct menu_root* menu = menus[i];
+ struct menu_root* menuroot = menus[i];
/* then over the menu_entries of a menu */
- for(int j = 0; j < menu->itemcount; j++)
+ for(int j = 0; j < menuroot->itemcount; j++)
{
- struct menu_entry* mentry = menu->items[j];
+ struct menu_entry* mentry = menuroot->items[j];
/* then over the search_instructions of each menu_entry */
for(int k = 0; k < mentry->si.tagorder_count; k++)
{
@@ -228,7 +246,7 @@ static int move_callback(int handle, void* current, void* new)
UPDATE(mentry->si.clause[k][l], diff);
}
}
- UPDATE(menu->items[j], diff);
+ UPDATE(menuroot->items[j], diff);
}
UPDATE(menus[i], diff);
}
@@ -251,16 +269,6 @@ static int move_callback(int handle, void* current, void* new)
}
#undef UPDATE
-static inline void tagtree_lock(void)
-{
- lock_count++;
-}
-
-static inline void tagtree_unlock(void)
-{
- lock_count--;
-}
-
static struct buflib_callbacks ops = {
.move_callback = move_callback,
.shrink_callback = NULL,
@@ -623,7 +631,7 @@ static int add_format(const char *buf)
int clause_count = 0;
strp++;
- tagtree_lock();
+ core_pin(tagtree_handle);
while (1)
{
struct tagcache_search_clause *new_clause;
@@ -646,7 +654,7 @@ static int add_format(const char *buf)
clause_count++;
}
- tagtree_unlock();
+ core_unpin(tagtree_handle);
formats[format_count]->clause_count = clause_count;
}
@@ -719,9 +727,9 @@ static int get_condition(struct search_instruction *inst)
}
else
{
- tagtree_lock();
+ core_pin(tagtree_handle);
bool ret = read_clause(new_clause);
- tagtree_unlock();
+ core_unpin(tagtree_handle);
if (!ret)
return -1;
}
@@ -787,7 +795,7 @@ static bool parse_search(struct menu_entry *entry, const char *str)
logf("tagtree failed to allocate %s", "menu");
return false;
}
- strlcpy(menus[menu_count]->id, buf, MAX_MENU_ID_SIZE);
+ strmemccpy(menus[menu_count]->id, buf, MAX_MENU_ID_SIZE);
entry->link = menu_count;
++menu_count;
@@ -812,9 +820,9 @@ static bool parse_search(struct menu_entry *entry, const char *str)
logf("tag: %d", inst->tagorder[inst->tagorder_count]);
- tagtree_lock();
+ core_pin(tagtree_handle);
while ( (ret = get_condition(inst)) > 0 ) ;
- tagtree_unlock();
+ core_unpin(tagtree_handle);
if (ret < 0)
return false;
@@ -832,22 +840,7 @@ static int compare(const void *p1, const void *p2)
{
struct tagentry *e1 = (struct tagentry *)p1;
struct tagentry *e2 = (struct tagentry *)p2;
-
- if (sort_inverse)
- return strncasecmp(e2->name, e1->name, MAX_PATH);
-
- return strncasecmp(e1->name, e2->name, MAX_PATH);
-}
-
-static int nat_compare(const void *p1, const void *p2)
-{
- struct tagentry *e1 = (struct tagentry *)p1;
- struct tagentry *e2 = (struct tagentry *)p2;
-
- if (sort_inverse)
- return strnatcasecmp(e2->name, e1->name);
-
- return strnatcasecmp(e1->name, e2->name);
+ return qsort_fn(e1->name, e2->name, MAX_PATH);
}
static void tagtree_buffer_event(unsigned short id, void *ev_data)
@@ -1126,7 +1119,7 @@ static int parse_line(int n, char *buf, void *parameters)
}
menu = menus[menu_count];
++menu_count;
- strlcpy(menu->id, data, MAX_MENU_ID_SIZE);
+ strmemccpy(menu->id, data, MAX_MENU_ID_SIZE);
}
if (get_token_str(menu->title, sizeof(menu->title)) < 0)
@@ -1176,10 +1169,10 @@ static int parse_line(int n, char *buf, void *parameters)
logf("tagtree failed to allocate %s", "menu items");
return -2;
}
- tagtree_lock();
+ core_pin(tagtree_handle);
if (parse_search(menu->items[menu->itemcount], buf))
menu->itemcount++;
- tagtree_unlock();
+ core_unpin(tagtree_handle);
return 0;
}
@@ -1212,8 +1205,8 @@ static bool parse_menu(const char *filename)
static void tagtree_unload(struct tree_context *c)
{
- int i;
- tagtree_lock();
+ /* may be spurious... */
+ core_pin(tagtree_handle);
remove_event(PLAYBACK_EVENT_TRACK_BUFFER, tagtree_buffer_event);
remove_event(PLAYBACK_EVENT_TRACK_FINISH, tagtree_track_finish_event);
@@ -1229,7 +1222,7 @@ static void tagtree_unload(struct tree_context *c)
return;
}
- for (i = 0; i < menu->itemcount; i++)
+ for (int i = 0; i < menu->itemcount; i++)
{
dptr->name = NULL;
dptr->newtable = 0;
@@ -1238,11 +1231,11 @@ static void tagtree_unload(struct tree_context *c)
}
}
- for (i = 0; i < menu_count; i++)
+ for (int i = 0; i < menu_count; i++)
menus[i] = NULL;
menu_count = 0;
- for (i = 0; i < format_count; i++)
+ for (int i = 0; i < format_count; i++)
formats[i] = NULL;
format_count = 0;
@@ -1253,13 +1246,11 @@ static void tagtree_unload(struct tree_context *c)
if (c)
tree_unlock_cache(c);
- tagtree_unlock();
- if (lock_count > 0)
- tagtree_unlock();/* second unlock to enable re-init */
}
void tagtree_init(void)
{
+ max_history_level = 0;
format_count = 0;
menu_count = 0;
menu = NULL;
@@ -1285,8 +1276,6 @@ void tagtree_init(void)
if (sizeof(struct tagentry) != sizeof(struct entry))
panicf("tagentry(%zu) and entry mismatch(%zu)",
sizeof(struct tagentry), sizeof(struct entry));
- if (lock_count > 0)
- panicf("tagtree locked after parsing");
/* If no root menu is set, assume it's the first single menu
* we have. That shouldn't normally happen. */
@@ -1440,6 +1429,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init)
int level = c->currextra;
int tag;
bool sort = false;
+ bool sort_inverse;
int sort_limit;
int strip;
@@ -1447,6 +1437,9 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init)
otherwise show it after the normal 1/2 second delay */
show_search_progress(
#ifdef HAVE_DISK_STORAGE
+#ifdef HAVE_TC_RAMCACHE
+ tagcache_is_in_ram() ? true :
+#endif
storage_disk_is_active()
#else
true
@@ -1495,7 +1488,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init)
/* because tagcache saves the clauses, we need to lock the buffer
* for the entire duration of the search */
- tagtree_lock();
+ core_pin(tagtree_handle);
for (i = 0; i <= level; i++)
{
int j;
@@ -1572,7 +1565,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init)
fmt = NULL;
/* Check the format */
- tagtree_lock();
+ core_pin(tagtree_handle);
for (i = 0; i < format_count; i++)
{
if (formats[i]->group_id != csi->format_id[level])
@@ -1585,18 +1578,18 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init)
break;
}
}
- tagtree_unlock();
+ core_unpin(tagtree_handle);
if (strcmp(tcs.result, UNTAGGED) == 0)
{
- if (tag == tag_title) /* Fallback to filename */
- {
+ if (tag == tag_title && tcs.type == tag_title && tcs.filter_count <= 1)
+ { /* Fallback to filename */
char *lastname = dptr->name;
dptr->name = core_get_data(c->cache.name_buffer_handle)+namebufused;
if (tagcache_retrieve(&tcs, tcs.idx_id, tag_filename, dptr->name,
c->cache.name_buffer_size - namebufused))
{
- namebufused += strlen(dptr->name)+1;
+ namebufused += tcs.result_len;
goto entry_skip_formatter;
}
dptr->name = lastname; /* restore last entry if filename failed */
@@ -1627,7 +1620,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init)
logf("format_str() failed");
tagcache_search_finish(&tcs);
tree_unlock_cache(c);
- tagtree_unlock();
+ core_unpin(tagtree_handle);
return 0;
}
else
@@ -1668,7 +1661,7 @@ entry_skip_formatter:
{ /* user aborted */
tagcache_search_finish(&tcs);
tree_unlock_cache(c);
- tagtree_unlock();
+ core_unpin(tagtree_handle);
return current_entry_count;
}
}
@@ -1676,18 +1669,23 @@ entry_skip_formatter:
if (sort)
{
+ if (global_settings.interpret_numbers)
+ qsort_fn = sort_inverse ? strnatcasecmp_n_inv : strnatcasecmp_n;
+ else
+ qsort_fn = sort_inverse ? strncasecmp_inv : strncasecmp;
+
struct tagentry *entries = get_entries(c);
qsort(&entries[special_entry_count],
current_entry_count - special_entry_count,
sizeof(struct tagentry),
- global_settings.interpret_numbers ? nat_compare : compare);
+ compare);
}
if (!init)
{
tagcache_search_finish(&tcs);
tree_unlock_cache(c);
- tagtree_unlock();
+ core_unpin(tagtree_handle);
return current_entry_count;
}
@@ -1703,7 +1701,7 @@ entry_skip_formatter:
tagcache_search_finish(&tcs);
tree_unlock_cache(c);
- tagtree_unlock();
+ core_unpin(tagtree_handle);
if (!sort && (sort_inverse || sort_limit))
{
@@ -1829,7 +1827,16 @@ int tagtree_load(struct tree_context* c)
return count;
}
-int tagtree_enter(struct tree_context* c)
+/* Enters menu or table for selected item in the database.
+ *
+ * Call this with the is_visible parameter set to false to
+ * prevent selected_item_history from being updated or applied, in
+ * case the menus aren't displayed to the user.
+ * Before calling tagtree_enter again with the parameter set to
+ * true, make sure that you are back at the previous dirlevel, by
+ * calling tagtree_exit as needed, with is_visible set to false.
+ */
+int tagtree_enter(struct tree_context* c, bool is_visible)
{
int rc = 0;
struct tagentry *dptr;
@@ -1837,14 +1844,17 @@ int tagtree_enter(struct tree_context* c)
int newextra;
int seek;
int source;
+ bool is_random_item = false;
+ bool adjust_selection = true;
dptr = tagtree_get_entry(c, c->selected_item);
c->dirfull = false;
seek = dptr->extraseek;
- if (seek == -1)
+ if (seek == -1) /* <Random> menu item was selected */
{
- if(c->filesindir<=2)
+ is_random_item = true;
+ if(c->filesindir<=2) /* Menu contains only <All> and <Random> menu items */
return 0;
srand(current_tick);
dptr = (tagtree_get_entry(c, 2+(rand() % (c->filesindir-2))));
@@ -1855,17 +1865,28 @@ int tagtree_enter(struct tree_context* c)
if (c->dirlevel >= MAX_DIR_LEVELS)
return 0;
- c->selected_item_history[c->dirlevel]=c->selected_item;
- c->table_history[c->dirlevel] = c->currtable;
- c->extra_history[c->dirlevel] = c->currextra;
- c->pos_history[c->dirlevel] = c->firstpos;
+ if (is_visible) /* update selection history only for user-selected items */
+ {
+ /* We need to discard selected item history for levels
+ descending from current one if selection has changed */
+ if (max_history_level < c->dirlevel + 1
+ || (max_history_level > c->dirlevel
+ && selected_item_history[c->dirlevel] != c->selected_item)
+ || is_random_item)
+ {
+ max_history_level = c->dirlevel + 1;
+ selected_item_history[c->dirlevel + 1] = 0;
+ }
+
+ selected_item_history[c->dirlevel]=c->selected_item;
+ }
+ table_history[c->dirlevel] = c->currtable;
+ extra_history[c->dirlevel] = c->currextra;
c->dirlevel++;
/* lock buflib for possible I/O to protect dptr */
tree_lock_cache(c);
- tagtree_lock();
-
- bool reset_selection = true;
+ core_pin(tagtree_handle);
switch (c->currtable) {
case ROOT:
@@ -1884,8 +1905,8 @@ int tagtree_enter(struct tree_context* c)
csi = &menu->items[seek]->si;
c->currextra = 0;
- strlcpy(current_title[c->currextra], dptr->name,
- sizeof(current_title[0]));
+ strmemccpy(current_title[c->currextra], dptr->name,
+ sizeof(current_title[0]));
/* Read input as necessary. */
for (i = 0; i < csi->tagorder_count; i++)
@@ -1902,6 +1923,10 @@ int tagtree_enter(struct tree_context* c)
if (source == source_constant)
continue;
+ /* discard history for lower levels when doing runtime searches */
+ if (is_visible)
+ max_history_level = c->dirlevel - 1;
+
searchstring=csi->clause[i][j]->str;
*searchstring = '\0';
@@ -1910,7 +1935,7 @@ int tagtree_enter(struct tree_context* c)
if (source == source_current_path && id3)
{
char *e;
- strlcpy(searchstring, id3->path, SEARCHSTR_SIZE);
+ strmemccpy(searchstring, id3->path, SEARCHSTR_SIZE);
e = strrchr(searchstring, '/');
if (e)
*e = '\0';
@@ -1923,7 +1948,7 @@ int tagtree_enter(struct tree_context* c)
char **src = (char**)((char*)id3 + offset);
if (*src)
{
- strlcpy(searchstring, *src, SEARCHSTR_SIZE);
+ strmemccpy(searchstring, *src, SEARCHSTR_SIZE);
}
}
else
@@ -1931,9 +1956,9 @@ int tagtree_enter(struct tree_context* c)
rc = kbd_input(searchstring, SEARCHSTR_SIZE, NULL);
if (rc < 0 || !searchstring[0])
{
- tagtree_exit(c);
+ tagtree_exit(c, is_visible);
tree_unlock_cache(c);
- tagtree_unlock();
+ core_unpin(tagtree_handle);
return 0;
}
if (csi->clause[i][j]->numeric)
@@ -1952,7 +1977,7 @@ int tagtree_enter(struct tree_context* c)
case ALLSUBENTRIES:
if (newextra == PLAYTRACK)
{
- reset_selection = false;
+ adjust_selection = false;
if (global_settings.party_mode && audio_status()) {
splash(HZ, ID2P(LANG_PARTY_MODE));
@@ -1976,8 +2001,8 @@ int tagtree_enter(struct tree_context* c)
c->dirlevel--;
/* Update the statusbar title */
- strlcpy(current_title[c->currextra], dptr->name,
- sizeof(current_title[0]));
+ strmemccpy(current_title[c->currextra], dptr->name,
+ sizeof(current_title[0]));
break;
default:
@@ -1985,28 +2010,32 @@ int tagtree_enter(struct tree_context* c)
break;
}
- if (reset_selection)
+ if (adjust_selection)
{
- c->selected_item=0;
- gui_synclist_select_item(&tree_lists, c->selected_item);
+ if (is_visible && c->dirlevel <= max_history_level)
+ c->selected_item = selected_item_history[c->dirlevel];
+ else
+ c->selected_item = 0;
}
tree_unlock_cache(c);
- tagtree_unlock();
+ core_unpin(tagtree_handle);
return rc;
}
-void tagtree_exit(struct tree_context* c)
+/* Exits current database menu or table */
+void tagtree_exit(struct tree_context* c, bool is_visible)
{
+ if (is_visible) /* update selection history only for user-selected items */
+ selected_item_history[c->dirlevel] = c->selected_item;
c->dirfull = false;
if (c->dirlevel > 0)
c->dirlevel--;
- c->selected_item=c->selected_item_history[c->dirlevel];
- gui_synclist_select_item(&tree_lists, c->selected_item);
- c->currtable = c->table_history[c->dirlevel];
- c->currextra = c->extra_history[c->dirlevel];
- c->firstpos = c->pos_history[c->dirlevel];
+ if (is_visible)
+ c->selected_item=selected_item_history[c->dirlevel];
+ c->currtable = table_history[c->dirlevel];
+ c->currextra = extra_history[c->dirlevel];
}
int tagtree_get_filename(struct tree_context* c, char *buf, int buflen)
@@ -2032,10 +2061,9 @@ int tagtree_get_filename(struct tree_context* c, char *buf, int buflen)
static bool insert_all_playlist(struct tree_context *c, int position, bool queue)
{
struct tagcache_search tcs;
- int i;
+ int i, n;
+ unsigned long last_tick;
char buf[MAX_PATH];
- int from, to, direction;
- int files_left = c->filesindir;
cpu_boost(true);
if (!tagcache_search(&tcs, tag_filename))
@@ -2056,15 +2084,19 @@ static bool insert_all_playlist(struct tree_context *c, int position, bool queue
}
}
- from = 0;
- to = c->filesindir;
- direction = 1;
-
- for (i = from; i != to; i += direction)
+ last_tick = current_tick + HZ/2; /* Show splash after 0.5 seconds have passed */
+ splash_progress_set_delay(HZ / 2); /* wait 1/2 sec before progress */
+ n = c->filesindir;
+ for (i = 0; i < n; i++)
{
- /* Count back to zero */
- if (!show_search_progress(false, files_left--))
- break;
+
+ splash_progress(i, n, "%s (%s)", str(LANG_WAIT), str(LANG_OFF_ABORT));
+ if (TIME_AFTER(current_tick, last_tick + HZ/4))
+ {
+ if (action_userabort(TIMEOUT_NOBLOCK))
+ break;
+ last_tick = current_tick;
+ }
if (!tagcache_retrieve(&tcs, tagtree_get_entry(c, i)->extraseek,
tcs.type, buf, sizeof buf))
@@ -2095,6 +2127,7 @@ bool tagtree_insert_selection_playlist(int position, bool queue)
{
char buf[MAX_PATH];
int dirlevel = tc->dirlevel;
+ int selected_item = tc->selected_item;
int newtable;
show_search_progress(
@@ -2124,7 +2157,7 @@ bool tagtree_insert_selection_playlist(int position, bool queue)
if (newtable == NAVIBROWSE)
{
- tagtree_enter(tc);
+ tagtree_enter(tc, false);
tagtree_load(tc);
newtable = tagtree_get_entry(tc, tc->selected_item)->newtable;
}
@@ -2137,7 +2170,7 @@ bool tagtree_insert_selection_playlist(int position, bool queue)
/* Now the current table should be allsubentries. */
if (newtable != PLAYTRACK)
{
- tagtree_enter(tc);
+ tagtree_enter(tc, false);
tagtree_load(tc);
newtable = tagtree_get_entry(tc, tc->selected_item)->newtable;
@@ -2145,7 +2178,9 @@ bool tagtree_insert_selection_playlist(int position, bool queue)
if (newtable != PLAYTRACK)
{
logf("newtable: %d !!", newtable);
- tc->dirlevel = dirlevel;
+ while (tc->dirlevel > dirlevel)
+ tagtree_exit(tc, false);
+ tagtree_load(tc);
return false;
}
}
@@ -2161,7 +2196,8 @@ bool tagtree_insert_selection_playlist(int position, bool queue)
/* Finally return the dirlevel to its original value. */
while (tc->dirlevel > dirlevel)
- tagtree_exit(tc);
+ tagtree_exit(tc, false);
+ tc->selected_item = selected_item;
tagtree_load(tc);
return true;
@@ -2169,6 +2205,8 @@ bool tagtree_insert_selection_playlist(int position, bool queue)
static int tagtree_play_folder(struct tree_context* c)
{
+ int start_index = c->selected_item;
+
if (playlist_create(NULL, NULL) < 0)
{
logf("Failed creating playlist\n");
@@ -2179,12 +2217,13 @@ static int tagtree_play_folder(struct tree_context* c)
return -2;
if (global_settings.playlist_shuffle)
- c->selected_item = playlist_shuffle(current_tick, c->selected_item);
- if (!global_settings.play_selected)
- c->selected_item = 0;
- gui_synclist_select_item(&tree_lists, c->selected_item);
+ {
+ start_index = playlist_shuffle(current_tick, c->selected_item);
+ if (!global_settings.play_selected)
+ start_index = 0;
+ }
- playlist_start(c->selected_item, 0, 0);
+ playlist_start(start_index, 0, 0);
playlist_get_current()->num_inserted_tracks = 0; /* make warn on playlist erase work */
return 0;
}
@@ -2219,7 +2258,7 @@ char* tagtree_get_entry_name(struct tree_context *c, int id,
struct tagentry *entry = tagtree_get_entry(c, id);
if (!entry)
return NULL;
- strlcpy(buf, entry->name, bufsize);
+ strmemccpy(buf, entry->name, bufsize);
return buf;
}
diff --git a/apps/tagtree.h b/apps/tagtree.h
index 427a602df6..5c938b1541 100644
--- a/apps/tagtree.h
+++ b/apps/tagtree.h
@@ -34,8 +34,8 @@
int tagtree_export(void);
int tagtree_import(void);
void tagtree_init(void) INIT_ATTR;
-int tagtree_enter(struct tree_context* c);
-void tagtree_exit(struct tree_context* c);
+int tagtree_enter(struct tree_context* c, bool is_visible);
+void tagtree_exit(struct tree_context* c, bool is_visible);
int tagtree_load(struct tree_context* c);
char* tagtree_get_entry_name(struct tree_context *c, int id,
char* buf, size_t bufsize);
diff --git a/apps/talk.c b/apps/talk.c
index 1be2a041c2..c3a1148df4 100644
--- a/apps/talk.c
+++ b/apps/talk.c
@@ -97,7 +97,7 @@ struct voicefile_header /* file format of our voice file */
#define MAX_CLIP_BUFFER_SIZE (1<<30)
#endif
#define THUMBNAIL_RESERVE (50000)
-
+#define NULL_TERMINATED ((size_t)-1)
/* Multiple thumbnails can be loaded back-to-back in this buffer. */
static volatile int thumbnail_buf_used SHAREDBSS_ATTR; /* length of data in
thumbnail buffer */
@@ -118,6 +118,7 @@ static unsigned char last_lang[MAX_FILENAME+1]; /* name of last used lang file (
static bool talk_initialized; /* true if talk_init has been called */
static bool give_buffer_away; /* true if we should give the buffers away in shrink_callback if requested */
static int talk_temp_disable_count; /* if positive, temporarily disable voice UI (not saved) */
+
/* size of the voice data in the voice file and the actually allocated buffer
* for it. voicebuf_size is always smaller or equal to voicefile_size */
static unsigned long voicefile_size, voicebuf_size;
@@ -226,7 +227,7 @@ static int shrink_callback(int handle, unsigned hints, void *start, size_t old_s
mutex_lock(&read_buffer_mutex);
/* the clip buffer isn't usable without index table */
- if (handle == index_handle && talk_handle > 0)
+ if (handle == index_handle)
talk_handle = core_free(talk_handle);
if (h)
*h = core_free(handle);
@@ -246,7 +247,7 @@ static struct buflib_callbacks talk_ops = {
static int open_voicefile(void)
{
- char buf[64];
+ char fname[MAX_PATH];
char* p_lang = DEFAULT_VOICE_LANG; /* default */
if ( global_settings.lang_file[0] &&
@@ -255,9 +256,8 @@ static int open_voicefile(void)
p_lang = (char *)global_settings.lang_file;
}
- snprintf(buf, sizeof(buf), LANG_DIR "/%s.voice", p_lang);
-
- return open(buf, O_RDONLY);
+ return open_pathfmt(fname, sizeof(fname),
+ O_RDONLY, LANG_DIR "/%s.voice", p_lang);
}
@@ -306,14 +306,15 @@ static int free_oldest_clip(void)
unsigned i;
int oldest = 0;
bool thumb = false;
- long age, now;
+ long age, now, next_age;
struct clip_entry* clipbuf;
struct clip_cache_metadata *cc = buflib_get_data(&clip_ctx, metadata_table_handle);
for(age = i = 0, now = current_tick; i < max_clips; i++)
{
if (cc[i].handle)
{
- if (thumb && cc[i].voice_id == VOICEONLY_DELIMITER && (now - cc[i].tick) > age)
+ next_age = (now - cc[i].tick);
+ if (thumb && cc[i].voice_id == VOICEONLY_DELIMITER && next_age > age)
{
/* thumb clips are freed first */
age = now - cc[i].tick;
@@ -323,14 +324,14 @@ static int free_oldest_clip(void)
{
if (cc[i].voice_id == VOICEONLY_DELIMITER)
{
- age = now - cc[i].tick;
+ age = next_age;
oldest = i;
thumb = true;
}
- else if ((now - cc[i].tick) > age && cc[i].voice_id != VOICE_PAUSE)
+ else if (next_age > age && cc[i].voice_id != VOICE_PAUSE)
{
/* find the last-used clip but never consider silence */
- age = now - cc[i].tick;
+ age = next_age;
oldest = i;
}
}
@@ -348,7 +349,6 @@ static int free_oldest_clip(void)
return oldest;
}
-
/* common code for load_initial_clips() and get_clip() */
static void add_cache_entry(int clip_handle, int table_index, int id)
{
@@ -546,16 +546,17 @@ static bool create_clip_buffer(size_t max_size)
alloc_err:
talk_status = TALK_STATUS_ERR_ALLOC;
- if (index_handle > 0)
- index_handle = core_free(index_handle);
+ index_handle = core_free(index_handle);
return false;
}
+
static inline int load_voicefile_failure(int fd)
{
if (fd >= 0)
close(fd);
return -1;
}
+
/* load the voice file into the mp3 buffer */
static bool load_voicefile_index(int fd)
{
@@ -621,8 +622,7 @@ static bool load_voicefile_data(int fd)
/* just allocate, populate on an as-needed basis later
* re-create the clip buffer to ensure clip_ctx is up-to-date */
- if (talk_handle > 0)
- talk_handle = core_free(talk_handle);
+ talk_handle = core_free(talk_handle);
if (!create_clip_buffer(voicebuf_size))
return false;
@@ -721,6 +721,102 @@ static void mp3_callback(const void** start, size_t* size)
talk_queue_unlock();
}
+/***************** Private routines *****************/
+
+/* return if a voice codec is required or not */
+static bool talk_voice_required(void)
+{
+ return (has_voicefile) /* Voice file is available */
+ || (global_settings.talk_dir_clip) /* Thumbnail clips are required */
+ || (global_settings.talk_file_clip);
+}
+
+static bool talk_is_disabled(void)
+{
+ if (talk_temp_disable_count > 0 || (!check_audio_status()))
+ return true;
+ return false;
+}
+
+static void do_enqueue(bool enqueue)
+{
+ if (!enqueue)
+ talk_shutup(); /* cut off all the pending stuff */
+}
+
+/* spell a string */
+static int _talk_spell(const char* spell, size_t len, bool enqueue)
+{
+ char c; /* currently processed char */
+
+ if (talk_is_disabled())
+ return -1;
+
+ do_enqueue(enqueue); /* cut off all the pending stuff */
+
+ size_t len0 = len - 1;
+
+ while ((c = *spell++) != '\0' && len0-- < len)
+ {
+ /* if this grows into too many cases, I should use a table */
+ if (c >= 'A' && c <= 'Z')
+ talk_id(VOICE_CHAR_A + c - 'A', true);
+ else if (c >= 'a' && c <= 'z')
+ talk_id(VOICE_CHAR_A + c - 'a', true);
+ else if (c >= '0' && c <= '9')
+ talk_id(VOICE_ZERO + c - '0', true);
+ else if (c == '-')
+ talk_id(VOICE_MINUS, true);
+ else if (c == '+')
+ talk_id(VOICE_PLUS, true);
+ else if (c == '.')
+ talk_id(VOICE_DOT, true);
+ else if (c == ' ')
+ talk_id(VOICE_PAUSE, true);
+ else if (c == '/')
+ talk_id(VOICE_CHAR_SLASH, true);
+
+ while (QUEUE_LEVEL == QUEUE_SIZE - 1) /* queue full - busy loop */
+ yield();
+ }
+ return 0;
+}
+
+static int talk_spell_basename(const char *path,
+ const long *prefix_ids, bool enqueue)
+{
+ if(prefix_ids)
+ {
+ talk_idarray(prefix_ids, enqueue);
+ enqueue = true;
+ }
+ const char *basename;
+ size_t len = path_basename(path, &basename);
+
+ return _talk_spell(basename, len, enqueue);
+}
+
+/* Say year like "nineteen ninety nine" instead of "one thousand 9
+ hundred ninety nine". */
+static int talk_year(long year, bool enqueue)
+{
+ int rem;
+ if(year < 1100 || (year >=2000 && year < 2100))
+ /* just say it as a regular number */
+ return talk_number(year, enqueue);
+ /* Say century */
+ talk_number(year/100, enqueue);
+ rem = year%100;
+ if(rem == 0)
+ /* as in 1900 */
+ return talk_id(VOICE_HUNDRED, true);
+ if(rem <10)
+ /* as in 1905 */
+ talk_id(VOICE_ZERO, true);
+ /* sub-century year */
+ return talk_number(rem, true);
+}
+
/***************** Public routines *****************/
/* stop the playback and the pending clips */
@@ -748,8 +844,8 @@ static void queue_clip(struct queue_entry *clip, bool enqueue)
struct queue_entry *qe;
int queue_level;
- if (!enqueue)
- talk_shutup(); /* cut off all the pending stuff */
+ do_enqueue(enqueue); /* cut off all the pending stuff */
+
/* Something is being enqueued, force_enqueue_next override is no
longer in effect. */
force_enqueue_next = false;
@@ -783,14 +879,6 @@ static void queue_clip(struct queue_entry *clip, bool enqueue)
return;
}
-/* return if a voice codec is required or not */
-static bool talk_voice_required(void)
-{
- return (has_voicefile) /* Voice file is available */
- || (global_settings.talk_dir_clip) /* Thumbnail clips are required */
- || (global_settings.talk_file_clip);
-}
-
/***************** Public implementation *****************/
void talk_init(void)
@@ -812,8 +900,8 @@ void talk_init(void)
talk_force_shutup(); /* In case we have something speaking! */
talk_initialized = true;
- strlcpy((char *)last_lang, (char *)global_settings.lang_file,
- MAX_FILENAME);
+ strmemccpy((char *)last_lang, (char *)global_settings.lang_file,
+ MAX_FILENAME);
/* reset some states */
queue_write = queue_read = 0; /* reset the queue */
@@ -823,8 +911,8 @@ void talk_init(void)
voicefile_size = has_voicefile = 0;
/* need to free these as their size depends on the voice file, and
* this function is called when the talk voice file changes */
- if (index_handle > 0) index_handle = core_free(index_handle);
- if (talk_handle > 0) talk_handle = core_free(talk_handle);
+ index_handle = core_free(index_handle);
+ talk_handle = core_free(talk_handle);
/* don't free thumb handle, it doesn't depend on the actual voice file
* and so we can re-use it if it's already allocated in any event */
@@ -887,6 +975,7 @@ out:
/* somebody else claims the mp3 buffer, e.g. for regular play/record */
void talk_buffer_set_policy(int policy)
{
+#ifdef DEBUG
switch(policy)
{
case TALK_BUFFER_DEFAULT:
@@ -894,6 +983,9 @@ void talk_buffer_set_policy(int policy)
case TALK_BUFFER_LOOSE: give_buffer_away = true; break;
default: DEBUGF("Ignoring unknown policy\n"); break;
}
+#else
+ give_buffer_away = (policy == TALK_BUFFER_LOOSE);
+#endif
}
/* play a voice ID from voicefile */
@@ -905,10 +997,8 @@ int talk_id(int32_t id, bool enqueue)
bool isloaded = true;
if (!has_voicefile)
- return 0; /* no voicefile loaded, not an error -> pretent success */
- if (talk_temp_disable_count > 0)
- return -1; /* talking has been disabled */
- if (!check_audio_status())
+ return 0; /* no voicefile loaded, not an error -> pretend success */
+ if (talk_is_disabled())
return -1;
if (talk_handle <= 0 || index_handle <= 0) /* reload needed? */
@@ -950,6 +1040,7 @@ int talk_id(int32_t id, bool enqueue)
return 0;
}
+
/* Speaks zero or more IDs (from an array). */
int talk_idarray(const long *ids, bool enqueue)
{
@@ -983,22 +1074,18 @@ static int _talk_file(const char* filename,
int oldest = -1;
/* reload needed? */
- if (talk_temp_disable_count > 0)
- return -1; /* talking has been disabled */
- if (!check_audio_status())
+ if (talk_is_disabled())
return -1;
if (talk_handle <= 0 || index_handle <= 0)
{
- int fd = open_voicefile();
+ fd = open_voicefile();
if (fd < 0 || !load_voicefile_index(fd))
return load_voicefile_failure(fd);
load_voicefile_data(fd);
close(fd);
}
- if (!enqueue)
- /* shutup now to free the thumbnail buffer */
- talk_shutup();
+ do_enqueue(enqueue); /* shutup now to free the thumbnail buffer */
fd = open(filename, O_RDONLY);
if (fd < 0) /* failed to open */
@@ -1047,38 +1134,18 @@ int talk_file(const char *root, const char *dir, const char *file,
/* Play a thumbnail file */
{
char buf[MAX_PATH];
+ const char *fmt = "%s%s%s%s%s";
/* Does root end with a slash */
- char *slash = (root && root[0]
- && root[strlen(root)-1] != '/') ? "/" : "";
- snprintf(buf, MAX_PATH, "%s%s%s%s%s%s",
- root ? root : "", slash,
+ if(root && root[0] && root[strlen(root)-1] != '/')
+ fmt = "%s/%s%s%s%s";
+ snprintf(buf, MAX_PATH, fmt,
+ root ? root : "",
dir ? dir : "", dir ? "/" : "",
file ? file : "",
ext ? ext : "");
return _talk_file(buf, prefix_ids, enqueue);
}
-static int talk_spell_basename(const char *path,
- const long *prefix_ids, bool enqueue)
-{
- if(prefix_ids)
- {
- talk_idarray(prefix_ids, enqueue);
- enqueue = true;
- }
- char buf[MAX_PATH];
- /* Spell only the path component after the last slash */
- strlcpy(buf, path, sizeof(buf));
- if(strlen(buf) >1 && buf[strlen(buf)-1] == '/')
- /* strip trailing slash */
- buf[strlen(buf)-1] = '\0';
- char *ptr = strrchr(buf, '/');
- if(ptr && strlen(buf) >1)
- ++ptr;
- else ptr = buf;
- return talk_spell(ptr, enqueue);
-}
-
/* Play a file's .talk thumbnail, fallback to spelling the filename, or
go straight to spelling depending on settings. */
int talk_file_or_spell(const char *dirname, const char *filename,
@@ -1090,7 +1157,7 @@ int talk_file_or_spell(const char *dirname, const char *filename,
prefix_ids, enqueue) >0)
return 0;
}
- if (global_settings.talk_file == 2)
+ if (global_settings.talk_file == TALK_SPEAK_SPELL)
/* Either .talk clips are disabled, or as a fallback */
return talk_spell_basename(filename, prefix_ids, enqueue);
return 0;
@@ -1107,7 +1174,7 @@ int talk_dir_or_spell(const char* dirname,
prefix_ids, enqueue) >0)
return 0;
}
- if (global_settings.talk_dir == 2)
+ if (global_settings.talk_dir == TALK_SPEAK_SPELL)
/* Either .talk clips disabled or as a fallback */
return talk_spell_basename(dirname, prefix_ids, enqueue);
return 0;
@@ -1117,14 +1184,14 @@ int talk_dir_or_spell(const char* dirname,
back or going straight to spelling depending on settings. */
int talk_fullpath(const char* path, bool enqueue)
{
- if (!enqueue)
- talk_shutup();
+ do_enqueue(enqueue); /* cut off all the pending stuff */
+
if(path[0] != '/')
/* path ought to start with /... */
return talk_spell(path, true);
talk_id(VOICE_CHAR_SLASH, true);
char buf[MAX_PATH];
- strlcpy(buf, path, MAX_PATH);
+ strmemccpy(buf, path, MAX_PATH);
char *start = buf+1; /* start of current component */
char *ptr = strchr(start, '/'); /* end of current component */
while(ptr) { /* There are more slashes ahead */
@@ -1147,13 +1214,10 @@ int talk_number(long n, bool enqueue)
int level = 2; /* mille count */
long mil = 1000000000; /* highest possible "-illion" */
- if (talk_temp_disable_count > 0)
- return -1; /* talking has been disabled */
- if (!check_audio_status())
+ if (talk_is_disabled())
return -1;
- if (!enqueue)
- talk_shutup(); /* cut off all the pending stuff */
+ do_enqueue(enqueue); /* cut off all the pending stuff */
if (n==0)
{ /* special case */
@@ -1238,27 +1302,6 @@ int talk_number(long n, bool enqueue)
return 0;
}
-/* Say year like "nineteen ninety nine" instead of "one thousand 9
- hundred ninety nine". */
-static int talk_year(long year, bool enqueue)
-{
- int rem;
- if(year < 1100 || (year >=2000 && year < 2100))
- /* just say it as a regular number */
- return talk_number(year, enqueue);
- /* Say century */
- talk_number(year/100, enqueue);
- rem = year%100;
- if(rem == 0)
- /* as in 1900 */
- return talk_id(VOICE_HUNDRED, true);
- if(rem <10)
- /* as in 1905 */
- talk_id(VOICE_ZERO, true);
- /* sub-century year */
- return talk_number(rem, true);
-}
-
/* Say time duration/interval. Input is time in seconds,
say hours,minutes,seconds. */
static int talk_time_unit(long secs, bool enqueue)
@@ -1331,9 +1374,7 @@ int talk_value_decimal(long n, int unit, int decimals, bool enqueue)
char tbuf[8];
char fmt[] = "%0nd";
- if (talk_temp_disable_count > 0)
- return -1; /* talking has been disabled */
- if (!check_audio_status())
+ if (talk_is_disabled())
return -1;
/* special pronounciation for year number */
@@ -1384,15 +1425,19 @@ int talk_value_decimal(long n, int unit, int decimals, bool enqueue)
return 0;
}
+static inline void talk_time_value(long n, int unit, bool enqueue)
+{
+ if (n != 0)
+ talk_value_decimal(n, unit, 0, enqueue);
+}
+
/* Say time duration/interval. Input is time unit specifies base unit,
say hours,minutes,seconds, milliseconds. or any combination thereof */
int talk_time_intervals(long time, int unit_idx, bool enqueue)
{
unsigned long units_in[UNIT_IDX_TIME_COUNT];
- if (talk_temp_disable_count > 0)
- return -1; /* talking has been disabled */
- if (!check_audio_status())
+ if (talk_is_disabled())
return -1;
if (talk_handle <= 0 || index_handle <= 0) /* reload needed? */
@@ -1404,8 +1449,7 @@ int talk_time_intervals(long time, int unit_idx, bool enqueue)
close(fd);
}
- if (!enqueue)
- talk_shutup(); /* cut off all the pending stuff */
+ do_enqueue(enqueue); /* cut off all the pending stuff */
time_split_units(unit_idx, labs(time), &units_in);
@@ -1416,22 +1460,10 @@ int talk_time_intervals(long time, int unit_idx, bool enqueue)
talk_value(0, unit_idx, true);
else
{
- if (units_in[UNIT_IDX_HR] != 0)
- {
- talk_value(units_in[UNIT_IDX_HR], UNIT_HOUR, true);
- }
- if (units_in[UNIT_IDX_MIN] != 0)
- {
- talk_value(units_in[UNIT_IDX_MIN], UNIT_MIN, true);
- }
- if (units_in[UNIT_IDX_SEC] != 0)
- {
- talk_value(units_in[UNIT_IDX_SEC], UNIT_SEC, true);
- }
- if (units_in[UNIT_IDX_MS] != 0)
- {
- talk_value(units_in[UNIT_IDX_MS], UNIT_MS, true);
- }
+ talk_time_value(units_in[UNIT_IDX_HR], UNIT_HOUR, true);
+ talk_time_value(units_in[UNIT_IDX_MIN], UNIT_MIN, true);
+ talk_time_value(units_in[UNIT_IDX_SEC], UNIT_SEC, true);
+ talk_time_value(units_in[UNIT_IDX_MS], UNIT_MS, true);
}
return -1;
@@ -1440,38 +1472,7 @@ int talk_time_intervals(long time, int unit_idx, bool enqueue)
/* spell a string */
int talk_spell(const char* spell, bool enqueue)
{
- char c; /* currently processed char */
-
- if (talk_temp_disable_count > 0)
- return -1; /* talking has been disabled */
- if (!check_audio_status())
- return -1;
-
- if (!enqueue)
- talk_shutup(); /* cut off all the pending stuff */
-
- while ((c = *spell++) != '\0')
- {
- /* if this grows into too many cases, I should use a table */
- if (c >= 'A' && c <= 'Z')
- talk_id(VOICE_CHAR_A + c - 'A', true);
- else if (c >= 'a' && c <= 'z')
- talk_id(VOICE_CHAR_A + c - 'a', true);
- else if (c >= '0' && c <= '9')
- talk_id(VOICE_ZERO + c - '0', true);
- else if (c == '-')
- talk_id(VOICE_MINUS, true);
- else if (c == '+')
- talk_id(VOICE_PLUS, true);
- else if (c == '.')
- talk_id(VOICE_DOT, true);
- else if (c == ' ')
- talk_id(VOICE_PAUSE, true);
- else if (c == '/')
- talk_id(VOICE_CHAR_SLASH, true);
- }
-
- return 0;
+ return _talk_spell(spell, NULL_TERMINATED, enqueue);
}
void talk_disable(bool disable)
@@ -1494,14 +1495,12 @@ void talk_setting(const void *global_settings_variable)
talk_id(setting->lang_id,false);
}
-
void talk_date(const struct tm *tm, bool enqueue)
{
const char *format = str(LANG_VOICED_DATE_FORMAT);
const char *ptr;
- if (!enqueue)
- talk_shutup(); /* cut off all the pending stuff */
+ do_enqueue(enqueue); /* cut off all the pending stuff */
for (ptr = format ; *ptr ; ptr++) {
switch(*ptr) {
@@ -1581,8 +1580,7 @@ void talk_announce_voice_invalid(void)
int buf_handle;
struct queue_entry qe;
- const char talkfile[] =
- LANG_DIR "/InvalidVoice_" DEFAULT_VOICE_LANG ".talk";
+ const char talkfile[] = LANG_DIR "/InvalidVoice_" DEFAULT_VOICE_LANG ".talk";
if (global_settings.talk_menu && talk_status != TALK_STATUS_OK)
{
@@ -1638,7 +1636,7 @@ bool talk_get_debug_data(struct talk_debug_data *data)
if (global_settings.lang_file[0] && global_settings.lang_file[0] != 0xff)
p_lang = (char *)global_settings.lang_file;
- strlcpy(data->voicefile, p_lang, sizeof(data->voicefile));
+ strmemccpy(data->voicefile, p_lang, sizeof(data->voicefile));
if (!has_voicefile || index_handle <= 0)
{
diff --git a/apps/talk.h b/apps/talk.h
index d5f3bb2996..6139b9ec46 100644
--- a/apps/talk.h
+++ b/apps/talk.h
@@ -64,6 +64,13 @@ enum talk_status {
TALK_STATUS_ERR_INCOMPATIBLE
};
+enum talk_speakmode {
+ /* voice mode: 0=off, 1=number, 2=spell */
+ TALK_SPEAK_OFF = 0,
+ TALK_SPEAK_NUMBER,
+ TALK_SPEAK_SPELL
+};
+
#define UNIT_SHIFT (32-5) /* this many bits left from UNIT_xx enum */
#define DECIMAL_SHIFT (32 - 8)
diff --git a/apps/tree.c b/apps/tree.c
index cef990617c..4a80591201 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -72,6 +72,7 @@
#include "list.h"
#include "splash.h"
#include "quickscreen.h"
+#include "shortcuts.h"
#include "appevents.h"
#include "root_menu.h"
@@ -88,7 +89,7 @@ static struct tree_context tc;
char lastfile[MAX_PATH];
static char lastdir[MAX_PATH];
#ifdef HAVE_TAGCACHE
-static int lasttable, lastextra, lastfirstpos;
+static int lasttable, lastextra;
#endif
static bool reload_dir = false;
@@ -247,6 +248,7 @@ static int tree_voice_cb(int selected_item, void * data)
did_clip = false;
}
}
+ bool spell_name = false;
if(!did_clip)
{
/* say the number or spell if required or as a fallback */
@@ -256,9 +258,6 @@ static int tree_voice_cb(int selected_item, void * data)
talk_id(is_dir ? VOICE_DIR : VOICE_FILE, false);
talk_number(selected_item+1 - (is_dir ? 0 : local_tc->dirsindir),
true);
- if(global_settings.talk_filetype
- && !is_dir && *local_tc->dirfilter < NUM_FILTER_MODES)
- say_filetype(attr);
break;
case 2: /* spelled */
talk_shutup();
@@ -266,13 +265,22 @@ static int tree_voice_cb(int selected_item, void * data)
{
if(is_dir)
talk_id(VOICE_DIR, true);
- else if(*local_tc->dirfilter < NUM_FILTER_MODES)
- say_filetype(attr);
}
- talk_spell(name, true);
+ spell_name = true;
break;
}
}
+
+ if(global_settings.talk_filetype && !is_dir
+ && *local_tc->dirfilter < NUM_FILTER_MODES)
+ {
+ say_filetype(attr);
+ }
+
+ /* spell name AFTER voicing filetype */
+ if (spell_name)
+ talk_spell(name, true);
+
return 0;
}
@@ -314,6 +322,18 @@ struct tree_context* tree_get_context(void)
return &tc;
}
+void tree_lock_cache(struct tree_context *t)
+{
+ core_pin(t->cache.name_buffer_handle);
+ core_pin(t->cache.entries_handle);
+}
+
+void tree_unlock_cache(struct tree_context *t)
+{
+ core_unpin(t->cache.name_buffer_handle);
+ core_unpin(t->cache.entries_handle);
+}
+
/*
* Returns the position of a given file in the current directory
* returns -1 if not found
@@ -351,7 +371,6 @@ static int update_dir(void)
if (id3db) {
if (tc.currtable != lasttable ||
tc.currextra != lastextra ||
- tc.firstpos != lastfirstpos ||
reload_dir)
{
if (tagtree_load(&tc) < 0)
@@ -359,7 +378,6 @@ static int update_dir(void)
lasttable = tc.currtable;
lastextra = tc.currextra;
- lastfirstpos = tc.firstpos;
changed = true;
}
}
@@ -372,15 +390,18 @@ static int update_dir(void)
{
if (ft_load(&tc, NULL) < 0)
return -1;
- strlcpy(lastdir, tc.currdir, MAX_PATH);
+ strmemccpy(lastdir, tc.currdir, MAX_PATH);
changed = true;
}
}
/* if selected item is undefined */
if (tc.selected_item == -1)
{
- /* use lastfile to determine the selected item */
- tc.selected_item = tree_get_file_position(lastfile);
+#ifdef HAVE_TAGCACHE
+ if (!id3db)
+#endif
+ /* use lastfile to determine the selected item */
+ tc.selected_item = tree_get_file_position(lastfile);
/* If the file doesn't exists, select the first one (default) */
if(tc.selected_item < 0)
@@ -497,10 +518,10 @@ char *getcwd(char *buf, getcwd_size_t size)
return tc.currdir;
else if (size)
{
- if ((getcwd_size_t)strlcpy(buf, tc.currdir, size) < size)
+ if (strmemccpy(buf, tc.currdir, size) != NULL)
return buf;
}
- /* size == 0, or truncation in strlcpy */
+ /* size == 0, or truncation in strmemccpy */
return NULL;
}
@@ -559,7 +580,7 @@ void set_current_file(const char *path)
name = strrchr(path+1,'/');
if (name)
{
- strlcpy(tc.currdir, path, name - path + 1);
+ strmemccpy(tc.currdir, path, name - path + 1);
name++;
}
else
@@ -568,7 +589,7 @@ void set_current_file(const char *path)
name = path+1;
}
- strlcpy(lastfile, name, MAX_PATH);
+ strmemccpy(lastfile, name, MAX_PATH);
/* If we changed dir we must recalculate the dirlevel
@@ -620,10 +641,8 @@ static int dirbrowse(void)
if (tc.selected_item < 0)
tc.selected_item = 0;
#ifdef HAVE_TAGCACHE
- tc.firstpos = 0;
lasttable = -1;
lastextra = -1;
- lastfirstpos = 0;
#endif
start_wps = false;
@@ -649,7 +668,7 @@ static int dirbrowse(void)
button = get_action(CONTEXT_TREE|ALLOW_SOFTLOCK,
list_do_action_timeout(&tree_lists, HZ/2));
oldbutton = button;
- gui_synclist_do_button(&tree_lists, &button,LIST_WRAP_UNLESS_HELD);
+ gui_synclist_do_button(&tree_lists, &button);
tc.selected_item = gui_synclist_get_sel_pos(&tree_lists);
switch ( button ) {
case ACTION_STD_OK:
@@ -671,7 +690,7 @@ static int dirbrowse(void)
}
}
#ifdef HAVE_TAGCACHE
- switch (id3db?tagtree_enter(&tc):ft_enter(&tc))
+ switch (id3db ? tagtree_enter(&tc, true) : ft_enter(&tc))
#else
switch (ft_enter(&tc))
#endif
@@ -711,7 +730,7 @@ static int dirbrowse(void)
#ifdef HAVE_TAGCACHE
if (id3db)
- tagtree_exit