From 4ad76652ef19daf6404e8a97eb73aeadfe1e66fb Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sat, 20 Jul 2019 17:32:49 -0400 Subject: Speech feedback in mpegplayer menus Patch by Igor Poretsky Change-Id: Idc6920e17be6537557f2b1cf00f7e559e30b45e8 --- apps/plugins/mpegplayer/mpeg_settings.c | 187 +++++++++++++++++++++----------- apps/plugins/mpegplayer/mpegplayer.c | 67 ++++++++++++ apps/plugins/mpegplayer/mpegplayer.h | 6 + apps/plugins/mpegplayer/pcm_output.c | 2 + 4 files changed, 196 insertions(+), 66 deletions(-) (limited to 'apps/plugins/mpegplayer') diff --git a/apps/plugins/mpegplayer/mpeg_settings.c b/apps/plugins/mpegplayer/mpeg_settings.c index d6b4fd4b84..8427db12b4 100644 --- a/apps/plugins/mpegplayer/mpeg_settings.c +++ b/apps/plugins/mpegplayer/mpeg_settings.c @@ -395,29 +395,20 @@ static struct configdata config[] = }; static const struct opt_items noyes[2] = { - { "No", -1 }, - { "Yes", -1 }, + { STR(LANG_SET_BOOL_NO) }, + { STR(LANG_SET_BOOL_YES) }, }; static const struct opt_items singleall[2] = { - { "Single", -1 }, - { "All", -1 }, -}; - -static const struct opt_items enabledisable[2] = { - { "Disable", -1 }, - { "Enable", -1 }, + { STR(LANG_SINGLE) }, + { STR(LANG_ALL) }, }; static const struct opt_items globaloff[2] = { - { "Force off", -1 }, - { "Use sound setting", -1 }, + { STR(LANG_OFF) }, + { STR(LANG_USE_SOUND_SETTING) }, }; -#ifdef HAVE_BACKLIGHT_BRIGHTNESS -#define BACKLIGHT_OPTION_DEFAULT "Use setting" -#endif - static void mpeg_settings(void); static bool mpeg_set_option(const char* string, void* variable, @@ -444,21 +435,28 @@ static bool mpeg_set_int(const char *string, const char *unit, void (*function)(int), int step, int min, int max, - const char* (*formatter)(char*, size_t, int, const char*)) + const char* (*formatter)(char*, size_t, int, const char*), + int32_t (*get_talk_id)(int, int)) { mpeg_sysevent_clear(); - bool usb = rb->set_int(string, unit, voice_unit, variable, function, - step, min, max, formatter); + bool usb = rb->set_int_ex(string, unit, voice_unit, variable, function, + step, min, max, formatter, get_talk_id); if (usb) mpeg_sysevent_set(); return usb; } -#endif /* HAVE_BACKLIGHT_BRIGHTNESS */ -#ifdef HAVE_BACKLIGHT_BRIGHTNESS +static int32_t backlight_brightness_getlang(int value, int unit) +{ + if (value < 0) + return LANG_USE_COMMON_SETTING; + + return TALK_ID(value + MIN_BRIGHTNESS_SETTING, unit); +} + void mpeg_backlight_update_brightness(int value) { if (value >= 0) @@ -483,7 +481,7 @@ static const char* backlight_brightness_formatter(char *buf, size_t length, (void)input; if (value < 0) - return BACKLIGHT_OPTION_DEFAULT; + return rb->str(LANG_USE_COMMON_SETTING); else rb->snprintf(buf, length, "%d", value + MIN_BRIGHTNESS_SETTING); return buf; @@ -764,6 +762,7 @@ static int get_start_time(uint32_t duration) uint32_t resume_time = settings.resume_time; struct vo_rect rc_vid, rc_bound; uint32_t aspect_vid, aspect_bound; + bool sliding = false; enum state_enum slider_state = STATE0; @@ -937,7 +936,18 @@ static int get_start_time(uint32_t duration) switch (slider_state) { case STATE0: - trigger_cpu_boost(); + if (!sliding) + { + if (rb->global_settings->talk_menu) + { + rb->talk_disable(true); +#ifdef PLUGIN_USE_IRAM + mpegplayer_iram_restore(); +#endif + } + trigger_cpu_boost(); + sliding = true; + } stream_seek(resume_time, SEEK_SET); show_loading(&rc_bound); draw_slider(duration, resume_time, NULL); @@ -947,9 +957,21 @@ static int get_start_time(uint32_t duration) case STATE1: display_thumb_image(&rc_vid); slider_state = STATE2; - case STATE2: - cancel_cpu_boost(); tmo = TIMEOUT_BLOCK; + if (sliding) + { + cancel_cpu_boost(); + if (rb->global_settings->talk_menu) + { +#ifdef PLUGIN_USE_IRAM + mpegplayer_iram_preserve(); +#endif + rb->talk_disable(false); + rb->talk_value(resume_time / TS_SECOND, UNIT_TIME, false); + rb->talk_value(resume_time * 100 / duration, UNIT_PERCENT, true); + } + sliding = false; + } default: break; } @@ -977,19 +999,20 @@ static int show_start_menu(uint32_t duration) int result = 0; bool menu_quit = false; - /* add the resume time to the menu display */ - static char resume_str[32]; - char hms_str[32]; - struct hms hms; - MENUITEM_STRINGLIST(menu, "Mpegplayer Menu", mpeg_sysevent_callback, - "Play from beginning", resume_str, "Set start time", - "Settings", "Quit mpegplayer"); + ID2P(LANG_RESTART_PLAYBACK), + ID2P(LANG_RESUME_PLAYBACK), + ID2P(LANG_SET_RESUME_TIME), + ID2P(LANG_SETTINGS), + ID2P(LANG_MENU_QUIT)); - ts_to_hms(settings.resume_time, &hms); - hms_format(hms_str, sizeof(hms_str), &hms); - rb->snprintf(resume_str, sizeof (resume_str), - "Resume at: %s", hms_str); + if (rb->global_settings->talk_menu) + { +#ifdef PLUGIN_USE_IRAM + mpegplayer_iram_preserve(); +#endif + rb->talk_disable(false); + } rb->button_clear_queue(); @@ -1012,7 +1035,7 @@ static int show_start_menu(uint32_t duration) case MPEG_START_SEEK: if (!stream_can_seek()) { - rb->splash(HZ, "Unavailable"); + rb->splash(HZ, ID2P(LANG_UNAVAILABLE)); break; } @@ -1039,6 +1062,14 @@ static int show_start_menu(uint32_t duration) } } + if (rb->global_settings->talk_menu) + { + rb->talk_disable(true); +#ifdef PLUGIN_USE_IRAM + mpegplayer_iram_restore(); +#endif + } + return result; } @@ -1069,7 +1100,17 @@ int mpeg_menu(void) int result; MENUITEM_STRINGLIST(menu, "Mpegplayer Menu", mpeg_sysevent_callback, - "Settings", "Resume playback", "Quit mpegplayer"); + ID2P(LANG_SETTINGS), + ID2P(LANG_RESUME_PLAYBACK), + ID2P(LANG_MENU_QUIT)); + + if (rb->global_settings->talk_menu) + { +#ifdef PLUGIN_USE_IRAM + mpegplayer_iram_preserve(); +#endif + rb->talk_disable(false); + } rb->button_clear_queue(); @@ -1096,6 +1137,14 @@ int mpeg_menu(void) if (mpeg_sysevent() != 0) result = MPEG_MENU_QUIT; + if (rb->global_settings->talk_menu) + { + rb->talk_disable(true); +#ifdef PLUGIN_USE_IRAM + mpegplayer_iram_restore(); +#endif + } + return result; } @@ -1107,11 +1156,13 @@ static void display_options(void) MENUITEM_STRINGLIST(menu, "Display Options", mpeg_sysevent_callback, #if MPEG_OPTION_DITHERING_ENABLED - "Dithering", + ID2P(LANG_DITHERING), #endif - "Display FPS", "Limit FPS", "Skip frames", + ID2P(LANG_DISPLAY_FPS), + ID2P(LANG_LIMIT_FPS), + ID2P(LANG_SKIP_FRAMES), #ifdef HAVE_BACKLIGHT_BRIGHTNESS - "Backlight brightness", + ID2P(LANG_BACKLIGHT_BRIGHTNESS), #endif ); @@ -1127,7 +1178,7 @@ static void display_options(void) #if MPEG_OPTION_DITHERING_ENABLED case MPEG_OPTION_DITHERING: result = (settings.displayoptions & LCD_YUV_DITHER) ? 1 : 0; - mpeg_set_option("Dithering", &result, INT, noyes, 2, NULL); + mpeg_set_option(rb->str(LANG_DITHERING), &result, INT, noyes, 2, NULL); settings.displayoptions = (settings.displayoptions & ~LCD_YUV_DITHER) | ((result != 0) ? LCD_YUV_DITHER : 0); @@ -1136,17 +1187,17 @@ static void display_options(void) #endif /* MPEG_OPTION_DITHERING_ENABLED */ case MPEG_OPTION_DISPLAY_FPS: - mpeg_set_option("Display FPS", &settings.showfps, INT, + mpeg_set_option(rb->str(LANG_DISPLAY_FPS), &settings.showfps, INT, noyes, 2, NULL); break; case MPEG_OPTION_LIMIT_FPS: - mpeg_set_option("Limit FPS", &settings.limitfps, INT, + mpeg_set_option(rb->str(LANG_LIMIT_FPS), &settings.limitfps, INT, noyes, 2, NULL); break; case MPEG_OPTION_SKIP_FRAMES: - mpeg_set_option("Skip frames", &settings.skipframes, INT, + mpeg_set_option(rb->str(LANG_SKIP_FRAMES), &settings.skipframes, INT, noyes, 2, NULL); break; @@ -1154,10 +1205,11 @@ static void display_options(void) case MPEG_OPTION_BACKLIGHT_BRIGHTNESS: result = settings.backlight_brightness; mpeg_backlight_update_brightness(result); - mpeg_set_int("Backlight brightness", NULL, -1, &result, + mpeg_set_int(rb->str(LANG_BACKLIGHT_BRIGHTNESS), NULL, UNIT_INT, &result, backlight_brightness_function, 1, -1, MAX_BRIGHTNESS_SETTING - MIN_BRIGHTNESS_SETTING, - backlight_brightness_formatter); + backlight_brightness_formatter, + backlight_brightness_getlang); settings.backlight_brightness = result; mpeg_backlight_update_brightness(-1); break; @@ -1173,6 +1225,7 @@ static void display_options(void) } } +#if CONFIG_CODEC == SWCODEC static void audio_options(void) { int selected = 0; @@ -1180,8 +1233,11 @@ static void audio_options(void) bool menu_quit = false; MENUITEM_STRINGLIST(menu, "Audio Options", mpeg_sysevent_callback, - "Tone Controls", "Channel Modes", "Crossfeed", - "Equalizer", "Dithering"); + ID2P(LANG_TONE_CONTROLS), + ID2P(LANG_CHANNEL_CONFIGURATION), + ID2P(LANG_CROSSFEED), + ID2P(LANG_EQUALIZER), + ID2P(LANG_DITHERING)); rb->button_clear_queue(); @@ -1193,31 +1249,31 @@ static void audio_options(void) switch (result) { case MPEG_AUDIO_TONE_CONTROLS: - mpeg_set_option("Tone Controls", &settings.tone_controls, INT, + mpeg_set_option(rb->str(LANG_TONE_CONTROLS), &settings.tone_controls, INT, globaloff, 2, NULL); sync_audio_setting(result, false); break; case MPEG_AUDIO_CHANNEL_MODES: - mpeg_set_option("Channel Modes", &settings.channel_modes, + mpeg_set_option(rb->str(LANG_CHANNEL_CONFIGURATION), &settings.channel_modes, INT, globaloff, 2, NULL); sync_audio_setting(result, false); break; case MPEG_AUDIO_CROSSFEED: - mpeg_set_option("Crossfeed", &settings.crossfeed, INT, + mpeg_set_option(rb->str(LANG_CROSSFEED), &settings.crossfeed, INT, globaloff, 2, NULL); sync_audio_setting(result, false); break; case MPEG_AUDIO_EQUALIZER: - mpeg_set_option("Equalizer", &settings.equalizer, INT, + mpeg_set_option(rb->str(LANG_EQUALIZER), &settings.equalizer, INT, globaloff, 2, NULL); sync_audio_setting(result, false); break; case MPEG_AUDIO_DITHERING: - mpeg_set_option("Dithering", &settings.dithering, INT, + mpeg_set_option(rb->str(LANG_DITHERING), &settings.dithering, INT, globaloff, 2, NULL); sync_audio_setting(result, false); break; @@ -1231,21 +1287,22 @@ static void audio_options(void) menu_quit = true; } } +#endif static void resume_options(void) { static const struct opt_items items[MPEG_RESUME_NUM_OPTIONS] = { [MPEG_RESUME_MENU_ALWAYS] = - { "Start menu", -1 }, + { STR(LANG_FORCE_START_MENU) }, [MPEG_RESUME_MENU_IF_INCOMPLETE] = - { "Start menu if not completed", -1 }, + { STR(LANG_CONDITIONAL_START_MENU) }, [MPEG_RESUME_ALWAYS] = - { "Resume automatically", -1 }, + { STR(LANG_AUTO_RESUME) }, [MPEG_RESUME_RESTART] = - { "Play from beginning", -1 }, + { STR(LANG_RESTART_PLAYBACK) }, }; - mpeg_set_option("Resume Options", &settings.resume_options, + mpeg_set_option(rb->str(LANG_MENU_RESUME_OPTIONS), &settings.resume_options, INT, items, MPEG_RESUME_NUM_OPTIONS, NULL); } @@ -1261,11 +1318,13 @@ static void mpeg_settings(void) int selected = 0; int result; bool menu_quit = false; - static char clear_str[32]; MENUITEM_STRINGLIST(menu, "Settings", mpeg_sysevent_callback, - "Display Options", "Audio Options", - "Resume Options", "Play Mode", clear_str); + ID2P(LANG_MENU_DISPLAY_OPTIONS), + ID2P(LANG_MENU_AUDIO_OPTIONS), + ID2P(LANG_MENU_RESUME_OPTIONS), + ID2P(LANG_MENU_PLAY_MODE), + ID2P(LANG_CLEAR_ALL_RESUMES)); rb->button_clear_queue(); @@ -1273,10 +1332,6 @@ static void mpeg_settings(void) { mpeg_sysevent_clear(); - /* Format and add resume option to the menu display */ - rb->snprintf(clear_str, sizeof(clear_str), - "Clear all resumes: %u", settings.resume_count); - result = rb->do_menu(&menu, &selected, NULL, false); switch (result) @@ -1294,7 +1349,7 @@ static void mpeg_settings(void) break; case MPEG_SETTING_PLAY_MODE: - mpeg_set_option("Play mode", &settings.play_mode, + mpeg_set_option(rb->str(LANG_MENU_PLAY_MODE), &settings.play_mode, INT, singleall, 2, NULL); break; diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c index 6a33a544db..39ea484ff2 100644 --- a/apps/plugins/mpegplayer/mpegplayer.c +++ b/apps/plugins/mpegplayer/mpegplayer.c @@ -634,6 +634,54 @@ static unsigned draw_blendcolor(unsigned c1, unsigned c2, unsigned char amount) } #endif +#ifdef PLUGIN_USE_IRAM +/* IRAM preserving mechanism to enable talking menus */ +static char *iram_saved_copy; +extern char iramstart[], iramend[]; + +static void iram_saving_init(void) +{ +#ifndef SIMULATOR + size_t size; + iram_saved_copy = (char *)rb->plugin_get_buffer(&size); + + if (size >= (size_t)(iramend-iramstart)) + iram_saved_copy += size - (size_t)(iramend - iramstart); + else +#endif + iram_saved_copy = NULL; + + return; +} + +void mpegplayer_iram_preserve(void) +{ + if (iram_saved_copy) + { + rb->memcpy(iram_saved_copy, iramstart, iramend-iramstart); +#ifdef HAVE_CPUCACHE_INVALIDATE + /* make the icache (if it exists) up to date with the new code */ + rb->cpucache_invalidate(); +#endif /* HAVE_CPUCACHE_INVALIDATE */ + } + return; +} + +void mpegplayer_iram_restore(void) +{ + if (iram_saved_copy) + { + rb->audio_hard_stop(); + rb->memcpy(iramstart, iram_saved_copy, iramend-iramstart); +#ifdef HAVE_CPUCACHE_INVALIDATE + /* make the icache (if it exists) up to date with the new code */ + rb->cpucache_invalidate(); +#endif /* HAVE_CPUCACHE_INVALIDATE */ + } + return; +} +#endif + /* Drawing functions that operate rotated on LCD_PORTRAIT displays - * most are just wrappers of lcd_* functions with transforms applied. * The origin is the upper-left corner of the OSD area */ @@ -2369,6 +2417,10 @@ enum plugin_status plugin_start(const void* parameter) int status = PLUGIN_OK; /* assume success */ bool quit = false; +#if defined(PLUGIN_USE_IRAM) && !defined(SIMULATOR) + bool preserved_talk_state; +#endif + if (parameter == NULL) { /* No file = GTFO */ rb->splash(HZ*2, "No File"); @@ -2378,6 +2430,16 @@ enum plugin_status plugin_start(const void* parameter) /* Disable all talking before initializing IRAM */ rb->talk_disable(true); +#ifdef PLUGIN_USE_IRAM + iram_saving_init(); + +#ifndef SIMULATOR + preserved_talk_state = rb->global_settings->talk_menu; + if (!iram_saved_copy) + rb->global_settings->talk_menu = false; +#endif +#endif + #ifdef HAVE_LCD_COLOR rb->lcd_set_backdrop(NULL); rb->lcd_set_foreground(LCD_WHITE); @@ -2528,6 +2590,11 @@ enum plugin_status plugin_start(const void* parameter) stream_exit(); +#if defined(PLUGIN_USE_IRAM) && !defined(SIMULATOR) + if (!iram_saved_copy) + rb->global_settings->talk_menu = preserved_talk_state; +#endif + rb->talk_disable(false); /* Actually handle delayed processing of system events of interest diff --git a/apps/plugins/mpegplayer/mpegplayer.h b/apps/plugins/mpegplayer/mpegplayer.h index 4ddf0ca7b1..51fb9a8f8a 100644 --- a/apps/plugins/mpegplayer/mpegplayer.h +++ b/apps/plugins/mpegplayer/mpegplayer.h @@ -86,4 +86,10 @@ #define LCD_ENABLE_EVENT_0 MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0) #define LCD_ENABLE_EVENT_1 MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 1) +#ifdef PLUGIN_USE_IRAM +/* IRAM preserving mechanism to enable talking menus */ +extern void mpegplayer_iram_preserve(void); +extern void mpegplayer_iram_restore(void); +#endif + #endif /* MPEGPLAYER_H */ diff --git a/apps/plugins/mpegplayer/pcm_output.c b/apps/plugins/mpegplayer/pcm_output.c index 82e3584277..5e95d16316 100644 --- a/apps/plugins/mpegplayer/pcm_output.c +++ b/apps/plugins/mpegplayer/pcm_output.c @@ -384,11 +384,13 @@ bool pcm_output_init(void) old_sampr = rb->mixer_get_frequency(); rb->mixer_set_frequency(CLOCK_RATE); + rb->pcmbuf_fade(false, true); return true; } void pcm_output_exit(void) { + rb->pcmbuf_fade(false, false); if (old_sampr != 0) rb->mixer_set_frequency(old_sampr); } -- cgit v1.2.3