diff --git a/apps/audio_thread.c b/apps/audio_thread.c index 74f18454cc..bb380a4eef 100644 --- a/apps/audio_thread.c +++ b/apps/audio_thread.c @@ -38,6 +38,11 @@ #include "talk.h" #include "settings.h" +#if defined(HAVE_PITCHCONTROL) +#include "pitchscreen.h" +#include "misc.h" +#include "strcasecmp.h" +#endif /* Macros to enable logf for queues logging on SYS_TIMEOUT can be disabled */ #ifdef SIMULATOR @@ -185,4 +190,36 @@ void INIT_ATTR audio_init(void) audio_is_initialized = true; sound_settings_apply(); + +#if defined(HAVE_PITCHCONTROL) + int fd; + char line[64]; + char* name; + char* value; + int32_t num; + + fd = open_utf8(PITCH_CFG_FILE, O_RDONLY); + if (fd >= 0) + { + while (read_line(fd, line, sizeof line) > 0) + { + if (!settings_parseline(line, &name, &value)) + continue; + if (strcasecmp(name, "pitch") == 0) + { + num = atoi(value); + if (num != PITCH_SPEED_100) + sound_set_pitch(num); + } + if (strcasecmp(name, "stretch") == 0) + { + num = atoi(value); + if (num != PITCH_SPEED_100) + dsp_set_timestretch(num); + } + } + } +#endif + + } diff --git a/apps/gui/pitchscreen.c b/apps/gui/pitchscreen.c index 9f42aedb5d..13ade6091c 100644 --- a/apps/gui/pitchscreen.c +++ b/apps/gui/pitchscreen.c @@ -19,7 +19,17 @@ * ****************************************************************************/ #include "plugin.h" +#include "pitchscreen.h" + int gui_syncpitchscreen_run(void) { return (plugin_load(VIEWERS_DIR"/pitch_screen.rock", NULL) == PLUGIN_USB_CONNECTED); } + +int reset_pitch(void) +{ + sound_set_pitch(PITCH_SPEED_100); + dsp_set_timestretch(PITCH_SPEED_100); + remove(PITCH_CFG_FILE); + return 0; +} diff --git a/apps/gui/pitchscreen.h b/apps/gui/pitchscreen.h index 41eb1fd415..43d0338a2e 100644 --- a/apps/gui/pitchscreen.h +++ b/apps/gui/pitchscreen.h @@ -22,6 +22,8 @@ #ifndef _PITCHSCREEN_H_ #define _PITCHSCREEN_H_ +#define PITCH_CFG_FILE ROCKBOX_DIR "/pitch.cfg" int gui_syncpitchscreen_run(void); +int reset_pitch(void); #endif /* _PITCHSCREEN_H_ */ diff --git a/apps/onplay.c b/apps/onplay.c index 5136151c90..24f8a7bc68 100644 --- a/apps/onplay.c +++ b/apps/onplay.c @@ -711,7 +711,35 @@ MENUITEM_FUNCTION(browse_id3_item, MENU_FUNC_CHECK_RETVAL, ID2P(LANG_MENU_SHOW_I #ifdef HAVE_PITCHCONTROL MENUITEM_FUNCTION(pitch_screen_item, 0, ID2P(LANG_PITCH), gui_syncpitchscreen_run, NULL, Icon_Audio); -#endif +MENUITEM_FUNCTION(pitch_reset_item, 0, ID2P(LANG_RESET_SETTING), + reset_pitch, NULL, Icon_Submenu_Entered); + +static int pitch_callback(int action, + const struct menu_item_ex *this_item, + struct gui_synclist *this_list) +{ + if (action == ACTION_ENTER_MENUITEM) + { + int32_t ts = dsp_get_timestretch(); + if (sound_get_pitch() == PITCH_SPEED_100 && ts == PITCH_SPEED_100) + { /* if default then run pitch screen directly */ + gui_syncpitchscreen_run(); + action = ACTION_EXIT_MENUITEM; + } + } + return action; + + (void)this_item; + (void)this_list; +} + +/* pitch submenu */ +MAKE_ONPLAYMENU(pitch_menu, ID2P(LANG_PITCH), + pitch_callback, Icon_Audio, + &pitch_screen_item, + &pitch_reset_item); + +#endif /*def HAVE_PITCHCONTROL*/ #ifdef HAVE_ALBUMART MENUITEM_FUNCTION(view_album_art_item, 0, ID2P(LANG_VIEW_ALBUMART), view_album_art, NULL, Icon_NOICON); @@ -1037,7 +1065,7 @@ MAKE_ONPLAYMENU( wps_onplay_menu, ID2P(LANG_ONPLAY_MENU_TITLE), &browse_id3_item, &list_viewers_item, &delete_file_item, &view_cue_item, #ifdef HAVE_PITCHCONTROL - &pitch_screen_item, + &pitch_menu, #endif #ifdef HAVE_ALBUMART &view_album_art_item, diff --git a/apps/plugins/lib/configfile.c b/apps/plugins/lib/configfile.c index 2ab8f77e26..0bfddc71f6 100644 --- a/apps/plugins/lib/configfile.c +++ b/apps/plugins/lib/configfile.c @@ -49,8 +49,15 @@ int configfile_save(const char *filename, const struct configdata *cfg, int i; char buf[MAX_PATH]; - get_cfg_filename(buf, MAX_PATH, filename); - fd = rb->creat(buf, 0666); + + if (rb->strncmp(filename, ROCKBOX_DIR, sizeof(ROCKBOX_DIR) - 1) != 0) + { + get_cfg_filename(buf, MAX_PATH, filename); + fd = rb->creat(buf, 0666); + } + else /* allow saving to the rockbox directory */ + fd = rb->creat(filename, 0666); + if(fd < 0) return fd*10 - 1; diff --git a/apps/plugins/pitch_screen.c b/apps/plugins/pitch_screen.c index 4af34fed3b..8d4802da28 100644 --- a/apps/plugins/pitch_screen.c +++ b/apps/plugins/pitch_screen.c @@ -22,6 +22,11 @@ #include "plugin.h" #include "lib/icon_helper.h" #include "lib/arg_helper.h" +#include "lib/configfile.h" +#include "../gui/pitchscreen.h" /*PITCH_CFG_FILE*/ + +#define CFG_FILE PITCH_CFG_FILE +#define CFG_VER 1 #define ICON_BORDER 12 /* icons are currently 7x8, so add ~2 pixels */ /* on both sides when drawing */ @@ -49,6 +54,12 @@ struct pvars }; static struct pvars pitch_vars; +static struct configdata pitchcfg[] = +{ + {TYPE_INT, PITCH_MIN, PITCH_MAX, { .int_p = &pitch_vars.pitch }, "pitch", NULL}, + {TYPE_INT, STRETCH_MIN, STRETCH_MAX, { .int_p = &pitch_vars.stretch }, "stretch", NULL}, +}; + enum { PITCH_TOP = 0, @@ -1218,6 +1229,9 @@ enum plugin_status plugin_start(const void* parameter) bool gui = false; rb->pcmbuf_set_low_latency(true); + struct pvars cur; + fill_pitchvars(&cur); + /* Figure out whether to be in timestretch mode */ if (parameter == NULL) /* gui mode */ { @@ -1230,8 +1244,6 @@ enum plugin_status plugin_start(const void* parameter) } else { - struct pvars cur; - fill_pitchvars(&cur); fill_pitchvars(&pitch_vars); argparse((const char*) parameter, -1, NULL, &arg_callback); if (pitch_vars.pitch != cur.pitch) @@ -1275,6 +1287,19 @@ enum plugin_status plugin_start(const void* parameter) if (gui && gui_syncpitchscreen_run() == 1) return PLUGIN_USB_CONNECTED; + + if (gui) + { + fill_pitchvars(&pitch_vars); + + if (pitch_vars.pitch != cur.pitch || pitch_vars.stretch != cur.stretch) + { + if (configfile_save(CFG_FILE, pitchcfg, 2, CFG_VER) >= 0) + rb->splash(HZ, ID2P(LANG_SETTINGS_SAVED)); + else + rb->splash(HZ, ID2P(LANG_ERROR_WRITING_CONFIG)); + } + } rb->pcmbuf_set_low_latency(false); return PLUGIN_OK; } diff --git a/manual/rockbox_interface/wps.tex b/manual/rockbox_interface/wps.tex index b00d066525..a81cce753d 100644 --- a/manual/rockbox_interface/wps.tex +++ b/manual/rockbox_interface/wps.tex @@ -287,12 +287,19 @@ This may even be the whole track. same ratio as well as remain between 50\% and 200\%. The value of the rate, pitch and speed - is not persistent, i.e. after the \dap\ is turned on it will - always be set to 100\%. However, the rate, pitch and speed - information will be stored in any bookmarks you may create - (see \reference{ref:Bookmarkconfigactual}) and will be restored upon + is persistent, i.e. when the \dap\ is turned on it will + always be set to your last value. Selecting \setting{Pitch} again + will now display a menu with \setting{Pitch} and \setting{Reset Setting}. + Selecting \setting{Reset Setting} will reset the pitch to 100\% now and at next boot. + However the rate, pitch and speed information will be stored in any bookmarks + you may create (see \reference{ref:Bookmarkconfigactual}) + while the pitch is altered and will be restored upon playing back those bookmarks. + \note{ If a bookmark has changed pitch, settings will remain till + the \dap{} is restarted and your (possibly different or default) + persistent settings will then be restored.} + \begin{btnmap} \ActionPsToggleMode \opt{HAVEREMOTEKEYMAP}{& \ActionRCPsToggleMode}