summaryrefslogtreecommitdiffstats
path: root/apps/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/2048.c14
-rw-r--r--apps/plugins/CATEGORIES2
-rw-r--r--apps/plugins/SOURCES5
-rw-r--r--apps/plugins/SUBDIRS3
-rw-r--r--apps/plugins/alarmclock.c6
-rw-r--r--apps/plugins/announce_status.c107
-rw-r--r--apps/plugins/battery_bench.c68
-rw-r--r--apps/plugins/bitmaps/native/SOURCES42
-rw-r--r--apps/plugins/bitmaps/native/creditslogo.112x30x1.bmpbin0 -> 542 bytes
-rw-r--r--apps/plugins/bitmaps/native/creditslogo.128x40x16.bmpbin0 -> 15414 bytes
-rw-r--r--apps/plugins/bitmaps/native/creditslogo.128x42x1.bmpbin0 -> 736 bytes
-rw-r--r--apps/plugins/bitmaps/native/creditslogo.128x42x2.bmpbin0 -> 2808 bytes
-rw-r--r--apps/plugins/bitmaps/native/creditslogo.132x40x16.bmpbin0 -> 15894 bytes
-rw-r--r--apps/plugins/bitmaps/native/creditslogo.138x46x2.bmpbin0 -> 3392 bytes
-rw-r--r--apps/plugins/bitmaps/native/creditslogo.160x50x16.bmpbin0 -> 24054 bytes
-rw-r--r--apps/plugins/bitmaps/native/creditslogo.160x53x1.bmpbin0 -> 1122 bytes
-rw-r--r--apps/plugins/bitmaps/native/creditslogo.160x53x2.bmpbin0 -> 4312 bytes
-rw-r--r--apps/plugins/bitmaps/native/creditslogo.176x54x16.bmpbin0 -> 28566 bytes
-rw-r--r--apps/plugins/bitmaps/native/creditslogo.220x68x16.bmpbin0 -> 44934 bytes
-rw-r--r--apps/plugins/bitmaps/native/creditslogo.240x74x16.bmpbin0 -> 53334 bytes
-rw-r--r--apps/plugins/bitmaps/native/creditslogo.320x98x16.bmpbin0 -> 94136 bytes
-rw-r--r--apps/plugins/bitmaps/native/creditslogo.480x149x16.bmpbin0 -> 214614 bytes
-rw-r--r--apps/plugins/bitmaps/native/creditslogo.640x198x16.bmpbin0 -> 380214 bytes
-rw-r--r--apps/plugins/bitmaps/native/creditslogo.96x30x16.bmpbin0 -> 8694 bytes
-rw-r--r--apps/plugins/bitmaps/remote_native/SOURCES7
-rw-r--r--apps/plugins/bitmaps/remote_native/remote_creditslogo.128x42x1.bmpbin0 -> 736 bytes
-rw-r--r--apps/plugins/bitmaps/remote_native/remote_creditslogo.128x42x2.bmpbin0 -> 2808 bytes
-rw-r--r--apps/plugins/bounce.c23
-rw-r--r--apps/plugins/brickmania.c23
-rw-r--r--apps/plugins/bubbles.c10
-rw-r--r--apps/plugins/calendar.c13
-rw-r--r--apps/plugins/chessbox/chessbox_pgn.c4
-rw-r--r--apps/plugins/chessbox/chessbox_pgn.h2
-rw-r--r--apps/plugins/chopper.c8
-rw-r--r--apps/plugins/clix.c8
-rw-r--r--apps/plugins/clock/clock.c10
-rw-r--r--apps/plugins/codebuster.c7
-rw-r--r--apps/plugins/credits.c79
-rw-r--r--apps/plugins/cube.c12
-rw-r--r--apps/plugins/demystify.c32
-rw-r--r--apps/plugins/dice.c7
-rw-r--r--apps/plugins/doom/d_deh.c3
-rw-r--r--apps/plugins/doom/i_video.c3
-rw-r--r--apps/plugins/doom/rockdoom.c8
-rw-r--r--apps/plugins/fft/fft.c42
-rw-r--r--apps/plugins/fire.c15
-rw-r--r--apps/plugins/fireworks.c17
-rw-r--r--apps/plugins/flipit.c4
-rw-r--r--apps/plugins/fractals/fractal.h2
-rw-r--r--apps/plugins/imageviewer/image_decoder.c5
-rw-r--r--apps/plugins/imageviewer/imageviewer.c38
-rw-r--r--apps/plugins/imageviewer/imageviewer.h14
-rw-r--r--apps/plugins/imageviewer/imageviewer_button.h6
-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/jackpot.c9
-rw-r--r--apps/plugins/jewels.c4
-rw-r--r--apps/plugins/keybox.c3
-rw-r--r--apps/plugins/keyremap.c165
-rw-r--r--apps/plugins/lamp.c22
-rw-r--r--apps/plugins/lastfm_scrobbler.c830
-rw-r--r--apps/plugins/lastfm_scrobbler_viewer.c1033
-rw-r--r--apps/plugins/lib/SOURCES6
-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/highscore.c9
-rw-r--r--apps/plugins/lib/id3.c39
-rw-r--r--apps/plugins/lib/id3.h26
-rw-r--r--apps/plugins/lib/mul_id3.c174
-rw-r--r--apps/plugins/lib/mul_id3.h27
-rw-r--r--apps/plugins/lib/osd.c8
-rw-r--r--apps/plugins/lib/overlay.c5
-rw-r--r--apps/plugins/lib/playback_control.c20
-rw-r--r--apps/plugins/lib/pluginlib_bmp.c2
-rw-r--r--apps/plugins/lib/printcell_helper.c299
-rw-r--r--apps/plugins/lib/printcell_helper.h68
-rw-r--r--apps/plugins/lib/wrappers.h1
-rw-r--r--apps/plugins/lib/xlcd_scroll.c4
-rw-r--r--apps/plugins/logo.c14
-rw-r--r--apps/plugins/lrcplayer.c32
-rw-r--r--apps/plugins/lua/rocklib.c7
-rw-r--r--apps/plugins/lua/rocklib_events.c6
-rw-r--r--apps/plugins/lua/rocklib_img.c2
-rw-r--r--apps/plugins/main_menu_config.c2
-rw-r--r--apps/plugins/matrix.c9
-rw-r--r--apps/plugins/maze.c20
-rw-r--r--apps/plugins/mazezam.c9
-rw-r--r--apps/plugins/metronome.c6
-rw-r--r--apps/plugins/mikmod/mikmod.c19
-rw-r--r--apps/plugins/mosaique.c11
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/idct_arm.S6
-rw-r--r--apps/plugins/mpegplayer/libmpeg2/idct_armv6.S7
-rw-r--r--apps/plugins/mpegplayer/mpeg_misc.h24
-rw-r--r--apps/plugins/mpegplayer/mpegplayer.c5
-rw-r--r--apps/plugins/open_plugins.c73
-rw-r--r--apps/plugins/oscilloscope.c16
-rw-r--r--apps/plugins/otp.c17
-rwxr-xr-xapps/plugins/pacbox/pacbox.c4
-rw-r--r--apps/plugins/pdbox/PDa/src/m_obj.c3
-rw-r--r--apps/plugins/pdbox/pdbox.c2
-rw-r--r--apps/plugins/pegbox.c4
-rw-r--r--apps/plugins/periodic_table.c1
-rw-r--r--apps/plugins/pictureflow/pictureflow.c611
-rw-r--r--apps/plugins/pitch_detector.c5
-rw-r--r--apps/plugins/plasma.c17
-rw-r--r--apps/plugins/pong.c7
-rw-r--r--apps/plugins/properties.c291
-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.c40
-rw-r--r--apps/plugins/resistor.c18
-rw-r--r--apps/plugins/robotfindskitten.c6
-rw-r--r--apps/plugins/rockblox.c14
-rw-r--r--apps/plugins/rockblox1d.c7
-rw-r--r--apps/plugins/rockboy/menu.c8
-rw-r--r--apps/plugins/rockboy/rockboy.c5
-rw-r--r--apps/plugins/rocklife.c12
-rw-r--r--apps/plugins/rockpaint.c18
-rw-r--r--apps/plugins/sdl/SDL_mixer/timidity/playmidi.c2
-rw-r--r--apps/plugins/sdl/main.c7
-rw-r--r--apps/plugins/sdl/src/audio/rockbox/SDL_rockboxaudio.c38
-rw-r--r--apps/plugins/shopper.c3
-rw-r--r--apps/plugins/shortcuts/shortcuts_view.c8
-rw-r--r--apps/plugins/sliding_puzzle.c8
-rw-r--r--apps/plugins/snake.c4
-rw-r--r--apps/plugins/snake2.c4
-rw-r--r--apps/plugins/snow.c8
-rw-r--r--apps/plugins/sokoban.c2
-rw-r--r--apps/plugins/solitaire.c2
-rw-r--r--apps/plugins/spacerocks.c19
-rw-r--r--apps/plugins/speedread.c24
-rw-r--r--apps/plugins/star.c4
-rw-r--r--apps/plugins/starfield.c18
-rw-r--r--apps/plugins/stats.c10
-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_usb.c137
-rw-r--r--apps/plugins/test_viewports.c4
-rw-r--r--apps/plugins/text_editor.c3
-rw-r--r--apps/plugins/text_viewer/tv_menu.c78
-rw-r--r--apps/plugins/vbrfix.c4
-rw-r--r--apps/plugins/viewers.config1
-rw-r--r--apps/plugins/vu_meter.c13
-rw-r--r--apps/plugins/wormlet.c9
-rw-r--r--apps/plugins/xobox.c11
-rw-r--r--apps/plugins/xworld/engine.c2
-rw-r--r--apps/plugins/xworld/sys.c20
152 files changed, 3988 insertions, 1341 deletions
diff --git a/apps/plugins/2048.c b/apps/plugins/2048.c
index 2633753071..2f4eb4c001 100644
--- a/apps/plugins/2048.c
+++ b/apps/plugins/2048.c
@@ -91,9 +91,16 @@ static const int BACKGROUND_Y = (BASE_Y-MIN_SPACE);
#define KEY_DOWN PLA_DOWN
#define KEY_LEFT PLA_LEFT
#define KEY_RIGHT PLA_RIGHT
-#define KEY_EXIT PLA_CANCEL
#define KEY_UNDO PLA_SELECT
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define KEY_EXIT PLA_SELECT_REPEAT
+#else
+#define KEY_EXIT PLA_CANCEL
+#endif
+
/* notice how "color" is spelled :P */
#ifdef HAVE_LCD_COLOR
@@ -148,9 +155,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 +705,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/CATEGORIES b/apps/plugins/CATEGORIES
index 332dd1bde4..cb0e407d31 100644
--- a/apps/plugins/CATEGORIES
+++ b/apps/plugins/CATEGORIES
@@ -50,6 +50,7 @@ keybox,apps
keyremap,apps
lamp,apps
lastfm_scrobbler,apps
+lastfm_scrobbler_viewer,viewers
logo,demos
lrcplayer,apps
lua,viewers
@@ -178,6 +179,7 @@ test_resize,apps
test_sampr,apps
test_scanrate,apps
test_touchscreen,apps
+test_usb,apps
test_viewports,apps
test_greylib_bitmap_scale,viewers
text_editor,apps
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index c169b61cd1..28a4bc38f5 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -13,6 +13,7 @@ jackpot.c
keybox.c
keyremap.c
lastfm_scrobbler.c
+lastfm_scrobbler_viewer.c
logo.c
lrcplayer.c
mosaique.c
@@ -82,8 +83,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
@@ -226,5 +226,6 @@ test_sampr.c
#ifdef HAVE_TOUCHSCREEN
test_touchscreen.c
#endif
+test_usb.c
test_viewports.c
#endif /* HAVE_TEST_PLUGINS */
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/alarmclock.c b/apps/plugins/alarmclock.c
index ecafceddc7..aa7c13d1a4 100644
--- a/apps/plugins/alarmclock.c
+++ b/apps/plugins/alarmclock.c
@@ -138,7 +138,13 @@ enum plugin_status plugin_start(const void* parameter)
while(!quit) {
button = get_button();
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+ if (button == PLA_EXIT || button == PLA_CANCEL || button == PLA_UP)
+#else
if (button == PLA_EXIT || button == PLA_CANCEL)
+#endif
quit = true;
FOR_NB_SCREENS(i) {
diff --git a/apps/plugins/announce_status.c b/apps/plugins/announce_status.c
index 77e9015000..1ccfc1e70a 100644
--- a/apps/plugins/announce_status.c
+++ b/apps/plugins/announce_status.c
@@ -97,6 +97,7 @@ enum plugin_status plugin_start(const void* parameter); /* entry */
static struct
{
bool exiting; /* signal to the thread that we want to exit */
+ bool resume;
unsigned int id; /* worker thread id */
struct event_queue queue; /* thread event queue */
long stack[THREAD_STACK_SIZE / sizeof(long)];
@@ -393,7 +394,7 @@ static int settings_menu(void)
break;
case 4: /*sep*/
continue;
- case 5:
+ case 5: /* quit the plugin */
return -1;
break;
case 6:
@@ -433,7 +434,8 @@ void thread(void)
in_usb = false;
/*fall through*/
case EV_STARTUP:
- rb->beep_play(1500, 100, 1000);
+ if (!gThread.resume)
+ rb->beep_play(1500, 100, 1000);
break;
case EV_EXIT:
return;
@@ -479,17 +481,45 @@ void thread_quit(void)
}
}
+static bool check_user_input(void)
+{
+ int i = 0;
+ rb->button_clear_queue();
+ if (rb->button_get_w_tmo(HZ) > BUTTON_NONE)
+ {
+ while ((rb->button_get(false) & BUTTON_REL) != BUTTON_REL)
+ {
+ if (i & 1)
+ rb->beep_play(800, 100, 1000 - i * (1000 / 15));
+
+ if (++i > 15)
+ {
+ return true;
+ }
+ rb->sleep(HZ / 5);
+ }
+ }
+ return false;
+}
+
/* callback to end the TSR plugin, called before a new one gets loaded */
-static bool exit_tsr(bool reenter)
+static int exit_tsr(bool reenter)
{
if (reenter)
{
rb->queue_post(&gThread.queue, EV_OTHINSTANCE, 0);
- return false; /* dont let it start again */
+
+ /* quit the plugin if user holds a button */
+ if (check_user_input() == true)
+ {
+ if (settings_menu() < 0)
+ return PLUGIN_TSR_TERMINATE; /*kill TSR dont let it start again */
+ }
+ return PLUGIN_TSR_CONTINUE; /* dont let new plugin start*/
}
thread_quit();
- return true;
+ return PLUGIN_TSR_SUSPEND;
}
@@ -497,58 +527,35 @@ static bool exit_tsr(bool reenter)
int plugin_main(const void* parameter)
{
- (void)parameter;
- bool settings = false;
- int i = 0;
-
rb->memset(&gThread, 0, sizeof(gThread));
gAnnounce.index = 0;
gAnnounce.timeout = 0;
-
- rb->splash(HZ / 2, "Announce Status");
-
- if (configfile_load(CFG_FILE, config, gCfg_sz, CFG_VER) < 0)
- {
- /* If the loading failed, save a new config file */
- config_set_defaults();
- configfile_save(CFG_FILE, config, gCfg_sz, CFG_VER);
-
- rb->splash(HZ, ID2P(LANG_HOLD_FOR_SETTINGS));
- }
-
- if (gAnnounce.show_prompt)
+ /* Resume plugin ? */
+ if (parameter == rb->plugin_tsr)
{
- if (rb->mixer_channel_status(PCM_MIXER_CHAN_PLAYBACK) != CHANNEL_PLAYING)
- {
- rb->talk_id(LANG_HOLD_FOR_SETTINGS, false);
- }
- rb->splash(HZ, ID2P(LANG_HOLD_FOR_SETTINGS));
+ gThread.resume = true;
}
-
- rb->button_clear_queue();
- if (rb->button_get_w_tmo(HZ) > BUTTON_NONE)
+ else
{
- while ((rb->button_get(false) & BUTTON_REL) != BUTTON_REL)
+ rb->splash(HZ / 2, "Announce Status");
+ if (gAnnounce.show_prompt)
{
- if (i & 1)
- rb->beep_play(800, 100, 1000);
-
- if (++i > 15)
+ if (rb->mixer_channel_status(PCM_MIXER_CHAN_PLAYBACK) != CHANNEL_PLAYING)
{
- settings = true;
- break;
+ rb->talk_id(LANG_HOLD_FOR_SETTINGS, false);
}
- rb->sleep(HZ / 5);
+ rb->splash(HZ, ID2P(LANG_HOLD_FOR_SETTINGS));
}
- }
- if (settings)
- {
- rb->splash(100, ID2P(LANG_SETTINGS));
- int ret = settings_menu();
- if (ret < 0)
- return 0;
+
+ if (check_user_input() == true)
+ {
+ rb->splash(100, ID2P(LANG_SETTINGS));
+ int ret = settings_menu();
+ if (ret < 0)
+ return 0;
+ }
}
gAnnounce.timeout = *rb->current_tick;
@@ -571,6 +578,16 @@ enum plugin_status plugin_start(const void* parameter)
/* now go ahead and have fun! */
if (rb->usb_inserted() == true)
return PLUGIN_USB_CONNECTED;
+
+ config_set_defaults();
+ if (configfile_load(CFG_FILE, config, gCfg_sz, CFG_VER) < 0)
+ {
+ /* If the loading failed, save a new config file */
+ config_set_defaults();
+ configfile_save(CFG_FILE, config, gCfg_sz, CFG_VER);
+ rb->splash(HZ, ID2P(LANG_HOLD_FOR_SETTINGS));
+ }
+
int ret = plugin_main(parameter);
return (ret==0) ? PLUGIN_OK : PLUGIN_ERROR;
}
diff --git a/apps/plugins/battery_bench.c b/apps/plugins/battery_bench.c
index 17d3b918cf..f258492363 100644
--- a/apps/plugins/battery_bench.c
+++ b/apps/plugins/battery_bench.c
@@ -289,11 +289,11 @@ static struct event_queue thread_q SHAREDBSS_ATTR;
static bool in_usb_mode;
static unsigned int buf_idx;
-static bool exit_tsr(bool reenter)
+static int exit_tsr(bool reenter)
{
- bool is_exit;
+ int exit_status;
long button;
- (void)reenter;
+
rb->lcd_clear_display();
rb->lcd_puts_scroll(0, 0, "Batt.Bench is currently running.");
rb->lcd_puts_scroll(0, 1, "Press " BATTERY_OFF_TXT " to cancel the test");
@@ -313,16 +313,17 @@ static bool exit_tsr(bool reenter)
rb->thread_wait(gThread.id);
/* remove the thread's queue from the broadcast list */
rb->queue_delete(&thread_q);
- is_exit = true;
+ exit_status = (reenter ? PLUGIN_TSR_TERMINATE : PLUGIN_TSR_SUSPEND);
+
}
- else is_exit = false;
+ else exit_status = PLUGIN_TSR_CONTINUE;
break;
}
FOR_NB_SCREENS(idx)
rb->screens[idx]->scroll_stop();
- return is_exit;
+ return exit_status;
}
#define BIT_CHARGER 0x1
@@ -502,14 +503,19 @@ static void put_centered_str(const char* str, plcdfunc putsxy, int lcd_width, in
enum plugin_status plugin_start(const void* parameter)
{
- (void)parameter;
int button, fd;
+ bool resume = false;
bool on = false;
start_tick = *rb->current_tick;
int i;
const char *msgs[] = { "Battery Benchmark","Check file", BATTERY_LOG,
"for more info", BATTERY_ON_TXT, BATTERY_OFF_TXT " - quit" };
- rb->lcd_clear_display();
+
+ if (parameter == rb->plugin_tsr)
+ {
+ resume = true;
+ on = true;
+ }
rb->lcd_clear_display();
rb->lcd_setfont(FONT_SYSFIXED);
@@ -529,36 +535,38 @@ enum plugin_status plugin_start(const void* parameter)
rb->lcd_remote_putsxy,LCD_REMOTE_WIDTH,2);
rb->lcd_remote_update();
#endif
-
- do
+ if (!resume)
{
- button = rb->button_get(true);
- switch (button)
+ do
{
- case BATTERY_ON:
-#ifdef BATTERY_RC_ON
- case BATTERY_RC_ON:
-#endif
- on = true;
- break;
- case BATTERY_OFF:
-#ifdef BATTERY_RC_OFF
- case BATTERY_RC_OFF:
-#endif
- return PLUGIN_OK;
-
- default:
- if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
- return PLUGIN_USB_CONNECTED;
- }
- }while(!on);
-
+ button = rb->button_get(true);
+ switch (button)
+ {
+ case BATTERY_ON:
+ #ifdef BATTERY_RC_ON
+ case BATTERY_RC_ON:
+ #endif
+ on = true;
+ break;
+ case BATTERY_OFF:
+ #ifdef BATTERY_RC_OFF
+ case BATTERY_RC_OFF:
+ #endif
+ return PLUGIN_OK;
+
+ default:
+ if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
+ return PLUGIN_USB_CONNECTED;
+ }
+ }while(!on);
+ }
fd = rb->open(BATTERY_LOG, O_RDONLY);
if (fd < 0)
{
fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT, 0666);
if (fd >= 0)
{
+
rb->fdprintf(fd,
"# This plugin will log your battery performance in a\n"
"# file (%s) every minute.\n"
diff --git a/apps/plugins/bitmaps/native/SOURCES b/apps/plugins/bitmaps/native/SOURCES
index f207f358b2..814845dc5b 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
@@ -974,6 +973,45 @@ rockboxlogo.91x32x1.bmp
#endif
#endif
+/* Credits logo */
+#if (LCD_DEPTH == 1)
+#if (LCD_WIDTH == 160)
+creditslogo.160x53x1.bmp
+#elif (LCD_WIDTH == 128)
+creditslogo.128x42x1.bmp
+#else
+creditslogo.112x30x1.bmp
+#endif
+#elif (LCD_WIDTH == 96) && (LCD_DEPTH >= 16)
+creditslogo.96x30x16.bmp
+#elif (LCD_WIDTH == 128) && (LCD_DEPTH == 2)
+creditslogo.128x42x2.bmp
+#elif (LCD_WIDTH == 128) && (LCD_DEPTH >= 16)
+creditslogo.128x40x16.bmp
+#elif (LCD_WIDTH == 132) && (LCD_DEPTH >= 16)
+creditslogo.132x40x16.bmp
+#elif (LCD_WIDTH == 138) && (LCD_DEPTH >= 2)
+creditslogo.138x46x2.bmp
+#elif (LCD_WIDTH == 160) && (LCD_DEPTH == 2)
+creditslogo.160x53x2.bmp
+#elif (LCD_WIDTH == 320) && (LCD_DEPTH == 2)
+creditslogo.160x53x2.bmp
+#elif (LCD_WIDTH == 160) && (LCD_DEPTH >= 16)
+creditslogo.160x50x16.bmp
+#elif (LCD_WIDTH == 176) && (LCD_DEPTH >= 16)
+creditslogo.176x54x16.bmp
+#elif (LCD_WIDTH == 220) && (LCD_DEPTH >= 16)
+creditslogo.220x68x16.bmp
+#elif (LCD_WIDTH == 240) && (LCD_DEPTH >= 16)
+creditslogo.240x74x16.bmp
+#elif (LCD_WIDTH >= 320) && (LCD_WIDTH < 480) && (LCD_DEPTH >= 16)
+creditslogo.320x98x16.bmp
+#elif (LCD_WIDTH >= 480) && (LCD_WIDTH < 640) && (LCD_DEPTH >= 16)
+creditslogo.480x149x16.bmp
+#elif (LCD_WIDTH >= 640) && (LCD_DEPTH >= 16)
+creditslogo.640x198x16.bmp
+#endif
+
/* Pitch detector */
/* The following preprocessor condition must match the condition */
/* for pitch detector from plugins/SOURCES */
diff --git a/apps/plugins/bitmaps/native/creditslogo.112x30x1.bmp b/apps/plugins/bitmaps/native/creditslogo.112x30x1.bmp
new file mode 100644
index 0000000000..c414ffb27b
--- /dev/null
+++ b/apps/plugins/bitmaps/native/creditslogo.112x30x1.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/creditslogo.128x40x16.bmp b/apps/plugins/bitmaps/native/creditslogo.128x40x16.bmp
new file mode 100644
index 0000000000..228dbddbd5
--- /dev/null
+++ b/apps/plugins/bitmaps/native/creditslogo.128x40x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/creditslogo.128x42x1.bmp b/apps/plugins/bitmaps/native/creditslogo.128x42x1.bmp
new file mode 100644
index 0000000000..27d8e5fc26
--- /dev/null
+++ b/apps/plugins/bitmaps/native/creditslogo.128x42x1.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/creditslogo.128x42x2.bmp b/apps/plugins/bitmaps/native/creditslogo.128x42x2.bmp
new file mode 100644
index 0000000000..fa12aa4bd7
--- /dev/null
+++ b/apps/plugins/bitmaps/native/creditslogo.128x42x2.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/creditslogo.132x40x16.bmp b/apps/plugins/bitmaps/native/creditslogo.132x40x16.bmp
new file mode 100644
index 0000000000..865a8ed59d
--- /dev/null
+++ b/apps/plugins/bitmaps/native/creditslogo.132x40x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/creditslogo.138x46x2.bmp b/apps/plugins/bitmaps/native/creditslogo.138x46x2.bmp
new file mode 100644
index 0000000000..4b5d7beb16
--- /dev/null
+++ b/apps/plugins/bitmaps/native/creditslogo.138x46x2.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/creditslogo.160x50x16.bmp b/apps/plugins/bitmaps/native/creditslogo.160x50x16.bmp
new file mode 100644
index 0000000000..59e472def1
--- /dev/null
+++ b/apps/plugins/bitmaps/native/creditslogo.160x50x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/creditslogo.160x53x1.bmp b/apps/plugins/bitmaps/native/creditslogo.160x53x1.bmp
new file mode 100644
index 0000000000..7e34b23c6b
--- /dev/null
+++ b/apps/plugins/bitmaps/native/creditslogo.160x53x1.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/creditslogo.160x53x2.bmp b/apps/plugins/bitmaps/native/creditslogo.160x53x2.bmp
new file mode 100644
index 0000000000..240cf10686
--- /dev/null
+++ b/apps/plugins/bitmaps/native/creditslogo.160x53x2.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/creditslogo.176x54x16.bmp b/apps/plugins/bitmaps/native/creditslogo.176x54x16.bmp
new file mode 100644
index 0000000000..bf43a65e42
--- /dev/null
+++ b/apps/plugins/bitmaps/native/creditslogo.176x54x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/creditslogo.220x68x16.bmp b/apps/plugins/bitmaps/native/creditslogo.220x68x16.bmp
new file mode 100644
index 0000000000..1dc68a09f2
--- /dev/null
+++ b/apps/plugins/bitmaps/native/creditslogo.220x68x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/creditslogo.240x74x16.bmp b/apps/plugins/bitmaps/native/creditslogo.240x74x16.bmp
new file mode 100644
index 0000000000..fd335b2fb8
--- /dev/null
+++ b/apps/plugins/bitmaps/native/creditslogo.240x74x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/creditslogo.320x98x16.bmp b/apps/plugins/bitmaps/native/creditslogo.320x98x16.bmp
new file mode 100644
index 0000000000..26dcac89c3
--- /dev/null
+++ b/apps/plugins/bitmaps/native/creditslogo.320x98x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/creditslogo.480x149x16.bmp b/apps/plugins/bitmaps/native/creditslogo.480x149x16.bmp
new file mode 100644
index 0000000000..c73d9374e4
--- /dev/null
+++ b/apps/plugins/bitmaps/native/creditslogo.480x149x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/creditslogo.640x198x16.bmp b/apps/plugins/bitmaps/native/creditslogo.640x198x16.bmp
new file mode 100644
index 0000000000..ec6a16da5d
--- /dev/null
+++ b/apps/plugins/bitmaps/native/creditslogo.640x198x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/creditslogo.96x30x16.bmp b/apps/plugins/bitmaps/native/creditslogo.96x30x16.bmp
new file mode 100644
index 0000000000..e032ebae34
--- /dev/null
+++ b/apps/plugins/bitmaps/native/creditslogo.96x30x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/remote_native/SOURCES b/apps/plugins/bitmaps/remote_native/SOURCES
index b3cc2157ff..2142674c67 100644
--- a/apps/plugins/bitmaps/remote_native/SOURCES
+++ b/apps/plugins/bitmaps/remote_native/SOURCES
@@ -22,3 +22,10 @@ remote_rockboxlogo.91x32x1.bmp
#elif (LCD_REMOTE_DEPTH == 2)
remote_rockboxlogo.91x32x2.bmp
#endif
+
+/* Credits logo */
+#if (LCD_REMOTE_DEPTH == 1)
+remote_creditslogo.128x42x1.bmp
+#elif (LCD_REMOTE_DEPTH == 2)
+remote_creditslogo.128x42x2.bmp
+#endif
diff --git a/apps/plugins/bitmaps/remote_native/remote_creditslogo.128x42x1.bmp b/apps/plugins/bitmaps/remote_native/remote_creditslogo.128x42x1.bmp
new file mode 100644
index 0000000000..27d8e5fc26
--- /dev/null
+++ b/apps/plugins/bitmaps/remote_native/remote_creditslogo.128x42x1.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/remote_native/remote_creditslogo.128x42x2.bmp b/apps/plugins/bitmaps/remote_native/remote_creditslogo.128x42x2.bmp
new file mode 100644
index 0000000000..fa12aa4bd7
--- /dev/null
+++ b/apps/plugins/bitmaps/remote_native/remote_creditslogo.128x42x2.bmp
Binary files differ
diff --git a/apps/plugins/bounce.c b/apps/plugins/bounce.c
index e6f29817d6..a42a0af6ba 100644
--- a/apps/plugins/bounce.c
+++ b/apps/plugins/bounce.c
@@ -34,10 +34,6 @@
static const struct button_mapping *plugin_contexts[] = { pla_main_ctx };
/* We set button maping with PLA */
-#define BOUNCE_UP PLA_UP
-#define BOUNCE_UP_REPEAT PLA_UP_REPEAT
-#define BOUNCE_DOWN PLA_DOWN
-#define BOUNCE_DOWN_REPEAT PLA_DOWN_REPEAT
#ifdef HAVE_SCROLLWHEEL
#define BOUNCE_LEFT PLA_SCROLL_BACK
@@ -52,7 +48,22 @@ static const struct button_mapping *plugin_contexts[] = { pla_main_ctx };
#endif
#define BOUNCE_QUIT PLA_EXIT
+
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define BOUNCE_QUIT2 PLA_UP
+#define BOUNCE_DOWN PLA_LEFT
+#define BOUNCE_DOWN_REPEAT PLA_LEFT_REPEAT
+#define BOUNCE_UP PLA_RIGHT
+#define BOUNCE_UP_REPEAT PLA_RIGHT_REPEAT
+#else
#define BOUNCE_QUIT2 PLA_CANCEL
+#define BOUNCE_DOWN PLA_DOWN
+#define BOUNCE_DOWN_REPEAT PLA_DOWN_REPEAT
+#define BOUNCE_UP PLA_UP
+#define BOUNCE_UP_REPEAT PLA_UP_REPEAT
+#endif
#define BOUNCE_MODE PLA_SELECT
#define LETTER_WIDTH 11
@@ -471,6 +482,10 @@ enum plugin_status plugin_start(const void* parameter)
#if (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD) || \
(CONFIG_KEYPAD == SAMSUNG_YH820_PAD)
"[Rew] to stop";
+#elif (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+ "[Menu] to stop";
#else
"[Off] to stop";
#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/bubbles.c b/apps/plugins/bubbles.c
index 88d7228d72..a64093492f 100644
--- a/apps/plugins/bubbles.c
+++ b/apps/plugins/bubbles.c
@@ -79,7 +79,6 @@ enum {
#define ANGLE_STEP_REP 6
#define BUBBLES_QUIT1 PLA_EXIT
-#define BUBBLES_QUIT2 PLA_CANCEL
/* these are better off shooting with up */
#if (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) \
@@ -92,10 +91,19 @@ enum {
#define BUBBLES_FIRE PLA_UP
#define BUBBLES_FIRE_REPEAT PLA_UP_REPEAT
#define BUBBLES_PAUSE PLA_SELECT
+#define BUBBLES_QUIT2 PLA_CANCEL
+#elif (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define BUBBLES_FIRE PLA_SELECT
+#define BUBBLES_FIRE_REPEAT PLA_SELECT_REPEAT
+#define BUBBLES_PAUSE PLA_DOWN
+#define BUBBLES_QUIT2 PLA_UP
#else
#define BUBBLES_FIRE PLA_SELECT
#define BUBBLES_FIRE_REPEAT PLA_SELECT_REPEAT
#define BUBBLES_PAUSE PLA_UP
+#define BUBBLES_QUIT2 PLA_CANCEL
#endif
/* external bitmaps */
diff --git a/apps/plugins/calendar.c b/apps/plugins/calendar.c
index 3299a81273..765b42ef59 100644
--- a/apps/plugins/calendar.c
+++ b/apps/plugins/calendar.c
@@ -39,14 +39,12 @@
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
(CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
-#define CALENDAR_QUIT (BUTTON_SELECT|BUTTON_MENU)
+#define CALENDAR_QUIT (BUTTON_MENU|BUTTON_REL)
#define CALENDAR_SELECT (BUTTON_SELECT|BUTTON_REL)
#define CALENDAR_NEXT_WEEK BUTTON_SCROLL_FWD
#define CALENDAR_PREV_WEEK BUTTON_SCROLL_BACK
#define CALENDAR_NEXT_DAY BUTTON_RIGHT
#define CALENDAR_PREV_DAY BUTTON_LEFT
-#define CALENDAR_NEXT_MONTH BUTTON_PLAY
-#define CALENDAR_PREV_MONTH (BUTTON_MENU|BUTTON_REL)
#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
#define CALENDAR_QUIT BUTTON_POWER
@@ -964,7 +962,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)
{
@@ -1095,17 +1093,18 @@ enum plugin_status plugin_start(const void* parameter)
case CALENDAR_QUIT:
exit = true;
break;
-
+#ifdef CALENDAR_NEXT_MONTH
case CALENDAR_NEXT_MONTH:
case CALENDAR_NEXT_MONTH | BUTTON_REPEAT:
next_month(&shown, 0);
break;
-
+#endif
+#ifdef CALENDAR_PREV_MONTH
case CALENDAR_PREV_MONTH:
case CALENDAR_PREV_MONTH | BUTTON_REPEAT:
prev_month(&shown, 0);
break;
-
+#endif
case CALENDAR_NEXT_WEEK:
case CALENDAR_NEXT_WEEK | BUTTON_REPEAT:
next_day(&shown, 7);
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/chessbox/chessbox_pgn.h b/apps/plugins/chessbox/chessbox_pgn.h
index 9d4f369ecc..7d0cb795cf 100644
--- a/apps/plugins/chessbox/chessbox_pgn.h
+++ b/apps/plugins/chessbox/chessbox_pgn.h
@@ -33,7 +33,7 @@
#define CB_PLAY (BUTTON_SELECT | BUTTON_PLAY)
#define CB_LEVEL (BUTTON_SELECT | BUTTON_RIGHT)
#define CB_RESTART (BUTTON_SELECT | BUTTON_LEFT)
-#define CB_MENU (BUTTON_SELECT | BUTTON_MENU)
+#define CB_MENU (BUTTON_SELECT | BUTTON_REPEAT)
#define CB_SCROLL_UP (BUTTON_SCROLL_FWD|BUTTON_REPEAT)
#define CB_SCROLL_DOWN (BUTTON_SCROLL_BACK|BUTTON_REPEAT)
#define CB_SCROLL_LEFT (BUTTON_LEFT|BUTTON_REPEAT)
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/clix.c b/apps/plugins/clix.c
index 9cd66a8034..06813f3a4d 100644
--- a/apps/plugins/clix.c
+++ b/apps/plugins/clix.c
@@ -66,9 +66,7 @@
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
(CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
-#define CLIX_BUTTON_QUIT (BUTTON_SELECT | BUTTON_MENU)
-#define CLIX_BUTTON_UP BUTTON_MENU
-#define CLIX_BUTTON_DOWN BUTTON_PLAY
+#define CLIX_BUTTON_QUIT BUTTON_MENU
#define CLIX_BUTTON_SCROLL_FWD BUTTON_SCROLL_FWD
#define CLIX_BUTTON_SCROLL_BACK BUTTON_SCROLL_BACK
#define CLIX_BUTTON_CLICK BUTTON_SELECT
@@ -921,8 +919,10 @@ static int clix_handle_game(struct clix_game_state_t* state)
case CLIX_BUTTON_SCROLL_BACK:
case CLIX_BUTTON_SCROLL_BACK|BUTTON_REPEAT:
#endif
+#ifdef CLIX_BUTTON_UP
case CLIX_BUTTON_UP:
case CLIX_BUTTON_UP|BUTTON_REPEAT:
+#endif
if( state->y == 0 ||
state->board[ XYPOS( state->x, state->y - 1)] ==
CC_BLACK
@@ -938,8 +938,10 @@ static int clix_handle_game(struct clix_game_state_t* state)
case CLIX_BUTTON_SCROLL_FWD:
case CLIX_BUTTON_SCROLL_FWD|BUTTON_REPEAT:
#endif
+#ifdef CLIX_BUTTON_DOWN
case CLIX_BUTTON_DOWN:
case CLIX_BUTTON_DOWN|BUTTON_REPEAT:
+#endif
if( state->y == (BOARD_HEIGHT - 1))
state->y = 0;
else
diff --git a/apps/plugins/clock/clock.c b/apps/plugins/clock/clock.c
index d287c75598..c61b466aba 100644
--- a/apps/plugins/clock/clock.c
+++ b/apps/plugins/clock/clock.c
@@ -44,13 +44,19 @@ const struct button_mapping* plugin_contexts[]={
#define ACTION_COUNTER_TOGGLE PLA_SELECT
#define ACTION_COUNTER_RESET PLA_SELECT_REPEAT
-#define ACTION_MENU PLA_CANCEL
#define ACTION_MODE_NEXT PLA_RIGHT
#define ACTION_MODE_NEXT_REPEAT PLA_RIGHT_REPEAT
#define ACTION_MODE_PREV PLA_LEFT
#define ACTION_MODE_PREV_REPEAT PLA_LEFT_REPEAT
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define ACTION_MENU PLA_UP
+#else
+#define ACTION_MENU PLA_CANCEL
#define ACTION_SKIN_NEXT PLA_UP
#define ACTION_SKIN_NEXT_REPEAT PLA_UP_REPEAT
+#endif
#define ACTION_SKIN_PREV PLA_DOWN
#define ACTION_SKIN_PREV_REPEAT PLA_DOWN_REPEAT
@@ -165,10 +171,12 @@ enum plugin_status plugin_start(const void* parameter){
case ACTION_SKIN_PREV:
clock_settings_skin_next(&clock_settings);
break;
+#if defined(ACTION_SKIN_NEXT) && defined(ACTION_SKIN_NEXT_REPEAT)
case ACTION_SKIN_NEXT_REPEAT:
case ACTION_SKIN_NEXT:
clock_settings_skin_previous(&clock_settings);
break;
+#endif
case ACTION_MENU:
clock_draw_restore_colors();
exit_clock=main_menu();
diff --git a/apps/plugins/codebuster.c b/apps/plugins/codebuster.c
index 956991575d..401ce6085f 100644
--- a/apps/plugins/codebuster.c
+++ b/apps/plugins/codebuster.c
@@ -438,6 +438,13 @@ enum plugin_status plugin_start(const void* parameter) {
if (button == PLA_SELECT)
break;
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+ if (button == PLA_UP) /* Menu button */
+ button = PLA_CANCEL;
+#endif
+
switch (button) {
/* Exit */
diff --git a/apps/plugins/credits.c b/apps/plugins/credits.c
index 9e43aab2a7..f4716651fd 100644
--- a/apps/plugins/credits.c
+++ b/apps/plugins/credits.c
@@ -21,7 +21,19 @@
#include "plugin.h"
#include "lib/helper.h"
-
+#ifdef HAVE_REMOTE_LCD
+#define REMOTE_WIDTH LCD_REMOTE_WIDTH
+#define REMOTE_HEIGHT LCD_REMOTE_HEIGHT
+#include "pluginbitmaps/remote_creditslogo.h"
+#define REMOTE_LOGO_WIDTH BMPWIDTH_remote_creditslogo
+#define REMOTE_LOGO_HEIGHT BMPHEIGHT_remote_creditslogo
+#define REMOTE_LOGO (const fb_remote_data*)remote_creditslogo
+#endif /* HAVE_REMOTE_LCD */
+
+#define LOGO (const fb_data*)creditslogo
+#include "pluginbitmaps/creditslogo.h"
+#define LOGO_WIDTH BMPWIDTH_creditslogo
+#define LOGO_HEIGHT BMPHEIGHT_creditslogo
static const char* const credits[] = {
#include "credits.raw" /* generated list of names from docs/CREDITS */
@@ -299,29 +311,78 @@ static void roll_credits(void)
}
}
+int show_logo(void)
+{
+ unsigned char version[32];
+ int font_h, ver_w;
+ rb->snprintf(version, sizeof(version), "Ver. %s", rb->rbversion);
+ ver_w = rb->font_getstringsize(version, NULL, &font_h, FONT_SYSFIXED);
+ rb->lcd_clear_display();
+ rb->lcd_setfont(FONT_SYSFIXED);
+#if defined(SANSA_CLIP) || defined(SANSA_CLIPV2) || defined(SANSA_CLIPPLUS)
+ /* display the logo in the blue area of the screen (bottom 48 pixels) */
+ if (ver_w > LCD_WIDTH)
+ rb->lcd_puts_scroll(0, 0, version);
+ else
+ rb->lcd_putsxy((LCD_WIDTH/2) - (ver_w/2), 0, version);
+ rb->lcd_bitmap(LOGO, (LCD_WIDTH - LOGO_WIDTH) / 2, 16,
+ LOGO_WIDTH, LOGO_HEIGHT);
+#else
+ rb->lcd_bitmap(LOGO, (LCD_WIDTH - LOGO_WIDTH) / 2, 10,
+ LOGO_WIDTH, LOGO_HEIGHT);
+ if (ver_w > LCD_WIDTH)
+ rb->lcd_puts_scroll(0, (LCD_HEIGHT-font_h) / font_h, version);
+ else
+ rb->lcd_putsxy((LCD_WIDTH/2) - (ver_w/2), LCD_HEIGHT-font_h, version);
+#endif
+ rb->lcd_setfont(FONT_UI);
+ rb->lcd_update();
+#ifdef HAVE_REMOTE_LCD
+ rb->lcd_remote_clear_display();
+ rb->lcd_remote_bitmap(REMOTE_LOGO, 0, 10,
+ REMOTE_LOGO_WIDTH, REMOTE_LOGO_HEIGHT);
+ rb->lcd_remote_setfont(FONT_SYSFIXED);
+ if (ver_w > LCD_REMOTE_WIDTH)
+ rb->lcd_remote_puts_scroll(0, (LCD_REMOTE_HEIGHT-font_h) / font_h, version);
+ else
+ rb->lcd_remote_putsxy((LCD_REMOTE_WIDTH/2) - (ver_w/2),
+ LCD_REMOTE_HEIGHT-font_h, version);
+ rb->lcd_remote_setfont(FONT_UI);
+ rb->lcd_remote_update();
+#endif
+
+ return 0;
+}
+
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
+#if LCD_DEPTH >= 16
rb->lcd_set_foreground (LCD_WHITE);
rb->lcd_set_background (LCD_BLACK);
#endif
- rb->show_logo();
- /* Show the logo for about 3 secs allowing the user to stop */
- if(!rb->action_userabort(3*HZ))
+ show_logo();
+
+ /* Show the logo for about 5 secs allowing the user to stop */
+ if(!rb->action_userabort(5*HZ))
+ {
+ rb->lcd_scroll_stop();
roll_credits();
+ }
+
+#ifdef HAVE_REMOTE_LCD
+ rb->lcd_remote_scroll_stop();
+#endif
-#ifdef HAVE_BACKLIGHT
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings();
-#endif
+
return PLUGIN_OK;
}
diff --git a/apps/plugins/cube.c b/apps/plugins/cube.c
index dfd7df8951..43318f5aee 100644
--- a/apps/plugins/cube.c
+++ b/apps/plugins/cube.c
@@ -52,12 +52,14 @@
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
(CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
-#define CUBE_QUIT (BUTTON_SELECT | BUTTON_MENU)
+#define CUBE_QUIT_PRE BUTTON_MENU
+#define CUBE_QUIT (BUTTON_MENU | BUTTON_REL)
#define CUBE_NEXT BUTTON_RIGHT
#define CUBE_PREV BUTTON_LEFT
#define CUBE_INC BUTTON_SCROLL_FWD
#define CUBE_DEC BUTTON_SCROLL_BACK
-#define CUBE_MODE BUTTON_MENU
+#define CUBE_MODE_PRE BUTTON_MENU
+#define CUBE_MODE (BUTTON_MENU | BUTTON_REPEAT)
#define CUBE_PAUSE BUTTON_PLAY
#define CUBE_HIGHSPEED_PRE BUTTON_SELECT
#define CUBE_HIGHSPEED (BUTTON_SELECT | BUTTON_REL)
@@ -729,6 +731,7 @@ enum plugin_status plugin_start(const void* parameter)
int button;
#if defined(CUBE_MODE_PRE) || \
+ defined(CUBE_QUIT_PRE) || \
defined(CUBE_PAUSE_PRE) || \
defined(CUBE_HIGHSPEED_PRE)
int lastbutton = BUTTON_NONE;
@@ -903,6 +906,10 @@ enum plugin_status plugin_start(const void* parameter)
case CUBE_RC_QUIT:
#endif
case CUBE_QUIT:
+#ifdef CUBE_QUIT_PRE
+ if (lastbutton != CUBE_QUIT_PRE)
+ break;
+#endif
quit = true;
break;
@@ -911,6 +918,7 @@ enum plugin_status plugin_start(const void* parameter)
break;
}
#if defined(CUBE_MODE_PRE) || \
+ defined(CUBE_QUIT_PRE) || \
defined(CUBE_PAUSE_PRE) || \
defined(CUBE_HIGHSPEED_PRE)
if (button != BUTTON_NONE)
diff --git a/apps/plugins/demystify.c b/apps/plugins/demystify.c
index 74537e94f8..cb8e4ddf72 100644
--- a/apps/plugins/demystify.c
+++ b/apps/plugins/demystify.c
@@ -37,26 +37,42 @@
#define MIN_POLYGONS 1
/* Key assignement */
-#define DEMYSTIFY_QUIT PLA_CANCEL
#ifdef HAVE_SCROLLWHEEL
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define DEMYSTIFY_QUIT PLA_UP
+#else
+#define DEMYSTIFY_QUIT PLA_CANCEL
+#endif
+
#define DEMYSTIFY_INCREASE_SPEED PLA_SCROLL_FWD
#define DEMYSTIFY_DECREASE_SPEED PLA_SCROLL_BACK
#define DEMYSTIFY_INCREASE_SPEED_REPEAT PLA_SCROLL_FWD_REPEAT
#define DEMYSTIFY_DECREASE_SPEED_REPEAT PLA_SCROLL_BACK_REPEAT
+
+#define DEMYSTIFY_ADD_POLYGON PLA_RIGHT
+#define DEMYSTIFY_REMOVE_POLYGON PLA_LEFT
+#define DEMYSTIFY_ADD_POLYGON_REPEAT PLA_RIGHT_REPEAT
+#define DEMYSTIFY_REMOVE_POLYGON_REPEAT PLA_LEFT_REPEAT
+
#else
+
+#define DEMYSTIFY_QUIT PLA_CANCEL
+
#define DEMYSTIFY_INCREASE_SPEED PLA_RIGHT
#define DEMYSTIFY_DECREASE_SPEED PLA_LEFT
#define DEMYSTIFY_INCREASE_SPEED_REPEAT PLA_RIGHT_REPEAT
#define DEMYSTIFY_DECREASE_SPEED_REPEAT PLA_LEFT_REPEAT
-#endif
#define DEMYSTIFY_ADD_POLYGON PLA_UP
#define DEMYSTIFY_REMOVE_POLYGON PLA_DOWN
#define DEMYSTIFY_ADD_POLYGON_REPEAT PLA_UP_REPEAT
#define DEMYSTIFY_REMOVE_POLYGON_REPEAT PLA_DOWN_REPEAT
+#endif
const struct button_mapping *plugin_contexts[]
= {pla_main_ctx,
#if defined(HAVE_REMOTE_LCD)
@@ -262,12 +278,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 +452,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/dice.c b/apps/plugins/dice.c
index 622c58d71d..7580697267 100644
--- a/apps/plugins/dice.c
+++ b/apps/plugins/dice.c
@@ -28,7 +28,14 @@
#define INITIAL_NB_DICES 1
#define INITIAL_NB_SIDES 2 /* corresponds to 6 sides in the array */
+
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define DICE_QUIT PLA_UP
+#else
#define DICE_QUIT PLA_CANCEL
+#endif
#define DICE_ROLL PLA_SELECT
diff --git a/apps/plugins/doom/d_deh.c b/apps/plugins/doom/d_deh.c
index 1a399e3b49..0a67aa0aad 100644
--- a/apps/plugins/doom/d_deh.c
+++ b/apps/plugins/doom/d_deh.c
@@ -63,7 +63,7 @@ char* strlwr(char* str)
typedef struct {
const byte *inp; // Pointer to string
size_t size; // Bytes remaining in string
- int fd; // Current file descriptor
+ int fd; // Current file descriptor
} DEHFILE;
// killough 10/98: emulate IO whether input really comes from a file or not
@@ -2868,6 +2868,7 @@ boolean deh_GetData(char *s, char *k, uint_64_t *l, char **strval, int fpout)
if (*t == '=') break;
buffer[i] = *t; // copy it
}
+ if (i == 0) i = 1; /* Just in case */
buffer[--i] = '\0'; // terminate the key before the '='
if (!*t) // end of string with no equal sign
{
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..4d36302ddf 100644
--- a/apps/plugins/fft/fft.c
+++ b/apps/plugins/fft/fft.c
@@ -40,13 +40,22 @@ GREY_INFO_STRUCT
/* this set the context to use with PLA */
static const struct button_mapping *plugin_contexts[] = { pla_main_ctx };
-#define FFT_PREV_GRAPH PLA_LEFT
-#define FFT_NEXT_GRAPH PLA_RIGHT
-#define FFT_ORIENTATION PLA_CANCEL
-#define FFT_WINDOW PLA_SELECT
-#define FFT_AMP_SCALE PLA_UP
-#define FFT_FREQ_SCALE PLA_DOWN
-#define FFT_QUIT PLA_EXIT
+#define FFT_PREV_GRAPH PLA_LEFT
+#define FFT_NEXT_GRAPH PLA_RIGHT
+#define FFT_ORIENTATION PLA_CANCEL
+#define FFT_WINDOW PLA_SELECT_REL
+#define FFT_AMP_SCALE PLA_SELECT_REPEAT
+#define FFT_AMP_SCALE_PRE PLA_SELECT
+#define FFT_FREQ_SCALE PLA_DOWN
+
+
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define FFT_QUIT PLA_UP
+#else
+#define FFT_QUIT PLA_EXIT
+#endif
#ifdef HAVE_LCD_COLOR
#include "pluginbitmaps/fft_colors.h"
@@ -1184,9 +1193,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 +1245,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();
@@ -1259,6 +1266,10 @@ enum plugin_status plugin_start(const void* parameter)
if(!fft_setup())
return PLUGIN_ERROR;
+#if defined(FFT_AMP_SCALE_PRE)
+ int lastbutton = BUTTON_NONE;
+#endif
+
while(run)
{
long delay = fft_draw();
@@ -1302,6 +1313,10 @@ enum plugin_status plugin_start(const void* parameter)
break;
case FFT_AMP_SCALE:
+#ifdef FFT_AMP_SCALE_PRE
+ if (lastbutton != FFT_AMP_SCALE_PRE)
+ break;
+#endif
if (++fft.amp_scale >= FFT_MAX_AS)
fft.amp_scale = FFT_MIN_AS;
@@ -1330,6 +1345,11 @@ enum plugin_status plugin_start(const void* parameter)
exit_on_usb(button);
break;
}
+
+#if defined(FFT_AMP_SCALE_PRE)
+ if (button != BUTTON_NONE)
+ lastbutton = button;
+#endif
}
return PLUGIN_OK;
diff --git a/apps/plugins/fire.c b/apps/plugins/fire.c
index f3e6fb35e4..5cdf4a2d3a 100644
--- a/apps/plugins/fire.c
+++ b/apps/plugins/fire.c
@@ -56,10 +56,17 @@ const struct button_mapping* plugin_contexts[]= {
};
#define FIRE_QUIT PLA_CANCEL
-#define FIRE_QUIT2 PLA_EXIT
#define FIRE_SWITCH_FLAMES_TYPE PLA_LEFT
#define FIRE_SWITCH_FLAMES_MOVING PLA_RIGHT
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define FIRE_QUIT2 PLA_UP
+#else
+#define FIRE_QUIT2 PLA_EXIT
+#endif
+
#ifdef HAVE_SCROLLWHEEL
#define FIRE_INCREASE_MULT PLA_SCROLL_FWD
#define FIRE_INCREASE_MULT_REP PLA_SCROLL_FWD_REPEAT
@@ -279,10 +286,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 +377,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..54a6d07c20 100644
--- a/apps/plugins/fireworks.c
+++ b/apps/plugins/fireworks.c
@@ -35,10 +35,17 @@ static const struct button_mapping *plugin_contexts[] = { pla_main_ctx };
/* We use PLA */
#define BTN_EXIT PLA_EXIT
-#define BTN_MENU PLA_CANCEL
#define BTN_FIRE PLA_SELECT
#define BTN_FIRE_REPEAT PLA_SELECT_REPEAT
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define BTN_MENU PLA_UP
+#else
+#define BTN_MENU PLA_CANCEL
+#endif
+
/* The lowdown on source terminology:
* a ROCKET is launched from the LCD bottom.
* FIREWORKs are ejected from the rocket when it explodes. */
@@ -358,9 +365,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 +531,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/flipit.c b/apps/plugins/flipit.c
index c659cf5ba5..278c77e188 100644
--- a/apps/plugins/flipit.c
+++ b/apps/plugins/flipit.c
@@ -49,7 +49,7 @@
#define FLIPIT_DOWN BUTTON_PLAY
#define FLIPIT_NEXT BUTTON_SCROLL_FWD
#define FLIPIT_PREV BUTTON_SCROLL_BACK
-#define FLIPIT_QUIT (BUTTON_SELECT | BUTTON_MENU)
+#define FLIPIT_QUIT (BUTTON_SELECT | BUTTON_REPEAT)
#define FLIPIT_SHUFFLE (BUTTON_SELECT | BUTTON_LEFT)
#define FLIPIT_SOLVE (BUTTON_SELECT | BUTTON_PLAY)
#define FLIPIT_STEP_BY_STEP (BUTTON_SELECT | BUTTON_RIGHT)
@@ -841,7 +841,7 @@ enum plugin_status plugin_start(const void* parameter)
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
(CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
- rb->lcd_putsxy(2, 8, "[S-MENU] to stop");
+ rb->lcd_putsxy(2, 8, "Long [SELECT] to stop");
rb->lcd_putsxy(2, 18, "[SELECT] toggle");
rb->lcd_putsxy(2, 28, "[S-LEFT] shuffle");
rb->lcd_putsxy(2, 38, "[S-PLAY] solution");
diff --git a/apps/plugins/fractals/fractal.h b/apps/plugins/fractals/fractal.h
index 8e9446df0d..8432546c1e 100644
--- a/apps/plugins/fractals/fractal.h
+++ b/apps/plugins/fractals/fractal.h
@@ -40,7 +40,7 @@
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
(CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
-#define FRACTAL_QUIT (BUTTON_SELECT | BUTTON_MENU)
+#define FRACTAL_QUIT (BUTTON_SELECT | BUTTON_REPEAT)
#define FRACTAL_UP BUTTON_MENU
#define FRACTAL_DOWN BUTTON_PLAY
#define FRACTAL_LEFT BUTTON_LEFT
diff --git a/apps/plugins/imageviewer/image_decoder.c b/apps/plugins/imageviewer/image_decoder.c
index eab1c01dbc..0c1776daaa 100644
--- a/apps/plugins/imageviewer/image_decoder.c
+++ b/apps/plugins/imageviewer/image_decoder.c
@@ -155,7 +155,10 @@ const struct image_decoder *load_decoder(struct loader_info *loader_info)
goto error_close;
}
- if (lc_hdr->api_version != IMGDEC_API_VERSION)
+ if (lc_hdr->api_version != IMGDEC_API_VERSION ||
+ hdr->img_api_size > sizeof(struct imgdec_api) ||
+ hdr->plugin_api_version != PLUGIN_API_VERSION ||
+ hdr->plugin_api_size > sizeof(struct plugin_api))
{
rb->splashf(2*HZ, "%s decoder: Incompatible version.", name);
goto error_close;
diff --git a/apps/plugins/imageviewer/imageviewer.c b/apps/plugins/imageviewer/imageviewer.c
index e30a98ef68..c77b22fdae 100644
--- a/apps/plugins/imageviewer/imageviewer.c
+++ b/apps/plugins/imageviewer/imageviewer.c
@@ -236,9 +236,9 @@ static bool set_option_dithering(void)
}
MENUITEM_FUNCTION(grayscale_item, 0, ID2P(LANG_GRAYSCALE),
- set_option_grayscale, NULL, NULL, Icon_NOICON);
+ set_option_grayscale, NULL, Icon_NOICON);
MENUITEM_FUNCTION(dithering_item, 0, ID2P(LANG_DITHERING),
- set_option_dithering, NULL, NULL, Icon_NOICON);
+ set_option_dithering, NULL, Icon_NOICON);
MAKE_MENU(display_menu, "Display Options", NULL, Icon_NOICON,
&grayscale_item, &dithering_item);
@@ -353,7 +353,7 @@ static int show_menu(void) /* return 1 to quit */
static int ask_and_get_audio_buffer(const char *filename)
{
int button;
-#if defined(IMGVIEW_ZOOM_PRE)
+#if defined(IMGVIEW_ZOOM_PRE) || defined(IMGVIEW_QUIT_PRE)
int lastbutton = BUTTON_NONE;
#endif
rb->lcd_setfont(FONT_SYSFIXED);
@@ -392,6 +392,10 @@ static int ask_and_get_audio_buffer(const char *filename)
#endif
#ifdef IMGVIEW_QUIT
case IMGVIEW_QUIT:
+#ifdef IMGVIEW_QUIT_PRE
+ if (lastbutton != IMGVIEW_QUIT_PRE)
+ break;
+#endif
#endif
case IMGVIEW_MENU:
return PLUGIN_OK;
@@ -424,7 +428,7 @@ static int ask_and_get_audio_buffer(const char *filename)
== SYS_USB_CONNECTED)
return PLUGIN_USB_CONNECTED;
}
-#if defined(IMGVIEW_ZOOM_PRE)
+#if defined(IMGVIEW_ZOOM_PRE) || defined(IMGVIEW_QUIT_PRE)
if (button != BUTTON_NONE)
lastbutton = button;
#endif
@@ -572,14 +576,19 @@ static void pan_view_down(struct image_info *info)
}
/* interactively scroll around the image */
-static int scroll_bmp(struct image_info *info)
+static int scroll_bmp(struct image_info *info, bool initial_frame)
{
static long ss_timeout = 0;
int button;
#if defined(IMGVIEW_ZOOM_PRE) || defined(IMGVIEW_MENU_PRE) \
- || defined(IMGVIEW_SLIDE_SHOW_PRE)
- int lastbutton = BUTTON_NONE;
+ || defined(IMGVIEW_SLIDE_SHOW_PRE) || defined(IMGVIEW_QUIT_PRE)
+ static int lastbutton;
+ if (initial_frame)
+ lastbutton = BUTTON_NONE;
+
+#else
+ (void) initial_frame;
#endif
if (!ss_timeout && iv_api.slideshow_enabled)
@@ -745,6 +754,10 @@ static int scroll_bmp(struct image_info *info)
#ifdef IMGVIEW_QUIT
case IMGVIEW_QUIT:
+#ifdef IMGVIEW_QUIT_PRE
+ if (lastbutton != IMGVIEW_QUIT_PRE)
+ break;
+#endif
return PLUGIN_OK;
break;
#endif
@@ -756,7 +769,8 @@ static int scroll_bmp(struct image_info *info)
break;
} /* switch */
-#if defined(IMGVIEW_ZOOM_PRE) || defined(IMGVIEW_MENU_PRE) || defined(IMGVIEW_SLIDE_SHOW_PRE)
+#if defined(IMGVIEW_ZOOM_PRE) || defined(IMGVIEW_MENU_PRE) ||\
+ defined(IMGVIEW_SLIDE_SHOW_PRE) || defined(IMGVIEW_QUIT_PRE)
if (button != BUTTON_NONE)
lastbutton = button;
#endif
@@ -922,6 +936,7 @@ static int load_and_show(char* filename, struct image_info *info)
/* used to loop through subimages in animated gifs */
int frame = 0;
+ bool initial_frame = true;
do /* loop the image prepare and decoding when zoomed */
{
status = imgdec->get_image(info, frame, ds); /* decode or fetch from cache */
@@ -954,7 +969,8 @@ static int load_and_show(char* filename, struct image_info *info)
*/
while (1)
{
- status = scroll_bmp(info);
+ status = scroll_bmp(info, initial_frame);
+ initial_frame = false;
if (status == ZOOM_IN)
{
@@ -1064,10 +1080,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 +1108,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/imageviewer.h b/apps/plugins/imageviewer/imageviewer.h
index 19b5db15bb..ac15df5960 100644
--- a/apps/plugins/imageviewer/imageviewer.h
+++ b/apps/plugins/imageviewer/imageviewer.h
@@ -136,14 +136,17 @@ struct image_decoder {
int x, int y, int width, int height);
};
-#define IMGDEC_API_VERSION (PLUGIN_API_VERSION << 4 | 0)
+#define IMGDEC_API_VERSION 1
/* image decoder header */
struct imgdec_header {
struct lc_header lc_hdr; /* must be the first */
const struct image_decoder *decoder;
const struct plugin_api **api;
+ unsigned short plugin_api_version;
+ size_t plugin_api_size;
const struct imgdec_api **img_api;
+ size_t img_api_size;
};
#ifdef IMGDEC
@@ -157,15 +160,18 @@ extern const struct image_decoder image_decoder;
const struct imgdec_header __header \
__attribute__ ((section (".header")))= { \
{ PLUGIN_MAGIC, TARGET_ID, IMGDEC_API_VERSION, \
- plugin_start_addr, plugin_end_addr }, &image_decoder, &rb, &iv };
+ plugin_start_addr, plugin_end_addr, }, &image_decoder, \
+ &rb, PLUGIN_API_VERSION, sizeof(struct plugin_api), \
+ &iv, sizeof(struct imgdec_api) };
#else /* PLATFORM_HOSTED */
#define IMGDEC_HEADER \
const struct plugin_api *rb DATA_ATTR; \
const struct imgdec_api *iv DATA_ATTR; \
const struct imgdec_header __header \
__attribute__((visibility("default"))) = { \
- { PLUGIN_MAGIC, TARGET_ID, IMGDEC_API_VERSION, \
- NULL, NULL }, &image_decoder, &rb, &iv };
+ { PLUGIN_MAGIC, TARGET_ID, IMGDEC_API_VERSION, NULL, NULL }, \
+ &image_decoder, &rb, PLUGIN_API_VERSION, sizeof(struct plugin_api), \
+ &iv, sizeof(struct imgdec_api), };
#endif /* CONFIG_PLATFORM */
#endif
diff --git a/apps/plugins/imageviewer/imageviewer_button.h b/apps/plugins/imageviewer/imageviewer_button.h
index b8b8c3baf7..d324f93292 100644
--- a/apps/plugins/imageviewer/imageviewer_button.h
+++ b/apps/plugins/imageviewer/imageviewer_button.h
@@ -53,8 +53,10 @@
#define IMGVIEW_RIGHT BUTTON_RIGHT
#define IMGVIEW_NEXT (BUTTON_SELECT | BUTTON_RIGHT)
#define IMGVIEW_PREVIOUS (BUTTON_SELECT | BUTTON_LEFT)
-#define IMGVIEW_MENU (BUTTON_SELECT | BUTTON_MENU)
-#define IMGVIEW_QUIT (BUTTON_SELECT | BUTTON_PLAY)
+#define IMGVIEW_MENU_PRE BUTTON_SELECT
+#define IMGVIEW_MENU (BUTTON_SELECT | BUTTON_REPEAT)
+#define IMGVIEW_QUIT_PRE BUTTON_SELECT
+#define IMGVIEW_QUIT (BUTTON_SELECT | BUTTON_REL)
#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
#define IMGVIEW_ZOOM_PRE BUTTON_SELECT
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/jackpot.c b/apps/plugins/jackpot.c
index 78f74568ca..fd878509cf 100644
--- a/apps/plugins/jackpot.c
+++ b/apps/plugins/jackpot.c
@@ -25,6 +25,13 @@
#include "lib/pluginlib_exit.h"
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define JACKPOT_QUIT PLA_UP
+#else
+#define JACKPOT_QUIT PLA_CANCEL
+#endif
const struct button_mapping* plugin_contexts[]={pla_main_ctx};
#define NB_PICTURES 9
@@ -248,7 +255,7 @@ enum plugin_status plugin_start(const void* parameter)
plugin_contexts, ARRAYLEN(plugin_contexts));
switch ( action )
{
- case PLA_CANCEL:
+ case JACKPOT_QUIT:
return PLUGIN_OK;
case PLA_SELECT:
jackpot_play_turn(&game);
diff --git a/apps/plugins/jewels.c b/apps/plugins/jewels.c
index 3f209ae556..1536b785b4 100644
--- a/apps/plugins/jewels.c
+++ b/apps/plugins/jewels.c
@@ -49,9 +49,9 @@
#define JEWELS_PREV BUTTON_SCROLL_BACK
#define JEWELS_NEXT BUTTON_SCROLL_FWD
#define JEWELS_SELECT BUTTON_SELECT
-#define JEWELS_CANCEL (BUTTON_SELECT | BUTTON_MENU)
+#define JEWELS_CANCEL (BUTTON_SELECT | BUTTON_REPEAT)
#define HK_SELECT "SELECT"
-#define HK_CANCEL "SEL + MENU"
+#define HK_CANCEL "Long SELECT"
#elif (CONFIG_KEYPAD == IPOD_3G_PAD)
#define JEWELS_LEFT BUTTON_LEFT
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..202d5fcfa4 100644
--- a/apps/plugins/keyremap.c
+++ b/apps/plugins/keyremap.c
@@ -42,8 +42,29 @@
#define KMFUSER "user_keyremap"
#define MAX_BUTTON_COMBO 5
#define MAX_BUTTON_NAME 32
+#define MAX_MENU_NAME 64
#define TEST_COUNTDOWN_MS 1590
+struct context_flags {
+ char * name;
+ int flag;
+};
+
+/* flags added to context_name[] */
+static struct context_flags context_flags[] = {
+ {"UNKNOWN", 0},/* index 0 is an Error */
+#ifndef HAS_BUTTON_HOLD
+ {"LOCKED", CONTEXT_LOCKED},
+#endif
+ /*{"PLUGIN", CONTEXT_PLUGIN}, need a custom action list and a way to supply */
+#if BUTTON_REMOTE != 0
+ {"REMOTE", CONTEXT_REMOTE},
+#ifndef HAS_BUTTON_HOLD
+ {"REMOTE_LOCKED", CONTEXT_REMOTE | CONTEXT_LOCKED},
+#endif
+#endif /* BUTTON_REMOTE != 0 */
+};
+
static struct keyremap_buffer_t {
char * buffer;
size_t buf_size;
@@ -138,7 +159,7 @@ MENU_ITEM(M_DELCORE, "Remove Core Remap", 1),
MENU_ITEM(M_EXIT, ID2P(LANG_MENU_QUIT), 0),
MENU_ITEM(M_ACTIONS, "Actions", LAST_ACTION_PLACEHOLDER),
MENU_ITEM(M_BUTTONS, "Buttons", -1), /* Set at runtime in plugin_start: */
-MENU_ITEM(M_CONTEXTS, "Contexts", LAST_CONTEXT_PLACEHOLDER ),
+MENU_ITEM(M_CONTEXTS, "Contexts", LAST_CONTEXT_PLACEHOLDER * ARRAYLEN(context_flags)),
MENU_ITEM(M_CONTEXT_EDIT, "", 5),
#undef MENU_ITEM
};
@@ -200,6 +221,47 @@ static void synclist_set_update(int id, int selected_item, int items, int sel_si
synclist_set(id, selected_item, items, sel_size);
}
+/* returns the actual context & index of the flag is passed in *flagidx */
+static int ctx_strip_flagidx(int ctx, int *flagidx)
+{
+ int ctx_out = ctx % (LAST_CONTEXT_PLACEHOLDER);
+ *flagidx = 0;
+ if (ctx_out != ctx)
+ {
+ while (ctx >= LAST_CONTEXT_PLACEHOLDER)
+ {
+ (*flagidx)++;
+ ctx -= LAST_CONTEXT_PLACEHOLDER;
+ }
+ if (*flagidx >= (int)ARRAYLEN(context_flags))
+ *flagidx = 0; /* unknown flag */
+
+ logf("%s ctx: (%d) %s flag idx: (%d) %s\n", __func__,
+ ctx, context_name(ctx), *flagidx, context_flags[*flagidx].name);
+ }
+ return ctx_out;
+}
+
+/* combines context name and flag name using '_' to join them */
+static char *ctx_name_and_flag(int index)
+{
+ static char ctx_namebuf[MAX_MENU_NAME];
+ char *ctx_name = "?";
+ int flagidx;
+ int ctx = ctx_strip_flagidx(index, &flagidx);
+ if (flagidx == 0)
+ {
+ ctx_name = context_name(ctx);
+ }
+ else if (flagidx >= 0 && flagidx < (int)ARRAYLEN(context_flags))
+ {
+ rb->snprintf(ctx_namebuf, sizeof(ctx_namebuf), "%s_%s",
+ context_name(ctx), context_flags[flagidx].name);
+ ctx_name = ctx_namebuf;
+ }
+ return ctx_name;
+}
+
static int btnval_to_index(unsigned int btnvalue)
{
int index = -1;
@@ -361,6 +423,7 @@ static int keyremap_map_is_valid(struct action_mapping_t *amap, int context)
static struct button_mapping *keyremap_create_temp(int *entries)
{
+ logf("%s()", __func__);
struct button_mapping *tempkeymap;
int action_offset = 1; /* start of action entries (ctx_count + 1)*/
int entry_count = 1;/* (ctx_count + ctx_count + act_count) */
@@ -390,8 +453,8 @@ 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("%s() entry count: %d", __func__, entry_count);
+ logf("keyremap bytes: %zu, avail: %zu", keymap_bytes,
(keyremap_buffer.end - keyremap_buffer.front));
if (keyremap_buffer.front + keymap_bytes < keyremap_buffer.end)
{
@@ -401,6 +464,7 @@ static struct button_mapping *keyremap_create_temp(int *entries)
for (i = 0; i < ctx_data.ctx_count; i++)
{
int actions_this_ctx = 0;
+ int flagidx;
int context = ctx_data.ctx_map[i].context;
/* how many actions are contained in each context? */
for (j = 0; j < ctx_data.act_count; j++)
@@ -413,6 +477,10 @@ static struct button_mapping *keyremap_create_temp(int *entries)
/*Don't save contexts with no actions */
if (actions_this_ctx == 0){ continue; }
+ /* convert context x flag to context | flag */
+ context = ctx_strip_flagidx(ctx_data.ctx_map[i].context, &flagidx);
+ context |= context_flags[flagidx].flag;
+
entry->action_code = CORE_CONTEXT_REMAP(context);
entry->button_code = action_offset; /* offset of first action entry */
entry->pre_button_code = actions_this_ctx; /* entries (excluding sentinel) */
@@ -431,6 +499,7 @@ static struct button_mapping *keyremap_create_temp(int *entries)
{
int actions_this_ctx = 0;
int context = ctx_data.ctx_map[i].context;
+
for (int j = 0; j < ctx_data.act_count; j++)
{
if (keyremap_map_is_valid(&ctx_data.act_map[j], context) > 0)
@@ -473,7 +542,7 @@ static int keyremap_save_current(const char *filename)
struct button_mapping *keymap = keyremap_create_temp(&entry_count);
- if (keymap == NULL || entry_count <= 3)
+ if (keymap == NULL || entry_count <= 3) /* there should be atleast 4 entries */
return status;
keyset.crc32 =
rb->crc_32(keymap, entry_count * sizeof(struct button_mapping), 0xFFFFFFFF);
@@ -505,6 +574,7 @@ static void keyremap_save_user_keys(bool notify)
if (keyremap_save_current(buf) == 0)
{
+ logf("Error Saving");
if(notify)
rb->splash(HZ *2, "Error Saving");
}
@@ -519,11 +589,13 @@ static int keyremap_export_current(char *filenamebuf, size_t bufsz)
int ctx_count = 0;
size_t entrylen;
- int entry_count = ctx_data.ctx_count + ctx_data.act_count + 1;;/* (ctx_count + ctx_count + act_count + 1) */
+ int entry_count = ctx_data.ctx_count + ctx_data.act_count + 1;
- if (entry_count <= 3)
+ if (entry_count < 3) /* the header is not counted should be at least 3 entries */
+ {
+ logf("%s: Not enough entries", __func__);
return 0;
-
+ }
int fd = rb->open(filenamebuf, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0)
@@ -613,13 +685,15 @@ static void keyremap_export_user_keys(void)
static void keyremap_import_user_keys(void)
{
char buf[MAX_PATH];
- struct browse_context browse;
-
- rb->browse_context_init(&browse, SHOW_ALL, BROWSE_SELECTONLY, "Select Keymap",
- Icon_Plugin, "/", NULL);
-
- browse.buf = buf;
- browse.bufsize = sizeof(buf);
+ struct browse_context browse = {
+ .dirfilter = SHOW_ALL,
+ .flags = BROWSE_SELECTONLY,
+ .title = "Select Keymap",
+ .icon = Icon_Plugin,
+ .buf = buf,
+ .bufsize = sizeof(buf),
+ .root = "/",
+ };
if (rb->rockbox_browse(&browse) == GO_TO_PREVIOUS)
{
@@ -928,9 +1002,13 @@ next_line:
{
bufleft = bufsz - (pctx - filenamebuf);
ctx = -1;
- for (int i=0;i < LAST_CONTEXT_PLACEHOLDER;i++)
+ int ctx_x_flag_count = (LAST_CONTEXT_PLACEHOLDER
+ * ARRAYLEN(context_flags));
+
+ for (int i=0;i < ctx_x_flag_count ;i++)
{
- if (rb->strncasecmp(pctx, context_name(i), bufleft) == 0)
+ /* context x flag */
+ if (rb->strncasecmp(pctx, ctx_name_and_flag(i), bufleft) == 0)
{
logf("ln: %d: Context Found: %s (%d)", line, pctx, i);
if (keymap_add_context_entry(i) <= 0)
@@ -1040,8 +1118,17 @@ static int keyremap_load_file(const char *filename)
}
if ((entry.action_code & CONTEXT_REMAPPED) == CONTEXT_REMAPPED)
{
-
int context = (entry.action_code & ~CONTEXT_REMAPPED);
+ for (int i = ARRAYLEN(context_flags) - 1; i > 0; i--) /* don't check idx 0*/
+ {
+ /* convert context | flag to context x flag */
+ if ((context & context_flags[i].flag) == context_flags[i].flag)
+ {
+ logf("found ctx flag %s", context_flags[i].name);
+ context &= ~context_flags[i].flag;
+ context += i * LAST_CONTEXT_PLACEHOLDER;
+ }
+ }
int offset = entry.button_code;
int entries = entry.pre_button_code;
if (offset == 0 || entries <= 0)
@@ -1197,10 +1284,10 @@ static const char *menu_useract_items_cb(int selected_item, void* data,
{
if (ctx_data.act_count == 0)
rb->snprintf(buf, buf_len, "%s$%s",
- context_name(ctx_data.ctx_map[i].context),
+ ctx_name_and_flag(ctx_data.ctx_map[i].context),
"Select$to add$actions");
else
- rb->snprintf(buf, buf_len, ctxfmt, context_name(ctx_data.ctx_map[i].context));
+ rb->snprintf(buf, buf_len, ctxfmt, ctx_name_and_flag(ctx_data.ctx_map[i].context));
return buf;
}
}
@@ -1215,7 +1302,7 @@ static const char *menu_useract_items_cb(int selected_item, void* data,
if (data != MENU_ID(M_EXPORTKEYS))
{
pctxbuf = ctxbuf;
- rb->snprintf(ctxbuf, sizeof(ctxbuf), ctxfmt, context_name(context));
+ rb->snprintf(ctxbuf, sizeof(ctxbuf), ctxfmt, ctx_name_and_flag(context));
pctxbuf += szctx;//sizeof("CONTEXT")
}
struct button_mapping * bm = &ctx_data.act_map[i].map;
@@ -1259,7 +1346,7 @@ static const char *test_keymap_name_cb(int selected_item, void* data,
if (keytest.context >= 0)
{
if (selected_item == 0)
- rb->snprintf(buf, buf_len, "< %s >", context_name(keytest.context));
+ rb->snprintf(buf, buf_len, "< %s >", ctx_name_and_flag(keytest.context));
else if (selected_item == 1)
{
if (keytest.countdown >= 10)
@@ -1300,7 +1387,7 @@ static const char* list_get_name_cb(int selected_item, void* data,
}
else if (data == MENU_ID(M_CONTEXTS))
{
- return context_name(selected_item);
+ return ctx_name_and_flag(selected_item);
}
else if (data == MENU_ID(M_DELKEYS) || data == MENU_ID(M_LOADKEYS))
{
@@ -1335,9 +1422,20 @@ static int list_voice_cb(int list_index, void* data)
else
rb->talk_spell(name, true);
}
+ else if(data == MENU_ID(M_SETKEYS))
+ {
+ char buf[MAX_MENU_NAME];
+ int selcol = printcell_get_column_selected();
+ const char* name = printcell_get_column_text(selcol, buf, sizeof(buf));
+ long id = P2ID((const unsigned char *)name);
+ if(id>=0)
+ rb->talk_id(id, true);
+ else
+ rb->talk_spell(name, true);
+ }
else
{
- char buf[64];
+ char buf[MAX_MENU_NAME];
const char* name = list_get_name_cb(list_index, data, buf, sizeof(buf));
long id = P2ID((const unsigned char *)name);
if(id>=0)
@@ -1519,14 +1617,14 @@ int menu_action_setkeys(int *action, int selected_item, bool* exit, struct gui_s
}
else
{
- keyset.view_lastcol = printcell_increment_column(lists, 1, true);
+ keyset.view_lastcol = printcell_increment_column(1, true);
*action = ACTION_NONE;
}
}
}
else if (*action == ACTION_STD_CANCEL)
{
- keyset.view_lastcol = printcell_increment_column(lists, -1, true);
+ keyset.view_lastcol = printcell_increment_column(-1, true);
if (keyset.view_lastcol != keyset.view_columns - 1)
{
*action = ACTION_NONE;
@@ -1950,9 +2048,8 @@ 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);
+ printcell_enable(false);
if (menu_id == MENU_ID(M_ROOT))
{
@@ -1961,15 +2058,16 @@ static void synclist_set(int id, int selected_item, int items, int sel_size)
}
else if (menu_id == MENU_ID(M_SETKEYS))
{
- printcell_enable(&lists, true, true);
- keyset.view_columns = printcell_set_columns(&lists, ACTVIEW_HEADER, Icon_Rockbox);
- int curcol = printcell_increment_column(&lists, 0, true);
+ keyset.view_columns = printcell_set_columns(&lists, NULL,
+ ACTVIEW_HEADER, Icon_Rockbox);
+ printcell_enable(true);
+ int curcol = printcell_get_column_selected();
if (keyset.view_lastcol >= keyset.view_columns)
keyset.view_lastcol = -1;
/* restore column position */
while (keyset.view_lastcol > -1 && curcol != keyset.view_lastcol)
{
- curcol = printcell_increment_column(&lists, 1, true);
+ curcol = printcell_increment_column(1, true);
}
keyset.view_lastcol = curcol;
}
@@ -1979,9 +2077,8 @@ static void synclist_set(int id, int selected_item, int items, int sel_size)
PEEK_MENU_ID(id);
lang_strlcpy(menu_title, mainitem(id)->name, sizeof(menu_title));
rb->gui_synclist_set_title(&lists, menu_title, Icon_Submenu_Entered);
- /* if (menu_title[0] == '$'){ printcell_enable(&lists, true, true); } */
+ /* if (menu_title[0] == '$'){ printcell_enable(true); } */
}
-
}
static void keyremap_set_buffer(void* buffer, size_t buf_size)
@@ -2055,7 +2152,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..5aa06f4d2d 100644
--- a/apps/plugins/lamp.c
+++ b/apps/plugins/lamp.c
@@ -58,7 +58,14 @@ static const struct button_mapping *plugin_contexts[] = { pla_main_ctx };
#define LAMP_EXIT PLA_EXIT
+
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define LAMP_EXIT2 PLA_UP
+#else
#define LAMP_EXIT2 PLA_CANCEL
+#endif
#ifdef HAVE_LCD_COLOR
@@ -103,9 +110,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 +122,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 +212,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/lastfm_scrobbler.c b/apps/plugins/lastfm_scrobbler.c
index 7bd213b6d2..1530ff7ae7 100644
--- a/apps/plugins/lastfm_scrobbler.c
+++ b/apps/plugins/lastfm_scrobbler.c
@@ -21,11 +21,56 @@
*
****************************************************************************/
/* Scrobbler Plugin
-Audioscrobbler spec at:
+Audioscrobbler spec at: (use wayback machine)
http://www.audioscrobbler.net/wiki/Portable_Player_Logging
+* EXCERPT:
+* The first lines of .scrobbler.log should be header lines, indicated by the leading '#' character:
+
+#AUDIOSCROBBLER/1.1
+#TZ/[UNKNOWN|UTC]
+#CLIENT/<IDENTIFICATION STRING>
+
+Where 1.1 is the version for this file format
+
+ If the device knows what timezone it is in,
+ it must convert all logged times to UTC (aka GMT+0)
+ eg: #TZ/UTC
+ If the device knows the time, but not the timezone
+ eg: #TZ/UNKNOWN
+
+<IDENTIFICATION STRING> should be replaced by the name/model of the hardware device
+ and the revision of the software producing the log file.
+
+After the header lines, simply append one line of text for every song
+ that is played or skipped.
+
+The following fields comprise each line, and are tab (\t)
+ separated (strip any tab characters from the data):
+
+ - artist name
+ - album name (optional)
+ - track name
+ - track position on album (optional)
+ - song duration in seconds
+ - rating (L if listened at least 50% or S if skipped)
+ - unix timestamp when song started playing
+ - MusicBrainz Track ID (optional)
+lines should be terminated with \n
+Example
+(listened to enter sandman, skipped cowboys, listened to the pusher) :
+ #AUDIOSCROBBLER/1.0
+ #TZ/UTC
+ #CLIENT/Rockbox h3xx 1.1
+ Metallica Metallica Enter Sandman 1 365 L 1143374412 62c2e20a?-559e-422f-a44c-9afa7882f0c4?
+ Portishead Roseland NYC Live Cowboys 2 312 S 1143374777 db45ed76-f5bf-430f-a19f-fbe3cd1c77d3
+ Steppenwolf Live The Pusher 12 350 L 1143374779 58ddd581-0fcc-45ed-9352-25255bf80bfb?
+ If the data for optional fields is not available to you, leave the field blank (\t\t).
+ All strings should be written as UTF-8, although the file does not use a BOM.
+ All fields except those marked (optional) above are required.
*/
#include "plugin.h"
+#include "lib/configfile.h"
#ifndef UNTAGGED
#define UNTAGGED "<UNTAGGED>"
@@ -39,22 +84,35 @@ http://www.audioscrobbler.net/wiki/Portable_Player_Logging
/****************** constants ******************/
#define EV_EXIT MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0xFF)
-#define EV_OTHINSTANCE MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0xFE)
+#define EV_FLUSHCACHE MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0xFE)
+#define EV_USER_ERROR MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0xFD)
#define EV_STARTUP MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0x01)
#define EV_TRACKCHANGE MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0x02)
#define EV_TRACKFINISH MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0x03)
-#define SCROBBLER_VERSION "1.1"
+#define ERR_NONE (0)
+#define ERR_WRITING_FILE (-1)
+#define ERR_ENTRY_LENGTH (-2)
+#define ERR_WRITING_DATA (-3)
/* increment this on any code change that effects output */
+#define SCROBBLER_VERSION "1.1"
+
#define SCROBBLER_REVISION " $Revision$"
-#define SCROBBLER_MAX_CACHE 32
+#define SCROBBLER_BAD_ENTRY "# FAILED - "
+
/* longest entry I've had is 323, add a safety margin */
-#define SCROBBLER_CACHE_LEN 512
+#define SCROBBLER_CACHE_LEN (512)
+#define SCROBBLER_MAX_CACHE (32 * SCROBBLER_CACHE_LEN)
+
+#define SCROBBLER_MAX_TRACK_MRU (32) /* list of hashes to detect repeats */
#define ITEM_HDR "#ARTIST #ALBUM #TITLE #TRACKNUM #LENGTH #RATING #TIMESTAMP #MUSICBRAINZ_TRACKID\n"
+#define CFG_FILE "/lastfm_scrobbler.cfg"
+#define CFG_VER 1
+
#if CONFIG_RTC
static time_t timestamp;
#define BASE_FILENAME HOME_DIR "/.scrobbler.log"
@@ -63,161 +121,212 @@ static time_t timestamp;
#define record_timestamp() ((void)(timestamp = rb->mktime(rb->get_time())))
#else /* !CONFIG_RTC */
#define HDR_STR_TIMELESS " Timeless"
-#define BASE_FILENAME ".scrobbler-timeless.log"
+#define BASE_FILENAME HOME_DIR "/.scrobbler-timeless.log"
#define get_timestamp() (0l)
#define record_timestamp() ({})
#endif /* CONFIG_RTC */
#define THREAD_STACK_SIZE 4*DEFAULT_STACK_SIZE
-#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
- (CONFIG_KEYPAD == IRIVER_H300_PAD)
-#define SCROBBLE_OFF BUTTON_OFF
-#define SCROBBLE_OFF_TXT "STOP"
-#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
- (CONFIG_KEYPAD == IPOD_3G_PAD) || \
- (CONFIG_KEYPAD == IPOD_1G2G_PAD)
-#define SCROBBLE_OFF BUTTON_MENU
-#define SCROBBLE_OFF_TXT "MENU"
-#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD || \
- CONFIG_KEYPAD == AGPTEK_ROCKER_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
- (CONFIG_KEYPAD == SANSA_C200_PAD) || \
- (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
- (CONFIG_KEYPAD == SANSA_M200_PAD)
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
-#define SCROBBLE_OFF BUTTON_HOME
-#define SCROBBLE_OFF_TXT "HOME"
-#elif (CONFIG_KEYPAD == IRIVER_H10_PAD || \
- CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD || \
- CONFIG_KEYPAD == SONY_NWZ_PAD || \
- CONFIG_KEYPAD == XDUOO_X3_PAD || \
- CONFIG_KEYPAD == IHIFI_770_PAD || \
- CONFIG_KEYPAD == IHIFI_800_PAD || \
- CONFIG_KEYPAD == XDUOO_X3II_PAD || \
- CONFIG_KEYPAD == XDUOO_X20_PAD || \
- CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD || \
- CONFIG_KEYPAD == EROSQ_PAD)
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == GIGABEAT_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == GIGABEAT_S_PAD \
- || CONFIG_KEYPAD == SAMSUNG_YPR0_PAD \
- || CONFIG_KEYPAD == CREATIVE_ZEN_PAD
-#define SCROBBLE_OFF BUTTON_BACK
-#define SCROBBLE_OFF_TXT "BACK"
-#elif CONFIG_KEYPAD == MROBE500_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == MROBE100_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
-#define SCROBBLE_OFF BUTTON_REC
-#define BATTERY_RC_OFF BUTTON_RC_REC
-#define SCROBBLE_OFF_TXT "REC"
-#elif CONFIG_KEYPAD == COWON_D2_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
-#define SCROBBLE_OFF BUTTON_BACK
-#define SCROBBLE_OFF_TXT "BACK"
-#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == ONDAVX747_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == ONDAVX777_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \
- (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD)
-#define SCROBBLE_OFF BUTTON_RIGHT
-#define SCROBBLE_OFF_TXT "RIGHT"
-#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
-#define SCROBBLE_OFF BUTTON_REC
-#define SCROBBLE_OFF_TXT "REC"
-#elif CONFIG_KEYPAD == MPIO_HD200_PAD
-#define SCROBBLE_OFF BUTTON_REC
-#define SCROBBLE_OFF_TXT "REC"
-#elif CONFIG_KEYPAD == MPIO_HD300_PAD
-#define SCROBBLE_OFF BUTTON_REC
-#define SCROBBLE_OFF_TXT "REC"
-#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif (CONFIG_KEYPAD == HM60X_PAD) || (CONFIG_KEYPAD == HM801_PAD)
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "POWER"
-#elif CONFIG_KEYPAD == DX50_PAD
-#define SCROBBLE_OFF BUTTON_POWER_LONG
-#define SCROBBLE_OFF_TXT "Power Long"
-#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "Power"
-#elif CONFIG_KEYPAD == FIIO_M3K_PAD
-#define SCROBBLE_OFF BUTTON_POWER
-#define SCROBBLE_OFF_TXT "Power"
-#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
-/* use touchscreen */
-#else
-#error "No keymap defined!"
-#endif
-#if defined(HAVE_TOUCHSCREEN)
-#ifndef SCROBBLE_OFF
-#define SCROBBLE_OFF BUTTON_TOPLEFT
-#endif
-#ifndef SCROBBLE_OFF_TXT
-#define SCROBBLE_OFF_TXT "TOPLEFT"
-#endif
-#endif
/****************** prototypes ******************/
-int plugin_main(const void* parameter); /* main loop */
enum plugin_status plugin_start(const void* parameter); /* entry */
-
+void play_tone(unsigned int frequency, unsigned int duration);
/****************** globals ******************/
-unsigned char **language_strings; /* for use with str() macro; must be init */
/* communication to the worker thread */
static struct
{
bool exiting; /* signal to the thread that we want to exit */
unsigned int id; /* worker thread id */
- struct event_queue queue; /* thread event queue */
+ struct event_queue queue; /* thread event queue */
+ struct queue_sender_list queue_send;
long stack[THREAD_STACK_SIZE / sizeof(long)];
} gThread;
-static struct
+struct cache_entry
{
+ size_t len;
+ uint32_t crc;
+ char buf[ ];
+};
+
+static struct scrobbler_cache
+{
+ int entries;
char *buf;
- int pos;
+ size_t pos;
size_t size;
bool pending;
bool force_flush;
+ struct mutex mtx;
} gCache;
+static struct scrobbler_cfg
+{
+ int uniqct;
+ int savepct;
+ int minms;
+ int beeplvl;
+ bool playback;
+ bool verbose;
+} gConfig;
+
+static struct configdata config[] =
+{
+ #define MAX_MRU (SCROBBLER_MAX_TRACK_MRU)
+ {TYPE_INT, 0, MAX_MRU, { .int_p = &gConfig.uniqct }, "UniqCt", NULL},
+ {TYPE_INT, 0, 100, { .int_p = &gConfig.savepct }, "SavePct", NULL},
+ {TYPE_INT, 0, 10000, { .int_p = &gConfig.minms }, "MinMs", NULL},
+ {TYPE_BOOL, 0, 1, { .bool_p = &gConfig.playback }, "Playback", NULL},
+ {TYPE_BOOL, 0, 1, { .bool_p = &gConfig.verbose }, "Verbose", NULL},
+ {TYPE_INT, 0, 10, { .int_p = &gConfig.beeplvl }, "BeepLvl", NULL},
+ #undef MAX_MRU
+};
+const int gCfg_sz = sizeof(config)/sizeof(*config);
+
+/****************** config functions *****************/
+static void config_set_defaults(void)
+{
+ gConfig.uniqct = SCROBBLER_MAX_TRACK_MRU;
+ gConfig.savepct = 50;
+ gConfig.minms = 500;
+ gConfig.playback = false;
+ gConfig.verbose = true;
+ gConfig.beeplvl = 10;
+}
+
+static int config_settings_menu(void)
+{
+ int selection = 0;
+
+ static uint32_t crc = 0;
+
+ struct viewport parentvp[NB_SCREENS];
+ FOR_NB_SCREENS(l)
+ {
+ rb->viewport_set_defaults(&parentvp[l], l);
+ rb->viewport_set_fullscreen(&parentvp[l], l);
+ }
+
+ #define MENUITEM_STRINGLIST_CUSTOM(name, str, callback, ... ) \
+ static const char *name##_[] = {__VA_ARGS__}; \
+ static const struct menu_callback_with_desc name##__ = \
+ {callback,str, Icon_NOICON}; \
+ struct menu_item_ex name = \
+ {MT_RETURN_ID|MENU_HAS_DESC| \
+ MENU_ITEM_COUNT(sizeof( name##_)/sizeof(*name##_)), \
+ { .strings = name##_},{.callback_and_desc = & name##__}};
+
+ MENUITEM_STRINGLIST_CUSTOM(settings_menu, ID2P(LANG_SETTINGS), NULL,
+ ID2P(LANG_RESUME_PLAYBACK),
+ "Save Threshold",
+ "Minimum Elapsed",
+ "Verbose",
+ "Beep Level",
+ "Unique Track MRU",
+ ID2P(LANG_REVERT_TO_DEFAULT_SETTINGS),
+ ID2P(VOICE_BLANK),
+ ID2P(LANG_CANCEL_0),
+ ID2P(LANG_SAVE_EXIT));
+
+ #undef MENUITEM_STRINGLIST_CUSTOM
+
+ const int items = MENU_GET_COUNT(settings_menu.flags);
+ const unsigned int flags = settings_menu.flags & (~MENU_ITEM_COUNT(MENU_COUNT_MASK));
+ if (crc == 0)
+ {
+ crc = rb->crc_32(&gConfig, sizeof(struct scrobbler_cfg), 0xFFFFFFFF);
+ }
+
+ do {
+ if (crc == rb->crc_32(&gConfig, sizeof(struct scrobbler_cfg), 0xFFFFFFFF))
+ {
+ /* hide save item -- there are no changes to save */
+ settings_menu.flags = flags|MENU_ITEM_COUNT((items - 1));
+ }
+ else
+ {
+ settings_menu.flags = flags|MENU_ITEM_COUNT(items);
+ }
+ selection=rb->do_menu(&settings_menu,&selection, parentvp, true);
+ switch(selection) {
+
+ case 0: /* resume playback on plugin start */
+ rb->set_bool(rb->str(LANG_RESUME_PLAYBACK), &gConfig.playback);
+ break;
+ case 1: /* % of track played to indicate listened status */
+ rb->set_int("Save Threshold", "%", UNIT_PERCENT,
+ &gConfig.savepct, NULL, 10, 0, 100, NULL );
+ break;
+ case 2: /* tracks played less than this will not be logged */
+ rb->set_int("Minimum Elapsed", "ms", UNIT_MS,
+ &gConfig.minms, NULL, 100, 0, 10000, NULL );
+ break;
+ case 3: /* suppress non-error messages */
+ rb->set_bool("Verbose", &gConfig.verbose);
+ break;
+ case 4: /* set volume of start-up beep */
+ rb->set_int("Beep Level", "", UNIT_INT,
+ &gConfig.beeplvl, NULL, 1, 0, 10, NULL);
+ play_tone(1500, 100);
+ break;
+ case 5: /* keep a list of tracks to prevent repeat [Skipped] entries */
+ rb->set_int("Unique Track MRU Size", "", UNIT_INT,
+ &gConfig.uniqct, NULL, 1, 0, SCROBBLER_MAX_TRACK_MRU, NULL);
+ break;
+ case 6: /* set defaults */
+ {
+ const struct text_message prompt = {
+ (const char*[]){ ID2P(LANG_AUDIOSCROBBLER),
+ ID2P(LANG_REVERT_TO_DEFAULT_SETTINGS)}, 2};
+ if(rb->gui_syncyesno_run(&prompt, NULL, NULL) == YESNO_YES)
+ {
+ config_set_defaults();
+ if (gConfig.verbose)
+ rb->splash(HZ, ID2P(LANG_REVERT_TO_DEFAULT_SETTINGS));
+ }
+ break;
+ }
+ case 7: /*sep*/
+ continue;
+ case 8: /* Cancel */
+ return -1;
+ break;
+ case 9: /* Save & exit */
+ {
+ int res = configfile_save(CFG_FILE, config, gCfg_sz, CFG_VER);
+ if (res >= 0)
+ {
+ crc = rb->crc_32(&gConfig, sizeof(struct scrobbler_cfg), 0xFFFFFFFF);
+ logf("SCROBBLER: cfg saved %s %d bytes", CFG_FILE, gCfg_sz);
+ return PLUGIN_OK;
+ }
+ logf("SCROBBLER: cfg FAILED (%d) %s", res, CFG_FILE);
+ return PLUGIN_ERROR;
+ }
+ case MENU_ATTACHED_USB:
+ return PLUGIN_USB_CONNECTED;
+ default:
+ return PLUGIN_OK;
+ }
+ } while ( selection >= 0 );
+ return 0;
+}
+
/****************** helper fuctions ******************/
+void play_tone(unsigned int frequency, unsigned int duration)
+{
+ if (gConfig.beeplvl > 0)
+ rb->beep_play(frequency, duration, 100 * gConfig.beeplvl);
+}
-int scrobbler_init(void)
+int scrobbler_init_cache(void)
{
+ memset(&gCache, 0, sizeof(struct scrobbler_cache));
gCache.buf = rb->plugin_get_buffer(&gCache.size);
- size_t reqsz = SCROBBLER_MAX_CACHE*SCROBBLER_CACHE_LEN;
+ /* we need to reserve the space we want for our use in TSR plugins since
+ * someone else could call plugin_get_buffer() and corrupt our memory */
+ size_t reqsz = SCROBBLER_MAX_CACHE;
gCache.size = PLUGIN_BUFFER_SIZE - rb->plugin_reserve_buffer(reqsz);
if (gCache.size < reqsz)
@@ -225,14 +334,80 @@ int scrobbler_init(void)
logf("SCROBBLER: OOM , %ld < req:%ld", gCache.size, reqsz);
return -1;
}
-
- gCache.pos = 0;
- gCache.pending = false;
gCache.force_flush = true;
- logf("Scrobbler Initialized");
+ rb->mutex_init(&gCache.mtx);
+ logf("SCROBBLER: Initialized");
return 1;
}
+static inline size_t cache_get_entry_size(int str_len)
+{
+ /* entry_sz consists of the cache entry + str_len + \0NULL terminator */
+ return str_len + 1 + sizeof(struct cache_entry);
+}
+
+static inline const char* str_chk_valid(const char *s, const char *alt)
+{
+ return (s != NULL ? s : alt);
+}
+
+static bool track_is_unique(uint32_t hash1, uint32_t hash2)
+{
+ bool is_unique = false;
+ static uint8_t mru_len = 0;
+
+ struct hash64 { uint32_t hash1; uint32_t hash2; };
+
+ static struct hash64 hash_mru[SCROBBLER_MAX_TRACK_MRU];
+ struct hash64 i = {0};
+ struct hash64 itmp;
+ uint8_t mru;
+
+ if (mru_len > gConfig.uniqct)
+ mru_len = gConfig.uniqct;
+
+ if (gConfig.uniqct < 1)
+ return true;
+
+ /* Search in MRU */
+ for (mru = 0; mru < mru_len; mru++)
+ {
+ /* Items shifted >> 1 */
+ itmp = i;
+ i = hash_mru[mru];
+ hash_mru[mru] = itmp;
+
+ /* Found in MRU */
+ if ((i.hash1 == hash1) && (i.hash2 == hash2))
+ {
+ logf("SCROBBLER: hash [%x, %x] found in MRU @ %d", i.hash1, i.hash2, mru);
+ goto Found;
+ }
+ }
+
+ /* Add MRU entry */
+ is_unique = true;
+ if (mru_len < SCROBBLER_MAX_TRACK_MRU && mru_len < gConfig.uniqct)
+ {
+ hash_mru[mru_len] = i;
+ mru_len++;
+ }
+ else
+ {
+ logf("SCROBBLER: hash [%x, %x] evicted from MRU", i.hash1, i.hash2);
+ }
+
+ i = (struct hash64){.hash1 = hash1, .hash2 = hash2};
+ logf("SCROBBLER: hash [%x, %x] added to MRU[%d]", i.hash1, i.hash2, mru_len);
+
+Found:
+
+ /* Promote MRU item to top of MRU */
+ hash_mru[0] = i;
+
+ return is_unique;
+}
+
static void get_scrobbler_filename(char *path, size_t size)
{
int used;
@@ -241,7 +416,7 @@ static void get_scrobbler_filename(char *path, size_t size)
if (used >= (int)size)
{
- logf("%s: not enough buffer space for log file", __func__);
+ logf("%s: not enough buffer space for log filename", __func__);
rb->memset(path, 0, size);
}
}
@@ -252,6 +427,9 @@ static void scrobbler_write_cache(void)
int fd;
logf("%s", __func__);
char scrobbler_file[MAX_PATH];
+
+ rb->mutex_lock(&gCache.mtx);
+
get_scrobbler_filename(scrobbler_file, sizeof(scrobbler_file));
/* If the file doesn't exist, create it.
@@ -261,6 +439,7 @@ static void scrobbler_write_cache(void)
fd = rb->open(scrobbler_file, O_RDWR | O_CREAT, 0666);
if(fd >= 0)
{
+ /* write file header */
rb->fdprintf(fd, "#AUDIOSCROBBLER/" SCROBBLER_VERSION "\n"
"#TZ/UNKNOWN\n" "#CLIENT/Rockbox "
TARGET_NAME SCROBBLER_REVISION
@@ -275,38 +454,72 @@ static void scrobbler_write_cache(void)
}
}
+ int entries = gCache.entries;
+ size_t used = gCache.pos;
+ size_t pos = 0;
+ /* clear even if unsuccessful - we don't want to overflow the buffer */
+ gCache.pos = 0;
+ gCache.entries = 0;
+
/* write the cache entries */
fd = rb->open(scrobbler_file, O_WRONLY | O_APPEND);
if(fd >= 0)
{
- logf("SCROBBLER: writing %d entries", gCache.pos);
- /* copy data to temporary storage in case data moves during I/O */
- char temp_buf[SCROBBLER_CACHE_LEN];
- for ( i=0; i < gCache.pos; i++ )
+ logf("SCROBBLER: writing %d entries", entries);
+ /* copy cached data to storage */
+ uint32_t prev_crc = 0x0;
+ uint32_t crc;
+ size_t entry_sz, len;
+ bool err = false;
+
+ for (i = 0; i < entries && pos < used; i++)
{
- logf("SCROBBLER: write %d", i);
- char* scrobbler_buf = gCache.buf;
- ssize_t len = rb->strlcpy(temp_buf, scrobbler_buf+(SCROBBLER_CACHE_LEN*i),
- sizeof(temp_buf));
- if (rb->write(fd, temp_buf, len) != len)
+ logf("SCROBBLER: write %d read pos [%ld]", i, pos);
+
+ struct cache_entry *entry = (struct cache_entry*)&gCache.buf[pos];
+
+ entry_sz = cache_get_entry_size(entry->len);
+ crc = rb->crc_32(entry->buf, entry->len, 0xFFFFFFFF) ^ prev_crc;
+ prev_crc = crc;
+
+ len = rb->strlen(entry->buf);
+ logf("SCROBBLER: write entry %d sz [%ld] len [%ld]", i, entry_sz, len);
+
+ if (len != entry->len || crc != entry->crc) /* the entry is corrupted */
+ {
+ rb->write(fd, SCROBBLER_BAD_ENTRY, sizeof(SCROBBLER_BAD_ENTRY)-1);
+ logf("SCROBBLER: Bad entry %d", i);
+ if(!err)
+ {
+ rb->queue_post(&gThread.queue, EV_USER_ERROR, ERR_WRITING_DATA);
+ err = true;
+ }
+ }
+
+ logf("SCROBBLER: writing %s", entry->buf);
+
+ if (rb->write(fd, entry->buf, len) != (ssize_t)len)
break;
+
+ if (entry->buf[len - 1] != '\n')
+ rb->write(fd, "\n", 1); /* ensure newline termination */
+
+ pos += entry_sz;
}
rb->close(fd);
}
else
{
logf("SCROBBLER: error writing file");
+ rb->queue_post(&gThread.queue, EV_USER_ERROR, ERR_WRITING_FILE);
}
-
- /* clear even if unsuccessful - don't want to overflow the buffer */
- gCache.pos = 0;
+ rb->mutex_unlock(&gCache.mtx);
}
#if USING_STORAGE_CALLBACK
static void scrobbler_flush_callback(void)
{
- (void) gCache.force_flush;
- if(gCache.pos <= 0)
+ if(gCache.pos == 0)
return;
#if (CONFIG_STORAGE & STORAGE_ATA)
else
@@ -321,69 +534,127 @@ static void scrobbler_flush_callback(void)
}
#endif
-static inline char* str_chk_valid(char *s, char *alt)
+static unsigned long scrobbler_get_threshold(unsigned long length)
{
- return (s != NULL ? s : alt);
+ /* length is assumed to be in miliseconds */
+ return length / 100 * gConfig.savepct;
+}
+
+static int create_log_entry(const struct mp3entry *id,
+ struct cache_entry *entry, int *trk_info_len)
+{
+ #define SEP "\t"
+ #define EOL "\n"
+ char* artist = id->artist ? id->artist : id->albumartist;
+ char rating = 'S'; /* Skipped */
+ if (id->elapsed >= scrobbler_get_threshold(id->length))
+ rating = 'L'; /* Listened */
+
+ char tracknum[11] = { "" };
+
+ if (id->tracknum > 0)
+ rb->snprintf(tracknum, sizeof (tracknum), "%d", id->tracknum);
+
+ int ret = rb->snprintf(entry->buf,
+ SCROBBLER_CACHE_LEN,
+ "%s"SEP"%s"SEP"%s"SEP"%s"SEP"%d%n"SEP"%c"SEP"%ld"SEP"%s"EOL"",
+ str_chk_valid(artist, UNTAGGED),
+ str_chk_valid(id->album, ""),
+ str_chk_valid(id->title, id->path),
+ tracknum,
+ (int)(id->length / 1000),
+ trk_info_len, /* receives len of the string written so far */
+ rating,
+ get_timestamp(),
+ str_chk_valid(id->mb_track_id, ""));
+
+ #undef SEP
+ #undef EOL
+ return ret;
}
static void scrobbler_add_to_cache(const struct mp3entry *id)
{
- static uint32_t last_crc = 0;
int trk_info_len = 0;
- if ( gCache.pos >= SCROBBLER_MAX_CACHE )
- scrobbler_write_cache();
+ if (id->elapsed < (unsigned long) gConfig.minms)
+ {
+ logf("SCROBBLER: skipping entry < %d ms: %s", gConfig.minms, id->path);
+ return;
+ }
- char rating = 'S'; /* Skipped */
- char* scrobbler_buf = gCache.buf;
+ rb->mutex_lock(&gCache.mtx);
- logf("SCROBBLER: add_to_cache[%d]", gCache.pos);
+ /* not enough room left to guarantee next entry will fit so flush the cache */
+ if ( gCache.pos > SCROBBLER_MAX_CACHE - SCROBBLER_CACHE_LEN )
+ scrobbler_write_cache();
- if (id->elapsed > id->length / 2)
- rating = 'L'; /* Listened */
+ logf("SCROBBLER: add_to_cache[%d] write pos[%ld]", gCache.entries, gCache.pos);
+ /* use prev_crc to allow whole buffer to be checked for consistency */
+ static uint32_t prev_crc = 0x0;
+ if (gCache.pos == 0)
+ prev_crc = 0x0;
- char tracknum[11] = { "" };
+ void *buf = &gCache.buf[gCache.pos];
+ memset(buf, 0, SCROBBLER_CACHE_LEN);
- if (id->tracknum > 0)
- rb->snprintf(tracknum, sizeof (tracknum), "%d", id->tracknum);
+ struct cache_entry *entry = buf;
- char* artist = id->artist ? id->artist : id->albumartist;
+ int ret = create_log_entry(id, entry, &trk_info_len);
- int ret = rb->snprintf(&scrobbler_buf[(SCROBBLER_CACHE_LEN*gCache.pos)],
- SCROBBLER_CACHE_LEN,
- "%s\t%s\t%s\t%s\t%d\t%c%n\t%ld\t%s\n",
- str_chk_valid(artist, UNTAGGED),
- str_chk_valid(id->album, ""),
- str_chk_valid(id->title, ""),
- tracknum,
- (int)(id->length / 1000),
- rating,
- &trk_info_len,
- get_timestamp(),
- str_chk_valid(id->mb_track_id, ""));
-
- if ( ret >= SCROBBLER_CACHE_LEN )
+ if (ret <= 0 || (size_t) ret >= SCROBBLER_CACHE_LEN)
{
logf("SCROBBLER: entry too long:");
logf("SCROBBLER: %s", id->path);
+ rb->queue_post(&gThread.queue, EV_USER_ERROR, ERR_ENTRY_LENGTH);
}
- else
+ else if (ret > 0)
{
- uint32_t crc = rb->crc_32(&scrobbler_buf[(SCROBBLER_CACHE_LEN*gCache.pos)],
- trk_info_len, 0xFFFFFFFF);
- if (crc != last_crc)
+ /* first generate a crc over the static portion of the track info data
+ this and a crc of the filename will be used to detect repeat entries
+ */
+ static uint32_t last_crc = 0;
+ uint32_t crc_entry = rb->crc_32(entry->buf, trk_info_len, 0xFFFFFFFF);
+ uint32_t crc_path = rb->crc_32(id->path, rb->strlen(id->path), 0xFFFFFFFF);
+ bool is_unique = track_is_unique(crc_entry, crc_path);
+ bool is_listened = (id->elapsed >= scrobbler_get_threshold(id->length));
+
+ if (is_unique || is_listened)
{
- last_crc = crc;
- logf("Added %s", scrobbler_buf);
- gCache.pos++;
+ /* finish calculating the CRC of the whole entry */
+ const void *src = entry->buf + trk_info_len;
+ entry->crc = rb->crc_32(src, ret - trk_info_len, crc_entry) ^ prev_crc;
+ prev_crc = entry->crc;
+ entry->len = ret;
+
+ /* since Listened entries are written regardless
+ make sure this isn't a direct repeat */
+ if ((entry->crc ^ crc_path) != last_crc)
+ {
+
+ if (is_listened)
+ last_crc = (entry->crc ^ crc_path);
+ else
+ last_crc = 0;
+
+ size_t entry_sz = cache_get_entry_size(ret);
+
+ logf("SCROBBLER: Added (#%d) sz[%ld] len[%d], %s",
+ gCache.entries, entry_sz, ret, entry->buf);
+
+ gCache.entries++;
+ /* increase pos by string len + null terminator + sizeof entry */
+ gCache.pos += entry_sz;
+
#if USING_STORAGE_CALLBACK
- rb->register_storage_idle_func(scrobbler_flush_callback);
+ rb->register_storage_idle_func(scrobbler_flush_callback);
#endif
+ }
}
else
logf("SCROBBLER: skipping repeat entry: %s", id->path);
}
-
+ rb->mutex_unlock(&gCache.mtx);
}
static void scrobbler_flush_cache(void)
@@ -404,16 +675,14 @@ static void scrobbler_flush_cache(void)
}
}
-static void scrobbler_change_event(unsigned short id, void *ev_data)
+static void track_change_event(unsigned short id, void *ev_data)
{
(void)id;
logf("%s", __func__);
struct mp3entry *id3 = ((struct track_event *)ev_data)->id3;
- /* check if track was resumed > %50 played ( likely got saved )
- check for blank artist or track name */
- if ((id3->elapsed > id3->length / 2)
- || (!id3->artist && !id3->albumartist) || !id3->title)
+ /* check if track was resumed > %threshold played ( likely got saved ) */
+ if ((id3->elapsed > scrobbler_get_threshold(id3->length)))
{
gCache.pending = false;
logf("SCROBBLER: skipping file %s", id3->path);
@@ -425,6 +694,7 @@ static void scrobbler_change_event(unsigned short id, void *ev_data)
gCache.pending = true;
}
}
+
#ifdef ROCKBOX_HAS_LOGF
static const char* track_event_info(struct track_event* te)
{
@@ -439,34 +709,39 @@ static const char* track_event_info(struct track_event* te)
* TEF_REWIND = 0x4, interpret as rewind, id3->elapsed is the
position before the seek back to 0
*/
- logf("flag %d", te->flags);
+ logf("SCROBBLER: flag %d", te->flags);
return strflags[te->flags&0x7];
}
-
#endif
-static void scrobbler_finish_event(unsigned short id, void *ev_data)
+
+static void track_finish_event(unsigned short id, void *ev_data)
{
(void)id;
struct track_event *te = ((struct track_event *)ev_data);
- struct mp3entry *id3 = te->id3;
logf("%s %s %s", __func__, gCache.pending?"True":"False", track_event_info(te));
/* add entry using the currently ending track */
if (gCache.pending && (te->flags & TEF_CURRENT) && !(te->flags & TEF_REWIND))
{
gCache.pending = false;
- if (id3->elapsed*2 >= id3->length)
- scrobbler_add_to_cache(te->id3);
- else
- {
- logf("%s Discarding < 50%% played", __func__);
- }
+ scrobbler_add_to_cache(te->id3);
}
+}
+/****************** main thread + helpers ******************/
+static void events_unregister(void)
+{
+ /* we don't want any more events */
+ rb->remove_event(PLAYBACK_EVENT_TRACK_CHANGE, track_change_event);
+ rb->remove_event(PLAYBACK_EVENT_TRACK_FINISH, track_finish_event);
+}
+static void events_register(void)
+{
+ rb->add_event(PLAYBACK_EVENT_TRACK_CHANGE, track_change_event);
+ rb->add_event(PLAYBACK_EVENT_TRACK_FINISH, track_finish_event);
}
-/****************** main thread + helper ******************/
void thread(void)
{
bool in_usb = false;
@@ -487,7 +762,8 @@ void thread(void)
in_usb = false;
/*fall through*/
case EV_STARTUP:
- rb->beep_play(1500, 100, 1000);
+ events_register();
+ play_tone(1500, 100);
break;
case SYS_POWEROFF:
case SYS_REBOOT:
@@ -495,15 +771,27 @@ void thread(void)
/*fall through*/
case EV_EXIT:
#if USING_STORAGE_CALLBACK
- rb->unregister_storage_idle_func(scrobbler_flush_callback, !in_usb);
+ rb->unregister_storage_idle_func(scrobbler_flush_callback, false);
#else
if (!in_usb)
scrobbler_flush_cache();
#endif
+ events_unregister();
return;
- case EV_OTHINSTANCE:
+ case EV_FLUSHCACHE:
scrobbler_flush_cache();
- rb->splashf(HZ * 2, "%s Cache Flushed", str(LANG_AUDIOSCROBBLER));
+ rb->queue_reply(&gThread.queue, 0);
+ break;
+ case EV_USER_ERROR:
+ if (!in_usb)
+ {
+ if (ev.data == ERR_WRITING_FILE)
+ rb->splash(HZ, "SCROBBLER: error writing log");
+ else if (ev.data == ERR_ENTRY_LENGTH)
+ rb->splash(HZ, "SCROBBLER: error entry too long");
+ else if (ev.data == ERR_WRITING_DATA)
+ rb->splash(HZ, "SCROBBLER: error bad entry data");
+ }
break;
default:
logf("default %ld", ev.id);
@@ -514,12 +802,13 @@ void thread(void)
void thread_create(void)
{
- /* put the thread's queue in the bcast list */
+ /* put the thread's queue in the broadcast list */
rb->queue_init(&gThread.queue, true);
gThread.id = rb->create_thread(thread, gThread.stack, sizeof(gThread.stack),
0, "Last.Fm_TSR"
IF_PRIO(, PRIORITY_BACKGROUND)
IF_COP(, CPU));
+ rb->queue_enable_queue_send(&gThread.queue, &gThread.queue_send, gThread.id);
rb->queue_post(&gThread.queue, EV_STARTUP, 0);
rb->yield();
}
@@ -527,79 +816,85 @@ void thread_create(void)
void thread_quit(void)
{
if (!gThread.exiting) {
+ gThread.exiting = true;
rb->queue_post(&gThread.queue, EV_EXIT, 0);
rb->thread_wait(gThread.id);
- /* we don't want any more events */
- rb->remove_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
- rb->remove_event(PLAYBACK_EVENT_TRACK_FINISH, scrobbler_finish_event);
/* remove the thread's queue from the broadcast list */
rb->queue_delete(&gThread.queue);
- gThread.exiting = true;
}
}
-/* callback to end the TSR plugin, called before a new one gets loaded */
-static bool exit_tsr(bool reenter)
+/* callback to end the TSR plugin, called before a new plugin gets loaded */
+static int plugin_exit_tsr(bool reenter)
{
- logf("%s", __func__);
- bool is_exit = false;
- int button;
- if (reenter)
- {
- logf(" reenter other instance ");
- rb->queue_post(&gThread.queue, EV_OTHINSTANCE, 0);
- return false; /* dont let it start again */
- }
- rb->lcd_clear_display();
- rb->lcd_puts_scroll(0, 0, "Scrobbler is currently running.");
- rb->lcd_puts_scroll(0, 1, "Press " SCROBBLE_OFF_TXT " to exit");
- rb->lcd_puts_scroll(0, 2, "Anything else will resume");
-
- rb->lcd_update();
- rb->button_clear_queue();
- while (1)
+ MENUITEM_STRINGLIST(menu, ID2P(LANG_AUDIOSCROBBLER), NULL, ID2P(LANG_SETTINGS),
+ "Flush Cache", "Exit Plugin", ID2P(LANG_BACK));
+
+ const struct text_message quit_prompt = {
+ (const char*[]){ ID2P(LANG_AUDIOSCROBBLER),
+ "is currently running.",
+ "Quit scrobbler?" }, 3
+ };
+
+ while(true)
{
- button = rb->button_get(true);
- if (IS_SYSEVENT(button))
- continue;
- if (button == SCROBBLE_OFF)
+ int result = reenter ? rb->do_menu(&menu, NULL, NULL, false) : 2;
+ switch(result)
{
- rb->queue_post(&gThread.queue, EV_EXIT, 0);
- rb->thread_wait(gThread.id);
- /* remove the thread's queue from the broadcast list */
- rb->queue_delete(&gThread.queue);
- is_exit = true;
- }
- else is_exit = false;
+ case 0: /* settings */
+ config_settings_menu();
+ break;
+ case 1: /* flush cache */
+ if (gCache.entries > 0)
+ {
+ rb->queue_send(&gThread.queue, EV_FLUSHCACHE, 0);
+ if (gConfig.verbose)
+ rb->splashf(2*HZ, "%s Cache Flushed", rb->str(LANG_AUDIOSCROBBLER));
+ }
+ break;
- break;
+ case 2: /* exit plugin - quit */
+ if(rb->gui_syncyesno_run(&quit_prompt, NULL, NULL) == YESNO_YES)
+ {
+ scrobbler_flush_cache();
+ thread_quit();
+ return (reenter ? PLUGIN_TSR_TERMINATE : PLUGIN_TSR_SUSPEND);
+ }
+ /* Fall Through */
+ case 3: /* back to menu */
+ return PLUGIN_TSR_CONTINUE;
+ }
}
- FOR_NB_SCREENS(idx)
- rb->screens[idx]->scroll_stop();
-
- if (is_exit)
- thread_quit();
-
- return is_exit;
}
/****************** main ******************/
-
-int plugin_main(const void* parameter)
+static int plugin_main(const void* parameter)
{
- (void)parameter;
+ struct scrobbler_cfg cfg;
+ rb->memcpy(&cfg, &gConfig, sizeof(struct scrobbler_cfg)); /* store settings */
+
+ /* Resume plugin ? -- silences startup */
+ if (parameter == rb->plugin_tsr)
+ {
+ gConfig.beeplvl = 0;
+ gConfig.playback = false;
+ gConfig.verbose = false;
+ }
rb->memset(&gThread, 0, sizeof(gThread));
- rb->splashf(HZ / 2, "%s Started",str(LANG_AUDIOSCROBBLER));
- logf("%s: %s Started", __func__, str(LANG_AUDIOSCROBBLER));
+ if (gConfig.verbose)
+ rb->splashf(HZ / 2, "%s Started",rb->str(LANG_AUDIOSCROBBLER));
+ logf("%s: %s Started", __func__, rb->str(LANG_AUDIOSCROBBLER));
- rb->plugin_tsr(exit_tsr); /* stay resident */
+ rb->plugin_tsr(plugin_exit_tsr); /* stay resident */
- rb->add_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
- rb->add_event(PLAYBACK_EVENT_TRACK_FINISH, scrobbler_finish_event);
thread_create();
+ rb->memcpy(&gConfig, &cfg, sizeof(struct scrobbler_cfg)); /*restore settings */
- return 0;
+ if (gConfig.playback)
+ return PLUGIN_GOTO_WPS;
+
+ return PLUGIN_OK;
}
/***************** Plugin Entry Point *****************/
@@ -609,9 +904,20 @@ enum plugin_status plugin_start(const void* parameter)
/* now go ahead and have fun! */
if (rb->usb_inserted() == true)
return PLUGIN_USB_CONNECTED;
- language_strings = rb->language_strings;
- if (scrobbler_init() < 0)
+
+ if (scrobbler_init_cache() < 0)
return PLUGIN_ERROR;
+
+ config_set_defaults();
+
+ if (configfile_load(CFG_FILE, config, gCfg_sz, CFG_VER) < 0)
+ {
+ /* If the loading failed, save a new config file */
+ configfile_save(CFG_FILE, config, gCfg_sz, CFG_VER);
+ if (gConfig.verbose)
+ rb->splash(HZ, ID2P(LANG_REVERT_TO_DEFAULT_SETTINGS));
+ }
+
int ret = plugin_main(parameter);
- return (ret==0) ? PLUGIN_OK : PLUGIN_ERROR;
+ return ret;
}
diff --git a/apps/plugins/lastfm_scrobbler_viewer.c b/apps/plugins/lastfm_scrobbler_viewer.c
new file mode 100644
index 0000000000..c8b125c293
--- /dev/null
+++ b/apps/plugins/lastfm_scrobbler_viewer.c
@@ -0,0 +1,1033 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// __ \_/ ___\| |/ /| __ \ / __ \ \/ /
+ * Jukebox | | ( (__) ) \___| ( | \_\ ( (__) ) (
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2023 William Wilgus
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "plugin.h"
+#include "lang_enum.h"
+
+#include "lib/printcell_helper.h"
+
+#include "lib/configfile.h"
+#define CFG_FILE "/lastfm_scrobbler_viewer.cfg"
+#define TMP_FILE ""PLUGIN_DATA_DIR "/lscrobbler_viewer_%d.tmp"
+#define CFG_VER 1
+
+#ifdef ROCKBOX_HAS_LOGF
+#define logf rb->logf
+#else
+#define logf(...) do { } while(0)
+#endif
+
+/*#ARTIST #ALBUM #TITLE #TRACKNUM #LENGTH #RATING #TIMESTAMP #MUSICBRAINZ_TRACKID*/
+
+#define SCROBBLE_HDR_FMT "$*%d$%s$*%d$%s$*%d$%s$Track#$Length$Rating$TimeStamp$TrackId"
+//#define SCROBBLE_HDR "$*128$Artist$*128$Album$*128$Title$Track#$Length$Rating$TimeStamp$TrackId"
+
+#define SCROBBLER_MIN_COLUMNS (6) /* a valid scrobbler file should have at least this many columns */
+
+#define GOTO_ACTION_DEFAULT_HANDLER (PLUGIN_OK + 1)
+#define CANCEL_CONTEXT_MENU (PLUGIN_OK + 2)
+#define QUIT_CONTEXT_MENU (PLUGIN_OK + 3)
+/* global lists, for everything */
+static struct gui_synclist lists;
+
+/* printcell data for the current file */
+struct printcell_data_t {
+ int view_columns;
+ int view_lastcol;
+
+ int items_buffered;
+ int items_total;
+ int fd_cur;
+ char *filename;
+
+ char *buf;
+ size_t buf_size;
+ off_t buf_used;
+ char header[PRINTCELL_MAXLINELEN];
+
+};
+
+enum e_find_type {
+ FIND_ALL = 0,
+ FIND_EXCLUDE,
+ FIND_EXCLUDE_CASE,
+ FIND_EXCLUDE_ANY,
+ FIND_INCLUDE,
+ FIND_INCLUDE_CASE,
+ FIND_INCLUDE_ANY,
+ FIND_CUSTOM,
+};
+
+static void synclist_set(int selected_item, int items, int sel_size, struct printcell_data_t *pc_data);
+static void pc_data_set_header(struct printcell_data_t *pc_data);
+
+static void browse_file(char *buf, size_t bufsz)
+{
+ struct browse_context browse = {
+ .dirfilter = SHOW_ALL,
+ .flags = BROWSE_SELECTONLY,
+ .title = "Select a scrobbler log file",
+ .icon = Icon_Playlist,
+ .buf = buf,
+ .bufsize = bufsz,
+ .root = "/",
+ };
+
+ if (rb->rockbox_browse(&browse) != GO_TO_PREVIOUS)
+ {
+ buf[0] = '\0';
+ }
+}
+
+static struct plugin_config
+{
+ bool separator;
+ bool talk;
+ int col_width;
+ int hidecol_flags;
+} gConfig;
+
+static struct configdata config[] =
+{
+ {TYPE_BOOL, 0, 1, { .bool_p = &gConfig.separator }, "Cell Separator", NULL},
+ {TYPE_BOOL, 0, 1, { .bool_p = &gConfig.talk }, "Voice", NULL},
+ {TYPE_INT, 32, LCD_WIDTH, { .int_p = &gConfig.col_width }, "Cell Width", NULL},
+ {TYPE_INT, INT_MIN, INT_MAX, { .int_p = &gConfig.hidecol_flags }, "Hidden Columns", NULL},
+};
+const int gCfg_sz = sizeof(config)/sizeof(*config);
+/****************** config functions *****************/
+static void config_set_defaults(void)
+{
+ gConfig.col_width = MIN(LCD_WIDTH, 128);
+ gConfig.hidecol_flags = 0;
+ gConfig.separator = true;
+ gConfig.talk = rb->global_settings->talk_menu;
+}
+
+static void config_save(void)
+{
+ configfile_save(CFG_FILE, config, gCfg_sz, CFG_VER);
+}
+
+static int config_settings_menu(struct printcell_data_t *pc_data)
+{
+ int selection = 0;
+
+ struct viewport parentvp[NB_SCREENS];
+ FOR_NB_SCREENS(l)
+ {
+ rb->viewport_set_defaults(&parentvp[l], l);
+ rb->viewport_set_fullscreen(&parentvp[l], l);
+ }
+
+ MENUITEM_STRINGLIST(settings_menu, ID2P(LANG_SETTINGS), NULL,
+ ID2P(LANG_LIST_SEPARATOR),
+ "Cell Width",
+ ID2P(LANG_VOICE),
+ ID2P(VOICE_BLANK),
+ ID2P(VOICE_BLANK),
+ ID2P(LANG_CANCEL_0),
+ ID2P(LANG_SAVE_EXIT));
+
+ do {
+ selection=rb->do_menu(&settings_menu,&selection, parentvp, true);
+ switch(selection) {
+
+ case 0:
+ rb->set_bool(rb->str(LANG_LIST_SEPARATOR), &gConfig.separator);
+ break;
+ case 1:
+ rb->set_int("Cell Width", "", UNIT_INT,
+ &gConfig.col_width, NULL, 1, 32, LCD_WIDTH, NULL );
+ break;
+ case 2:
+ rb->set_bool(rb->str(LANG_VOICE), &gConfig.talk);
+ break;
+ case 3:
+ continue;
+ case 4: /*sep*/
+ continue;
+ case 5:
+ return -1;
+ break;
+ case 6:
+ {
+ pc_data_set_header(pc_data);
+ synclist_set(0, pc_data->items_total, 1, pc_data);
+ int res = configfile_save(CFG_FILE, config, gCfg_sz, CFG_VER);
+ if (res >= 0)
+ {
+ logf("Cfg saved %s %d bytes", CFG_FILE, gCfg_sz);
+ return PLUGIN_OK;
+ }
+ logf("Cfg FAILED (%d) %s", res, CFG_FILE);
+ return PLUGIN_ERROR;
+ }
+ case MENU_ATTACHED_USB:
+ return PLUGIN_USB_CONNECTED;
+ default:
+ return PLUGIN_OK;
+ }
+ } while ( selection >= 0 );
+ return 0;
+}
+
+/* open file pass back file descriptor and return file size */
+static size_t file_open(const char *filename, int *fd)
+{
+ size_t fsize = 0;
+
+ if (filename && fd)
+ {
+ *fd = rb->open(filename, O_RDONLY);
+ if (*fd >= 0)
+ {
+ fsize = rb->filesize(*fd);
+ }
+ }
+ return fsize;
+}
+
+static const char* list_get_name_cb(int selected_item, void* data,
+ char* buf, size_t buf_len)
+{
+ const int slush_pos = 32; /* entries around the current entry to keep buffered */
+ /* keep track of the last position in the buffer */
+ static int buf_line_num = 0;
+ static off_t buf_last_pos = 0;
+ /* keep track of the last position in the file */
+ static int file_line_num = 0;
+ static off_t file_last_seek = 0;
+
+ if (selected_item < 0)
+ {
+ logf("[%s] Reset positions", __func__);
+ buf_line_num = 0;
+ buf_last_pos = 0;
+ file_line_num = 0;
+ file_last_seek = 0;
+ return "";
+ }
+
+ int line_num;
+ struct printcell_data_t *pc_data = (struct printcell_data_t*) data;
+ bool found = false;
+
+ if (pc_data->buf && selected_item < pc_data->items_buffered)
+ {
+ int buf_pos;
+
+ if (buf_line_num > selected_item || buf_last_pos >= pc_data->buf_used
+ || buf_line_num < 0)
+ {
+ logf("[%s] Set pos buffer 0", __func__);
+ buf_line_num = 0;
+ buf_last_pos = 0;
+ }
+ buf_pos = buf_last_pos;
+ line_num = buf_line_num;
+
+ while (buf_pos < pc_data->buf_used
+ && line_num < pc_data->items_buffered)
+ {
+ size_t len = rb->strlen(&pc_data->buf[buf_pos]);
+ if(line_num == selected_item)
+ {
+ rb->strlcpy(buf, &pc_data->buf[buf_pos], MIN(buf_len, len));
+ logf("(%d) in buffer: %s", line_num, buf);
+ found = true;
+ break;
+ }
+ else
+ {
+ buf_pos += len + 1; /* need to go past the NULL terminator */
+ line_num++;
+
+ if (buf_line_num + slush_pos < selected_item)
+ {
+ logf("[%s] Set pos buffer %d", __func__, line_num);
+ buf_line_num = line_num;
+ buf_last_pos = buf_pos;
+ }
+ }
+ }
+ }
+
+ /* didn't find the item try the file */
+ if(!found && pc_data->fd_cur >= 0)
+ {
+ int fd = pc_data->fd_cur;
+
+ if (file_line_num < 0 || file_line_num > selected_item)
+ {
+ logf("[%s] Set seek file 0", __func__);
+ file_line_num = 0;
+ file_last_seek = 0;
+ }
+
+ rb->lseek(fd, file_last_seek, SEEK_SET);
+ line_num = file_line_num;
+
+ while ((rb->read_line(fd, buf, buf_len)) > 0)
+ {
+ if(buf[0] == '#')
+ continue;
+ if(line_num == selected_item)
+ {
+ logf("(%d) in file: %s", line_num, buf);
+ found = true;
+ break;
+ }
+ else
+ {
+ line_num++;
+
+ if (file_line_num + slush_pos < selected_item)
+ {
+ logf("[%s] Set seek file %d", __func__, line_num);
+ file_line_num = line_num;
+ file_last_seek = rb->lseek(fd, 0, SEEK_CUR);
+ }
+ }
+ }
+ }
+
+ if(!found)
+ {
+ logf("(%d) Not Found!", selected_item);
+ buf_line_num = -1;
+ file_line_num = -1;
+ buf[0] = '\0';
+ }
+ return buf;
+}
+
+static int list_voice_cb(int list_index, void* data)
+{
+ (void) list_index;
+ struct printcell_data_t *pc_data = (struct printcell_data_t*) data;
+ if (!gConfig.talk)
+ return -1;
+
+ int selcol = printcell_get_column_selected();
+ char buf[MAX_PATH];
+ char* name;
+ long id;
+
+ if (pc_data->view_lastcol != selcol)
+ {
+ name = printcell_get_title_text(selcol, buf, sizeof(buf));
+
+ id = P2ID((const unsigned char *)name);
+
+ if(id>=0)
+ rb->talk_id(id, true);
+ else if (selcol >= 0)
+ {
+ switch (selcol)
+ {
+ case 0:
+ rb->talk_id(LANG_ID3_ARTIST, true);
+ break;
+ case 1:
+ rb->talk_id(LANG_ID3_ALBUM, true);
+ break;
+ case 2:
+ rb->talk_id(LANG_ID3_TITLE, true);
+ break;
+ case 3:
+ rb->talk_id(LANG_ID3_TRACKNUM, true);
+ break;
+ case 4:
+ rb->talk_id(LANG_ID3_LENGTH, true);
+ break;
+
+ default:
+ rb->talk_spell(name, true);
+ break;
+ }
+ }
+ else
+ rb->talk_id(LANG_ALL, true);
+
+ rb->talk_id(VOICE_PAUSE, true);
+ }
+
+ name = printcell_get_column_text(selcol, buf, sizeof(buf));
+
+ id = P2ID((const unsigned char *)name);
+
+ if(id>=0)
+ rb->talk_id(id, true);
+ else if (selcol >= 0)
+ rb->talk_spell(name, true);
+
+ return 0;
+}
+
+static enum themable_icons list_icon_cb(int selected_item, void *data)
+{
+ struct printcell_data_t *pc_data = (struct printcell_data_t*) data;
+ if (lists.selected_item == selected_item)
+ {
+ if (pc_data->view_lastcol < 0)
+ return Icon_Config;
+ return Icon_Audio;
+ }
+ return Icon_NOICON;
+}
+
+/* load file entries into pc_data buffer, file should already be opened
+ * and will be closed if the whole file was buffered */
+static int file_load_entries(struct printcell_data_t *pc_data)
+{
+ int items = 0;
+ int count = 0;
+ int buffered = 0;
+ unsigned int pos = 0;
+ bool comment = false;
+ char ch;
+ int fd = pc_data->fd_cur;
+ if (fd < 0)
+ return 0;
+
+ rb->lseek(fd, 0, SEEK_SET);
+
+ while (rb->read(fd, &ch, 1) > 0)
+ {
+ if (count++ == 0 && ch == '#') /* skip comments */
+ comment = true;
+ else if (!comment && ch != '\r' && pc_data->buf_size > pos)
+ pc_data->buf[pos++] = ch;
+
+ if (items == 0 && pos > PRINTCELL_MAXLINELEN * 2)
+ break;
+
+ if (ch == '\n')
+ {
+ if (!comment)
+ {
+ pc_data->buf[pos] = '\0';
+ if (pc_data->buf_size > pos)
+ {
+ pos++;
+ buffered++;
+ }
+ items++;
+ }
+ comment = false;
+ count = 0;
+ rb->yield();
+ }
+ }
+
+ logf("[%s] items: %d buffered: %d", __func__, items, buffered);
+
+ pc_data->items_total = items;
+ pc_data->items_buffered = buffered;
+ pc_data->buf[pos] = '\0';
+ pc_data->buf_used = pos;
+
+ if (items == buffered) /* whole file fit into buffer; close file */
+ {
+ rb->close(pc_data->fd_cur);
+ pc_data->fd_cur = -1;
+ }
+
+ list_get_name_cb(-1, NULL, NULL, 0); /* prime name cb */
+ return items;
+}
+
+static int filter_items(struct printcell_data_t *pc_data,
+ enum e_find_type find_type, int col)
+{
+ /* saves filtered items to a temp file and loads it */
+ int fd;
+ bool reload = false;
+ char buf[PRINTCELL_MAXLINELEN];
+ char find_exclude_buf[PRINTCELL_MAXLINELEN];
+ int selcol = printcell_get_column_selected();
+ char *find_exclude = printcell_get_column_text(selcol, find_exclude_buf,
+ sizeof(find_exclude_buf));
+ const char colsep = '\t';
+ int find_len = rb->strlen(find_exclude);
+
+ if (find_type == FIND_CUSTOM || find_len == 0)
+ {
+ int option = 0;
+ struct opt_items find_types[] = {
+ {"Exclude", -1}, {"Exclude Case Sensitive", -1},
+ {"Exclude Any", -1}, {"Include", -1},
+ {"Include Case Sensitive", -1}, {"Include Any", -1}
+ };
+ if (rb->set_option("Find Type", &option, INT,
+ find_types, 6, NULL))
+ {
+ return 0;
+ }
+ switch (option)
+ {
+ case 0:
+ find_type = FIND_EXCLUDE;
+ break;
+ case 1:
+ find_type = FIND_EXCLUDE_CASE;
+ break;
+ case 2:
+ find_type = FIND_EXCLUDE_ANY;
+ break;
+ case 3:
+ find_type = FIND_INCLUDE;
+ break;
+ case 4:
+ find_type = FIND_INCLUDE_CASE;
+ break;
+ case 5:
+ find_type = FIND_INCLUDE_ANY;
+ break;
+ default:
+ find_type = FIND_ALL;
+ break;
+ }
+
+ /* copy data to beginning of buf */
+ rb->memmove(find_exclude_buf, find_exclude, find_len);
+ find_exclude_buf[find_len] = '\0';
+
+ if (rb->kbd_input(find_exclude_buf, sizeof(find_exclude_buf), NULL) < 0)
+ return -1;
+ find_exclude = find_exclude_buf;
+ find_len = rb->strlen(find_exclude);
+ }
+
+ char tmp_filename[MAX_PATH];
+ static int tmp_num = 0;
+ rb->snprintf(tmp_filename, sizeof(tmp_filename), TMP_FILE, tmp_num);
+ tmp_num++;
+
+ fd = rb->open(tmp_filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
+ if(fd >= 0)
+ {
+ rb->splash_progress_set_delay(HZ * 5);
+ for (int i = 0; i < pc_data->items_total; i++)
+ {
+ rb->splash_progress(i, pc_data->items_total, "Filtering...");
+ const char * data = list_get_name_cb(i, pc_data, buf, sizeof(buf));
+
+ if (find_type != FIND_ALL)
+ {
+ int index = col;
+
+ if (index < 0)
+ index = 0;
+ if (find_len > 0)
+ {
+ char *bcol = buf;
+ while (*bcol != '\0' && index > 0)
+ {
+ if (*bcol == colsep)
+ index--;
+ bcol++;
+ }
+ if (index > 0)
+ continue;
+
+ if (find_type == FIND_EXCLUDE)
+ {
+ if (rb->strncasecmp(bcol, find_exclude, find_len) == 0)
+ {
+ logf("[%s] exclude [%s]", find_exclude, bcol);
+ continue;
+ }
+ }
+ else if (find_type == FIND_INCLUDE)
+ {
+ if (rb->strncasecmp(bcol, find_exclude, find_len) != 0)
+ {
+ logf("%s include %s", find_exclude, bcol);
+ continue;
+ }
+ }
+ else if (find_type == FIND_EXCLUDE_CASE)
+ {
+ if (rb->strncmp(bcol, find_exclude, find_len) == 0)
+ {
+ logf("[%s] exclude case [%s]", find_exclude, bcol);
+ continue;
+ }
+ }
+ else if (find_type == FIND_INCLUDE_CASE)
+ {
+ if (rb->strncmp(bcol, find_exclude, find_len) != 0)
+ {
+ logf("%s include case %s", find_exclude, bcol);
+ continue;
+ }
+ }
+ else if (find_type == FIND_EXCLUDE_ANY)
+ {
+ bool found = false;
+ while (*bcol != '\0' && *bcol != colsep)
+ {
+ if (rb->strncasecmp(bcol, find_exclude, find_len) == 0)
+ {
+ logf("[%s] exclude any [%s]", find_exclude, bcol);
+ found = true;
+ break;
+ }
+ bcol++;
+ }
+ if (found)
+ continue;
+ }
+ else if (find_type == FIND_INCLUDE_ANY)
+ {
+ bool found = false;
+ while (*bcol != '\0' && *bcol != colsep)
+ {
+ if (rb->strncasecmp(bcol, find_exclude, find_len) == 0)
+ {
+ found = true;
+ logf("[%s] include any [%s]", find_exclude, bcol);
+ break;
+ }
+ bcol++;
+ }
+ if (!found)
+ continue;
+ }
+ }
+ }
+ int len = rb->strlen(data);
+ if (len > 0)
+ {
+ logf("writing [%d bytes][%s]", len + 1, data);
+ rb->write(fd, data, len);
+ rb->write(fd, "\n", 1);
+ }
+ }
+ reload = true;
+ }
+
+ if (reload)
+ {
+ if (pc_data->fd_cur >= 0)
+ rb->close(pc_data->fd_cur);
+
+ pc_data->fd_cur = fd;
+ int items = file_load_entries(pc_data);
+ if (items >= 0)
+ {
+ lists.selected_item = 0;
+ rb->gui_synclist_set_nb_items(&lists, items);
+ }
+ }
+ logf("Col text '%s'", find_exclude);
+ logf("text '%s'", find_exclude_buf);
+
+ return pc_data->items_total;
+}
+
+static int scrobbler_context_menu(struct printcell_data_t *pc_data)
+{
+ struct viewport parentvp[NB_SCREENS];
+ FOR_NB_SCREENS(l)
+ {
+ rb->viewport_set_defaults(&parentvp[l], l);
+ rb->viewport_set_fullscreen(&parentvp[l], l);
+ }
+
+ int col = printcell_get_column_selected();
+ int selection = 0;
+ int items = 0;
+ uint32_t visible = printcell_get_column_visibility(-1);
+ bool hide_col = PRINTCELL_COLUMN_IS_VISIBLE(visible, col);
+
+ char namebuf[PRINTCELL_MAXLINELEN];
+ enum e_find_type find_type = FIND_ALL;
+
+ char *colname = pc_data->filename;
+ if (col >= 0)
+ colname = printcell_get_title_text(col, namebuf, sizeof(namebuf));
+
+#define MENUITEM_STRINGLIST_CUSTOM(name, str, callback, ... ) \
+ const char *name##_[] = {__VA_ARGS__}; \
+ const struct menu_callback_with_desc name##__ = \
+ {callback,str, Icon_NOICON}; \
+ const struct menu_item_ex name = \
+ {MT_RETURN_ID|MENU_HAS_DESC| \
+ MENU_ITEM_COUNT(sizeof( name##_)/sizeof(*name##_)), \
+ { .strings = name##_},{.callback_and_desc = & name##__}};
+
+ const char *menu_item[4];
+
+ menu_item[0]= hide_col ? "Hide":"Show";
+ menu_item[1]= "Exclude";
+ menu_item[2]= "Include";
+ menu_item[3]= "Custom Filter";
+
+ if (col == -1)
+ {
+ menu_item[0]= hide_col ? "Hide All":"Show All";
+ menu_item[1]= "Open";
+ menu_item[2]= "Reload";
+ menu_item[3]= ID2P(LANG_SETTINGS);
+ }
+
+ MENUITEM_STRINGLIST_CUSTOM(context_menu, colname, NULL,
+ menu_item[0],
+ menu_item[1],
+ menu_item[2],
+ menu_item[3],
+ ID2P(VOICE_BLANK),
+ ID2P(LANG_CANCEL_0),
+ ID2P(LANG_MENU_QUIT));
+
+#undef MENUITEM_STRINGLIST_CUSTOM
+ do {
+ selection=rb->do_menu(&context_menu,&selection, parentvp, true);
+ switch(selection) {
+
+ case 0:
+ {
+ printcell_set_column_visible(col, !hide_col);
+ if (hide_col)
+ {
+ do
+ {
+ col = printcell_increment_column(1, true);
+ } while (col >= 0 && printcell_get_column_visibility(col) == 1);
+ pc_data->view_lastcol = col;
+ }
+ gConfig.hidecol_flags = printcell_get_column_visibility(-1);
+ break;
+ }
+ case 1: /* Exclude / Open */
+ {
+ if (col == -1)/*Open*/
+ {
+ char buf[MAX_PATH];
+ browse_file(buf, sizeof(buf));
+ if (rb->file_exists(buf))
+ {
+ rb->strlcpy(pc_data->filename, buf, MAX_PATH);
+ if (pc_data->fd_cur >= 0)
+ rb->close(pc_data->fd_cur);
+ if (file_open(pc_data->filename, &pc_data->fd_cur) > 0)
+ items = file_load_entries(pc_data);
+ if (items >= 0)
+ synclist_set(0, items, 1, pc_data);
+ }
+ else
+ rb->splash(HZ *2, "Error Opening");
+
+ return CANCEL_CONTEXT_MENU;
+ }
+
+ find_type = FIND_EXCLUDE;
+ }
+ /* fall-through */
+ case 2: /* Include / Reload */
+ {
+ if (col == -1) /*Reload*/
+ {
+ if (pc_data->fd_cur >= 0)
+ rb->close(pc_data->fd_cur);
+ if (file_open(pc_data->filename, &pc_data->fd_cur) > 0)
+ items = file_load_entries(pc_data);
+ if (items >= 0)
+ rb->gui_synclist_set_nb_items(&lists, items);
+ return CANCEL_CONTEXT_MENU;
+ }
+
+ if (find_type == FIND_ALL)
+ find_type = FIND_INCLUDE;
+ /* fall-through */
+ }
+ case 3: /*Custom Filter / Settings */
+ {
+ if (col == -1)/*Settings*/
+ return config_settings_menu(pc_data);
+
+ if (find_type == FIND_ALL)
+ find_type = FIND_CUSTOM;
+ items = filter_items(pc_data, find_type, col);
+
+ if (items >= 0)
+ rb->gui_synclist_set_nb_items(&lists, items);
+ break;
+ }
+ case 4: /*sep*/
+ continue;
+ case 5:
+ return CANCEL_CONTEXT_MENU;
+ break;
+ case 6: /* Quit */
+ return QUIT_CONTEXT_MENU;
+ break;
+ case MENU_ATTACHED_USB:
+ return PLUGIN_USB_CONNECTED;
+ default:
+ return PLUGIN_OK;
+ }
+ } while ( selection < 0 );
+ return 0;
+}
+
+static void cleanup(void *parameter)
+{
+ struct printcell_data_t *pc_data = (struct printcell_data_t*) parameter;
+ if (pc_data->fd_cur >= 0)
+ rb->close(pc_data->fd_cur);
+ pc_data->fd_cur = -1;
+}
+
+static void menu_action_printcell(int *action, int selected_item, bool* exit, struct gui_synclist *lists)
+{
+ (void) exit;
+ struct printcell_data_t *pc_data = (struct printcell_data_t*) lists->data;
+ if (*action == ACTION_STD_OK)
+ {
+ if (selected_item < lists->nb_items)
+ {
+ pc_data->view_lastcol = printcell_increment_column(1, true);
+ *action = ACTION_NONE;
+ }
+ }
+ else if (*action == ACTION_STD_CANCEL)
+ {
+ pc_data->view_lastcol = printcell_increment_column(-1, true);
+ if (pc_data->view_lastcol != pc_data->view_columns - 1)
+ {
+ *action = ACTION_NONE;
+ }
+ }
+ else if (*action == ACTION_STD_CONTEXT)
+ {
+ int ctxret = scrobbler_context_menu(pc_data);
+ if (ctxret == QUIT_CONTEXT_MENU)
+ *exit = true;
+ }
+}
+
+int menu_action_cb(int *action, int selected_item, bool* exit, struct gui_synclist *lists)
+{
+
+ menu_action_printcell(action, selected_item, exit, lists);
+
+ if (rb->default_event_handler_ex(*action, cleanup, lists->data) == SYS_USB_CONNECTED)
+ {
+ *exit = true;
+ return PLUGIN_USB_CONNECTED;
+ }
+ return PLUGIN_OK;
+}
+
+static int count_max_columns(int items, char delimeter,
+ int expected_cols, struct printcell_data_t *pc_data)
+{
+ int max_cols = 0;
+ int cols = 0;
+ char buf[PRINTCELL_MAXLINELEN];
+ for (int i = 0; i < items; i++)
+ {
+ const char *txt = list_get_name_cb(i, pc_data, buf, sizeof(buf));
+ while (*txt != '\0')
+ {
+ if (*txt == delimeter)
+ {
+ cols++;
+ if (cols == expected_cols)
+ {
+ max_cols = cols;
+ break;
+ }
+ }
+ txt++;
+ }
+
+ if(max_cols < expected_cols && i > 32)
+ break;
+
+ if (cols > max_cols)
+ max_cols = cols;
+ cols = 0;
+ }
+ return max_cols;
+}
+
+static void synclist_set(int selected_item, int items, int sel_size, struct printcell_data_t *pc_data)
+{
+ if (items <= 0)
+ return;
+ if (selected_item < 0)
+ selected_item = 0;
+
+ rb->gui_synclist_init(&lists,list_get_name_cb,
+ pc_data, false, sel_size, NULL);
+
+ rb->gui_synclist_set_icon_callback(&lists, list_icon_cb);
+ rb->gui_synclist_set_voice_callback(&lists, list_voice_cb);
+ rb->gui_synclist_set_nb_items(&lists,items);
+ rb->gui_synclist_select_item(&lists, selected_item);
+
+ struct printcell_settings pcs = {.cell_separator = gConfig.separator,
+ .title_delimeter = '$',
+ .text_delimeter = '\t',
+ .hidecol_flags = gConfig.hidecol_flags};
+
+ pc_data->view_columns = printcell_set_columns(&lists, &pcs,
+ pc_data->header, Icon_Rockbox);
+ printcell_enable(true);
+
+
+ int max_cols = count_max_columns(items, pcs.text_delimeter,
+ SCROBBLER_MIN_COLUMNS, pc_data);
+ if (max_cols < SCROBBLER_MIN_COLUMNS) /* not a scrobbler file? */
+ {
+ rb->gui_synclist_set_voice_callback(&lists, NULL);
+ pc_data->view_columns = printcell_set_columns(&lists, NULL,
+ "$*512$", Icon_Questionmark);
+ }
+
+ int curcol = printcell_get_column_selected();
+ while (curcol >= 0)
+ curcol = printcell_increment_column(-1, false);
+
+ if (pc_data->view_lastcol >= pc_data->view_columns)
+ pc_data->view_lastcol = -1;
+
+ /* restore column position */
+ while (pc_data->view_lastcol > -1 && curcol != pc_data->view_lastcol)
+ {
+ curcol = printcell_increment_column(1, true);
+ }
+ pc_data->view_lastcol = curcol;
+ list_voice_cb(0, pc_data);
+}
+
+static void pc_data_set_header(struct printcell_data_t *pc_data)
+{
+ int col_w = gConfig.col_width;
+ rb->snprintf(pc_data->header, PRINTCELL_MAXLINELEN,
+ SCROBBLE_HDR_FMT, col_w, rb->str(LANG_ID3_ARTIST),
+ col_w, rb->str(LANG_ID3_ALBUM),
+ col_w, rb->str(LANG_ID3_TITLE));
+}
+
+enum plugin_status plugin_start(const void* parameter)
+{
+ int ret = PLUGIN_OK;
+ int selected_item = -1;
+ int action;
+ int items = 0;
+#if CONFIG_RTC
+ static char filename[MAX_PATH] = HOME_DIR "/.scrobbler.log";
+#else /* !CONFIG_RTC */
+ static char filename[MAX_PATH] = HOME_DIR "/.scrobbler-timeless.log";
+#endif /* CONFIG_RTC */
+ bool redraw = true;
+ bool exit = false;
+
+ static struct printcell_data_t printcell_data;
+
+ if (parameter)
+ {
+ rb->strlcpy(filename, (const char*)parameter, MAX_PATH);
+ filename[MAX_PATH - 1] = '\0';
+ }
+
+ if (!rb->file_exists(filename))
+ {
+ browse_file(filename, sizeof(filename));
+ if (!rb->file_exists(filename))
+ {
+ rb->splash(HZ, "No Scrobbler file Goodbye.");
+ return PLUGIN_ERROR;
+ }
+
+ }
+
+ config_set_defaults();
+ if (configfile_load(CFG_FILE, config, gCfg_sz, CFG_VER) < 0)
+ {
+ /* If the loading failed, save a new config file */
+ config_set_defaults();
+ configfile_save(CFG_FILE, config, gCfg_sz, CFG_VER);
+
+ rb->splash(HZ, ID2P(LANG_REVERT_TO_DEFAULT_SETTINGS));
+ }
+
+ rb->memset(&printcell_data, 0, sizeof (struct printcell_data_t));
+ printcell_data.fd_cur = -1;
+ printcell_data.view_lastcol = -1;
+
+ if (rb->file_exists(filename))
+ {
+ if (file_open(filename, &printcell_data.fd_cur) == 0)
+ printcell_data.fd_cur = -1;
+ else
+ {
+ size_t buf_size;
+ printcell_data.buf = rb->plugin_get_buffer(&buf_size);
+ printcell_data.buf_size = buf_size;
+ printcell_data.buf_used = 0;
+ printcell_data.filename = filename;
+ items = file_load_entries(&printcell_data);
+ }
+ }
+ int col_w = gConfig.col_width;
+ rb->snprintf(printcell_data.header, PRINTCELL_MAXLINELEN,
+ SCROBBLE_HDR_FMT, col_w, rb->str(LANG_ID3_ARTIST),
+ col_w, rb->str(LANG_ID3_ALBUM),
+ col_w, rb->str(LANG_ID3_TITLE));
+
+ if (!exit && items > 0)
+ {
+ synclist_set(0, items, 1, &printcell_data);
+ rb->gui_synclist_draw(&lists);
+
+ while (!exit)
+ {
+ action = rb->get_action(CONTEXT_LIST, HZ / 10);
+
+ if (action == ACTION_NONE)
+ {
+ if (redraw)
+ {
+ action = ACTION_REDRAW;
+ redraw = false;
+ }
+ }
+ else
+ redraw = true;
+
+ ret = menu_action_cb(&action, selected_item, &exit, &lists);
+ if (rb->gui_synclist_do_button(&lists, &action))
+ continue;
+ selected_item = rb->gui_synclist_get_sel_pos(&lists);
+
+ }
+ }
+ config_save();
+ cleanup(&printcell_data);
+ return ret;
+}
diff --git a/apps/plugins/lib/SOURCES b/apps/plugins/lib/SOURCES
index bff9017404..09a8b1c5ed 100644
--- a/apps/plugins/lib/SOURCES
+++ b/apps/plugins/lib/SOURCES
@@ -69,3 +69,9 @@ kbd_helper.c
#ifdef HAVE_TOUCHSCREEN
pluginlib_touchscreen.c
#endif
+
+id3.c
+
+#ifdef HAVE_TAGCACHE
+mul_id3.c
+#endif
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/highscore.c b/apps/plugins/lib/highscore.c
index 3aae955bfc..04faf27891 100644
--- a/apps/plugins/lib/highscore.c
+++ b/apps/plugins/lib/highscore.c
@@ -124,11 +124,16 @@ void highscore_show(int position, struct highscore *scores, int num_scores,
bool show_level)
{
int i, w, h;
-#ifdef HAVE_LCD_COLOR
+#if defined(HAVE_LCD_COLOR) || LCD_DEPTH >= 2
unsigned bgcolor = rb->lcd_get_background();
unsigned fgcolor = rb->lcd_get_foreground();
+#ifdef HAVE_LCD_COLOR
rb->lcd_set_background(LCD_BLACK);
rb->lcd_set_foreground(LCD_WHITE);
+#else
+ rb->lcd_set_background(LCD_WHITE);
+ rb->lcd_set_foreground(LCD_BLACK);
+#endif
#endif
rb->lcd_clear_display();
@@ -173,7 +178,7 @@ void highscore_show(int position, struct highscore *scores, int num_scores,
rb->button_clear_queue();
rb->button_get(true);
rb->lcd_setfont(FONT_SYSFIXED);
-#ifdef HAVE_LCD_COLOR
+#if defined(HAVE_LCD_COLOR) || LCD_DEPTH >= 2
rb->lcd_set_background(bgcolor);
rb->lcd_set_foreground(fgcolor);
#endif
diff --git a/apps/plugins/lib/id3.c b/apps/plugins/lib/id3.c
new file mode 100644
index 0000000000..b0202b1d9c
--- /dev/null
+++ b/apps/plugins/lib/id3.c
@@ -0,0 +1,39 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2023 Christian Soffke
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "plugin.h"
+
+/* Fills mp3entry with metadata retrieved from RAM, if possible, or by reading from
+ * the file directly. Note that the tagcache only stores a subset of metadata and
+ * will thus not return certain properties of the file, such as frequency, size, or
+ * codec.
+ */
+bool retrieve_id3(struct mp3entry *id3, const char* file)
+{
+#if defined (HAVE_TAGCACHE) && defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
+ if (rb->tagcache_fill_tags(id3, file))
+ {
+ rb->strlcpy(id3->path, file, sizeof(id3->path));
+ return true;
+ }
+#endif
+
+ return !rb->mp3info(id3, file);
+}
diff --git a/apps/plugins/lib/id3.h b/apps/plugins/lib/id3.h
new file mode 100644
index 0000000000..6ae1688798
--- /dev/null
+++ b/apps/plugins/lib/id3.h
@@ -0,0 +1,26 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2023 Christian Soffke
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef ID3_H
+#define ID3_H
+
+bool retrieve_id3(struct mp3entry *id3, const char* file);
+
+#endif /* ID3_H */
diff --git a/apps/plugins/lib/mul_id3.c b/apps/plugins/lib/mul_id3.c
new file mode 100644
index 0000000000..edf44f7282
--- /dev/null
+++ b/apps/plugins/lib/mul_id3.c
@@ -0,0 +1,174 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2023 Christian Soffke
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "plugin.h"
+#include "mul_id3.h"
+
+struct multiple_tracks_id3 {
+ unsigned long long filesize;
+ unsigned long long length;
+ unsigned long frequency;
+ unsigned int artist_hash;
+ unsigned int composer_hash;
+ unsigned int albumartist_hash;
+ unsigned int grouping_hash;
+ unsigned int comment_hash;
+ unsigned int album_hash;
+ unsigned int genre_hash;
+ unsigned int codectype;
+ unsigned int bitrate;
+ int year;
+ bool vbr;
+};
+
+static struct multiple_tracks_id3 mul_id3;
+
+
+/* Calculate modified FNV hash of string
+ * has good avalanche behaviour and uniform distribution
+ * see http://home.comcast.net/~bretm/hash/ */
+static unsigned int mfnv(char *str)
+{
+ const unsigned int p = 16777619;
+ unsigned int hash = 0x811C9DC5; // 2166136261;
+
+ if (!str)
+ return 0;
+
+ while(*str)
+ hash = (hash ^ *str++) * p;
+ hash += hash << 13;
+ hash ^= hash >> 7;
+ hash += hash << 3;
+ hash ^= hash >> 17;
+ hash += hash << 5;
+ return hash;
+}
+
+static void init_mul_id3(void)
+{
+ mul_id3.artist_hash = 0;
+ mul_id3.album_hash = 0;
+ mul_id3.genre_hash = 0;
+ mul_id3.composer_hash = 0;
+ mul_id3.albumartist_hash = 0;
+ mul_id3.grouping_hash = 0;
+ mul_id3.comment_hash = 0;
+ mul_id3.codectype = 0;
+ mul_id3.vbr = false;
+ mul_id3.bitrate = 0;
+ mul_id3.frequency = 0;
+ mul_id3.length = 0;
+ mul_id3.filesize = 0;
+ mul_id3.year = 0;
+}
+
+void collect_id3(struct mp3entry *id3, bool is_first_track)
+{
+ if (is_first_track)
+ {
+ init_mul_id3();
+ mul_id3.artist_hash = mfnv(id3->artist);
+ mul_id3.album_hash = mfnv(id3->album);
+ mul_id3.genre_hash = mfnv(id3->genre_string);
+ mul_id3.composer_hash = mfnv(id3->composer);
+ mul_id3.albumartist_hash = mfnv(id3->albumartist);
+ mul_id3.grouping_hash = mfnv(id3->grouping);
+ mul_id3.comment_hash = mfnv(id3->comment);
+ mul_id3.codectype = id3->codectype;
+ mul_id3.vbr = id3->vbr;
+ mul_id3.bitrate = id3->bitrate;
+ mul_id3.frequency = id3->frequency;
+ mul_id3.year = id3->year;
+ }
+ else
+ {
+ if (mul_id3.artist_hash && (mfnv(id3->artist) != mul_id3.artist_hash))
+ mul_id3.artist_hash = 0;
+ if (mul_id3.album_hash && (mfnv(id3->album) != mul_id3.album_hash))
+ mul_id3.album_hash = 0;
+ if (mul_id3.genre_hash && (mfnv(id3->genre_string) != mul_id3.genre_hash))
+ mul_id3.genre_hash = 0;
+ if (mul_id3.composer_hash && (mfnv(id3->composer) != mul_id3.composer_hash))
+ mul_id3.composer_hash = 0;
+ if (mul_id3.albumartist_hash && (mfnv(id3->albumartist) !=
+ mul_id3.albumartist_hash))
+ mul_id3.albumartist_hash = 0;
+ if (mul_id3.grouping_hash && (mfnv(id3->grouping) != mul_id3.grouping_hash))
+ mul_id3.grouping_hash = 0;
+ if (mul_id3.comment_hash && (mfnv(id3->comment) != mul_id3.comment_hash))
+ mul_id3.comment_hash = 0;
+
+ if (mul_id3.codectype && (id3->codectype != mul_id3.codectype))
+ mul_id3.codectype = AFMT_UNKNOWN;
+ if (mul_id3.bitrate && (id3->bitrate != mul_id3.bitrate ||
+ id3->vbr != mul_id3.vbr))
+ mul_id3.bitrate = 0;
+ if (mul_id3.frequency && (id3->frequency != mul_id3.frequency))
+ mul_id3.frequency = 0;
+ if (mul_id3.year && (id3->year != mul_id3.year))
+ mul_id3.year = 0;
+ }
+ mul_id3.length += id3->length;
+ mul_id3.filesize += id3->filesize;
+}
+
+/* (!) Note scale factor applied to returned metadata:
+ * - Unit for filesize will be KiB instead of Bytes
+ * - Unit for length will be s instead of ms
+ *
+ * Use result only as input for browse_id3,
+ * with the track_ct parameter set to > 1.
+ */
+void finalize_id3(struct mp3entry *id3)
+{
+ id3->path[0] = '\0';
+ id3->title = NULL;
+ if (!mul_id3.artist_hash)
+ id3->artist = NULL;
+ if (!mul_id3.album_hash)
+ id3->album = NULL;
+ if (!mul_id3.genre_hash)
+ id3->genre_string = NULL;
+ if (!mul_id3.composer_hash)
+ id3->composer = NULL;
+ if (!mul_id3.albumartist_hash)
+ id3->albumartist = NULL;
+ if (!mul_id3.grouping_hash)
+ id3->grouping = NULL;
+ if (!mul_id3.comment_hash)
+ id3->comment = NULL;
+ id3->disc_string = NULL;
+ id3->track_string = NULL;
+ id3->year_string = NULL;
+ id3->year = mul_id3.year;
+ mul_id3.length /= 1000;
+ mul_id3.filesize >>= 10;
+ id3->length = mul_id3.length > ULONG_MAX ? 0 : mul_id3.length;
+ id3->filesize = mul_id3.filesize > INT_MAX ? 0 : mul_id3.filesize;
+ id3->frequency = mul_id3.frequency;
+ id3->bitrate = mul_id3.bitrate;
+ id3->codectype = mul_id3.codectype;
+ id3->vbr = mul_id3.vbr;
+ id3->discnum = 0;
+ id3->tracknum = 0;
+ id3->track_level = 0;
+ id3->album_level = 0;
+}
diff --git a/apps/plugins/lib/mul_id3.h b/apps/plugins/lib/mul_id3.h
new file mode 100644
index 0000000000..d08095de5c
--- /dev/null
+++ b/apps/plugins/lib/mul_id3.h
@@ -0,0 +1,27 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2023 Christian Soffke
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef MUL_ID3_H
+#define MUL_ID3_H
+
+void collect_id3(struct mp3entry *id3, bool is_first_track);
+void finalize_id3(struct mp3entry *id3);
+
+#endif /* MUL_ID3_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/overlay.c b/apps/plugins/lib/overlay.c
index 0ecc1bf3e7..065273534e 100644
--- a/apps/plugins/lib/overlay.c
+++ b/apps/plugins/lib/overlay.c
@@ -83,9 +83,8 @@ enum plugin_status run_overlay(const void* parameter,
goto error_close;
}
-
- if (hdr->api_version > PLUGIN_API_VERSION
- || hdr->api_version < PLUGIN_MIN_API_VERSION)
+ if (hdr->api_version != PLUGIN_API_VERSION ||
+ p_hdr->api_size > sizeof(struct plugin_api))
{
rb->splashf(2*HZ, "%s overlay: Incompatible version.", name);
goto error_close;
diff --git a/apps/plugins/lib/playback_control.c b/apps/plugins/lib/playback_control.c
index 363033b1f2..3e97916400 100644
--- a/apps/plugins/lib/playback_control.c
+++ b/apps/plugins/lib/playback_control.c
@@ -65,21 +65,21 @@ static bool nexttrack(void)
static bool volume(void)
{
const struct settings_list* vol =
- rb->find_setting(&rb->global_settings->volume, NULL);
+ rb->find_setting(&rb->global_settings->volume);
return rb->option_screen((struct settings_list*)vol, parentvp, false, "Volume");
}
static bool shuffle(void)
{
const struct settings_list* shuffle =
- rb->find_setting(&rb->global_settings->playlist_shuffle, NULL);
+ rb->find_setting(&rb->global_settings->playlist_shuffle);
return rb->option_screen((struct settings_list*)shuffle, parentvp, false, "Shuffle");
}
static bool repeat_mode(void)
{
const struct settings_list* repeat =
- rb->find_setting(&rb->global_settings->repeat_mode, NULL);
+ rb->find_setting(&rb->global_settings->repeat_mode);
int old_repeat = rb->global_settings->repeat_mode;
rb->option_screen((struct settings_list*)repeat, parentvp, false, "Repeat");
@@ -91,19 +91,19 @@ static bool repeat_mode(void)
return false;
}
MENUITEM_FUNCTION(prevtrack_item, 0, ID2P(LANG_PREVTRACK),
- prevtrack, NULL, NULL, Icon_NOICON);
+ prevtrack, NULL, Icon_NOICON);
MENUITEM_FUNCTION(playpause_item, 0, ID2P(LANG_PLAYPAUSE),
- play, NULL, NULL, Icon_NOICON);
+ play, NULL, Icon_NOICON);
MENUITEM_FUNCTION(stop_item, 0, ID2P(LANG_STOP_PLAYBACK),
- stop, NULL, NULL, Icon_NOICON);
+ stop, NULL, Icon_NOICON);
MENUITEM_FUNCTION(nexttrack_item, 0, ID2P(LANG_NEXTTRACK),
- nexttrack, NULL, NULL, Icon_NOICON);
+ nexttrack, NULL, Icon_NOICON);
MENUITEM_FUNCTION(volume_item, 0, ID2P(LANG_CHANGE_VOLUME),
- volume, NULL, NULL, Icon_NOICON);
+ volume, NULL, Icon_NOICON);
MENUITEM_FUNCTION(shuffle_item, 0, ID2P(LANG_CHANGE_SHUFFLE_MODE),
- shuffle, NULL, NULL, Icon_NOICON);
+ shuffle, NULL, Icon_NOICON);
MENUITEM_FUNCTION(repeat_mode_item, 0, ID2P(LANG_CHANGE_REPEAT_MODE),
- repeat_mode, NULL, NULL, Icon_NOICON);
+ repeat_mode, NULL, Icon_NOICON);
MAKE_MENU(playback_control_menu, ID2P(LANG_PLAYBACK_CONTROL), NULL, Icon_NOICON,
&prevtrack_item, &playpause_item, &stop_item, &nexttrack_item,
&volume_item, &shuffle_item, &repeat_mode_item);
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..48b8b2c9d2 100644
--- a/apps/plugins/lib/printcell_helper.c
+++ b/apps/plugins/lib/printcell_helper.c
@@ -22,10 +22,6 @@
#include "plugin.h"
#include "lib/printcell_helper.h"
-#ifndef PRINTCELL_MAX_COLUMNS
-#define PRINTCELL_MAX_COLUMNS 16
-#endif
-
#define COLUMN_ENDLEN 3
#define TITLE_FLAG 0xFF
#define SELECTED_FLAG 0x1
@@ -37,48 +33,54 @@
#endif
struct printcell_info_t {
- int offw[NB_SCREENS];
- int iconw[NB_SCREENS];
- int selcol_offw[NB_SCREENS];
- int totalcolw[NB_SCREENS];
- int firstcolxw[NB_SCREENS];
- uint16_t colw[NB_SCREENS][PRINTCELL_MAX_COLUMNS];
- int ncols;
- int selcol;
- int selcol_index;
- char title[PRINTCELL_MAXLINELEN];
- bool separator;
+ struct gui_synclist *gui_list; /* list to display */
+ int offw[NB_SCREENS]; /* padding between column boundries and text */
+ int iconw[NB_SCREENS]; /* width of an icon */
+ int selcol_offw[NB_SCREENS]; /* offset width calculated for selected item */
+ int totalcolw[NB_SCREENS]; /* total width of all columns */
+ int firstcolxw[NB_SCREENS]; /* first column x + width, save recalculating */
+ int ncols; /* number of columns */
+ int selcol; /* selected column (-1 to ncols-1) */
+ uint32_t hidecol_flags; /*bits 0-31 set bit to 1 to hide a column (1<<col#) */
+ uint16_t colw[NB_SCREENS][PRINTCELL_MAX_COLUMNS]; /* width of title text
+ or MIN(or user defined width / screen width) */
+ char title[PRINTCELL_MAXLINELEN]; /* title buffer */
+ char titlesep; /* character that separates title column items (ex '$') */
+ char colsep; /* character that separates text column items (ex ',') */
+ bool separator; /* draw grid */
};
+
static struct printcell_info_t printcell;
-static void parse_dsptext(int ncols, const char *dsp_text, char* buffer, uint16_t *sidx)
+static void parse_dsptext(char splitchr, int ncols, const char *dsp_text,
+ char* buffer, size_t bufsz, uint16_t *sidx)
{
/*Internal function loads sidx with split offsets indexing
- the buffer of null terminated strings, splits on '$'
+ the buffer of null terminated strings, splits on 'splitchr'
_assumptions_:
dsp_text[len - 1] = \0,
- buffer[PRINTCELL_MAXLINELEN],
sidx[PRINTCELL_MAX_COLUMNS]
*/
int i = 0;
- int j = 0;
- int ch = '$'; /* first column $ is optional */
- if (*dsp_text == '$')
+ size_t j = 0;
+ int ch = splitchr; /* first column $ is optional */
+ if (*dsp_text == splitchr)
dsp_text++;
/* add null to the start of the text buffer */
buffer[j++] = '\0';
do
{
- if (ch == '$')
+ if (ch == splitchr)
{
- sidx[i] = j;
- if (*dsp_text == '$') /* $$ escaped user must want to display $*/
- buffer[j++] = *dsp_text++;
- while (*dsp_text != '\0' && *dsp_text != '$' && j < PRINTCELL_MAXLINELEN - 1)
+ sidx[i] = j; /* save start index and copy next column to the buffer */
+ while (*dsp_text != '\0' && *dsp_text != splitchr && j < (bufsz - 1))
+ {
buffer[j++] = *dsp_text++;
+ }
buffer[j++] = '\0';
+
i++;
- if (i >= ncols || j >= (PRINTCELL_MAXLINELEN - 1))
+ if (i >= ncols || j >= (bufsz - 1))
break;
}
ch = *dsp_text++;
@@ -146,23 +148,39 @@ static inline void set_cell_width(struct viewport *vp, int max_w, int new_w)
static inline int printcells(struct screen *display, char* buffer,
uint16_t *sidx, struct line_desc *linedes,
struct viewport *vp, int vp_w, int separator,
- int x, int y, int offw, int selected_flag, bool scroll)
+ int x, int y, int offw, int selected_flag, int last_col,
+ bool scroll, bool is_title)
{
/* Internal function prints remaining cells */
int text_offset = offw + offw;
- int ncols = printcell.ncols;
int screen = display->screen_type;
int height = linedes->height;
int selsep = (selected_flag == 0) ? 0: separator;
uint16_t *screencolwidth = printcell.colw[screen];
- for(int i = 1; i < ncols; i++)
+ for(int i = 1; i <= last_col; i++)
{
int ny = y;
int nw = screencolwidth[i] + text_offset;
+ int offx = 0;
+
+ if (i == last_col || x + nw >= vp_w - offw + 1)
+ { /* not enough space for next column use up excess */
+ if (nw < (vp_w - x))
+ {
+ if (is_title)
+ offx = ((vp_w - x) - nw) / 2;
+ nw = vp_w - x;
+ }
+ }
+
+ if (!PRINTCELL_COLUMN_IS_VISIBLE(printcell.hidecol_flags, i))
+ nw = 0;
+
int nx = x + nw;
char *buftext;
- if (nx > 0 && x < vp_w)
+
+ if (nx > 0 && nw > offw && x < vp_w)
{
set_cell_width(vp, vp_w, nx);
@@ -173,11 +191,15 @@ static inline int printcells(struct screen *display, char* buffer,
}
else
{
+ if (vp_w < x + text_offset)
+ {
+ scroll = false;
+ }
linedes->scroll = scroll;
linedes->separator_height = separator;
}
buftext = &buffer[sidx[i]];
- display->put_line(x + offw, ny, linedes, "$t", buftext);
+ display->put_line(x + offw + offx, ny, linedes, "$t", buftext);
vp->width += COLUMN_ENDLEN + 1;
draw_selector(display, linedes, selected_flag, i, separator, x, ny, nw, height);
}
@@ -192,12 +214,18 @@ static inline int calcvisible(int screen, int vp_w, int text_offset, int sbwidth
uint16_t *screencolwidth = printcell.colw[screen];
int screenicnwidth = printcell.iconw[screen];
int offset = 0;
- int selcellw = screencolwidth[printcell.selcol] + text_offset;
+ int selcellw = 0;
+ if (printcell.selcol >= 0)
+ selcellw = screencolwidth[printcell.selcol] + text_offset;
int maxw = vp_w - (sbwidth + selcellw + 1);
for (int i = printcell.selcol - 1; i >= 0; i--)
{
int cw = screencolwidth[i] + text_offset;
+
+ if (!PRINTCELL_COLUMN_IS_VISIBLE(printcell.hidecol_flags, i))
+ cw = 0;
+
if (i == 0)
cw += screenicnwidth;
if (offset > 0 || cw > maxw)
@@ -234,7 +262,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;
@@ -255,15 +283,30 @@ static void printcell_listdraw_fn(struct list_putlineinfo_t *list_info)
separator = 1;
int nx = x;
+ int last_col = printcell.ncols - 1;
+ int hidden_w = 0;
int nw, colxw;
-
+ char *buftext;
printcell_buffer[0] = '\0';
- parse_dsptext(printcell.ncols, dsp_text, printcell_buffer, sidx);
- char *buftext = &printcell_buffer[sidx[0]];
+
uint16_t *screencolwidth = printcell.colw[screen];
+ if (printcell.hidecol_flags > 0)
+ {
+ for (int i = 0; i < printcell.ncols; i++)
+ {
+ if (PRINTCELL_COLUMN_IS_VISIBLE(printcell.hidecol_flags, i))
+ last_col = i;
+ else
+ hidden_w += (screencolwidth[i] + text_offset);
+ }
+ }
if (is_title)
{
+ parse_dsptext(printcell.titlesep, printcell.ncols, dsp_text,
+ printcell_buffer, sizeof(printcell_buffer), sidx);
+
+ buftext = &printcell_buffer[sidx[0]]; /* set to first column text */
int sbwidth = 0;
if (rb->global_settings->scrollbar == SCROLLBAR_LEFT)
sbwidth = rb->global_settings->scrollbar_width;
@@ -276,6 +319,9 @@ static void printcell_listdraw_fn(struct list_putlineinfo_t *list_info)
nx -= printcell.selcol_offw[screen];
nw = screencolwidth[0] + printcell.iconw[screen] + text_offset;
+
+ if (!PRINTCELL_COLUMN_IS_VISIBLE(printcell.hidecol_flags, 0))
+ nw = printcell.iconw[screen] - 1;
nw += sbwidth;
colxw = nx + nw;
@@ -299,16 +345,21 @@ static void printcell_listdraw_fn(struct list_putlineinfo_t *list_info)
}
else
{
+ parse_dsptext(printcell.colsep, printcell.ncols, dsp_text,
+ printcell_buffer, sizeof(printcell_buffer), sidx);
+
+ buftext = &printcell_buffer[sidx[0]]; /* set to first column text */
int cursor = Icon_NOICON;
nx -= printcell.selcol_offw[screen];
if (selected_flag & SELECTED_FLAG)
{
- printcell.selcol_index = sidx[printcell.selcol]; /* save the item offset*/
cursor = Icon_Cursor;
/* limit length of selection if columns don't reach end */
int maxw = nx + printcell.totalcolw[screen] + printcell.iconw[screen];
maxw += text_offset * printcell.ncols;
+ maxw -= hidden_w;
+
if (vp_w > maxw)
vp->width = maxw;
/* display a blank line first to draw selector across all cells */
@@ -358,7 +409,7 @@ static void printcell_listdraw_fn(struct list_putlineinfo_t *list_info)
nx += nw;
/* display remaining cells */
printcells(display, printcell_buffer, sidx, linedes, vp, vp_w, separator,
- nx, y, col_offset_width, selected_flag, scroll_items);
+ nx, y, col_offset_width, selected_flag, last_col, scroll_items, is_title);
/* draw a line at the bottom of the list */
if (separator > 0 && line == list->nb_items - 1)
@@ -371,14 +422,17 @@ static void printcell_listdraw_fn(struct list_putlineinfo_t *list_info)
vp->width = vp_w;
}
-void printcell_enable(struct gui_synclist *gui_list, bool enable, bool separator)
+void printcell_enable(bool enable)
{
- printcell.separator = separator;
+ if (!printcell.gui_list)
+ return;
+ struct gui_synclist *gui_list = printcell.gui_list;
#ifdef HAVE_LCD_COLOR
static int list_sep_color = INT_MIN;
if (enable)
{
- list_sep_color = rb->global_settings->list_separator_color;
+ if (list_sep_color == INT_MIN)
+ list_sep_color = rb->global_settings->list_separator_color;
rb->global_settings->list_separator_color = rb->global_settings->fg_color;
gui_list->callback_draw_item = printcell_listdraw_fn;
}
@@ -398,8 +452,11 @@ void printcell_enable(struct gui_synclist *gui_list, bool enable, bool separator
}
-int printcell_increment_column(struct gui_synclist *gui_list, int increment, bool wrap)
+int printcell_increment_column(int increment, bool wrap)
{
+ if (!printcell.gui_list)
+ return -1;
+ struct gui_synclist *gui_list = printcell.gui_list;
int item = printcell.selcol + increment;
int imin = -1;
int imax = printcell.ncols - 1;
@@ -419,36 +476,94 @@ int printcell_increment_column(struct gui_synclist *gui_list, int increment, boo
FOR_NB_SCREENS(n) /* offset needs recalculated */
printcell.selcol_offw[n] = 0;
printcell.selcol = item;
- printcell.selcol_index = 0;
+
rb->gui_synclist_draw(gui_list);
+ rb->gui_synclist_speak_item(gui_list);
}
return item;
}
+int printcell_get_column_selected(void)
+{
+ if (!printcell.gui_list)
+ return -1;
+ return printcell.selcol;
+}
+
+uint32_t printcell_get_column_visibility(int col)
+{
+ if (col >= 0)
+ return (PRINTCELL_COLUMN_IS_VISIBLE(printcell.hidecol_flags, col) ? 0:1);
+ else /* return flag of all columns */
+ return printcell.hidecol_flags;
+}
+
+void printcell_set_column_visible(int col, bool visible)
+{
+ /* visible columns have 0 for the column bit hidden columns have the bit set */
+ if (col >= 0)
+ {
+ if (visible)
+ printcell.hidecol_flags &= ~(PRINTCELL_COLUMN_FLAG(col));
+ else
+ printcell.hidecol_flags |= PRINTCELL_COLUMN_FLAG(col);
+ }
+ else
+ {
+ if (visible) /* set to everything visible */
+ printcell.hidecol_flags = 0;
+ else /* set to everything hidden */
+ printcell.hidecol_flags = ((uint32_t)-1);
+ }
+}
+
int printcell_set_columns(struct gui_synclist *gui_list,
- char * title, enum themable_icons icon)
+ struct printcell_settings * pcs,
+ char * title, enum themable_icons icon)
{
+
if (title == NULL)
title = "$PRINTCELL NOT SETUP";
+
+ if (pcs == NULL) /* DEFAULTS */
+ {
+#if LCD_DEPTH > 1
+ /* If line sep is set to automatic then outline cells */
+ bool sep = (rb->global_settings->list_separator_height < 0);
+#else
+ bool sep = (rb->global_settings->cursor_style == 0);
+#endif
+ pcs = &(struct printcell_settings){ .cell_separator = sep,
+ .title_delimeter = '$',
+ .text_delimeter = '$',
+ .hidecol_flags = 0};
+ }
+
uint16_t sidx[PRINTCELL_MAX_COLUMNS]; /* starting position of column in title string */
int width, height, user_minwidth;
int i = 0;
- int j = 0;
- int ch = '$'; /* first column $ is optional */
-
+ size_t j = 0;
rb->memset(&printcell, 0, sizeof(struct printcell_info_t));
+ printcell.gui_list = gui_list;
+ printcell.separator = pcs->cell_separator;
+ printcell.titlesep = pcs->title_delimeter;
+ printcell.colsep = pcs->text_delimeter;
+ printcell.hidecol_flags = pcs->hidecol_flags;
+
+ int ch = printcell.titlesep; /* first column $ is optional */
+
FOR_NB_SCREENS(n)
{
rb->screens[n]->getstringsize("W", &width, &height);
printcell.offw[n] = width; /* set column text offset */
}
- if (*title == '$')
+ if (*title == printcell.titlesep)
title++;
do
{
- if (ch == '$')
+ if (ch == printcell.titlesep)
{
printcell.title[j++] = ch;
user_minwidth = 0;
@@ -460,7 +575,7 @@ int printcell_set_columns(struct gui_synclist *gui_list,
user_minwidth = 10*user_minwidth + *title - '0';
title++;
}
- if (*title != '$') /* user forgot $ or wants to display '*' */
+ if (*title != printcell.titlesep) /* user forgot titlesep or wants to display '*' */
{
title = dspst;
user_minwidth = 0;
@@ -470,17 +585,25 @@ int printcell_set_columns(struct gui_synclist *gui_list,
}
sidx[i] = j;
- if (*title == '$') /* $$ escaped user must want to display $*/
- printcell.title[j++] = *title++;
- while (*title != '\0' && *title != '$' && j < PRINTCELL_MAXLINELEN - 1)
+ while (*title != '\0'
+ && *title != printcell.titlesep
+ && j < PRINTCELL_MAXLINELEN - 1)
+ {
printcell.title[j++] = *title++;
+ }
FOR_NB_SCREENS(n)
{
- rb->screens[n]->getstringsize(&printcell.title[sidx[i]], &width, &height);
+ rb->screens[n]->getstringsize(&printcell.title[sidx[i]],
+ &width, &height);
+
if (width < user_minwidth)
width = user_minwidth;
+
+ if (width > LCD_WIDTH)
+ width = LCD_WIDTH;
+
printcell.colw[n][i] = width;
printcell.totalcolw[n] += width;
}
@@ -492,37 +615,67 @@ int printcell_set_columns(struct gui_synclist *gui_list,
printcell.ncols = i;
printcell.title[j] = '\0';
printcell.selcol = -1;
- printcell.selcol_index = 0;
rb->gui_synclist_set_title(gui_list, printcell.title, icon);
return printcell.ncols;
}
-char *printcell_get_selected_column_text(struct gui_synclist *gui_list, char *buf, size_t bufsz)
+char *printcell_get_title_text(int selcol, char *buf, size_t bufsz)
{
- int selected = gui_list->selected_item;
- int index = printcell.selcol_index - 1;
+ /* note offsets are calculated everytime this function is called
+ * shouldn't be used in hot code paths */
+ int index = 0;
+ buf[0] = '\0';
+ if (selcol < 0) /* return entire string incld col formatting '$'*/
+ return printcell.title;
+
+ if (selcol < printcell.ncols)
+ {
+ uint16_t sidx[PRINTCELL_MAX_COLUMNS]; /*indexes zero terminated strings in buffer*/
+ parse_dsptext(printcell.titlesep, selcol + 1, printcell.title, buf, bufsz, sidx);
+ index = sidx[selcol];
+ }
+ return &buf[index];
+}
- if (index < 0)
- index = 0;
+char *printcell_get_column_text(int selcol, char *buf, size_t bufsz)
+{
+ int index = 0;
char *bpos;
+ struct gui_synclist *gui_list = printcell.gui_list;
- if (gui_list->callback_get_item_name(selected, gui_list->data, buf, bufsz) == buf)
+ if (gui_list && gui_list->callback_draw_item == printcell_listdraw_fn)
{
- bpos = &buf[index];
- if (printcell.selcol < 0) /* return entire string incld col formatting '$'*/
- return bpos;
- while(bpos < &buf[bufsz - 1])
+ int col = selcol;
+ int item = gui_list->selected_item;
+ void *data = gui_list->data;
+
+ if (col < printcell.ncols
+ && gui_list->callback_get_item_name(item, data, buf, bufsz) == buf)
{
- if (*bpos == '$' || *bpos == '\0')
- goto success;
- bpos++;
+ bpos = buf;
+ if (col < 0) /* return entire string incld col formatting '$'*/
+ {
+ return bpos;
+ }
+ bpos++; /* Skip sep/NULL */
+
+ while(bpos < &buf[bufsz - 1])
+ {
+ if (*bpos == printcell.colsep || *bpos == '\0')
+ {
+ if (col-- == 0)
+ goto success;
+ index = bpos - buf + 1; /* Skip sep/NULL */
+ }
+ bpos++;
+ }
}
}
/*failure*/
- bpos = buf;
- index = 0;
+ bpos = buf;
+ index = 0;
success:
- *bpos = '\0';
- return &buf[index];
+ *bpos = '\0';
+ return &buf[index];
}
diff --git a/apps/plugins/lib/printcell_helper.h b/apps/plugins/lib/printcell_helper.h
index adc98e5a5f..f58e73c0a5 100644
--- a/apps/plugins/lib/printcell_helper.h
+++ b/apps/plugins/lib/printcell_helper.h
@@ -21,25 +21,67 @@
#ifndef _PRINTCELL_LIST_H_
#define _PRINTCELL_LIST_H_
+#ifndef PRINTCELL_MAX_COLUMNS
+#define PRINTCELL_MAX_COLUMNS 16 /* Max 32 (hidecol_flags)*/
+#endif
+
#define PRINTCELL_MAXLINELEN MAX_PATH
+#define PC_COL_FLAG(col) ((uint32_t)(col >= 0 \
+ && col < PRINTCELL_MAX_COLUMNS) ? 1u<<col : -1u)
+
+#define PRINTCELL_COLUMN_IS_VISIBLE(flag, col) ((flag & PC_COL_FLAG(col)) == 0)
+#define PRINTCELL_COLUMN_FLAG(col) (PC_COL_FLAG(col))
-/* sets the printcell function enabled */
-void printcell_enable(struct gui_synclist *gui_list, bool enable, bool separator);
+struct printcell_settings
+{
+ bool cell_separator;
+ char title_delimeter;
+ char text_delimeter;
+ uint32_t hidecol_flags;
+};
-/* sets title and calculates cell widths each column is identified by '$' character
- ex 3 columns title = "Col1$Col2$Col3" also accepts $*WIDTH$
- ex 3 columns varying width title = "$*64$Col1$*128$Col2$Col3
- returns number of columns
+/* Printcell initialization - Sets title and calculates cell widths
+* by default each column is identified by '$' character
+* ex 3 columns title = "Col1$Col2$Col3" also accepts $*WIDTH$
+* ex 3 columns varying width title = "$*64$Col1$*128$Col2$Col3
+* supplying struct printcell_settings pcs allows changing default settings
+* supply NULL to use defaults
+*
+* Returns number of columns
*/
-int printcell_set_columns(struct gui_synclist *gui_list,
- char * title, enum themable_icons icon);
+int printcell_set_columns(struct gui_synclist *gui_list,
+ struct printcell_settings * pcs,
+ char * title, enum themable_icons icon);
+
+/* Sets the printcell function enabled (use after initializing with set_column)
+ * Note you should call printcell_enable(false) if the list might be reused */
+void printcell_enable(bool enable);
-/* increments the current selected column negative increment is allowed
- returns the selected column
+/* Increments the current selected column negative increment is allowed
+ returns the selected column
range: -1(no selection) to ncols - 1 */
-int printcell_increment_column(struct gui_synclist *gui_list, int increment, bool wrap);
+int printcell_increment_column(int increment, bool wrap);
+
+/* Return index of the currently selected column (-1 to ncols - 1) */
+int printcell_get_column_selected(void);
+
+/* Return the text of currently selected column buffer should be sized
+ * for max item len, buf[PRINTCELL_MAXLINELEN] is a safe bet */
+char *printcell_get_column_text(int selcol, char *buf, size_t bufsz);
-/* return the text of currently selected column buffer should be sized
+/* Return the text of currently selected column title should be sized
* for max item len, buf[PRINTCELL_MAXLINELEN] is a safe bet */
-char *printcell_get_selected_column_text(struct gui_synclist *gui_list, char *buf, size_t bufsz);
+char *printcell_get_title_text(int selcol, char *buf, size_t bufsz);
+
+
+/* Hide or show a specified column - supply col = -1 to affect all columns */
+void printcell_set_column_visible(int col, bool visible);
+
+/* Return visibility of a specified column
+* returns (1 visible or 0 hidden)
+* if supply col == -1 a flag with visibility of all columns will be returned
+* NOTE: flag denotes a hidden column by a 1 in the column bit (1 << col#)
+* PRINTCELL_COLUMN_IS_VISIBLE(flag,col) macro will convert to bool
+*/
+uint32_t printcell_get_column_visibility(int col);
#endif /*_PRINTCELL_LIST_H_*/
diff --git a/apps/plugins/lib/wrappers.h b/apps/plugins/lib/wrappers.h
index b6fbd51a39..761854fa05 100644
--- a/apps/plugins/lib/wrappers.h
+++ b/apps/plugins/lib/wrappers.h
@@ -53,6 +53,7 @@
#define strlen rb->strlen
#define strlcpy rb->strlcpy
#define strrchr rb->strrchr
+#define fix_path_part rb->fix_path_part
#endif
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/logo.c b/apps/plugins/logo.c
index 984a65aa34..9df73a9d0b 100644
--- a/apps/plugins/logo.c
+++ b/apps/plugins/logo.c
@@ -49,15 +49,27 @@ static const struct button_mapping *plugin_contexts[]
/* We use PLA */
#define LP_QUIT PLA_EXIT
-#define LP_QUIT2 PLA_CANCEL
#define LP_DEC_X PLA_LEFT
#define LP_DEC_X_REPEAT PLA_LEFT_REPEAT
#define LP_INC_X PLA_RIGHT
#define LP_INC_X_REPEAT PLA_RIGHT_REPEAT
+
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define LP_QUIT2 PLA_UP
+#define LP_DEC_Y PLA_SCROLL_BACK
+#define LP_DEC_Y_REPEAT PLA_SCROLL_BACK_REPEAT
+#define LP_INC_Y PLA_SCROLL_FWD
+#define LP_INC_Y_REPEAT PLA_SCROLL_FWD_REPEAT
+#else
+#define LP_QUIT2 PLA_CANCEL
#define LP_DEC_Y PLA_DOWN
#define LP_DEC_Y_REPEAT PLA_DOWN_REPEAT
#define LP_INC_Y PLA_UP
#define LP_INC_Y_REPEAT PLA_UP_REPEAT
+#endif
+
enum plugin_status plugin_start(const void* parameter) {
int button;
diff --git a/apps/plugins/lrcplayer.c b/apps/plugins/lrcplayer.c
index f42b96b5b3..de31733671 100644
--- a/apps/plugins/lrcplayer.c
+++ b/apps/plugins/lrcplayer.c
@@ -643,22 +643,6 @@ static void init_time_tag(void)
* /ddd.lrc
*/
-/* taken from apps/recorder/albumart.c */
-static void fix_filename(char* name)
-{
- static const char invalid_chars[] = "*/:<>?\\|";
-
- while (1)
- {
- if (*name == 0)
- return;
- if (*name == '"')
- *name = '\'';
- else if (rb->strchr(invalid_chars, *name))
- *name = '_';
- name++;
- }
-}
static bool find_lrc_file_helper(const char *base_dir)
{
char fname[MAX_PATH];
@@ -678,7 +662,7 @@ static bool find_lrc_file_helper(const char *base_dir)
if (current.id3->title && rb->strcmp(names[0], current.id3->title))
{
rb->strlcpy(fname, current.id3->title, sizeof(fname));
- fix_filename(fname);
+ rb->fix_path_part(fname, 0, sizeof(fname) - 1);
names[1] = fname;
}
@@ -2078,8 +2062,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 +2420,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);
@@ -2643,16 +2625,10 @@ static int handle_button(void)
ff_rewind(0, false);
break;
case ACTION_WPS_VOLDOWN:
- limit = rb->sound_min(SOUND_VOLUME);
- if (--rb->global_settings->volume < limit)
- rb->global_settings->volume = limit;
- rb->sound_set(SOUND_VOLUME, rb->global_settings->volume);
+ rb->adjust_volume(-1);
break;
case ACTION_WPS_VOLUP:
- limit = rb->sound_max(SOUND_VOLUME);
- if (++rb->global_settings->volume > limit)
- rb->global_settings->volume = limit;
- rb->sound_set(SOUND_VOLUME, rb->global_settings->volume);
+ rb->adjust_volume(1);
break;
case ACTION_WPS_CONTEXT:
ret = LRC_GOTO_EDITOR;
diff --git a/apps/plugins/lua/rocklib.c b/apps/plugins/lua/rocklib.c
index cadc8be6ac..8efaaab169 100644
--- a/apps/plugins/lua/rocklib.c
+++ b/apps/plugins/lua/rocklib.c
@@ -930,12 +930,6 @@ RB_WRAP(restart_lua)
return -1;
}
-RB_WRAP(show_logo)
-{
- rb->show_logo();
- return 0;
-}
-
RB_WRAP(mem_stats)
{
/* used, allocd, free = rb.mem_stats() */
@@ -1032,7 +1026,6 @@ static const luaL_Reg rocklib[] =
/* MISC */
RB_FUNC(restart_lua),
- RB_FUNC(show_logo),
RB_FUNC(mem_stats),
{NULL, NULL}
diff --git a/apps/plugins/lua/rocklib_events.c b/apps/plugins/lua/rocklib_events.c
index 1c13a6758f..52e87f3d61 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;
@@ -421,7 +423,7 @@ static void init_event_thread(bool init, struct event_data *ev_data)
0,
EVENT_THREAD
IF_PRIO(, PRIORITY_SYSTEM)
- IF_COP(, COP));
+ IF_COP(, CPU));
/* Timer is used to poll waiting events */
if (!rb->timer_register(1, NULL, EV_TIMER_FREQ, rev_timer_isr IF_COP(, CPU)))
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/matrix.c b/apps/plugins/matrix.c
index 1b2f6d465a..6e96aae10c 100644
--- a/apps/plugins/matrix.c
+++ b/apps/plugins/matrix.c
@@ -52,6 +52,14 @@
/* this set the context to use with PLA */
static const struct button_mapping *plugin_contexts[] = { pla_main_ctx };
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define MATRIX_EXIT2 PLA_UP
+#else
+#define MATRIX_EXIT2 PLA_CANCEL
+#endif
+
#ifdef HAVE_SCROLLWHEEL
#define MATRIX_SLEEP_MORE PLA_SCROLL_BACK
#define MATRIX_SLEEP_MORE_REPEAT PLA_SCROLL_BACK_REPEAT
@@ -65,7 +73,6 @@ static const struct button_mapping *plugin_contexts[] = { pla_main_ctx };
#endif /* HAVE_SCROLLWHEEL */
#define MATRIX_PAUSE PLA_SELECT
#define MATRIX_EXIT PLA_EXIT
-#define MATRIX_EXIT2 PLA_CANCEL
#define SLEEP HZ/50
diff --git a/apps/plugins/maze.c b/apps/plugins/maze.c
index 20d5c82495..ebb83ab15c 100644
--- a/apps/plugins/maze.c
+++ b/apps/plugins/maze.c
@@ -37,11 +37,14 @@
/* key assignments */
-#if (CONFIG_KEYPAD == IPOD_3G_PAD)
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
# define MAZE_NEW (BUTTON_SELECT | BUTTON_REPEAT)
# define MAZE_NEW_PRE BUTTON_SELECT
# define MAZE_QUIT BUTTON_MENU
-# define MAZE_SOLVE (BUTTON_SELECT | BUTTON_PLAY)
+# define MAZE_SOLVE (BUTTON_SELECT | BUTTON_REL)
+# define MAZE_SOLVE_PRE BUTTON_SELECT
# define MAZE_RIGHT BUTTON_RIGHT
# define MAZE_RIGHT_REPEAT BUTTON_RIGHT|BUTTON_REPEAT
# define MAZE_LEFT BUTTON_LEFT
@@ -491,17 +494,15 @@ static void maze_move_player_left(struct maze* maze)
enum plugin_status plugin_start(const void* parameter)
{
int button;
-#ifdef MAZE_NEW_PRE
+#if defined(MAZE_NEW_PRE) || defined(MAZE_SOLVE_PRE)
int lastbutton = BUTTON_NONE;
#endif
int quit = 0;
struct maze maze;
(void)parameter;
-#ifdef HAVE_BACKLIGHT
/* Turn off backlight timeout */
backlight_ignore_timeout();
-#endif
/* Seed the RNG */
rb->srand(*rb->current_tick);
@@ -546,6 +547,10 @@ enum plugin_status plugin_start(const void* parameter)
maze_draw(&maze, rb->screens[i]);
break;
case MAZE_SOLVE:
+#ifdef MAZE_SOLVE_PRE
+ if(lastbutton != MAZE_SOLVE_PRE)
+ break;
+#endif
maze_solve(&maze);
FOR_NB_SCREENS(i)
maze_draw(&maze, rb->screens[i]);
@@ -585,14 +590,13 @@ enum plugin_status plugin_start(const void* parameter)
}
break;
}
-#ifdef MAZE_NEW_PRE
+#if defined(MAZE_NEW_PRE) || defined(MAZE_SOLVE_PRE)
if( button != BUTTON_NONE )
lastbutton = button;
#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..1183f8f502 100644
--- a/apps/plugins/mazezam.c
+++ b/apps/plugins/mazezam.c
@@ -27,7 +27,9 @@
/* Include standard plugin macro */
-#if (CONFIG_KEYPAD == IPOD_3G_PAD)
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
# define MAZEZAM_MENU BUTTON_MENU
# define MAZEZAM_RIGHT BUTTON_RIGHT
# define MAZEZAM_LEFT BUTTON_LEFT
@@ -256,9 +258,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 +272,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/metronome.c b/apps/plugins/metronome.c
index 157d116ff9..9d61c067fd 100644
--- a/apps/plugins/metronome.c
+++ b/apps/plugins/metronome.c
@@ -82,7 +82,13 @@ enum metronome_errors
#define MET_SYNC
#endif
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define METRONOME_QUIT PLA_UP
+#else
#define METRONOME_QUIT PLA_EXIT
+#endif
#ifdef HAVE_SCROLLWHEEL
#define METRONOME_VOL_UP PLA_SCROLL_FWD
diff --git a/apps/plugins/mikmod/mikmod.c b/apps/plugins/mikmod/mikmod.c
index 6622b5fdb6..65633c0ad1 100644
--- a/apps/plugins/mikmod/mikmod.c
+++ b/apps/plugins/mikmod/mikmod.c
@@ -710,7 +710,6 @@ static void mm_errorhandler(void)
static int playfile(char* filename)
{
- int vol = 0;
int button;
int retval = PLUGIN_OK;
bool changingpos = false;
@@ -789,13 +788,8 @@ static int playfile(char* filename)
}
break;
}
- vol = rb->global_settings->volume;
- if (vol < rb->sound_max(SOUND_VOLUME))
- {
- vol++;
- rb->sound_set(SOUND_VOLUME, vol);
- rb->global_settings->volume = vol;
- }
+
+ rb->adjust_volume(1);
break;
case ACTION_WPS_VOLDOWN:
@@ -808,13 +802,8 @@ static int playfile(char* filename)
}
break;
}
- vol = rb->global_settings->volume;
- if (vol > rb->sound_min(SOUND_VOLUME))
- {
- vol--;
- rb->sound_set(SOUND_VOLUME, vol);
- rb->global_settings->volume = vol;
- }
+
+ rb->adjust_volume(-1);
break;
case ACTION_WPS_SKIPPREV:
diff --git a/apps/plugins/mosaique.c b/apps/plugins/mosaique.c
index caf5346dc5..cf3f42521a 100644
--- a/apps/plugins/mosaique.c
+++ b/apps/plugins/mosaique.c
@@ -37,10 +37,17 @@
static const struct button_mapping *plugin_contexts[] = { pla_main_ctx };
#define MOSAIQUE_QUIT PLA_EXIT
-#define MOSAIQUE_QUIT2 PLA_CANCEL
-#define MOSAIQUE_SPEED PLA_UP
+#define MOSAIQUE_SPEED PLA_RIGHT
#define MOSAIQUE_RESTART PLA_SELECT
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define MOSAIQUE_QUIT2 PLA_UP
+#else
+#define MOSAIQUE_QUIT2 PLA_CANCEL
+#endif
+
enum plugin_status plugin_start(const void* parameter)
{
int button;
diff --git a/apps/plugins/mpegplayer/libmpeg2/idct_arm.S b/apps/plugins/mpegplayer/libmpeg2/idct_arm.S
index 97a87a8b59..90eb5031c7 100644
--- a/apps/plugins/mpegplayer/libmpeg2/idct_arm.S
+++ b/apps/plugins/mpegplayer/libmpeg2/idct_arm.S
@@ -43,8 +43,8 @@
ldrsh r7, [r0, #12] /* d2 */
ldrsh r8, [r0, #14] /* d3 */
orrs r9, r2, r3
- orreqs r9, r4, r5
- orreqs r9, r6, r7
+ orrseq r9, r4, r5
+ orrseq r9, r6, r7
cmpeq r8, #0
bne 2f
mov r1, r1, asl #15
@@ -320,7 +320,7 @@ mpeg2_idct_copy:
mpeg2_idct_add:
cmp r0, #129
mov r0, r1
- ldreqsh r1, [r0, #0]
+ ldrsheq r1, [r0, #0]
bne 1f
and r1, r1, #0x70
cmp r1, #0x40
diff --git a/apps/plugins/mpegplayer/libmpeg2/idct_armv6.S b/apps/plugins/mpegplayer/libmpeg2/idct_armv6.S
index dc53cbd7bd..a259721410 100644
--- a/apps/plugins/mpegplayer/libmpeg2/idct_armv6.S
+++ b/apps/plugins/mpegplayer/libmpeg2/idct_armv6.S
@@ -19,6 +19,7 @@
*
****************************************************************************/
+#include "config.h"
.global mpeg2_idct_copy
.type mpeg2_idct_copy, %function
@@ -228,7 +229,7 @@ mpeg2_idct_copy:
mpeg2_idct_add:
cmp r0, #129
mov r0, r1
- ldreqsh r1, [r0, #0]
+ ldrsheq r1, [r0, #0]
bne 1f
and r1, r1, #0x70
cmp r1, #0x40
@@ -260,7 +261,7 @@ mpeg2_idct_add:
strd r4, [r1] @ r4, r5
add r1, r1, r2
cmp r0, r3
- ldrlod r8, [r1] @ r8, r9
+ ldrdlo r8, [r1] @ r8, r9
blo 2b
ldmfd sp!, {r4-r11, pc}
@@ -291,7 +292,7 @@ mpeg2_idct_add:
strd r0, [r2] @ r0, r1
add r2, r2, r3
cmp r2, r12
- ldrlod r0, [r2] @ r0, r1
+ ldrdlo r0, [r2] @ r0, r1
blo 4b
ldmfd sp!, {r4, pc}
diff --git a/apps/plugins/mpegplayer/mpeg_misc.h b/apps/plugins/mpegplayer/mpeg_misc.h
index e04db0e19d..233b815493 100644
--- a/apps/plugins/mpegplayer/mpeg_misc.h
+++ b/apps/plugins/mpegplayer/mpeg_misc.h
@@ -53,12 +53,14 @@ enum state_enum
#define CMP_3_CONST(_a, _b) \
({ int _x; \
asm volatile ( \
+ BEGIN_ARM_ASM_SYNTAX_UNIFIED \
"ldrb %[x], [%[a], #0] \n" \
"eors %[x], %[x], %[b0] \n" \
- "ldreqb %[x], [%[a], #1] \n" \
- "eoreqs %[x], %[x], %[b1] \n" \
- "ldreqb %[x], [%[a], #2] \n" \
- "eoreqs %[x], %[x], %[b2] \n" \
+ "ldrbeq %[x], [%[a], #1] \n" \
+ "eorseq %[x], %[x], %[b1] \n" \
+ "ldrbeq %[x], [%[a], #2] \n" \
+ "eorseq %[x], %[x], %[b2] \n" \
+ END_ARM_ASM_SYNTAX_UNIFIED \
: [x]"=&r"(_x) \
: [a]"r"(_a), \
[b0]"i"(((_b) >> 24) & 0xff), \
@@ -70,14 +72,16 @@ enum state_enum
#define CMP_4_CONST(_a, _b) \
({ int _x; \
asm volatile ( \
+ BEGIN_ARM_ASM_SYNTAX_UNIFIED \
"ldrb %[x], [%[a], #0] \n" \
"eors %[x], %[x], %[b0] \n" \
- "ldreqb %[x], [%[a], #1] \n" \
- "eoreqs %[x], %[x], %[b1] \n" \
- "ldreqb %[x], [%[a], #2] \n" \
- "eoreqs %[x], %[x], %[b2] \n" \
- "ldreqb %[x], [%[a], #3] \n" \
- "eoreqs %[x], %[x], %[b3] \n" \
+ "ldrbeq %[x], [%[a], #1] \n" \
+ "eorseq %[x], %[x], %[b1] \n" \
+ "ldrbeq %[x], [%[a], #2] \n" \
+ "eorseq %[x], %[x], %[b2] \n" \
+ "ldrbeq %[x], [%[a], #3] \n" \
+ "eorseq %[x], %[x], %[b3] \n" \
+ END_ARM_ASM_SYNTAX_UNIFIED \
: [x]"=&r"(_x) \
: [a]"r"(_a), \
[b0]"i"(((_b) >> 24) & 0xff), \
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..b608aff789 100644
--- a/apps/plugins/open_plugins.c
+++ b/apps/plugins/open_plugins.c
@@ -87,14 +87,23 @@ 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)
{
rb->memset(&op_entry, 0, op_entry_sz);
op_entry.lang_id = -1;
- return ((selected_item >= 0) &&
+ return ((selected_item >= 0) && (fd >= 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)
@@ -188,17 +189,20 @@ static void op_entry_set_name(void)
static int op_entry_set_path(void)
{
int ret = 0;
- struct browse_context browse;
char tmp_buf[OPEN_PLUGIN_BUFSZ+1];
if (op_entry.path[0] == '\0')
rb->strcpy(op_entry.path, PLUGIN_DIR"/");
- rb->browse_context_init(&browse, SHOW_ALL, BROWSE_SELECTONLY, rb->str(LANG_ADD),
- Icon_Plugin, op_entry.path, NULL);
-
- browse.buf = tmp_buf;
- browse.bufsize = OPEN_PLUGIN_BUFSZ;
+ struct browse_context browse = {
+ .dirfilter = SHOW_ALL,
+ .flags = BROWSE_SELECTONLY | BROWSE_DIRFILTER,
+ .title = rb->str(LANG_ADD),
+ .icon = Icon_Plugin,
+ .root = op_entry.path,
+ .buf = tmp_buf,
+ .bufsize = sizeof(tmp_buf),
+ };
if (rb->rockbox_browse(&browse) == GO_TO_PREVIOUS)
{
@@ -212,7 +216,6 @@ static int op_entry_set_path(void)
static int op_entry_set_param_path(void)
{
int ret = 0;
- struct browse_context browse;
char tmp_buf[OPEN_PLUGIN_BUFSZ+1];
if (op_entry.param[0] == '\0')
@@ -220,11 +223,15 @@ static int op_entry_set_param_path(void)
else
rb->strcpy(tmp_buf, op_entry.param);
- rb->browse_context_init(&browse, SHOW_ALL, BROWSE_SELECTONLY, "",
- Icon_Plugin, tmp_buf, NULL);
-
- browse.buf = tmp_buf;
- browse.bufsize = OPEN_PLUGIN_BUFSZ;
+ struct browse_context browse = {
+ .dirfilter = SHOW_ALL,
+ .flags = BROWSE_SELECTONLY | BROWSE_DIRFILTER,
+ .title = rb->str(LANG_PARAMETER),
+ .icon = Icon_Plugin,
+ .root = tmp_buf,
+ .buf = tmp_buf,
+ .bufsize = sizeof(tmp_buf),
+ };
if (rb->rockbox_browse(&browse) == GO_TO_PREVIOUS)
{
@@ -405,6 +412,7 @@ static uint32_t op_entry_add_path(const char *key, const char *plugin, const cha
{
rb->close(fd_tmp);
rb->close(fd_dat);
+ fd_dat = -1;
rb->remove(OPEN_PLUGIN_DAT);
rb->rename(OPEN_PLUGIN_DAT ".tmp", OPEN_PLUGIN_DAT);
}
@@ -461,12 +469,12 @@ static void op_entry_remove(int selection)
static void op_entry_remove_empty(void)
{
bool resave = false;
- if (fd_dat && rb->lseek(fd_dat, 0, SEEK_SET) == 0)
+ if (fd_dat >= 0 && rb->lseek(fd_dat, 0, SEEK_SET) == 0)
{
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;
}
}
@@ -482,6 +490,7 @@ static void op_entry_remove_empty(void)
{
rb->close(fd_tmp);
rb->close(fd_dat);
+ fd_dat = -1;
rb->remove(OPEN_PLUGIN_DAT);
rb->rename(OPEN_PLUGIN_DAT ".tmp", OPEN_PLUGIN_DAT);
}
@@ -623,7 +632,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 +690,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 +848,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 +879,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)
@@ -892,6 +906,7 @@ reopen_datfile:
}
break;
case ACTION_STD_CANCEL:
+ case ACTION_STD_MENU:
{
selection = -2;
exit = true;
diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c
index ae84e14f7f..00d03fb03e 100644
--- a/apps/plugins/oscilloscope.c
+++ b/apps/plugins/oscilloscope.c
@@ -47,12 +47,14 @@
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
-#define OSCILLOSCOPE_QUIT (BUTTON_SELECT | BUTTON_MENU)
-#define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_PLAY)
+#define OSCILLOSCOPE_QUIT BUTTON_MENU
+#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_SELECT
+#define OSCILLOSCOPE_GRAPHMODE (BUTTON_SELECT | BUTTON_REL)
+#define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_SELECT
+#define OSCILLOSCOPE_DRAWMODE (BUTTON_SELECT | BUTTON_REPEAT)
#define OSCILLOSCOPE_ADVMODE (BUTTON_SELECT | BUTTON_RIGHT)
#define OSCILLOSCOPE_ORIENTATION (BUTTON_SELECT | BUTTON_LEFT)
-#define OSCILLOSCOPE_GRAPHMODE BUTTON_MENU
-#define OSCILLOSCOPE_PAUSE BUTTON_PLAY
+#define OSCILLOSCOPE_PAUSE BUTTON_PLAY | BUTTON_REL
#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT
#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT
#define OSCILLOSCOPE_VOL_UP BUTTON_SCROLL_FWD
@@ -1939,10 +1941,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 +1976,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/otp.c b/apps/plugins/otp.c
index 4d302563fb..356e1e5eb6 100644
--- a/apps/plugins/otp.c
+++ b/apps/plugins/otp.c
@@ -208,17 +208,16 @@ static int base32_encode(const uint8_t *data, int length, uint8_t *result,
static bool browse( char *dst, int dst_size, const char *start )
{
- struct browse_context browse;
-
- rb->browse_context_init(&browse, SHOW_ALL,
- BROWSE_SELECTONLY|BROWSE_NO_CONTEXT_MENU,
- NULL, NOICON, start, NULL);
-
- browse.buf = dst;
- browse.bufsize = dst_size;
+ struct browse_context browse = {
+ .dirfilter = SHOW_ALL,
+ .flags = BROWSE_SELECTONLY | BROWSE_NO_CONTEXT_MENU,
+ .icon = Icon_NOICON,
+ .root = start,
+ .buf = dst,
+ .bufsize = dst_size,
+ };
rb->rockbox_browse(&browse);
-
return (browse.flags & BROWSE_SELECTED);
}
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/pdbox/PDa/src/m_obj.c b/apps/plugins/pdbox/PDa/src/m_obj.c
index d06caa12fd..8d4947f202 100644
--- a/apps/plugins/pdbox/PDa/src/m_obj.c
+++ b/apps/plugins/pdbox/PDa/src/m_obj.c
@@ -272,6 +272,9 @@ static int outlet_eventno;
recursion */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
+#if __GNUC__ >= 13
+#pragma GCC diagnostic ignored "-Wdangling-pointer"
+#endif
void outlet_setstacklim(void)
{
char c;
diff --git a/apps/plugins/pdbox/pdbox.c b/apps/plugins/pdbox/pdbox.c
index f21913788b..08236bfeba 100644
--- a/apps/plugins/pdbox/pdbox.c
+++ b/apps/plugins/pdbox/pdbox.c
@@ -229,7 +229,7 @@ enum plugin_status plugin_start(const void* parameter)
0, /* FIXME Which flags? */
"PD core"
IF_PRIO(, PRIORITY_REALTIME)
- IF_COP(, COP));
+ IF_COP(, CPU));
gui_thread_id =
rb->create_thread(&gui_thread,
diff --git a/apps/plugins/pegbox.c b/apps/plugins/pegbox.c
index cb6361547d..8b88aad052 100644
--- a/apps/plugins/pegbox.c
+++ b/apps/plugins/pegbox.c
@@ -65,7 +65,7 @@
(CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
#define PEGBOX_SELECT (BUTTON_SELECT|BUTTON_RIGHT)
-#define PEGBOX_QUIT (BUTTON_SELECT|BUTTON_PLAY)
+#define PEGBOX_QUIT (BUTTON_SELECT|BUTTON_REPEAT)
#define PEGBOX_RESTART (BUTTON_SELECT|BUTTON_LEFT)
#define PEGBOX_LVL_UP (BUTTON_SELECT|BUTTON_MENU)
#define PEGBOX_UP BUTTON_MENU
@@ -74,7 +74,7 @@
#define PEGBOX_LEFT BUTTON_LEFT
#define SELECT_TEXT "SELECT+RIGHT"
-#define QUIT_TEXT "SELECT+PLAY"
+#define QUIT_TEXT "Long SELECT"
#define RESTART_TEXT "SELECT+LEFT"
#define LVL_UP_TEXT "SELECT+MENU"
#define LVL_DOWN_TEXT "-"
diff --git a/apps/plugins/periodic_table.c b/apps/plugins/periodic_table.c
index b77dd07432..2dd84baacd 100644
--- a/apps/plugins/periodic_table.c
+++ b/apps/plugins/periodic_table.c
@@ -619,7 +619,6 @@ enum plugin_status plugin_start(const void* parameter)
switch (button)
{
case PERIODIC_KEY_SELECT:
- break;
case PERIODIC_KEY_MENU:
return PLUGIN_OK;
break;
diff --git a/apps/plugins/pictureflow/pictureflow.c b/apps/plugins/pictureflow/pictureflow.c
index a2782b6a2b..b21faf1dd8 100644
--- a/apps/plugins/pictureflow/pictureflow.c
+++ b/apps/plugins/pictureflow/pictureflow.c
@@ -33,6 +33,7 @@
#include "lib/grey.h"
#include "lib/mylcd.h"
#include "lib/feature_wrappers.h"
+#include "lib/id3.h"
/******************************* Globals ***********************************/
static fb_data *lcd_fb;
@@ -44,6 +45,7 @@ static fb_data *lcd_fb;
#if PF_PLAYBACK_CAPABLE
#include "lib/playback_control.h"
+#include "lib/mul_id3.h"
#endif
#define PF_PREV ACTION_STD_PREV
@@ -151,8 +153,12 @@ 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_MENU, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU},
+ {PF_QUIT, BUTTON_MENU|BUTTON_REL, 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},
@@ -268,7 +274,6 @@ typedef fb_data pix_t;
/* some magic numbers for cache_version. */
#define CACHE_REBUILD 0
-#define CACHE_UPDATE 1
/* Error return values */
#define SUCCESS 0
@@ -306,6 +311,8 @@ struct pf_config_t
bool resize;
bool show_fps;
+
+ bool update_albumart;
};
struct pf_index_t {
@@ -511,6 +518,7 @@ static struct configdata config[] =
{ TYPE_ENUM, 0, 2, { .int_p = &pf_cfg.year_sort_order }, "year order",
year_sort_order_conf },
{ TYPE_BOOL, 0, 1, { .bool_p = &pf_cfg.show_year }, "show year", NULL },
+ { TYPE_BOOL, 0, 1, { .bool_p = &pf_cfg.update_albumart }, "update albumart", NULL }
};
#define CONFIG_NUM_ITEMS (sizeof(config) / sizeof(struct configdata))
@@ -532,6 +540,7 @@ static PFreal offsetX;
static PFreal offsetY;
static int number_of_slides;
static bool is_initial_slide = true;
+static bool show_tracks_while_browsing = false;
static struct pf_slide_cache pf_sldcache;
@@ -552,6 +561,8 @@ static struct pf_index_t pf_idx;
static struct pf_track_t pf_tracks;
+static struct mp3entry id3;
+
void reset_track_list(void);
static bool thread_is_running;
@@ -624,7 +635,7 @@ static inline void buf_ctx_unlock(void)
buf_ctx_locked = false;
}
-static bool check_database(bool prompt)
+static bool check_database(void)
{
bool needwarn = true;
int spin = 5;
@@ -642,9 +653,7 @@ static bool check_database(bool prompt)
needwarn = false;
rb->splash(0, ID2P(LANG_TAGCACHE_BUSY));
}
- else if (!prompt)
- return false;
- else if (rb->action_userabort(HZ/5))
+ else
return false;
rb->yield();
@@ -667,9 +676,10 @@ static bool confirm_quit(void)
return true;
}
-static void config_save(int cache_version)
+static void config_save(int cache_version, bool update_albumart)
{
pf_cfg.cache_version = cache_version;
+ pf_cfg.update_albumart = update_albumart;
configfile_save(CONFIG_FILE, config, CONFIG_NUM_ITEMS, CONFIG_VERSION);
}
@@ -684,12 +694,13 @@ static void config_set_defaults(struct pf_config_t *cfg)
cfg->last_album = 0;
cfg->backlight_mode = 0;
cfg->resize = true;
- cfg->cache_version = 0;
+ 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;
+ cfg->update_albumart = false;
}
static inline PFreal fmul(PFreal a, PFreal b)
@@ -959,6 +970,7 @@ const struct custom_format format_transposed = {
static const struct button_mapping* get_context_map(int context)
{
+ context &= ~CONTEXT_LOCKED;
return pf_contexts[context & ~CONTEXT_PLUGIN];
}
@@ -1923,17 +1935,10 @@ static int pf_tcs_retrieve_track_title(int string_index, int disc_num, int track
if (rb->strcmp(UNTAGGED, tcs.result) == 0)
{
/* show filename instead of <untaggged> */
- if (!rb->tagcache_retrieve(&tcs, tcs.idx_id, tag_filename,
+ if (!rb->tagcache_retrieve(&tcs, tcs.idx_id, tag_virt_basename,
file_name, MAX_PATH))
return 0;
track_title = file_name;
- if (track_title)
- {
- /* if filename remove the '/' */
- track_title = rb->strrchr(track_title, PATH_SEPCH);
- if (track_title)
- track_title++;
- }
}
if (!track_title)
@@ -2067,15 +2072,11 @@ static inline void free_borrowed_tracks(void)
static bool get_albumart_for_index_from_db(const int slide_index, char *buf,
int buflen)
{
- if ( slide_index == -1 )
- {
- rb->strlcpy( buf, EMPTY_SLIDE, buflen );
- }
+ bool ret;
if (tcs.valid || !rb->tagcache_search(&tcs, tag_filename))
return false;
- bool result;
/* find the first track of the album */
rb->tagcache_search_add_filter(&tcs, tag_album,
pf_idx.album_index[slide_index].seek);
@@ -2083,36 +2084,12 @@ static bool get_albumart_for_index_from_db(const int slide_index, char *buf,
rb->tagcache_search_add_filter(&tcs, tag_albumartist,
pf_idx.album_index[slide_index].artist_seek);
- if ( rb->tagcache_get_next(&tcs) ) {
- struct mp3entry id3;
- int fd;
+ ret = rb->tagcache_get_next(&tcs) &&
+ retrieve_id3(&id3, tcs.result) &&
+ search_albumart_files(&id3, ":", buf, buflen);
-#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
- if (rb->tagcache_fill_tags(&id3, tcs.result))
- {
- rb->strlcpy(id3.path, tcs.result, sizeof(id3.path));
- }
- else
-#endif
- {
- fd = rb->open(tcs.result, O_RDONLY);
- if (fd) {
- rb->get_metadata(&id3, fd, tcs.result);
- rb->close(fd);
- }
- }
-
- if ( search_albumart_files(&id3, ":", buf, buflen) )
- result = true;
- else
- result = false;
- }
- else {
- /* did not find a matching track */
- result = false;
- }
rb->tagcache_search_finish(&tcs);
- return result;
+ return ret;
}
/**
@@ -2209,6 +2186,9 @@ static unsigned int mfnv(char *str)
const unsigned int p = 16777619;
unsigned int hash = 0x811C9DC5; // 2166136261;
+ if (!str)
+ return 0;
+
while(*str)
hash = (hash ^ *str++) * p;
hash += hash << 13;
@@ -2250,8 +2230,6 @@ static bool incremental_albumart_cache(bool verbose)
unsigned int hash_artist, hash_album;
unsigned int format = FORMAT_NATIVE;
- bool update = (pf_cfg.cache_version == CACHE_UPDATE);
-
if (pf_cfg.resize)
format |= FORMAT_RESIZE|FORMAT_KEEP_ASPECT;
@@ -2263,8 +2241,6 @@ static bool incremental_albumart_cache(bool verbose)
aa_cache.inspected++;
if (aa_cache.idx >= pf_idx.album_ct) { aa_cache.idx = 0; } /* Rollover */
- if (!get_albumart_for_index_from_db(idx, aa_cache.file, sizeof(aa_cache.file)))
- goto aa_failure; //rb->strcpy(aa_cache.file, EMPTY_SLIDE_BMP);
hash_artist = mfnv(get_album_artist(idx));
hash_album = mfnv(get_album_name(idx));
@@ -2272,13 +2248,15 @@ static bool incremental_albumart_cache(bool verbose)
rb->snprintf(aa_cache.pfraw_file, sizeof(aa_cache.pfraw_file),
CACHE_PREFIX "/%x%x.pfraw", hash_album, hash_artist);
- if(rb->file_exists(aa_cache.pfraw_file)) {
- if(update) {
- aa_cache.slides++;
- goto aa_success;
- }
+ if(pf_cfg.update_albumart && rb->file_exists(aa_cache.pfraw_file)) {
+ aa_cache.slides++;
+ goto aa_success;
}
+ if (!get_albumart_for_index_from_db(idx, aa_cache.file, sizeof(aa_cache.file)))
+ goto aa_failure; //rb->strcpy(aa_cache.file, EMPTY_SLIDE_BMP);
+
+
aa_cache.input_bmp.data = aa_cache.buf;
aa_cache.input_bmp.width = DISPLAY_WIDTH;
aa_cache.input_bmp.height = DISPLAY_HEIGHT;
@@ -2316,6 +2294,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 */
@@ -3096,7 +3076,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
@@ -3169,19 +3149,19 @@ static inline void set_current_slide(const int slide_index)
{
int old_center_index = center_index;
step = 0;
- center_index = fbound(slide_index, 0, number_of_slides - 1);
+ center_index = fbound(0, slide_index, number_of_slides - 1);
if (old_center_index != center_index)
{
rb->queue_remove_from_head(&thread_q, EV_WAKEUP);
rb->queue_post(&thread_q, EV_WAKEUP, 0);
}
target = center_index;
- slide_frame = slide_index << 16;
+ slide_frame = center_index << 16;
reset_slides();
}
-static void interrupt_cover_out_animation(void);
+static void skip_animation_to_idle_state(void);
static bool sort_albums(int new_sorting, bool from_settings)
{
int i, album_idx, artist_idx;
@@ -3215,7 +3195,7 @@ static bool sort_albums(int new_sorting, bool from_settings)
if (pf_state == pf_show_tracks ||
pf_state == pf_cover_in ||
pf_state == pf_cover_out)
- interrupt_cover_out_animation();
+ skip_animation_to_idle_state();
else if (pf_state == pf_scrolling)
set_current_slide(target);
pf_state = pf_idle;
@@ -3225,6 +3205,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
@@ -3255,7 +3241,10 @@ static bool sort_albums(int new_sorting, bool from_settings)
if(!rb->strcmp(pf_idx.album_names + album_idx, current_album_name) &&
!rb->strcmp(pf_idx.artist_names + artist_idx, current_album_artist))
+ {
set_current_slide(i);
+ pf_cfg.last_album = i;
+ }
}
return true;
}
@@ -3269,6 +3258,8 @@ static void start_animation(void)
pf_state = pf_scrolling;
}
+static void update_scroll_animation(void);
+
/**
Go to the previous slide
*/
@@ -3282,6 +3273,8 @@ static void show_previous_slide(void)
} else if ( step > 0 ) {
target = center_index;
step = (target <= center_slide.slide_index) ? -1 : 1;
+ if (step < 0)
+ update_scroll_animation();
} else {
target = fmax(0, center_index - 2);
}
@@ -3301,6 +3294,8 @@ static void show_next_slide(void)
} else if ( step < 0 ) {
target = center_index;
step = (target < center_slide.slide_index) ? -1 : 1;
+ if (step > 0)
+ update_scroll_animation();
} else {
target = fmin(center_index + 2, number_of_slides - 1);
}
@@ -3477,16 +3472,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 skip_animation_to_show_tracks(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)
+ skip_animation_to_show_tracks();
+}
+
/**
Shows the settings menu
*/
@@ -3542,11 +3550,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);
@@ -3568,38 +3575,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:
@@ -3609,6 +3618,7 @@ static int settings_menu(void)
break;
/* fallthrough if changed, since cache needs to be rebuilt */
case 10:
+ pf_cfg.update_albumart = false;
pf_cfg.cache_version = CACHE_REBUILD;
rb->remove(EMPTY_SLIDE);
configfile_save(CONFIG_FILE, config,
@@ -3616,7 +3626,8 @@ static int settings_menu(void)
rb->splash(HZ, ID2P(LANG_CACHE_REBUILT_NEXT_RESTART));
break;
case 11:
- pf_cfg.cache_version = CACHE_UPDATE;
+ pf_cfg.update_albumart = true;
+ pf_cfg.cache_version = CACHE_REBUILD;
rb->remove(EMPTY_SLIDE);
configfile_save(CONFIG_FILE, config,
CONFIG_NUM_ITEMS, CONFIG_VERSION);
@@ -3642,45 +3653,67 @@ static int settings_menu(void)
Show the main menu
*/
enum {
+ PF_SHOW_TRACKS_WHILE_BROWSING,
+ PF_GOTO_LAST_ALBUM,
PF_GOTO_WPS,
#if PF_PLAYBACK_CAPABLE
- PF_MENU_CLEAR_PLAYLIST,
PF_MENU_PLAYBACK_CONTROL,
#endif
PF_MENU_SETTINGS,
- PF_MENU_RETURN,
PF_MENU_QUIT,
};
static int main_menu(void)
{
int selection = 0;
- int result;
+ int result, curr_album;
#if LCD_DEPTH > 1
rb->lcd_set_foreground(N_BRIGHT(255));
#endif
MENUITEM_STRINGLIST(main_menu, "PictureFlow Main Menu", NULL,
+ ID2P(LANG_SHOW_TRACKS_WHILE_BROWSING),
+ ID2P(LANG_GOTO_LAST_ALBUM),
ID2P(LANG_GOTO_WPS),
#if PF_PLAYBACK_CAPABLE
- ID2P(LANG_CLEAR_PLAYLIST),
ID2P(LANG_PLAYBACK_CONTROL),
#endif
ID2P(LANG_SETTINGS),
- ID2P(LANG_RETURN),
ID2P(LANG_MENU_QUIT));
while (1) {
switch (rb->do_menu(&main_menu,&selection, NULL, false)) {
+ case PF_SHOW_TRACKS_WHILE_BROWSING:
+ if (pf_state != pf_show_tracks)
+ {
+ if (pf_state == pf_scrolling)
+ set_current_slide(target);
+
+ skip_animation_to_show_tracks();
+ }
+ show_tracks_while_browsing = true;
+ return 0;
+ case PF_GOTO_LAST_ALBUM:
+ if (pf_state == pf_scrolling)
+ curr_album = target;
+ else
+ curr_album = center_index;
+
+ if (pf_state == pf_show_tracks)
+ free_borrowed_tracks();
+ if (pf_state == pf_show_tracks ||
+ pf_state == pf_cover_in ||
+ pf_state == pf_cover_out)
+ skip_animation_to_idle_state();
+
+ set_current_slide(pf_cfg.last_album);
+ pf_cfg.last_album = curr_album;
+
+ pf_state = pf_idle;
+ return 0;
case PF_GOTO_WPS: /* WPS */
return -2;
#if PF_PLAYBACK_CAPABLE
- case PF_MENU_CLEAR_PLAYLIST:
- if(rb->warn_on_pl_erase() && rb->playlist_remove_all_tracks(NULL) == 0) {
- rb->playlist_create(NULL, NULL);
- rb->splash(HZ*2, ID2P(LANG_PLAYLIST_CLEARED));
- }
- break;
case PF_MENU_PLAYBACK_CONTROL: /* Playback Control */
playback_control(NULL);
break;
@@ -3689,8 +3722,6 @@ static int main_menu(void)
result = settings_menu();
if ( result != 0 ) return result;
break;
- case PF_MENU_RETURN:
- return 0;
case PF_MENU_QUIT:
return -1;
@@ -3703,21 +3734,33 @@ static int main_menu(void)
}
}
+#define ZOOMIN_FRAME_COUNT 19
+#define ZOOMIN_FRAME_DIST -5
+#define ZOOMIN_FRAME_ANGLE 1
+#define ZOOMIN_FRAME_FADE 13
+
+#define ROTATE_FRAME_COUNT 15
+#define ROTATE_FRAME_ANGLE 16
+
+#define KEYFRAME_COUNT ZOOMIN_FRAME_COUNT + ROTATE_FRAME_COUNT
+
/**
Animation step for zooming into the current cover
*/
static void update_cover_in_animation(void)
{
cover_animation_keyframe++;
- if( cover_animation_keyframe < 20 ) {
- center_slide.distance-=5;
- center_slide.angle+=1;
- extra_fade += 13;
- }
- else if( cover_animation_keyframe < 35 ) {
- center_slide.angle+=16;
+
+ if(cover_animation_keyframe <= ZOOMIN_FRAME_COUNT)
+ {
+ center_slide.distance += ZOOMIN_FRAME_DIST;
+ center_slide.angle += ZOOMIN_FRAME_ANGLE;
+ extra_fade += ZOOMIN_FRAME_FADE;
}
- else {
+ else if(cover_animation_keyframe <= KEYFRAME_COUNT)
+ center_slide.angle += ROTATE_FRAME_ANGLE;
+ else
+ {
cover_animation_keyframe = 0;
pf_state = pf_show_tracks;
}
@@ -3729,36 +3772,40 @@ static void update_cover_in_animation(void)
static void update_cover_out_animation(void)
{
cover_animation_keyframe++;
- if( cover_animation_keyframe <= 15 ) {
- center_slide.angle-=16;
- }
- else if( cover_animation_keyframe < 35 ) {
- center_slide.distance+=5;
- center_slide.angle-=1;
- extra_fade -= 13;
+
+ if(cover_animation_keyframe <= ROTATE_FRAME_COUNT)
+ center_slide.angle -= ROTATE_FRAME_ANGLE;
+ else if(cover_animation_keyframe <= KEYFRAME_COUNT)
+ {
+ center_slide.distance -= ZOOMIN_FRAME_DIST;
+ center_slide.angle -= ZOOMIN_FRAME_ANGLE;
+ extra_fade -= ZOOMIN_FRAME_FADE;
}
- else {
+ else
+ {
cover_animation_keyframe = 0;
pf_state = pf_idle;
}
}
/**
- Skip steps for zooming into the current cover
+ Immediately show tracks and skip any animation frames
*/
-static void interrupt_cover_in_animation(void)
+static void skip_animation_to_show_tracks(void)
{
pf_state = pf_show_tracks;
cover_animation_keyframe = 0;
- extra_fade = 13 * 19;
- center_slide.distance = -5 * 19;
- center_slide.angle = 19 + (15 * 16);
+
+ extra_fade = ZOOMIN_FRAME_COUNT * ZOOMIN_FRAME_FADE;
+ center_slide.distance = ZOOMIN_FRAME_COUNT * ZOOMIN_FRAME_DIST;
+ center_slide.angle = (ZOOMIN_FRAME_COUNT * ZOOMIN_FRAME_ANGLE) +
+ (ROTATE_FRAME_COUNT * ROTATE_FRAME_ANGLE);
}
/**
- Skip steps for zooming out the current cover
+ Immediately transition to idle state and skip any animation frames
*/
-static void interrupt_cover_out_animation(void)
+static void skip_animation_to_idle_state(void)
{
pf_state = pf_idle;
cover_animation_keyframe = 0;
@@ -3767,21 +3814,12 @@ static void interrupt_cover_out_animation(void)
}
/**
- Stop zooming out the current cover and start zooming in
+ Change direction during cover in/out animation
*/
-static void revert_cover_out_animation(void)
+static void reverse_animation(void)
{
- pf_state = pf_cover_in;
- cover_animation_keyframe = 34 - cover_animation_keyframe;
-}
-
-/**
- Stop zooming into the current cover and start zooming out
-*/
-static void revert_cover_in_animation(void)
-{
- pf_state = pf_cover_out;
- cover_animation_keyframe = 34 - cover_animation_keyframe;
+ pf_state = pf_state == pf_cover_out ? pf_cover_in : pf_cover_out;
+ cover_animation_keyframe = KEYFRAME_COUNT - cover_animation_keyframe;
}
/**
@@ -3888,7 +3926,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)
{
@@ -3909,7 +3950,7 @@ static void show_track_list(void)
for (; track_i < pf_tracks.list_visible + pf_tracks.list_start; track_i++)
{
char *trackname = get_track_name(track_i);
- if ( track_i == pf_tracks.sel ) {
+ if (track_i == pf_tracks.sel && !show_tracks_while_browsing) {
if (pf_tracks.sel != pf_tracks.last_sel) {
set_scroll_line(trackname, PF_SCROLL_TRACK);
pf_tracks.last_sel = pf_tracks.sel;
@@ -3961,7 +4002,7 @@ static void select_next_album(void)
free_borrowed_tracks();
target = center_index + 1;
set_current_slide(target);
- interrupt_cover_in_animation();
+ skip_animation_to_show_tracks();
}
}
@@ -3971,13 +4012,50 @@ static void select_prev_album(void)
free_borrowed_tracks();
target = center_index - 1;
set_current_slide(target);
- interrupt_cover_in_animation();
+ skip_animation_to_show_tracks();
}
}
#if PF_PLAYBACK_CAPABLE
+static int show_id3_info(const char *selected_file)
+{
+ int i;
+ unsigned long last_tick;
+ const char *file_name;
+ bool is_multiple_tracks = insert_whole_album && pf_tracks.count > 1;
+
+ last_tick = *(rb->current_tick) + HZ/2;
+ rb->splash_progress_set_delay(HZ / 2); /* wait 1/2 sec before progress */
+ i = 0;
+ do {
+ file_name = i == 0 ? selected_file : get_track_filename(i);
+ if (rb->mp3info(&id3, file_name))
+ return 0;
-static bool playlist_insert(int position, bool queue, bool create_new)
+ if (is_multiple_tracks)
+ {
+ rb->splash_progress(i, pf_tracks.count,
+ "%s (%s)", rb->str(LANG_WAIT), rb->str(LANG_OFF_ABORT));
+ if (TIME_AFTER(*(rb->current_tick), last_tick + HZ/4))
+ {
+ if (rb->action_userabort(TIMEOUT_NOBLOCK))
+ return 0;
+ last_tick = *(rb->current_tick);
+ }
+
+ collect_id3(&id3, i == 0);
+ rb->yield();
+ }
+ } while (++i < pf_tracks.count && is_multiple_tracks);
+
+ if (is_multiple_tracks)
+ finalize_id3(&id3);
+
+ return rb->browse_id3(&id3, 0, 0, NULL, i) ? PLUGIN_USB_CONNECTED : 0;
+}
+
+
+static bool pf_current_playlist_insert(int position, bool queue, bool create_new)
{
if (position == PLAYLIST_REPLACE)
{
@@ -4008,11 +4086,52 @@ static bool playlist_insert(int position, bool queue, bool create_new)
return true;
}
+
+static int pf_add_to_playlist(const char* playlist, bool new_playlist)
+{
+ int fd;
+ int result = 0;
+
+ if (new_playlist)
+ fd = rb->open_utf8(playlist, O_CREAT|O_WRONLY|O_TRUNC);
+ else
+ fd = rb->open(playlist, O_CREAT|O_WRONLY|O_APPEND, 0666);
+
+ if(fd < 0)
+ return -1;
+
+ rb->reload_directory();
+
+ if (!insert_whole_album)
+ {
+ if (rb->fdprintf(fd, "%s\n", get_track_filename(pf_tracks.sel)) <= 0)
+ result = -1;
+ }
+ else
+ {
+ int i = 0;
+ do {
+ if (rb->fdprintf(fd, "%s\n", get_track_filename(i)) <= 0)
+ {
+ result = -1;
+ break;
+ }
+ rb->yield();
+ } while(++i < pf_tracks.count);
+ }
+ rb->close(fd);
+ return result;
+}
+
+
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)
{
@@ -4024,14 +4143,8 @@ static bool track_list_ready(void)
return true;
}
-/**
- Brings up "Current Playlist" menu with first
- track of selection.
- Onplay menu code calls back playlist_insert for
- adding all of the tracks.
-*/
-static void show_current_playlist_menu(void)
+static bool context_menu_ready(void)
{
#ifdef USEGSLIB
grey_show(false);
@@ -4043,16 +4156,26 @@ static void show_current_playlist_menu(void)
#ifdef USEGSLIB
grey_show(true);
#endif
- return;
+ return false;
}
- insert_whole_album = pf_state != pf_show_tracks;
+#if LCD_DEPTH > 1
+#ifdef USEGSLIB
+ rb->lcd_set_foreground(N_BRIGHT(0));
+ rb->lcd_set_background(N_BRIGHT(255));
+#endif
+#endif
+ insert_whole_album = (pf_state != pf_show_tracks) || show_tracks_while_browsing;
FOR_NB_SCREENS(i)
rb->viewportmanager_theme_enable(i, true, NULL);
- rb->onplay_show_playlist_menu(get_track_filename(pf_tracks.sel),
- &playlist_insert);
+
+ return true;
+}
+
+static void context_menu_cleanup(void)
+{
FOR_NB_SCREENS(i)
rb->viewportmanager_theme_undo(i, false);
- if (insert_whole_album)
+ if (pf_state != pf_show_tracks)
free_borrowed_tracks();
#ifdef USEGSLIB
grey_show(true);
@@ -4061,6 +4184,60 @@ static void show_current_playlist_menu(void)
}
+static int context_menu(void)
+{
+ char album_name[MAX_PATH];
+ char *file_name = get_track_filename(show_tracks_while_browsing ? 0 : pf_tracks.sel);
+ int attr = FILE_ATTR_AUDIO;
+
+ enum {
+ PF_CURRENT_PLAYLIST = 0,
+ PF_CATALOG,
+ PF_ID3_INFO
+ };
+ MENUITEM_STRINGLIST(context_menu, ID2P(LANG_ONPLAY_MENU_TITLE), NULL,
+ ID2P(LANG_PLAYING_NEXT),
+ ID2P(LANG_ADD_TO_PL),
+ ID2P(LANG_MENU_SHOW_ID3_INFO));
+
+ while (1) {
+ switch (rb->do_menu(&context_menu,
+ NULL, NULL, false)) {
+
+ case PF_CURRENT_PLAYLIST:
+ if (insert_whole_album && pf_tracks.count > 1)
+ {
+ attr = ATTR_DIRECTORY;
+ file_name = NULL;
+ }
+ rb->onplay_show_playlist_menu(file_name, attr, &pf_current_playlist_insert);
+ return 0;
+ case PF_CATALOG:
+ if (insert_whole_album)
+ {
+ /* add a leading slash so that catalog_add_to_a_playlist
+ later prefills the name when creating a new playlist */
+ rb->snprintf(album_name, MAX_PATH, "/%s", get_album_name(center_index));
+ rb->fix_path_part(album_name, 1, sizeof(album_name) - 2);
+ file_name = album_name;
+ attr = ATTR_DIRECTORY;
+ }
+
+ rb->onplay_show_playlist_cat_menu(file_name, attr, &pf_add_to_playlist);
+ return 0;
+ case PF_ID3_INFO:
+ return show_id3_info(file_name);
+ case MENU_ATTACHED_USB:
+ return PLUGIN_USB_CONNECTED;
+ default:
+ return 0;
+
+ }
+ }
+}
+
+
+
/*
* Puts selected album's tracks into a newly created playlist and starts playing
*/
@@ -4093,7 +4270,7 @@ static bool start_playback(bool return_to_WPS)
if (shuffle || center_slide.slide_index != old_playlist
|| (old_shuffle != shuffle))
{
- if (!playlist_insert(PLAYLIST_REPLACE, false, true))
+ if (!pf_current_playlist_insert(PLAYLIST_REPLACE, false, true))
{
#ifdef USEGSLIB
grey_show(true);
@@ -4104,7 +4281,7 @@ static bool start_playback(bool return_to_WPS)
start_index = rb->playlist_shuffle(*rb->current_tick, pf_tracks.sel);
}
rb->playlist_start(start_index, 0, 0);
- rb->playlist_get_current()->num_inserted_tracks = 0; /* prevent warn_on_pl_erase */
+ rb->playlist_set_modified(NULL, false);
old_shuffle = shuffle;
#ifdef USEGSLIB
if (!return_to_WPS)
@@ -4204,32 +4381,15 @@ static void draw_album_text(void)
static void set_initial_slide(const char* selected_file)
{
- if (selected_file == NULL)
+ if (selected_file)
+ set_current_slide(retrieve_id3(&id3, selected_file) ?
+ id3_get_index(&id3) :
+ pf_cfg.last_album);
+ else
set_current_slide(rb->audio_status() ?
id3_get_index(rb->audio_current_track()) :
pf_cfg.last_album);
- else
- {
- 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));
- else
-#endif
- {
- int fd = rb->open(selected_file, O_RDONLY);
- if (fd >= 0)
- {
- if (rb->get_metadata(&id3, fd, selected_file))
- set_current_slide(id3_get_index(&id3));
- else
- set_current_slide(pf_cfg.last_album);
- rb->close(fd);
- }
- else
- set_current_slide(pf_cfg.last_album);
- }
- }
+
}
/**
@@ -4264,14 +4424,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);
@@ -4319,13 +4476,13 @@ static int pictureflow_main(const char* selected_file)
pf_idx.buf_sz -= aa_bufsz;
if (!create_empty_slide(pf_cfg.cache_version != CACHE_VERSION)) {
- config_save(CACHE_REBUILD);
+ config_save(CACHE_REBUILD, false);
error_wait("Could not load the empty slide");
return PLUGIN_ERROR;
}
if ((pf_cfg.cache_version != CACHE_VERSION) && !create_albumart_cache()) {
- config_save(CACHE_REBUILD);
+ config_save(CACHE_REBUILD, false);
error_wait("Could not create album art cache");
} else if(aa_cache.inspected < pf_idx.album_ct) {
rb->splash(HZ * 2, "Updating album art cache in background");
@@ -4333,7 +4490,7 @@ static int pictureflow_main(const char* selected_file)
if (pf_cfg.cache_version != CACHE_VERSION)
{
- config_save(CACHE_VERSION);
+ config_save(CACHE_VERSION, pf_cfg.update_albumart);
}
rb->buflib_init(&buf_ctx, (void *)pf_idx.buf, pf_idx.buf_sz);
@@ -4407,6 +4564,7 @@ static int pictureflow_main(const char* selected_file)
instant_update = true;
break;
case pf_cover_out:
+ show_tracks_while_browsing = false;
update_cover_out_animation();
render_all_slides();
instant_update = true;
@@ -4415,8 +4573,14 @@ static int pictureflow_main(const char* selected_file)
show_track_list();
break;
case pf_idle:
+ show_tracks_while_browsing = false;
render_all_slides();
- incremental_albumart_cache(false);
+ if (aa_cache.inspected < pf_idx.album_ct)
+ {
+ buf_ctx_lock();
+ incremental_albumart_cache(false);
+ buf_ctx_unlock();
+ }
break;
}
@@ -4442,7 +4606,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
@@ -4471,15 +4636,17 @@ static int pictureflow_main(const char* selected_file)
case PF_WPS:
return PLUGIN_GOTO_WPS;
case PF_BACK:
- if ( pf_state == pf_show_tracks )
+ if (show_tracks_while_browsing)
+ show_tracks_while_browsing = false;
+ else if (pf_state == pf_show_tracks)
{
pf_state = pf_cover_out;
free_borrowed_tracks();
}
else if (pf_state == pf_cover_in)
- revert_cover_in_animation();
+ reverse_animation();
else if (pf_state == pf_cover_out)
- interrupt_cover_out_animation();
+ skip_animation_to_idle_state();
else if (pf_state == pf_idle || pf_state == pf_scrolling)
return PLUGIN_OK;
break;
@@ -4504,11 +4671,16 @@ static int pictureflow_main(const char* selected_file)
case PF_NEXT:
case PF_NEXT_REPEAT:
if ( pf_state == pf_show_tracks )
- select_next_track();
+ {
+ if (show_tracks_while_browsing)
+ select_next_album();
+ else
+ select_next_track();
+ }
else if (pf_state == pf_cover_in)
- interrupt_cover_in_animation();
+ skip_animation_to_show_tracks();
else if (pf_state == pf_cover_out)
- interrupt_cover_out_animation();
+ skip_animation_to_idle_state();
if ( pf_state == pf_idle || pf_state == pf_scrolling )
show_next_slide();
@@ -4517,11 +4689,16 @@ static int pictureflow_main(const char* selected_file)
case PF_PREV:
case PF_PREV_REPEAT:
if ( pf_state == pf_show_tracks )
- select_prev_track();
+ {
+ if (show_tracks_while_browsing)
+ select_prev_album();
+ else
+ select_prev_track();
+ }
else if (pf_state == pf_cover_in)
- interrupt_cover_in_animation();
+ skip_animation_to_show_tracks();
else if (pf_state == pf_cover_out)
- interrupt_cover_out_animation();
+ skip_animation_to_idle_state();
if ( pf_state == pf_idle || pf_state == pf_scrolling )
show_previous_slide();
@@ -4557,21 +4734,30 @@ static int pictureflow_main(const char* selected_file)
}
else if ( pf_state == pf_show_tracks )
select_prev_album();
+ else if (pf_state == pf_cover_in)
+ reverse_animation();
+ else if (pf_state == pf_cover_out)
+ skip_animation_to_idle_state();
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)
- interrupt_cover_out_animation();
+ }
+ else if (pf_state == pf_cover_out)
+ skip_animation_to_idle_state();
- show_current_playlist_menu();
+ if (context_menu_ready())
+ {
+ ret = context_menu();
+ context_menu_cleanup();
+ if ( ret != 0 ) return ret;
+ }
}
break;
#endif
@@ -4594,19 +4780,22 @@ static int pictureflow_main(const char* selected_file)
pf_state = pf_cover_in;
}
else if (pf_state == pf_cover_out)
- revert_cover_out_animation();
+ reverse_animation();
else if (pf_state == pf_cover_in)
- interrupt_cover_in_animation();
+ skip_animation_to_show_tracks();
+ else if (pf_state == pf_show_tracks)
+ {
+ if (show_tracks_while_browsing)
+ show_tracks_while_browsing = false;
#if PF_PLAYBACK_CAPABLE
- else if (pf_state == pf_show_tracks) {
- if(pf_cfg.auto_wps != 0) {
+ else if(pf_cfg.auto_wps != 0) {
if (start_playback(true))
return PLUGIN_GOTO_WPS;
}
else
start_playback(false);
- }
#endif
+ }
break;
default:
exit_on_usb(button);
@@ -4627,17 +4816,12 @@ enum plugin_status plugin_start(const void *parameter)
void * buf;
size_t buf_size;
- bool prompt = (parameter && (((char *) parameter)[0] == ACTIVITY_MAINMENU));
bool file_id3 = (parameter && (((char *) parameter)[0] == '/'));
- if (!check_database(prompt))
+ if (!check_database())
{
- if (prompt)
- return PLUGIN_OK;
- else
- error_wait("Please enable database");
-
- return PLUGIN_ERROR;
+ error_wait("Please enable database");
+ return PLUGIN_OK;
}
atexit(cleanup);
@@ -4677,7 +4861,10 @@ enum plugin_status plugin_start(const void *parameter)
ret = file_id3 ? pictureflow_main(file) : pictureflow_main(NULL);
if ( ret == PLUGIN_OK || ret == PLUGIN_GOTO_WPS) {
- pf_cfg.last_album = center_index;
+ if (pf_state == pf_scrolling)
+ pf_cfg.last_album = target;
+ else
+ pf_cfg.last_album = center_index;
if (configfile_save(CONFIG_FILE, config, CONFIG_NUM_ITEMS,
CONFIG_VERSION))
{
diff --git a/apps/plugins/pitch_detector.c b/apps/plugins/pitch_detector.c
index 4ae43b3236..e9b1fb11b0 100644
--- a/apps/plugins/pitch_detector.c
+++ b/apps/plugins/pitch_detector.c
@@ -1013,6 +1013,11 @@ static void record_and_get_pitch(void)
break;
case PLA_CANCEL:
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+ case PLA_UP:
+#endif
rb->pcm_stop_recording();
quit = main_menu();
if(!quit)
diff --git a/apps/plugins/plasma.c b/apps/plugins/plasma.c
index f944d3d775..cdb6e66569 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
@@ -268,6 +268,11 @@ int main(void)
switch(action)
{
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+ case PLA_UP:
+#endif
case PLA_EXIT:
case PLA_CANCEL:
return PLUGIN_OK;
@@ -277,7 +282,11 @@ int main(void)
case PLA_SCROLL_FWD:
case PLA_SCROLL_FWD_REPEAT:
#endif
+#if (CONFIG_KEYPAD != IPOD_1G2G_PAD) \
+ && (CONFIG_KEYPAD != IPOD_3G_PAD) \
+ && (CONFIG_KEYPAD != IPOD_4G_PAD)
case PLA_UP:
+#endif
case PLA_UP_REPEAT:
++plasma_frequency;
wave_table_generate();
@@ -321,10 +330,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 e5f00e307b..53af4c5bab 100644
--- a/apps/plugins/properties.c
+++ b/apps/plugins/properties.c
@@ -20,32 +20,47 @@
****************************************************************************/
#include "plugin.h"
+#ifdef HAVE_TAGCACHE
+#include "lib/mul_id3.h"
+#endif
+
#if !defined(ARRAY_SIZE)
#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,
+ PROPS_MUL_ID3,
PROPS_DIR
};
static int props_type = PROPS_FILE;
static struct mp3entry id3;
+#ifdef HAVE_TAGCACHE
+static int mul_id3_count;
+#endif
-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[] =
@@ -111,14 +126,8 @@ static bool file_properties(const char* selected_file)
rb->snprintf(str_time, sizeof str_time, "%02d:%02d:%02d",
tm.tm_hour, tm.tm_min, tm.tm_sec);
- int fd = rb->open(selected_file, O_RDONLY);
- if (fd >= 0)
- {
- if (rb->get_metadata(&id3, fd, selected_file))
- props_type = PROPS_ID3;
-
- rb->close(fd);
- }
+ if (!rb->mp3info(&id3, selected_file))
+ props_type = PROPS_ID3;
found = true;
break;
}
@@ -128,15 +137,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 +148,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 +161,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 +170,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 +203,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 +226,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 +257,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 +297,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,33 +309,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) 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)
@@ -344,76 +362,95 @@ 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;
+}
- if(!found)
- {
- /* weird: we couldn't find the entry. This Should Never Happen (TM) */
- rb->splashf(0, "File/Dir not found: %s", file);
- rb->action_userabort(TIMEOUT_BLOCK);
- return PLUGIN_OK;
- }
+#ifdef HAVE_TAGCACHE
+bool mul_id3_add(const char *file_name)
+{
+ if (rb->mp3info(&id3, file_name))
+ return false;
- /* get the info depending on its_a_dir */
- if(!(props_type == PROPS_DIR ? dir_properties(file, &dps) : file_properties(file)))
+ collect_id3(&id3, mul_id3_count == 0);
+ mul_id3_count++;
+
+ return true;
+}
+#endif
+
+enum plugin_status plugin_start(const void* parameter)
+{
+ static struct dir_stats stats =
{
- /* something went wrong (to do: tell user what it was (nesting,...) */
- rb->splash(0, ID2P(LANG_PROPERTIES_FAIL));
- rb->action_userabort(TIMEOUT_BLOCK);
- return PLUGIN_OK;
- }
+ .len = MAX_PATH,
+ .dir_count = 0,
+ .file_count = 0,
+ .byte_count = 0,
+ };
- FOR_NB_SCREENS(i)
- rb->viewportmanager_theme_enable(i, true, NULL);
+ const char *file = parameter;
+ if(!parameter)
+ return PLUGIN_ERROR;
+
+#ifdef HAVE_TOUCHSCREEN
+ rb->touchscreen_set_mode(rb->global_settings->touch_mode);
+#endif
- if (props_type == PROPS_ID3)
- usb = rb->browse_id3(&id3, 0, 0);
+#ifdef HAVE_TAGCACHE
+ if (!rb->strcmp(file, MAKE_ACT_STR(ACTIVITY_DATABASEBROWSER))) /* db table selected */
+ {
+ props_type = PROPS_MUL_ID3;
+ mul_id3_count = 0;
+
+ if (!rb->tagtree_subentries_do_action(&mul_id3_add) || mul_id3_count == 0)
+ return PLUGIN_ERROR;
+ else if (mul_id3_count > 1) /* otherwise, the retrieved id3 can be used as-is */
+ finalize_id3(&id3);
+ }
else
+#endif
+ if (file[0] == '/') /* single track selected */
{
- 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)
+ 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(!determine_file_or_dir())
{
- 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;
- }
+ /* weird: we couldn't find the entry. This Should Never Happen (TM) */
+ rb->splashf(0, "File/Dir not found: %s", file);
+ rb->action_userabort(TIMEOUT_BLOCK);
+ return PLUGIN_OK;
+ }
+
+ /* get the info depending on its_a_dir */
+ 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));
+ rb->action_userabort(TIMEOUT_BLOCK);
+ return PLUGIN_OK;
}
}
+ else
+ return PLUGIN_ERROR;
+
+ FOR_NB_SCREENS(i)
+ rb->viewportmanager_theme_enable(i, true, NULL);
+
+ bool usb = props_type == PROPS_ID3 ? rb->browse_id3(&id3, 0, 0, &tm, 1) :
+#ifdef HAVE_TAGCACHE
+ props_type == PROPS_MUL_ID3 ? rb->browse_id3(&id3, 0, 0, NULL, mul_id3_count) :
+#endif
+ 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..a89cc658cc 100644
--- a/apps/plugins/rb_info.c
+++ b/apps/plugins/rb_info.c
@@ -335,6 +335,17 @@ static int list_voice_cb(int list_index, void* data)
rb->talk_spell(name, true);
}
}
+ else if (data == MENU_ID(M_TESTPUT))
+ {
+ char buf[64];
+ const char* name = printcell_get_column_text(printcell_get_column_selected(),
+ buf, sizeof(buf));
+ long id = P2ID((const unsigned char *)name);
+ if(id>=0)
+ rb->talk_id(id, true);
+ else
+ rb->talk_spell(name, true);
+ }
else
{
char buf[64];
@@ -354,12 +365,12 @@ int menu_action_cb(int *action, int selected_item, bool* exit, struct gui_syncli
{
if (*action == ACTION_STD_OK)
{
- printcell_increment_column(lists, 1, true);
+ printcell_increment_column(1, true);
*action = ACTION_NONE;
}
else if (*action == ACTION_STD_CANCEL)
{
- if (printcell_increment_column(lists, -1, true) != testput_cols - 1)
+ if (printcell_increment_column(-1, true) != testput_cols - 1)
{
*action = ACTION_NONE;
}
@@ -368,7 +379,8 @@ int menu_action_cb(int *action, int selected_item, bool* exit, struct gui_syncli
{
char buf[PRINTCELL_MAXLINELEN];
char* bufp = buf;
- bufp = printcell_get_selected_column_text(lists, bufp, PRINTCELL_MAXLINELEN);
+ int selcol = printcell_get_column_selected();
+ bufp = printcell_get_column_text(selcol, bufp, PRINTCELL_MAXLINELEN);
rb->splashf(HZ * 2, "Item: %s", bufp);
}
}
@@ -428,20 +440,13 @@ 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 */
- bool showlinesep = (rb->global_settings->list_separator_height < 0);
-#else
- bool showlinesep = (rb->global_settings->cursor_style == 0);
-#endif
- printcell_enable(lists, true, showlinesep);
+ printcell_enable(true);
//lists->callback_draw_item = test_listdraw_fn;
}
else
{
- printcell_enable(lists, false, false);
+ printcell_enable(false);
synclist_set(cur->menuid, 1, cur->items, 1);
}
rb->gui_synclist_draw(lists);
@@ -473,9 +478,8 @@ 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);
+ printcell_enable(false);
}
if (lists->data != MENU_ID(M_ROOT))
{
@@ -507,7 +511,8 @@ static void synclist_set(char* menu_id, int selected_item, int items, int sel_si
menu_id, false, sel_size, NULL);
if (menu_id == MENU_ID(M_TESTPUT))
{
- testput_cols = printcell_set_columns(&lists, TESTPUT_HEADER, Icon_Rockbox);
+ testput_cols = printcell_set_columns(&lists, NULL,
+ TESTPUT_HEADER, Icon_Rockbox);
}
else
{
@@ -516,7 +521,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,11 +564,11 @@ 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);
}
}
-
+ printcell_enable(false);
return ret;
}
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/robotfindskitten.c b/apps/plugins/robotfindskitten.c
index 4f228423b6..31c419e33d 100644
--- a/apps/plugins/robotfindskitten.c
+++ b/apps/plugins/robotfindskitten.c
@@ -469,7 +469,13 @@ static char* messages[] =
#define RFK_VERSION "v1.4142135.406"
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+# define RFK_QUIT PLA_SELECT_REPEAT
+#else
# define RFK_QUIT PLA_CANCEL
+#endif
# define RFK_RIGHT PLA_RIGHT
# define RFK_LEFT PLA_LEFT
# define RFK_UP PLA_UP
diff --git a/apps/plugins/rockblox.c b/apps/plugins/rockblox.c
index 927710b37b..a0105a1ffb 100644
--- a/apps/plugins/rockblox.c
+++ b/apps/plugins/rockblox.c
@@ -33,7 +33,7 @@
(CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
-#define ROCKBLOX_OFF (BUTTON_MENU | BUTTON_SELECT)
+#define ROCKBLOX_OFF (BUTTON_SELECT | BUTTON_REPEAT)
#define ROCKBLOX_ROTATE_CCW BUTTON_SCROLL_BACK
#define ROCKBLOX_ROTATE_CCW2 (BUTTON_MENU | BUTTON_REL)
#define ROCKBLOX_ROTATE_CW BUTTON_SCROLL_FWD
@@ -41,6 +41,7 @@
#define ROCKBLOX_RIGHT BUTTON_RIGHT
#define ROCKBLOX_DOWN BUTTON_PLAY
#define ROCKBLOX_RESTART (BUTTON_SELECT | BUTTON_PLAY)
+#define ROCKBLOX_DROP_PRE BUTTON_SELECT
#define ROCKBLOX_DROP (BUTTON_SELECT | BUTTON_REL)
#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
@@ -1498,16 +1499,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 +1675,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 +1725,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/rockblox1d.c b/apps/plugins/rockblox1d.c
index 6a2b013c44..6d535bbcd7 100644
--- a/apps/plugins/rockblox1d.c
+++ b/apps/plugins/rockblox1d.c
@@ -28,7 +28,14 @@ static const struct button_mapping *plugin_contexts[] = { pla_main_ctx };
#define ONEDROCKBLOX_DOWN PLA_DOWN
#define ONEDROCKBLOX_DOWN_REPEAT PLA_DOWN_REPEAT
#define ONEDROCKBLOX_QUIT PLA_EXIT
+
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define ONEDROCKBLOX_QUIT2 PLA_UP
+#else
#define ONEDROCKBLOX_QUIT2 PLA_CANCEL
+#endif
#define mrand(max) (short)(rb->rand()%max)
diff --git a/apps/plugins/rockboy/menu.c b/apps/plugins/rockboy/menu.c
index 6fafdc11a6..7fd7aabdc8 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;
}
@@ -430,7 +428,7 @@ static void do_opt_menu(void)
options.dirty=1; /* Assume that the settings have been changed */
struct viewport *parentvp = NULL;
- const struct settings_list* vol = rb->find_setting(&rb->global_settings->volume, NULL);
+ const struct settings_list* vol = rb->find_setting(&rb->global_settings->volume);
while(!done)
{
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..c4c7842fe0 100644
--- a/apps/plugins/rocklife.c
+++ b/apps/plugins/rocklife.c
@@ -70,7 +70,13 @@
#define ROCKLIFE_INIT PLA_DOWN
#define ROCKLIFE_NEXT PLA_RIGHT
#define ROCKLIFE_NEXT_REP PLA_RIGHT_REPEAT
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define ROCKLIFE_QUIT PLA_UP
+#else
#define ROCKLIFE_QUIT PLA_CANCEL
+#endif
#define ROCKLIFE_STATUS PLA_LEFT
#define PATTERN_RANDOM 0
@@ -474,9 +480,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 +585,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/rockpaint.c b/apps/plugins/rockpaint.c
index 09fa2c8c5f..cba1701eb6 100644
--- a/apps/plugins/rockpaint.c
+++ b/apps/plugins/rockpaint.c
@@ -1084,15 +1084,15 @@ static bool callback_show_item(char *name, int attr, struct tree_context *tc)
static bool browse( char *dst, int dst_size, const char *start )
{
- struct browse_context browse;
-
- rb->browse_context_init(&browse, SHOW_ALL,
- BROWSE_SELECTONLY|BROWSE_NO_CONTEXT_MENU,
- NULL, NOICON, start, NULL);
-
- browse.callback_show_item = callback_show_item;
- browse.buf = dst;
- browse.bufsize = dst_size;
+ struct browse_context browse = {
+ .dirfilter = SHOW_ALL,
+ .flags = BROWSE_SELECTONLY | BROWSE_NO_CONTEXT_MENU,
+ .icon = Icon_NOICON,
+ .root = start,
+ .buf = dst,
+ .bufsize = dst_size,
+ .callback_show_item = callback_show_item,
+ };
rb->rockbox_browse(&browse);
diff --git a/apps/plugins/sdl/SDL_mixer/timidity/playmidi.c b/apps/plugins/sdl/SDL_mixer/timidity/playmidi.c
index 1638732dc5..38f7109b13 100644
--- a/apps/plugins/sdl/SDL_mixer/timidity/playmidi.c
+++ b/apps/plugins/sdl/SDL_mixer/timidity/playmidi.c
@@ -21,6 +21,8 @@
#include "tables.h"
+/* ROCKBOX HACK: avoid a conflict with adjust_volume() in misc.h */
+#define adjust_volume adjust_midi_volume
static int opt_expression_curve = 2;
static int opt_volume_curve = 2;
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/sdl/src/audio/rockbox/SDL_rockboxaudio.c b/apps/plugins/sdl/src/audio/rockbox/SDL_rockboxaudio.c
index cb72687d48..ac268b4a19 100644
--- a/apps/plugins/sdl/src/audio/rockbox/SDL_rockboxaudio.c
+++ b/apps/plugins/sdl/src/audio/rockbox/SDL_rockboxaudio.c
@@ -132,38 +132,42 @@ static void ROCKBOXAUD_WaitAudio(_THIS)
}
/* when this is called, SDL wants us to play the samples in mixbuf */
-static void ROCKBOXAUD_PlayAudio(_THIS)
+static void
+ROCKBOXAUD_PlayAudio(_THIS)
{
/* There are two cases in which we should be called:
* - There is an empty buffer (marked with status = 0)
* - There are more than two buffers marked as playing, meaning at least one is stale.
*/
- int idx = -1;
/* Find the next empty or stale buffer and fill. */
- for(int i = 1; i < this->hidden->n_buffers; ++i)
+ for(int i = 1; i <= this->hidden->n_buffers; ++i)
{
- idx = (this->hidden->current_playing + i) % this->hidden->n_buffers;
+ int idx = (this->hidden->current_playing + i) % this->hidden->n_buffers;
/* Empty or stale. */
if(this->hidden->status[idx] == 0 ||
- this->hidden->status[idx] == 2)
- break;
- }
- if(idx < 0)
- return;
+ this->hidden->status[idx] == 2) {
+
+ LOGF("found empty buffer: %d (status: %d)", idx, this->hidden->status[idx]);
+
+ /* probably premature optimization here */
+ char *dst = (char*)this->hidden->rb_buf[idx], *src = this->hidden->mixbuf;
+ int size = this->spec.size / 2;
+ memcpy(dst, src, size);
- /* probably premature optimization here */
- char *dst = (char*)this->hidden->rb_buf[idx], *src = this->hidden->mixbuf;
- int size = this->hidden->mixlen / 2;
- memcpy(dst, src, size);
+ this->hidden->status[idx] = 1;
+ rb->yield();
- this->hidden->status[idx] = 1;
- rb->yield();
+ memcpy(dst + size, src + size, this->spec.size - size);
- memcpy(dst + size, src + size, this->hidden->mixlen - size);
+ LOGF("filled buffer %d (status %d %d %d %d)", idx, this->hidden->status[0], this->hidden->status[1], this->hidden->status[2], this->hidden->status[3]);
+
+ return;
+ }
+ }
- //LOGF("filled buffer %d (status %d %d %d)", idx, this->hidden->status[0], this->hidden->status[1], this->hidden->status[2]);
+ LOGF("WARNING: PlayDevice could not find buffer to fill; DROPPING SAMPLES!");
}
static SDL_AudioDevice *ROCKBOXAUD_CreateDevice(int devindex)
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/sliding_puzzle.c b/apps/plugins/sliding_puzzle.c
index a34cb77669..33d2bb68f6 100644
--- a/apps/plugins/sliding_puzzle.c
+++ b/apps/plugins/sliding_puzzle.c
@@ -36,7 +36,7 @@
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
(CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
-#define PUZZLE_QUIT (BUTTON_SELECT | BUTTON_MENU)
+#define PUZZLE_QUIT (BUTTON_SELECT | BUTTON_REPEAT)
#define PUZZLE_LEFT BUTTON_LEFT
#define PUZZLE_RIGHT BUTTON_RIGHT
#define PUZZLE_UP BUTTON_MENU
@@ -468,8 +468,8 @@ static const char * initial_bmp_path=NULL;
static const char * get_albumart_bmp_path(void)
{
struct mp3entry* track = rb->audio_current_track();
-
- if (!track || !track->path || track->path[0] == '\0')
+ /* Note rb->audio_current_track->path should never be null */
+ if (!track || track->path[0] == '\0')
return NULL;
if (!rb->search_albumart_files(track, "", albumart_path, MAX_PATH ) )
@@ -848,7 +848,7 @@ enum plugin_status plugin_start(
#if (CONFIG_KEYPAD == IPOD_4G_PAD) || \
(CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
- rb->lcd_putsxy(0, 18, "[S-MENU] to stop");
+ rb->lcd_putsxy(0, 18, "Long [SELECT] to stop");
rb->lcd_putsxy(0, 28, "[S-LEFT] shuffle");
rb->lcd_putsxy(0, 38, "[S-RIGHT] change pic");
#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
diff --git a/apps/plugins/snake.c b/apps/plugins/snake.c
index 25c89b264b..359077c9fa 100644
--- a/apps/plugins/snake.c
+++ b/apps/plugins/snake.c
@@ -55,12 +55,12 @@ dir is the current direction of the snake - 0=up, 1=right, 2=down, 3=left;
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
(CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
-#define SNAKE_QUIT (BUTTON_SELECT|BUTTON_MENU)
+#define SNAKE_QUIT (BUTTON_SELECT|BUTTON_REPEAT)
#define SNAKE_LEFT BUTTON_LEFT
#define SNAKE_RIGHT BUTTON_RIGHT
#define SNAKE_UP BUTTON_MENU
#define SNAKE_DOWN BUTTON_PLAY
-#define SNAKE_PLAYPAUSE BUTTON_SELECT
+#define SNAKE_PLAYPAUSE (BUTTON_SELECT|BUTTON_REL)
#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
#define SNAKE_QUIT BUTTON_POWER
diff --git a/apps/plugins/snake2.c b/apps/plugins/snake2.c
index 094fd854eb..7a43b235b7 100644
--- a/apps/plugins/snake2.c
+++ b/apps/plugins/snake2.c
@@ -181,8 +181,8 @@ Head and Tail are stored
#define SNAKE2_RIGHT BUTTON_RIGHT
#define SNAKE2_UP BUTTON_MENU
#define SNAKE2_DOWN BUTTON_PLAY
-#define SNAKE2_QUIT (BUTTON_SELECT | BUTTON_MENU)
-#define SNAKE2_PLAYPAUSE BUTTON_SELECT
+#define SNAKE2_QUIT (BUTTON_SELECT | BUTTON_REPEAT)
+#define SNAKE2_PLAYPAUSE (BUTTON_SELECT | BUTTON_REL)
#define SNAKE2_PLAYPAUSE_TEXT "Select"
#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
diff --git a/apps/plugins/snow.c b/apps/plugins/snow.c
index 10b41c972b..c7d7ad31d8 100644
--- a/apps/plugins/snow.c
+++ b/apps/plugins/snow.c
@@ -30,8 +30,14 @@ static const struct button_mapping *plugin_contexts[] = { pla_main_ctx };
/* PLA definitions */
#define SNOW_QUIT PLA_EXIT
-#define SNOW_QUIT2 PLA_CANCEL
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define SNOW_QUIT2 PLA_UP
+#else
+#define SNOW_QUIT2 PLA_CANCEL
+#endif
static short particles[NUM_PARTICLES][2];
#if LCD_WIDTH >= 160
diff --git a/apps/plugins/sokoban.c b/apps/plugins/sokoban.c
index 247663a5c2..bf61db7d88 100644
--- a/apps/plugins/sokoban.c
+++ b/apps/plugins/sokoban.c
@@ -125,7 +125,7 @@
#define SOKOBAN_RIGHT BUTTON_RIGHT
#define SOKOBAN_UP BUTTON_MENU
#define SOKOBAN_DOWN BUTTON_PLAY
-#define SOKOBAN_MENU (BUTTON_SELECT | BUTTON_MENU)
+#define SOKOBAN_MENU (BUTTON_SELECT | BUTTON_REPEAT)
#define SOKOBAN_UNDO_PRE BUTTON_SELECT
#define SOKOBAN_UNDO (BUTTON_SELECT | BUTTON_REL)
#define SOKOBAN_REDO (BUTTON_SELECT | BUTTON_PLAY)
diff --git a/apps/plugins/solitaire.c b/apps/plugins/solitaire.c
index ebc042f6db..874d872d95 100644
--- a/apps/plugins/solitaire.c
+++ b/apps/plugins/solitaire.c
@@ -56,7 +56,7 @@
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
-# define SOL_QUIT (BUTTON_SELECT | BUTTON_MENU)
+# define SOL_QUIT (BUTTON_SELECT | BUTTON_REPEAT)
# define SOL_UP BUTTON_SCROLL_BACK
# define SOL_DOWN BUTTON_SCROLL_FWD
# define SOL_LEFT_PRE BUTTON_LEFT
diff --git a/apps/plugins/spacerocks.c b/apps/plugins/spacerocks.c
index 8203fad612..36729f8453 100644
--- a/apps/plugins/spacerocks.c
+++ b/apps/plugins/spacerocks.c
@@ -51,10 +51,10 @@
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
-#define AST_PAUSE (BUTTON_SELECT | BUTTON_PLAY)
-#define AST_QUIT (BUTTON_SELECT | BUTTON_MENU)
-#define AST_THRUST BUTTON_MENU
-#define AST_HYPERSPACE BUTTON_PLAY
+#define AST_PAUSE BUTTON_PLAY
+#define AST_QUIT BUTTON_MENU
+#define AST_THRUST BUTTON_RIGHT
+#define AST_HYPERSPACE BUTTON_LEFT
#define AST_LEFT BUTTON_SCROLL_BACK
#define AST_RIGHT BUTTON_SCROLL_FWD
#define AST_FIRE BUTTON_SELECT
@@ -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..7a9ab61e7c 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);
@@ -483,16 +482,19 @@ static void load_font(void)
static void font_menu(void)
{
/* taken from text_viewer */
- struct browse_context browse;
char font[MAX_PATH], name[MAX_FILENAME+10];
-
rb->snprintf(name, sizeof(name), "%s.fnt", rb->global_settings->font_file);
- rb->browse_context_init(&browse, SHOW_FONT,
- BROWSE_SELECTONLY|BROWSE_NO_CONTEXT_MENU,
- "Font", Icon_Menu_setting, FONT_DIR, name);
- browse.buf = font;
- browse.bufsize = sizeof(font);
+ struct browse_context browse = {
+ .dirfilter = SHOW_FONT,
+ .flags = BROWSE_SELECTONLY | BROWSE_NO_CONTEXT_MENU,
+ .title = rb->str(LANG_CUSTOM_FONT),
+ .icon = Icon_Menu_setting,
+ .root = FONT_DIR,
+ .selected = name,
+ .buf = font,
+ .bufsize = sizeof(font),
+ };
rb->rockbox_browse(&browse);
diff --git a/apps/plugins/star.c b/apps/plugins/star.c
index 874afc1cf1..59cefa2c15 100644
--- a/apps/plugins/star.c
+++ b/apps/plugins/star.c
@@ -80,7 +80,7 @@
(CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
-#define STAR_QUIT (BUTTON_SELECT | BUTTON_MENU)
+#define STAR_QUIT (BUTTON_SELECT | BUTTON_REPEAT)
#define STAR_LEFT BUTTON_LEFT
#define STAR_RIGHT BUTTON_RIGHT
#define STAR_UP BUTTON_MENU
@@ -91,7 +91,7 @@
#define STAR_LEVEL_DOWN (BUTTON_SELECT | BUTTON_LEFT)
#define STAR_LEVEL_REPEAT (BUTTON_SELECT | BUTTON_PLAY)
#define STAR_TOGGLE_CONTROL_NAME "SELECT"
-#define STAR_QUIT_NAME "S + MENU"
+#define STAR_QUIT_NAME "Long SELECT"
#define STAR_LEVEL_UP_NAME "S >"
#define STAR_LEVEL_DOWN_NAME "S <"
#define STAR_LEVEL_REPEAT_NAME "S + PLAY"
diff --git a/apps/plugins/starfield.c b/apps/plugins/starfield.c
index 7fc400d0ee..239b7c1396 100644
--- a/apps/plugins/starfield.c
+++ b/apps/plugins/starfield.c
@@ -27,11 +27,21 @@ static const struct button_mapping *plugin_contexts[] = { pla_main_ctx };
/* Key assignement */
#define STARFIELD_QUIT PLA_EXIT
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define STARFIELD_QUIT2 PLA_UP
+#define STARFIELD_INCREASE_ZMOVE PLA_SCROLL_FWD
+#define STARFIELD_INCREASE_ZMOVE_REPEAT PLA_SCROLL_FWD_REPEAT
+#define STARFIELD_DECREASE_ZMOVE PLA_SCROLL_BACK
+#define STARFIELD_DECREASE_ZMOVE_REPEAT PLA_SCROLL_BACK_REPEAT
+#else
#define STARFIELD_QUIT2 PLA_CANCEL
#define STARFIELD_INCREASE_ZMOVE PLA_UP
#define STARFIELD_INCREASE_ZMOVE_REPEAT PLA_UP_REPEAT
#define STARFIELD_DECREASE_ZMOVE PLA_DOWN
#define STARFIELD_DECREASE_ZMOVE_REPEAT PLA_DOWN_REPEAT
+#endif
#define STARFIELD_INCREASE_NB_STARS PLA_RIGHT
#define STARFIELD_INCREASE_NB_STARS_REPEAT PLA_RIGHT_REPEAT
#define STARFIELD_DECREASE_NB_STARS PLA_LEFT
@@ -324,14 +334,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/stats.c b/apps/plugins/stats.c
index 19ccd9f452..b48259a0e4 100644
--- a/apps/plugins/stats.c
+++ b/apps/plugins/stats.c
@@ -29,7 +29,15 @@ static bool cancel;
/* we use PLA */
#define STATS_STOP PLA_EXIT
+
+#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define STATS_STOP2 PLA_UP
+#else
#define STATS_STOP2 PLA_CANCEL
+#endif
+
/* this set the context to use with PLA */
static const struct button_mapping *plugin_contexts[] = { pla_main_ctx };
@@ -149,7 +157,7 @@ static void traversedir(char* location, char* name)
lasttick = *rb->current_tick;
button = pluginlib_getaction(TIMEOUT_NOBLOCK, plugin_contexts,
ARRAYLEN(plugin_contexts));
- if (button == STATS_STOP) {
+ if (button == STATS_STOP || button == STATS_STOP2) {
cancel = true;
break;
}
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_usb.c b/apps/plugins/test_usb.c
new file mode 100644
index 0000000000..28ef8f7e5f
--- /dev/null
+++ b/apps/plugins/test_usb.c
@@ -0,0 +1,137 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2022 Aidan MacDonald
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "plugin.h"
+#include "logf.h"
+
+#undef DEBUGF
+#define DEBUGF(...)
+//#define DEBUGF printf
+
+#define EV_EXIT MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0xFF)
+
+unsigned char stack[DEFAULT_STACK_SIZE];
+struct event_queue queue;
+int thread_id;
+const char* state = "none";
+const char* prev_state = "none";
+
+static void main_loop(void)
+{
+ bool exiting = false;
+ struct queue_event ev;
+
+ while(true) {
+ rb->queue_wait(&queue, &ev);
+
+ /* events that are handled whether exiting or not */
+ switch(ev.id) {
+ case EV_EXIT:
+ return;
+ }
+
+ if(exiting)
+ continue;
+
+ /* events handled only when not exiting */
+ switch(ev.id) {
+ case SYS_USB_CONNECTED:
+ prev_state = state;
+ state = "connected";
+ logf("test_usb: connect ack %ld", *rb->current_tick);
+ DEBUGF("test_usb: connect ack %ld\n", *rb->current_tick);
+ rb->usb_acknowledge(SYS_USB_CONNECTED_ACK);
+ break;
+
+ case SYS_USB_DISCONNECTED:
+ prev_state = state;
+ state = "disconnected";
+ logf("test_usb: disconnect %ld", *rb->current_tick);
+ DEBUGF("test_usb: disconnect %ld\n", *rb->current_tick);
+ break;
+
+ case SYS_POWEROFF:
+ case SYS_REBOOT:
+ prev_state = state;
+ state = "exiting";
+ exiting = true;
+ break;
+ }
+ }
+}
+
+static void kill_tsr(void)
+{
+ rb->queue_post(&queue, EV_EXIT, 0);
+ rb->thread_wait(thread_id);
+ rb->queue_delete(&queue);
+}
+
+static int exit_tsr(bool reenter)
+{
+ MENUITEM_STRINGLIST(menu, "USB test menu", NULL,
+ "Status", "Stop plugin", "Back");
+
+ while(true) {
+ int result = reenter ? rb->do_menu(&menu, NULL, NULL, false) : 1;
+ switch(result) {
+ case 0:
+ rb->splashf(HZ, "State: %s", state);
+ rb->splashf(HZ, "Prev: %s", prev_state);
+ break;
+ case 1:
+ rb->splashf(HZ, "Stopping USB test thread");
+ kill_tsr();
+ return (reenter ? PLUGIN_TSR_TERMINATE : PLUGIN_TSR_SUSPEND);
+ case 2:
+ return PLUGIN_TSR_CONTINUE;
+ }
+ }
+}
+
+static void run_tsr(void)
+{
+ rb->queue_init(&queue, true);
+ thread_id = rb->create_thread(main_loop, stack, sizeof(stack),
+ 0, "test_usb TSR"
+ IF_PRIO(, PRIORITY_BACKGROUND)
+ IF_COP(, CPU));
+ rb->plugin_tsr(exit_tsr);
+}
+
+enum plugin_status plugin_start(const void* parameter)
+{
+ bool resume = (parameter == rb->plugin_tsr);
+
+ MENUITEM_STRINGLIST(menu, "USB test menu", NULL,
+ "Start", "Quit");
+
+ switch(!resume ? rb->do_menu(&menu, NULL, NULL, false) : 0) {
+ case 0:
+ run_tsr();
+ rb->splashf(HZ, "USB test thread started");
+ return PLUGIN_OK;
+ case 1:
+ return PLUGIN_OK;
+ default:
+ return PLUGIN_ERROR;
+ }
+}
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/text_viewer/tv_menu.c b/apps/plugins/text_viewer/tv_menu.c
index 53e0adaf67..1cc471e207 100644
--- a/apps/plugins/text_viewer/tv_menu.c
+++ b/apps/plugins/text_viewer/tv_menu.c
@@ -51,10 +51,9 @@ static bool tv_horizontal_scroll_mode_setting(void)
}
MENUITEM_FUNCTION(horizontal_scrollbar_item, 0, "Scrollbar",
- tv_horizontal_scrollbar_setting,
- NULL, NULL, Icon_NOICON);
+ tv_horizontal_scrollbar_setting, NULL, Icon_NOICON);
MENUITEM_FUNCTION(horizontal_scroll_mode_item, 0, "Scroll Mode",
- tv_horizontal_scroll_mode_setting, NULL, NULL, Icon_NOICON);
+ tv_horizontal_scroll_mode_setting, NULL, Icon_NOICON);
MAKE_MENU(horizontal_scroll_menu, "Horizontal", NULL, Icon_NOICON,
&horizontal_scrollbar_item,
@@ -103,16 +102,14 @@ static bool tv_narrow_mode_setting(void)
}
MENUITEM_FUNCTION(vertical_scrollbar_item, 0, "Scrollbar",
- tv_vertical_scrollbar_setting,
- NULL, NULL, Icon_NOICON);
+ tv_vertical_scrollbar_setting, NULL, Icon_NOICON);
MENUITEM_FUNCTION(vertical_scroll_mode_item, 0, "Scroll Mode",
- tv_vertical_scroll_mode_setting, NULL, NULL, Icon_NOICON);
-MENUITEM_FUNCTION(overlap_page_mode_item, 0, "Overlap Pages", tv_overlap_page_mode_setting,
- NULL, NULL, Icon_NOICON);
+ tv_vertical_scroll_mode_setting, NULL, Icon_NOICON);
+MENUITEM_FUNCTION(overlap_page_mode_item, 0, "Overlap Pages", tv_overlap_page_mode_setting, NULL, Icon_NOICON);
MENUITEM_FUNCTION(autoscroll_speed_item, 0, "Auto-Scroll Speed",
- tv_autoscroll_speed_setting, NULL, NULL, Icon_NOICON);
+ tv_autoscroll_speed_setting, NULL, Icon_NOICON);
MENUITEM_FUNCTION(narrow_mode_item, 0, "Left/Right Key (Narrow mode)",
- tv_narrow_mode_setting, NULL, NULL, Icon_NOICON);
+ tv_narrow_mode_setting, NULL, Icon_NOICON);
MAKE_MENU(vertical_scroll_menu, "Vertical", NULL, Icon_NOICON,
&vertical_scrollbar_item,
@@ -203,16 +200,19 @@ static bool tv_statusbar_setting(void)
static bool tv_font_setting(void)
{
- struct browse_context browse;
char font[MAX_PATH], name[MAX_FILENAME+10];
-
rb->snprintf(name, sizeof(name), "%s.fnt", new_prefs.font_name);
- rb->browse_context_init(&browse, SHOW_FONT,
- BROWSE_SELECTONLY|BROWSE_NO_CONTEXT_MENU,
- "Font", Icon_Menu_setting, FONT_DIR, name);
- browse.buf = font;
- browse.bufsize = sizeof(font);
+ struct browse_context browse = {
+ .dirfilter = SHOW_FONT,
+ .flags = BROWSE_SELECTONLY | BROWSE_NO_CONTEXT_MENU,
+ .title = "Font", /* XXX: Translate? */
+ .icon = Icon_Menu_setting,
+ .root = FONT_DIR,
+ .selected = name,
+ .buf = font,
+ .bufsize = sizeof(font),
+ };
rb->rockbox_browse(&browse);
@@ -240,29 +240,29 @@ static bool tv_night_mode_setting(void)
}
#endif
-MENUITEM_FUNCTION(encoding_item, 0, "Encoding", tv_encoding_setting,
- NULL, NULL, Icon_NOICON);
-MENUITEM_FUNCTION(word_wrap_item, 0, "Word Wrap", tv_word_wrap_setting,
- NULL, NULL, Icon_NOICON);
-MENUITEM_FUNCTION(line_mode_item, 0, "Line Mode", tv_line_mode_setting,
- NULL, NULL, Icon_NOICON);
-MENUITEM_FUNCTION(windows_item, 0, "Screens Per Page", tv_windows_setting,
- NULL, NULL, Icon_NOICON);
-MENUITEM_FUNCTION(alignment_item, 0, "Alignment", tv_alignment_setting,
- NULL, NULL, Icon_NOICON);
-MENUITEM_FUNCTION(header_item, 0, "Show Header", tv_header_setting,
- NULL, NULL, Icon_NOICON);
-MENUITEM_FUNCTION(footer_item, 0, "Show Footer", tv_footer_setting,
- NULL, NULL, Icon_NOICON);
-MENUITEM_FUNCTION(statusbar_item, 0, "Show Statusbar", tv_statusbar_setting,
- NULL, NULL, Icon_NOICON);
-MENUITEM_FUNCTION(font_item, 0, "Font", tv_font_setting,
- NULL, NULL, Icon_NOICON);
-MENUITEM_FUNCTION(indent_spaces_item, 0, "Indent Spaces", tv_indent_spaces_setting,
- NULL, NULL, Icon_NOICON);
+MENUITEM_FUNCTION(encoding_item, 0, "Encoding",
+ tv_encoding_setting, NULL, Icon_NOICON);
+MENUITEM_FUNCTION(word_wrap_item, 0, "Word Wrap",
+ tv_word_wrap_setting, NULL, Icon_NOICON);
+MENUITEM_FUNCTION(line_mode_item, 0, "Line Mode",
+ tv_line_mode_setting, NULL, Icon_NOICON);
+MENUITEM_FUNCTION(windows_item, 0, "Screens Per Page",
+ tv_windows_setting, NULL, Icon_NOICON);
+MENUITEM_FUNCTION(alignment_item, 0, "Alignment",
+ tv_alignment_setting, NULL, Icon_NOICON);
+MENUITEM_FUNCTION(header_item, 0, "Show Header",
+ tv_header_setting, NULL, Icon_NOICON);
+MENUITEM_FUNCTION(footer_item, 0, "Show Footer",
+ tv_footer_setting, NULL, Icon_NOICON);
+MENUITEM_FUNCTION(statusbar_item, 0, "Show Statusbar",
+ tv_statusbar_setting, NULL, Icon_NOICON);
+MENUITEM_FUNCTION(font_item, 0, "Font",
+ tv_font_setting, NULL, Icon_NOICON);
+MENUITEM_FUNCTION(indent_spaces_item, 0, "Indent Spaces",
+ tv_indent_spaces_setting, NULL, Icon_NOICON);
#ifdef HAVE_LCD_COLOR
-MENUITEM_FUNCTION(night_mode_item, 0, "Night Mode", tv_night_mode_setting,
- NULL, NULL, Icon_NOICON);
+MENUITEM_FUNCTION(night_mode_item, 0, "Night Mode",
+ tv_night_mode_setting, NULL, Icon_NOICON);
#endif
MAKE_MENU(option_menu, "Viewer Options", NULL, Icon_NOICON,
diff --git a/apps/plugins/vbrfix.c b/apps/plugins/vbrfix.c
index 88f0a6579e..79fa134499 100644
--- a/apps/plugins/vbrfix.c
+++ b/apps/plugins/vbrfix.c
@@ -150,7 +150,7 @@ static bool vbr_fix(const char *selected_file)
xingupdate(0);
rc = rb->mp3info(&entry, selected_file);
- if(rc < 0) {
+ if(rc) {
fileerror(rc);
return true;
}
@@ -258,6 +258,8 @@ static bool vbr_fix(const char *selected_file)
}
else
{
+ rb->close(fd);
+
/* Not a VBR file */
DEBUGF("Not a VBR file\n");
rb->splash(HZ*2, ID2P(LANG_NOT_A_VBR_FILE));
diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config
index 8d266966d0..c0b76d45d5 100644
--- a/apps/plugins/viewers.config
+++ b/apps/plugins/viewers.config
@@ -105,4 +105,5 @@ shopper,viewers/shopper,1
lnk,viewers/windows_lnk,-
#ifdef HAVE_TAGCACHE
*,demos/pictureflow,-
+log,viewers/lastfm_scrobbler_viewer,4
#endif
diff --git a/apps/plugins/vu_meter.c b/apps/plugins/vu_meter.c
index 356a7fdd93..39deae6947 100644
--- a/apps/plugins/vu_meter.c
+++ b/apps/plugins/vu_meter.c
@@ -20,6 +20,8 @@
#include "plugin.h"
#include "fixedpoint.h"
#include "lib/playback_control.h"
+#include "lib/helper.h"
+#include "lib/pluginlib_exit.h"
@@ -910,6 +912,12 @@ static void digital_meter(void) {
rb->lcd_hline(0,LCD_WIDTH-1,half_height+3);
}
+static void vu_meter_cleanup(void)
+{
+ /* Turn on backlight timeout (revert to settings) */
+ backlight_use_settings();
+}
+
enum plugin_status plugin_start(const void* parameter) {
int button;
#if defined(VUMETER_HELP_PRE) || defined(VUMETER_MENU_PRE)
@@ -920,12 +928,17 @@ enum plugin_status plugin_start(const void* parameter) {
calc_scales();
+ atexit(vu_meter_cleanup);
+
load_settings();
rb->lcd_setfont(FONT_SYSFIXED);
#ifdef HAVE_LCD_COLOR
screen_foreground = rb->lcd_get_foreground();
#endif
+ /* Turn off backlight timeout */
+ backlight_ignore_timeout();
+
while (1)
{
rb->lcd_clear_display();
diff --git a/apps/plugins/wormlet.c b/apps/plugins/wormlet.c
index 162cea6208..abdb6a4725 100644
--- a/apps/plugins/wormlet.c
+++ b/apps/plugins/wormlet.c
@@ -54,7 +54,7 @@ static long max_cycle;
#define BTN_DIR_LEFT BUTTON_LEFT
#define BTN_DIR_RIGHT BUTTON_RIGHT
#define BTN_STARTPAUSE (BUTTON_SELECT|BUTTON_REL)
-#define BTN_QUIT (BUTTON_SELECT|BUTTON_MENU)
+#define BTN_QUIT (BUTTON_SELECT|BUTTON_REPEAT)
#define BTN_STOPRESET (BUTTON_SELECT|BUTTON_PLAY)
#elif (CONFIG_KEYPAD == IRIVER_H300_PAD) || (CONFIG_KEYPAD == IRIVER_H100_PAD)
@@ -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..336d92bd4e 100644
--- a/apps/plugins/xobox.c
+++ b/apps/plugins/xobox.c
@@ -42,10 +42,10 @@
(CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
-#define QUIT (BUTTON_SELECT | BUTTON_MENU)
+#define QUIT (BUTTON_SELECT | BUTTON_REPEAT)
#define LEFT BUTTON_LEFT
#define RIGHT BUTTON_RIGHT
-#define PAUSE BUTTON_SELECT
+#define PAUSE (BUTTON_SELECT | BUTTON_REL)
#define MENU_UP BUTTON_SCROLL_FWD
#define MENU_DOWN BUTTON_SCROLL_BACK
#define UP BUTTON_MENU
@@ -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/engine.c b/apps/plugins/xworld/engine.c
index b09e320078..d99d9df6c6 100644
--- a/apps/plugins/xworld/engine.c
+++ b/apps/plugins/xworld/engine.c
@@ -293,7 +293,7 @@ void engine_processInput(struct Engine* e) {
e->sys->input.save = false;
}
if (e->sys->input.fastMode) {
- e->vm._fastMode = !&e->vm._fastMode;
+ e->vm._fastMode = !e->vm._fastMode;
e->sys->input.fastMode = false;
}
if (e->sys->input.stateSlot != 0) {
diff --git a/apps/plugins/xworld/sys.c b/apps/plugins/xworld/sys.c
index c57da9456b..e20322258d 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)
@@ -287,7 +286,7 @@ static void do_sound_settings(struct System* sys)
case 2:
{
const struct settings_list* vol =
- rb->find_setting(&rb->global_settings->volume, NULL);
+ rb->find_setting(&rb->global_settings->volume);
rb->option_screen((struct settings_list*)vol, NULL, false, "Volume");
break;
}
@@ -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)