Compare commits

...

5 commits

Author SHA1 Message Date
Christian Soffke
f83cb1f7d5 fix manual a1ccb79727
Change-Id: Ic1729fb81386e2010c662373baaa31c302a80ff7
2026-04-16 14:07:17 +02:00
Roman Artiukhin
a496e01173 hiby: ability to add/remove input device
Required for dynamic inputs (like bluetooth).
Files are now opened with O_NONBLOCK, and inputs are automatically removed on poll errors.
Also added call to close all devices on power off.

Change-Id: I8991bdb881fdc00135d1fd5b01ac900c0b007aeb
2026-04-16 08:03:06 -04:00
Christian Soffke
f4dc4d89dc plugins: imageviewer: Hide info by default when loading file
Looks nicer, especially when the "View Album Art"
option is used.

Add delay to progress bar, so it only appears when
250ms have passed.

Change-Id: I183c839f1ab206385cd01327922933b544c4b78b
2026-04-16 07:58:27 -04:00
Christian Soffke
fd7ae09e7a fix FS#13864: Last char of folder and filename not voiced
Change-Id: I9c237bb7721224c6ba44b6511d72094722fa980c
2026-04-16 07:57:21 -04:00
Christian Soffke
a1ccb79727 pitchscreen: adjust keymaps for ipod and fiiom3k
ipod:
- To be more consistent with other plugins and
  (Settings) menus, press Long Select, instead of Menu,
  to reset, and press Menu, or Select, to exit screen

fiiom3k:
- Press Back, or Select, to exit screen
- Press Menu, instead of Select, to switch between modes
- Use repeat button events and adjust values by 1%, instead of
  by 0.1%, when scrolling, to speed up setting changes
- Get rid of surprising actions for Back/Menu/Volume buttons

Change-Id: Ifd16958bf56c7e20fb182aa157b4cb4dd19ac9b9
2026-04-16 13:35:38 +02:00
44 changed files with 264 additions and 161 deletions

View file

@ -185,20 +185,23 @@ static const struct button_mapping button_context_quickscreen[] = {
static const struct button_mapping button_context_pitchscreen[] = { static const struct button_mapping button_context_pitchscreen[] = {
{ACTION_PS_INC_SMALL, BUTTON_UP, BUTTON_NONE}, {ACTION_PS_INC_SMALL, BUTTON_UP, BUTTON_NONE},
{ACTION_PS_INC_SMALL, BUTTON_SCROLL_BACK, BUTTON_NONE}, {ACTION_PS_INC_BIG, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE},
{ACTION_PS_INC_BIG, BUTTON_VOL_UP, BUTTON_NONE}, {ACTION_PS_INC_BIG, BUTTON_SCROLL_BACK, BUTTON_NONE},
{ACTION_PS_INC_BIG, BUTTON_SCROLL_BACK|BUTTON_REPEAT, BUTTON_NONE},
{ACTION_PS_DEC_SMALL, BUTTON_DOWN, BUTTON_NONE}, {ACTION_PS_DEC_SMALL, BUTTON_DOWN, BUTTON_NONE},
{ACTION_PS_DEC_SMALL, BUTTON_SCROLL_FWD, BUTTON_NONE}, {ACTION_PS_DEC_BIG, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE},
{ACTION_PS_DEC_BIG, BUTTON_VOL_DOWN, BUTTON_NONE}, {ACTION_PS_DEC_BIG, BUTTON_SCROLL_FWD, BUTTON_NONE},
{ACTION_PS_DEC_BIG, BUTTON_SCROLL_FWD|BUTTON_REPEAT, BUTTON_NONE},
{ACTION_PS_NUDGE_LEFT, BUTTON_LEFT, BUTTON_NONE}, {ACTION_PS_NUDGE_LEFT, BUTTON_LEFT, BUTTON_NONE},
{ACTION_PS_NUDGE_RIGHT, BUTTON_RIGHT, BUTTON_NONE}, {ACTION_PS_NUDGE_RIGHT, BUTTON_RIGHT, BUTTON_NONE},
{ACTION_PS_NUDGE_LEFTOFF, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE}, {ACTION_PS_NUDGE_LEFTOFF, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE},
{ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE}, {ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE},
{ACTION_PS_TOGGLE_MODE, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT}, {ACTION_PS_TOGGLE_MODE, BUTTON_MENU, BUTTON_NONE},
{ACTION_PS_EXIT, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT},
{ACTION_PS_RESET, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT}, {ACTION_PS_RESET, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT},
{ACTION_PS_EXIT, BUTTON_POWER, BUTTON_NONE}, {ACTION_PS_EXIT, BUTTON_BACK, BUTTON_NONE},
{ACTION_PS_FASTER, BUTTON_BACK, BUTTON_NONE}, {ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE},
{ACTION_PS_SLOWER, BUTTON_MENU, BUTTON_NONE}, {ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE},
LAST_ITEM_IN_LIST LAST_ITEM_IN_LIST
}; /* button_context_pitchscreen */ }; /* button_context_pitchscreen */

View file

@ -151,8 +151,9 @@ static const struct button_mapping button_context_pitchscreen[] = {
{ ACTION_PS_NUDGE_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, { ACTION_PS_NUDGE_RIGHT, BUTTON_RIGHT, BUTTON_NONE },
{ ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE }, { ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE },
{ ACTION_PS_TOGGLE_MODE, BUTTON_PLAY, BUTTON_NONE }, { ACTION_PS_TOGGLE_MODE, BUTTON_PLAY, BUTTON_NONE },
{ ACTION_PS_RESET, BUTTON_MENU, BUTTON_NONE }, { ACTION_PS_EXIT, BUTTON_MENU, BUTTON_NONE },
{ ACTION_PS_EXIT, BUTTON_SELECT, BUTTON_NONE }, { ACTION_PS_EXIT, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT},
{ ACTION_PS_RESET, BUTTON_SELECT|BUTTON_REPEAT,BUTTON_SELECT},
{ ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
{ ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },

View file

@ -14597,11 +14597,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Скриване на информацията" *: "Скриване на информацията"

View file

@ -14601,11 +14601,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "隐藏信息" *: "隐藏信息"

View file

@ -14615,11 +14615,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Information verbergen" *: "Information verbergen"

View file

@ -14591,17 +14591,17 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Hide information" *: "Hide Information"
</dest> </dest>
<voice> <voice>
*: "Hide information" *: "Hide Information"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>

View file

@ -14844,17 +14844,17 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Hide information" *: "Hide Information"
</dest> </dest>
<voice> <voice>
*: "Hide information" *: "Hide Information"
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>

View file

@ -14701,11 +14701,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Ocultar información" *: "Ocultar información"

View file

@ -12290,11 +12290,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Masquer les informations" *: "Masquer les informations"

View file

@ -14300,11 +14300,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Nascondere le informazioni" *: "Nascondere le informazioni"

View file

@ -14794,11 +14794,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "情報を隠す" *: "情報を隠す"

View file

@ -14609,11 +14609,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "정보 숨기기" *: "정보 숨기기"

View file

@ -14706,11 +14706,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Paslēpt informāciju" *: "Paslēpt informāciju"

View file

@ -14709,11 +14709,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Információ elrejtése" *: "Információ elrejtése"

View file

@ -14712,11 +14712,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Ascunde informațiile" *: "Ascunde informațiile"

View file

@ -14360,11 +14360,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Verberg informatie" *: "Verberg informatie"

View file

@ -14779,11 +14779,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Gøym informasjon" *: "Gøym informasjon"

View file

@ -14306,11 +14306,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Ukryj informacje" *: "Ukryj informacje"

View file

@ -14817,11 +14817,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Ocultar informações" *: "Ocultar informações"

View file

@ -14712,11 +14712,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Ascunde informațiile" *: "Ascunde informațiile"

View file

@ -14328,11 +14328,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Ничего не показывать" *: "Ничего не показывать"

View file

@ -14326,11 +14326,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Skryť info" *: "Skryť info"

View file

@ -14705,11 +14705,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Сакриј информације" *: "Сакриј информације"

View file

@ -14714,11 +14714,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Göm information" *: "Göm information"

View file

@ -14597,11 +14597,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Bilgileri gizle" *: "Bilgileri gizle"

View file

@ -14706,11 +14706,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Приховати інформацію" *: "Приховати інформацію"

View file

@ -14615,11 +14615,11 @@
</voice> </voice>
</phrase> </phrase>
<phrase> <phrase>
id: LANG_HIDE_ALBUM_TITLE_NEW id: LANG_HIDE_INFO
desc: in the pictureflow settings desc: Hide Information
user: core user: core
<source> <source>
*: "Hide information" *: "Hide Information"
</source> </source>
<dest> <dest>
*: "Ẩn thông tin" *: "Ẩn thông tin"

View file

@ -176,7 +176,8 @@ static int load_image(char *filename, struct image_info *info,
return PLUGIN_OUTOFMEM; return PLUGIN_OUTOFMEM;
} }
if (!iv->running_slideshow) if (!iv->settings->hide_info &&
!iv->running_slideshow)
{ {
rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1); rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1);
rb->lcd_putsf(0, 1, "loading %dx%d%s", rb->lcd_putsf(0, 1, "loading %dx%d%s",
@ -206,7 +207,8 @@ static int load_image(char *filename, struct image_info *info,
return PLUGIN_ERROR; return PLUGIN_ERROR;
} }
if (!iv->running_slideshow) if (!iv->settings->hide_info &&
!iv->running_slideshow)
{ {
rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ); rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */ rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
@ -225,7 +227,8 @@ static int load_image(char *filename, struct image_info *info,
buf_images = buf_root = buf + size; buf_images = buf_root = buf + size;
buf_images_size = root_size = *buf_size - size; buf_images_size = root_size = *buf_size - size;
if (!iv->running_slideshow) if (!iv->settings->hide_info &&
!iv->running_slideshow)
{ {
rb->lcd_putsf(0, 2, "image %dx%d", bmp.width, bmp.height); rb->lcd_putsf(0, 2, "image %dx%d", bmp.width, bmp.height);
rb->lcd_update(); rb->lcd_update();

View file

@ -56,7 +56,7 @@ static void draw_image_rect(struct image_info *info,
#ifdef HAVE_LCD_COLOR #ifdef HAVE_LCD_COLOR
rb->lcd_bitmap_part((fb_data *)*pdisp, info->x + x, info->y + y, rb->lcd_bitmap_part((fb_data *)*pdisp, info->x + x, info->y + y,
STRIDE(SCREEN_MAIN, info->width, info->height), STRIDE(SCREEN_MAIN, info->width, info->height),
x + MAX(0, (LCD_WIDTH-info->width)/2), x + MAX(0, (LCD_WIDTH-info->width)/2),
y + MAX(0, (LCD_HEIGHT-info->height)/2), y + MAX(0, (LCD_HEIGHT-info->height)/2),
width, height); width, height);
@ -100,7 +100,7 @@ static int load_image(char *filename, struct image_info *info,
} }
#endif #endif
/* initialize decoder context struct, set buffer decoder is free /* initialize decoder context struct, set buffer decoder is free
* to use. * to use.
*/ */
gif_decoder_init(p_decoder, memory, memory_size); gif_decoder_init(p_decoder, memory, memory_size);
@ -111,7 +111,8 @@ static int load_image(char *filename, struct image_info *info,
if (!p_decoder->error) if (!p_decoder->error)
{ {
if (!iv->running_slideshow) if (!iv->settings->hide_info &&
!iv->running_slideshow)
{ {
rb->lcd_putsf(0, 2, "file: %s", rb->lcd_putsf(0, 2, "file: %s",
filename); filename);
@ -137,7 +138,9 @@ static int load_image(char *filename, struct image_info *info,
gif_decoder_destroy_memory_pool(p_decoder); gif_decoder_destroy_memory_pool(p_decoder);
if (!iv->running_slideshow && !p_decoder->error) if (!iv->settings->hide_info &&
!iv->running_slideshow &&
!p_decoder->error)
{ {
rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ); rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */ rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
@ -215,7 +218,9 @@ static int get_image(struct image_info *info, int frame, int ds)
/* assign image buffer */ /* assign image buffer */
if (ds > 1) if (ds > 1)
{ {
if (!iv->running_slideshow && (info->frames_count == 1)) if (!iv->settings->hide_info &&
!iv->running_slideshow &&
(info->frames_count == 1))
{ {
rb->lcd_putsf(0, 3, "resizing %d*%d", info->width, info->height); rb->lcd_putsf(0, 3, "resizing %d*%d", info->width, info->height);
rb->lcd_update(); rb->lcd_update();

View file

@ -64,7 +64,8 @@ static struct imgview_settings settings =
COLOURMODE_COLOUR, COLOURMODE_COLOUR,
DITHER_NONE, DITHER_NONE,
#endif #endif
SS_DEFAULT_TIMEOUT SS_DEFAULT_TIMEOUT,
true
}; };
static struct imgview_settings old_settings; static struct imgview_settings old_settings;
@ -78,6 +79,7 @@ static struct configdata config[] =
#endif #endif
{ TYPE_INT, SS_MIN_TIMEOUT, SS_MAX_TIMEOUT, { TYPE_INT, SS_MIN_TIMEOUT, SS_MAX_TIMEOUT,
{ .int_p = &settings.ss_timeout }, "Slideshow Time", NULL }, { .int_p = &settings.ss_timeout }, "Slideshow Time", NULL },
{ TYPE_BOOL, 0, 1, { .bool_p = &settings.hide_info }, "Hide Info", NULL },
}; };
static void cb_progress(int current, int total); static void cb_progress(int current, int total);
@ -244,12 +246,22 @@ static bool set_option_dithering(void)
return false; return false;
} }
static bool set_option_hide_info(void)
{
rb->set_bool(rb->str(LANG_HIDE_INFO), &settings.hide_info);
return false;
}
MENUITEM_FUNCTION(grayscale_item, 0, ID2P(LANG_GRAYSCALE), MENUITEM_FUNCTION(grayscale_item, 0, ID2P(LANG_GRAYSCALE),
set_option_grayscale, NULL, Icon_NOICON); set_option_grayscale, NULL, Icon_NOICON);
MENUITEM_FUNCTION(dithering_item, 0, ID2P(LANG_DITHERING), MENUITEM_FUNCTION(dithering_item, 0, ID2P(LANG_DITHERING),
set_option_dithering, NULL, Icon_NOICON); set_option_dithering, NULL, Icon_NOICON);
MAKE_MENU(display_menu, "Display Options", NULL, Icon_NOICON, MENUITEM_FUNCTION(hide_info_item, 0, ID2P(LANG_HIDE_INFO),
&grayscale_item, &dithering_item); set_option_hide_info, NULL, Icon_NOICON);
MAKE_MENU(display_menu, ID2P(LANG_MENU_DISPLAY_OPTIONS), NULL, Icon_NOICON,
&grayscale_item,
&dithering_item,
&hide_info_item);
static void display_options(void) static void display_options(void)
{ {
@ -451,6 +463,10 @@ static void cb_progress(int current, int total)
{ {
/* do not yield or update the progress bar if we did so too recently */ /* do not yield or update the progress bar if we did so too recently */
long now = *rb->current_tick; long now = *rb->current_tick;
if (total == 0)
next_progress_tick = now + HZ/4; /* delay by 250ms initially */
if(!TIME_AFTER(now, next_progress_tick)) if(!TIME_AFTER(now, next_progress_tick))
return; return;
@ -965,6 +981,7 @@ reload_decoder:
bool initial_frame = true; bool initial_frame = true;
do /* loop the image prepare and decoding when zoomed */ do /* loop the image prepare and decoding when zoomed */
{ {
cb_progress(0, 0); /* delay showing progress bar*/
status = imgdec->get_image(info, frame, ds); /* decode or fetch from cache */ status = imgdec->get_image(info, frame, ds); /* decode or fetch from cache */
if (status == PLUGIN_ERROR) if (status == PLUGIN_ERROR)
{ {
@ -973,8 +990,9 @@ reload_decoder:
} }
set_view(info, cx, cy); set_view(info, cx, cy);
if(!settings.hide_info &&
if(!iv_api.running_slideshow && (info->frames_count == 1)) !iv_api.running_slideshow &&
(info->frames_count == 1))
{ {
rb->lcd_putsf(0, 3, "showing %dx%d", info->width, info->height); rb->lcd_putsf(0, 3, "showing %dx%d", info->width, info->height);
rb->lcd_update(); rb->lcd_update();

View file

@ -77,6 +77,7 @@ struct imgview_settings
int jpeg_dither_mode; int jpeg_dither_mode;
#endif #endif
int ss_timeout; int ss_timeout;
bool hide_info;
}; };
/* structure passed to image decoder. */ /* structure passed to image decoder. */

View file

@ -150,7 +150,8 @@ static int load_image(char *filename, struct image_info *info,
return PLUGIN_OUTOFMEM; return PLUGIN_OUTOFMEM;
} }
if(!iv->running_slideshow) if(!iv->settings->hide_info &&
!iv->running_slideshow)
{ {
rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1); rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1);
rb->lcd_putsf(0, 1, "loading %d bytes", filesize); rb->lcd_putsf(0, 1, "loading %d bytes", filesize);
@ -160,7 +161,8 @@ static int load_image(char *filename, struct image_info *info,
rb->read(fd, buf_jpeg, filesize); rb->read(fd, buf_jpeg, filesize);
rb->close(fd); rb->close(fd);
if(!iv->running_slideshow) if(!iv->settings->hide_info &&
!iv->running_slideshow)
{ {
rb->lcd_puts(0, 2, "decoding markers"); rb->lcd_puts(0, 2, "decoding markers");
rb->lcd_update(); rb->lcd_update();
@ -190,7 +192,8 @@ static int load_image(char *filename, struct image_info *info,
default_huff_tbl(p_jpg); /* use default */ default_huff_tbl(p_jpg); /* use default */
build_lut(p_jpg); /* derive Huffman and other lookup-tables */ build_lut(p_jpg); /* derive Huffman and other lookup-tables */
if(!iv->running_slideshow) if(!iv->settings->hide_info &&
!iv->running_slideshow)
{ {
rb->lcd_putsf(0, 2, "image %dx%d", p_jpg->x_size, p_jpg->y_size); rb->lcd_putsf(0, 2, "image %dx%d", p_jpg->x_size, p_jpg->y_size);
rb->lcd_update(); rb->lcd_update();
@ -263,7 +266,8 @@ static int get_image(struct image_info *info, int frame, int ds)
buf_images += size; buf_images += size;
buf_images_size -= size; buf_images_size -= size;
if(!iv->running_slideshow) if(!iv->settings->hide_info &&
!iv->running_slideshow)
{ {
rb->lcd_putsf(0, 3, "decoding %d*%d", info->width, info->height); rb->lcd_putsf(0, 3, "decoding %d*%d", info->width, info->height);
rb->lcd_update(); rb->lcd_update();
@ -288,7 +292,8 @@ static int get_image(struct image_info *info, int frame, int ds)
} }
time = *rb->current_tick - time; time = *rb->current_tick - time;
if(!iv->running_slideshow) if(!iv->settings->hide_info &&
!iv->running_slideshow)
{ {
rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ); rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */ rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */

View file

@ -117,7 +117,8 @@ static int load_image(char *filename, struct image_info *info,
POS(offset); POS(offset);
} }
if (!iv->running_slideshow) if (!iv->settings->hide_info &&
!iv->running_slideshow)
{ {
rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1); rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1);
rb->lcd_puts(0, 2, "decoding..."); rb->lcd_puts(0, 2, "decoding...");
@ -142,7 +143,8 @@ static int load_image(char *filename, struct image_info *info,
return PLUGIN_ERROR; return PLUGIN_ERROR;
} }
if (!iv->running_slideshow) if (!iv->settings->hide_info &&
!iv->running_slideshow)
{ {
rb->lcd_putsf(0, 2, "image %dx%d", p_jpg->X, p_jpg->Y); rb->lcd_putsf(0, 2, "image %dx%d", p_jpg->X, p_jpg->Y);
int w, h; /* used to center output */ int w, h; /* used to center output */
@ -262,7 +264,7 @@ static int get_image(struct image_info *info, int frame, int ds)
c2 = (sumV + area/2) / area; c2 = (sumV + area/2) / area;
} }
// ITU BT.601 full-range YUV-to-RGB integer approximation // ITU BT.601 full-range YUV-to-RGB integer approximation
{ {
int y = (c0 << 5) + 16; int y = (c0 << 5) + 16;
int u = c1 - 128; int u = c1 - 128;

View file

@ -62,7 +62,7 @@ static void draw_image_rect(struct image_info *info,
#ifdef HAVE_LCD_COLOR #ifdef HAVE_LCD_COLOR
rb->lcd_bitmap_part((fb_data *)*pdisp, info->x + x, info->y + y, rb->lcd_bitmap_part((fb_data *)*pdisp, info->x + x, info->y + y,
STRIDE(SCREEN_MAIN, info->width, info->height), STRIDE(SCREEN_MAIN, info->width, info->height),
x + MAX(0, (LCD_WIDTH-info->width)/2), x + MAX(0, (LCD_WIDTH-info->width)/2),
y + MAX(0, (LCD_HEIGHT-info->height)/2), y + MAX(0, (LCD_HEIGHT-info->height)/2),
width, height); width, height);
@ -82,8 +82,8 @@ static int img_mem(int ds)
#ifdef USEGSLIB #ifdef USEGSLIB
return (p_decoder->infoPng.width/ds) * (p_decoder->infoPng.height/ds); return (p_decoder->infoPng.width/ds) * (p_decoder->infoPng.height/ds);
#else #else
return (p_decoder->infoPng.width/ds) * return (p_decoder->infoPng.width/ds) *
(p_decoder->infoPng.height/ds) * (p_decoder->infoPng.height/ds) *
FB_DATA_SZ; FB_DATA_SZ;
#endif #endif
} }
@ -126,7 +126,9 @@ static int load_image(char *filename, struct image_info *info,
DEBUGF("reading file '%s'\n", filename); DEBUGF("reading file '%s'\n", filename);
if (!iv->running_slideshow) { if (!iv->settings->hide_info &&
!iv->running_slideshow)
{
rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1); rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1);
rb->lcd_update(); rb->lcd_update();
} }
@ -136,7 +138,9 @@ static int load_image(char *filename, struct image_info *info,
rb->close(fd); rb->close(fd);
} else { } else {
if (!iv->running_slideshow) { if (!iv->settings->hide_info &&
!iv->running_slideshow)
{
rb->lcd_putsf(0, 1, "loading %zu bytes", file_size); rb->lcd_putsf(0, 1, "loading %zu bytes", file_size);
rb->lcd_update(); rb->lcd_update();
} }
@ -146,7 +150,9 @@ static int load_image(char *filename, struct image_info *info,
rb->read(fd, image, file_size); rb->read(fd, image, file_size);
rb->close(fd); rb->close(fd);
if (!iv->running_slideshow) { if (!iv->settings->hide_info &&
!iv->running_slideshow)
{
rb->lcd_puts(0, 2, "decoding image"); rb->lcd_puts(0, 2, "decoding image");
rb->lcd_update(); rb->lcd_update();
} }
@ -171,7 +177,8 @@ static int load_image(char *filename, struct image_info *info,
if (!p_decoder->error) { if (!p_decoder->error) {
if (!iv->running_slideshow) { if (!iv->settings->hide_info &&
!iv->running_slideshow) {
rb->lcd_putsf(0, 2, "image %dx%d", rb->lcd_putsf(0, 2, "image %dx%d",
p_decoder->infoPng.width, p_decoder->infoPng.width,
p_decoder->infoPng.height); p_decoder->infoPng.height);
@ -194,7 +201,8 @@ static int load_image(char *filename, struct image_info *info,
} }
} }
if (!iv->running_slideshow && !p_decoder->error) if (!iv->settings->hide_info &&
!iv->running_slideshow && !p_decoder->error)
{ {
rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ); rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */ rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
@ -253,7 +261,8 @@ static int get_image(struct image_info *info, int frame, int ds)
/* assign image buffer */ /* assign image buffer */
if (ds > 1) { if (ds > 1) {
if (!iv->running_slideshow) if (!iv->settings->hide_info &&
!iv->running_slideshow)
{ {
rb->lcd_putsf(0, 3, "resizing %d*%d", info->width, info->height); rb->lcd_putsf(0, 3, "resizing %d*%d", info->width, info->height);
rb->lcd_update(); rb->lcd_update();

View file

@ -51,7 +51,7 @@ static void draw_image_rect(struct image_info *info,
#ifdef HAVE_LCD_COLOR #ifdef HAVE_LCD_COLOR
rb->lcd_bitmap_part((fb_data *)*pdisp, info->x + x, info->y + y, rb->lcd_bitmap_part((fb_data *)*pdisp, info->x + x, info->y + y,
STRIDE(SCREEN_MAIN, info->width, info->height), STRIDE(SCREEN_MAIN, info->width, info->height),
x + MAX(0, (LCD_WIDTH-info->width)/2), x + MAX(0, (LCD_WIDTH-info->width)/2),
y + MAX(0, (LCD_HEIGHT-info->height)/2), y + MAX(0, (LCD_HEIGHT-info->height)/2),
width, height); width, height);
@ -111,7 +111,8 @@ static int load_image(char *filename, struct image_info *info,
} }
DEBUGF("reading file '%s'\n", filename); DEBUGF("reading file '%s'\n", filename);
if (!iv->running_slideshow) if (!iv->settings->hide_info &&
!iv->running_slideshow)
{ {
rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1); rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1);
rb->lcd_putsf(0, 1, "loading %zu bytes", filesize); rb->lcd_putsf(0, 1, "loading %zu bytes", filesize);
@ -140,7 +141,8 @@ static int load_image(char *filename, struct image_info *info,
return rc; return rc;
} }
if (!iv->running_slideshow) if (!iv->settings->hide_info &&
!iv->running_slideshow)
{ {
rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ); rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */ rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
@ -177,7 +179,8 @@ static int get_image(struct image_info *info, int frame, int ds)
/* assign image buffer */ /* assign image buffer */
if (ds > 1) if (ds > 1)
{ {
if (!iv->running_slideshow) if (!iv->settings->hide_info &&
!iv->running_slideshow)
{ {
rb->lcd_putsf(0, 3, "resizing %d*%d", info->width, info->height); rb->lcd_putsf(0, 3, "resizing %d*%d", info->width, info->height);
rb->lcd_update(); rb->lcd_update();

View file

@ -3619,7 +3619,7 @@ static int settings_menu(void)
ID2P(LANG_DISPLAY)); ID2P(LANG_DISPLAY));
static const struct opt_items album_name_options[] = { static const struct opt_items album_name_options[] = {
{ STR(LANG_HIDE_ALBUM_TITLE_NEW) }, { STR(LANG_HIDE_INFO) },
{ STR(LANG_SHOW_AT_THE_BOTTOM_NEW) }, { STR(LANG_SHOW_AT_THE_BOTTOM_NEW) },
{ STR(LANG_SHOW_AT_THE_TOP_NEW) }, { STR(LANG_SHOW_AT_THE_TOP_NEW) },
{ STR(LANG_SHOW_ALL_AT_THE_TOP) }, { STR(LANG_SHOW_ALL_AT_THE_TOP) },

View file

@ -765,7 +765,7 @@ static int _talk_spell(const char* spell, size_t len, bool enqueue)
do_enqueue(enqueue); /* cut off all the pending stuff */ do_enqueue(enqueue); /* cut off all the pending stuff */
const char *last = spell; const char *last = spell;
size_t len0 = len - 1; size_t len0 = len;
/* Tokenize into UTF8 codepoints */ /* Tokenize into UTF8 codepoints */
while ((spell = utf8decode(spell, &c)), c != '\0') while ((spell = utf8decode(spell, &c)), c != '\0')
{ {

View file

@ -21,6 +21,7 @@
****************************************************************************/ ****************************************************************************/
#include <poll.h> #include <poll.h>
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <linux/input.h> #include <linux/input.h>
@ -49,42 +50,60 @@
* Compute to angular velocity (degrees per second) * Compute to angular velocity (degrees per second)
*/ */
#define NR_POLL_DESC 4 #define NR_POLL_DESC 5
static int num_devices = 0; static int num_devices = 0;
static struct pollfd poll_fds[NR_POLL_DESC]; static struct pollfd poll_fds[NR_POLL_DESC];
void button_add_input_device(int i)
{
int fd = poll_fds[i].fd;
if (fd >= 0)
close(fd);
char path[32];
snprintf(path, sizeof(path), "/dev/input/event%d", i);
fd = open(path, O_RDONLY | O_CLOEXEC | O_NONBLOCK);
poll_fds[i].fd = fd >= 0 ? fd : -1;
if(fd >= 0)
{
poll_fds[i].events = POLLIN;
poll_fds[i].revents = 0;
if (num_devices <= i)
num_devices = i + 1;
}
}
void button_init_device(void) void button_init_device(void)
{ {
const char * const input_devs[NR_POLL_DESC] = {
"/dev/input/event0",
"/dev/input/event1",
"/dev/input/event2",
"/dev/input/event3",
};
for(int i = 0; i < NR_POLL_DESC; i++) for(int i = 0; i < NR_POLL_DESC; i++)
{ {
int fd = open(input_devs[i], O_RDONLY | O_CLOEXEC); poll_fds[i].fd = -1;
button_add_input_device(i);
if(fd >= 0)
{
poll_fds[num_devices].fd = fd;
poll_fds[num_devices].events = POLLIN;
poll_fds[num_devices].revents = 0;
num_devices++;
}
} }
} }
void button_remove_input_device(int i)
{
int fd = poll_fds[i].fd;
if (fd < 0)
return;
if (i == num_devices - 1)
num_devices = i;
close(fd);
poll_fds[i].fd = -1;
}
void button_close_device(void) void button_close_device(void)
{ {
/* close descriptors */
for(int i = 0; i < num_devices; i++)
{
close(poll_fds[i].fd);
}
num_devices = 0; num_devices = 0;
/* close descriptors */
for(int i = 0; i < NR_POLL_DESC; i++)
{
button_remove_input_device(i);
}
} }
#ifdef BUTTON_DELAY_RELEASE #ifdef BUTTON_DELAY_RELEASE
@ -261,6 +280,10 @@ int button_read_device(BDATA)
} }
} }
} }
/* device was removed/disconnected — close it to stop poll returning POLLHUP forever */
else if (poll_fds[i].revents & (POLLERR | POLLHUP)) {
button_remove_input_device(i);
}
} }
} }

View file

@ -0,0 +1,28 @@
/***************************************************************************
* __________ __ ___
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
*
* Copyright (C) 2026 by Roman Artiukhin
*
* 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 __BUTTON_DEVINPUT_H__
#define __BUTTON_DEVINPUT_H__
void button_close_device(void);
void button_add_input_device(int i);
void button_remove_input_device(int i);
#endif

View file

@ -29,6 +29,7 @@
#include "font.h" #include "font.h"
#include "power.h" #include "power.h"
#include "button.h" #include "button.h"
#include "button-devinput.h"
#include "backlight-target.h" #include "backlight-target.h"
#include "lcd.h" #include "lcd.h"
#include "filesystem-hosted.h" #include "filesystem-hosted.h"
@ -92,6 +93,7 @@ static void sig_handler(int sig, siginfo_t *siginfo, void *context)
void power_off(void) void power_off(void)
{ {
backlight_hw_off(); backlight_hw_off();
button_close_device();
sync(); sync();
system("/sbin/poweroff"); system("/sbin/poweroff");
while (1) { while (1) {

View file

@ -78,17 +78,17 @@
\newcommand{\ActionKbdAbort}{\ButtonPower} \newcommand{\ActionKbdAbort}{\ButtonPower}
%Button actions, Pitch Screen context %Button actions, Pitch Screen context
\newcommand{\ActionPsToggleMode}{\ButtonSelect} \newcommand{\ActionPsToggleMode}{\ButtonMenu}
\newcommand{\ActionPsIncSmall}{\ButtonUp{} or \ButtonScrollBack} \newcommand{\ActionPsIncSmall}{\ButtonUp}
\newcommand{\ActionPsDecSmall}{\ButtonDown{} or \ButtonScrollFwd} \newcommand{\ActionPsDecSmall}{\ButtonDown}
\newcommand{\ActionPsIncBig}{\ButtonVolUp} \newcommand{\ActionPsIncBig}{Long \ButtonUp{} or \ButtonScrollBack}
\newcommand{\ActionPsDecBig}{\ButtonVolDown} \newcommand{\ActionPsDecBig}{Long \ButtonDown {} or \ButtonScrollFwd}
\newcommand{\ActionPsNudgeLeft}{\ButtonLeft} \newcommand{\ActionPsNudgeLeft}{\ButtonLeft}
\newcommand{\ActionPsNudgeRight}{\ButtonRight} \newcommand{\ActionPsNudgeRight}{\ButtonRight}
\newcommand{\ActionPsReset}{Long \ButtonSelect} \newcommand{\ActionPsReset}{Long \ButtonSelect}
\newcommand{\ActionPsExit}{\ButtonPower} \newcommand{\ActionPsExit}{\ButtonBack{} or \ButtonSelect}
\newcommand{\ActionPsFaster}{\ButtonBack} \newcommand{\ActionPsFaster}{Long \ButtonRight}
\newcommand{\ActionPsSlower}{\ButtonMenu} \newcommand{\ActionPsSlower}{Long \ButtonLeft}
%Button actions, Bookmark screen context %Button actions, Bookmark screen context
\newcommand{\ActionBmDelete}{\ButtonPlay} \newcommand{\ActionBmDelete}{\ButtonPlay}

View file

@ -77,8 +77,8 @@
\newcommand{\ActionPsDecBig}{Long \ButtonScrollBack} \newcommand{\ActionPsDecBig}{Long \ButtonScrollBack}
\newcommand{\ActionPsNudgeLeft}{\ButtonLeft} \newcommand{\ActionPsNudgeLeft}{\ButtonLeft}
\newcommand{\ActionPsNudgeRight}{\ButtonRight} \newcommand{\ActionPsNudgeRight}{\ButtonRight}
\newcommand{\ActionPsReset}{\ButtonMenu} \newcommand{\ActionPsReset}{Long \ButtonSelect}
\newcommand{\ActionPsExit}{\ButtonSelect} \newcommand{\ActionPsExit}{\ButtonMenu{} or \ButtonSelect}
%Button actions, Bookmark screen context %Button actions, Bookmark screen context
\newcommand{\ActionBmDelete}{Long \ButtonMenu} \newcommand{\ActionBmDelete}{Long \ButtonMenu}

View file

@ -77,8 +77,8 @@
\newcommand{\ActionPsDecBig}{Long \ButtonScrollBack} \newcommand{\ActionPsDecBig}{Long \ButtonScrollBack}
\newcommand{\ActionPsNudgeLeft}{\ButtonLeft} \newcommand{\ActionPsNudgeLeft}{\ButtonLeft}
\newcommand{\ActionPsNudgeRight}{\ButtonRight} \newcommand{\ActionPsNudgeRight}{\ButtonRight}
\newcommand{\ActionPsReset}{\ButtonMenu} \newcommand{\ActionPsReset}{Long \ButtonSelect}
\newcommand{\ActionPsExit}{\ButtonSelect} \newcommand{\ActionPsExit}{\ButtonMenu{} or \ButtonSelect}
%Button actions, Bookmark screen context %Button actions, Bookmark screen context
\newcommand{\ActionBmDelete}{Long \ButtonMenu} \newcommand{\ActionBmDelete}{Long \ButtonMenu}

View file

@ -78,8 +78,8 @@
\newcommand{\ActionPsDecBig}{Long \ButtonScrollBack} \newcommand{\ActionPsDecBig}{Long \ButtonScrollBack}
\newcommand{\ActionPsNudgeLeft}{\ButtonLeft} \newcommand{\ActionPsNudgeLeft}{\ButtonLeft}
\newcommand{\ActionPsNudgeRight}{\ButtonRight} \newcommand{\ActionPsNudgeRight}{\ButtonRight}
\newcommand{\ActionPsReset}{\ButtonMenu} \newcommand{\ActionPsReset}{Long \ButtonSelect}
\newcommand{\ActionPsExit}{\ButtonSelect} \newcommand{\ActionPsExit}{\ButtonMenu{} or \ButtonSelect}
%Button actions, Recording screen context %Button actions, Recording screen context
\newcommand{\ActionRecPause}{\ButtonPlay} \newcommand{\ActionRecPause}{\ButtonPlay}