From ab0f7e17ef225f2db908276f903d1354b7777618 Mon Sep 17 00:00:00 2001 From: Stéphane Doyon Date: Sun, 4 May 2008 13:47:58 +0000 Subject: Accept FS#6188: study mode. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17355 a1c6a512-1295-4272-9138-f99709370657 --- apps/gui/gwps-common.c | 34 ++++++++++++ apps/gui/gwps-common.h | 1 + apps/gui/gwps.c | 127 +++++++++++++++++++++++++++++---------------- apps/lang/english.lang | 56 ++++++++++++++++++++ apps/menus/playback_menu.c | 6 +++ apps/onplay.c | 36 +++++++++++++ apps/playback.h | 4 +- apps/settings.h | 2 + apps/settings_list.c | 4 ++ 9 files changed, 222 insertions(+), 48 deletions(-) diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c index ed4ca17b2a..bcb82df100 100644 --- a/apps/gui/gwps-common.c +++ b/apps/gui/gwps-common.c @@ -78,6 +78,7 @@ static void gui_wps_statusbar_draw(struct gui_wps *wps, bool force) #define gui_wps_statusbar_draw(wps, force) \ gui_statusbar_draw((wps)->statusbar, (force)) #endif +#include "pcmbuf.h" /* fades the volume */ void fade(bool fade_in) @@ -143,6 +144,39 @@ bool update_onvol_change(struct gui_wps * gwps) return false; } +void play_hop(int direction) +{ + if(!wps_state.id3 || !wps_state.id3->length + || global_settings.study_hop_step == 0) + return; +#define STEP ((unsigned)global_settings.study_hop_step *1000) + if(direction == 1 + && wps_state.id3->length - wps_state.id3->elapsed < STEP+1000) { +#if CONFIG_CODEC == SWCODEC + if(global_settings.beep) + pcmbuf_beep(1000, 150, 1500*global_settings.beep); +#endif + return; + } + if((direction == -1 && wps_state.id3->elapsed < STEP)) + wps_state.id3->elapsed = 0; + else + wps_state.id3->elapsed += STEP *direction; + if((audio_status() & AUDIO_STATUS_PLAY) && !wps_state.paused) { +#if (CONFIG_CODEC == SWCODEC) + audio_pre_ff_rewind(); +#else + audio_pause(); +#endif + } + audio_ff_rewind(wps_state.id3->elapsed); +#if (CONFIG_CODEC != SWCODEC) + if (!wps_state.paused) + audio_resume(); +#endif +#undef STEP +} + bool ffwd_rew(int button) { unsigned int step = 0; /* current ff/rewind step */ diff --git a/apps/gui/gwps-common.h b/apps/gui/gwps-common.h index 76555c1c06..23080254f2 100644 --- a/apps/gui/gwps-common.h +++ b/apps/gui/gwps-common.h @@ -27,6 +27,7 @@ void fade(bool fade_in); bool gui_wps_display(void); bool update_onvol_change(struct gui_wps * gwps); bool update(struct gui_wps *gwps); +void play_hop(int direction); bool ffwd_rew(int button); void display_keylock_text(bool locked); diff --git a/apps/gui/gwps.c b/apps/gui/gwps.c index 2e72813d73..28aea4945f 100644 --- a/apps/gui/gwps.c +++ b/apps/gui/gwps.c @@ -90,6 +90,51 @@ static void gui_wps_set_margin(struct gui_wps *gwps) } #endif +static void prev_track(unsigned skip_thresh) +{ + if (!wps_state.id3 || (wps_state.id3->elapsed < skip_thresh*1000)) { + audio_prev(); + } + else { + if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type) + { + curr_cuesheet_skip(-1, wps_state.id3->elapsed); + return; + } + + if (!wps_state.paused) +#if (CONFIG_CODEC == SWCODEC) + audio_pre_ff_rewind(); +#else + audio_pause(); +#endif + + audio_ff_rewind(0); + +#if (CONFIG_CODEC != SWCODEC) + if (!wps_state.paused) + audio_resume(); +#endif + } +} + +void next_track(void) +{ + /* take care of if we're playing a cuesheet */ + if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type) + { + if (curr_cuesheet_skip(1, wps_state.id3->elapsed)) + { + /* if the result was false, then we really want + to skip to the next track */ + return; + } + } + + audio_next(); +} + + long gui_wps_show(void) { long button = 0; @@ -335,11 +380,13 @@ long gui_wps_show(void) } break; /* fast forward - OR next dir if this is straight after ACTION_WPS_SKIPNEXT */ + OR next dir if this is straight after ACTION_WPS_SKIPNEXT + OR in study mode, next track if straight after SKIPPREV. */ case ACTION_WPS_SEEKFWD: if (global_settings.party_mode) break; - if (current_tick -last_right < HZ) + if (!global_settings.study_mode + && current_tick -last_right < HZ) { if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type) { @@ -350,15 +397,23 @@ long gui_wps_show(void) audio_next_dir(); } } + else if(global_settings.study_mode + && current_tick -last_left < HZ) { + next_track(); + update_track = true; + } else ffwd_rew(ACTION_WPS_SEEKFWD); - last_right = 0; + last_right = last_left = 0; break; /* fast rewind - OR prev dir if this is straight after ACTION_WPS_SKIPPREV */ + OR prev dir if this is straight after ACTION_WPS_SKIPPREV, + OR in study mode, beg of track or prev track if this is + straight after SKIPPREV */ case ACTION_WPS_SEEKBACK: if (global_settings.party_mode) break; - if (current_tick -last_left < HZ) + if (!global_settings.study_mode + && current_tick -last_left < HZ) { if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type) { @@ -375,8 +430,14 @@ long gui_wps_show(void) audio_prev_dir(); } } + else if(global_settings.study_mode + && current_tick -last_right < HZ) + { + prev_track(3+global_settings.study_hop_step); + update_track = true; + } else ffwd_rew(ACTION_WPS_SEEKBACK); - last_left = 0; + last_left = last_right = 0; break; /* prev / restart */ @@ -404,34 +465,13 @@ long gui_wps_show(void) /* ...otherwise, do it normally */ #endif - if (!wps_state.id3 || (wps_state.id3->elapsed < 3*1000)) { - audio_prev(); - } - else { - - if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type) - { - curr_cuesheet_skip(-1, wps_state.id3->elapsed); - break; - } - - if (!wps_state.paused) -#if (CONFIG_CODEC == SWCODEC) - audio_pre_ff_rewind(); -#else - audio_pause(); -#endif - - audio_ff_rewind(0); - -#if (CONFIG_CODEC != SWCODEC) - if (!wps_state.paused) - audio_resume(); -#endif - } + if(global_settings.study_mode) + play_hop(-1); + else prev_track(3); break; - /* next */ + /* next + OR in study mode, hop by predetermined amount. */ case ACTION_WPS_SKIPNEXT: if (global_settings.party_mode) break; @@ -456,18 +496,9 @@ long gui_wps_show(void) /* ...otherwise, do it normally */ #endif - /* take care of if we're playing a cuesheet */ - if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type) - { - if (curr_cuesheet_skip(1, wps_state.id3->elapsed)) - { - /* if the result was false, then we really want - to skip to the next track */ - break; - } - } - - audio_next(); + if(global_settings.study_mode) + play_hop(1); + else next_track(); break; /* next / prev directories */ /* and set A-B markers if in a-b mode */ @@ -484,7 +515,9 @@ long gui_wps_show(void) else #endif { - audio_next_dir(); + if(global_settings.study_mode) + next_track(); + else audio_next_dir(); } break; case ACTION_WPS_ABSETA_PREVDIR: @@ -496,7 +529,9 @@ long gui_wps_show(void) else #endif { - audio_prev_dir(); + if(global_settings.study_mode) + prev_track(3); + else audio_prev_dir(); } break; /* menu key functions */ diff --git a/apps/lang/english.lang b/apps/lang/english.lang index eb19bcef3b..dd1cfc37ba 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -11604,3 +11604,59 @@ *: "Unknown" + + id: LANG_STUDY_MODE + desc: playback settings menu + user: + + *: "Study Mode" + + + *: "Study Mode" + + + *: "Study Mode" + + + + id: LANG_STUDY_HOP_STEP + desc: playback settings menu + user: + + *: "Study Increment" + + + *: "Study Increment" + + + *: "Study Increment" + + + + id: LANG_ENABLE_STUDY_MODE + desc: WPS context menu + user: + + *: "Enable Study Mode" + + + *: "Enable Study Mode" + + + *: "Enable Study Mode" + + + + id: LANG_DISABLE_STUDY_MODE + desc: WPS context menu + user: + + *: "Disable Study Mode" + + + *: "Disable Study Mode" + + + *: "Disable Study Mode" + + diff --git a/apps/menus/playback_menu.c b/apps/menus/playback_menu.c index 390d5cc9a1..1dcb42b0c5 100644 --- a/apps/menus/playback_menu.c +++ b/apps/menus/playback_menu.c @@ -174,6 +174,11 @@ MAKE_MENU(unplug_menu, ID2P(LANG_HEADPHONE_UNPLUG), 0, Icon_NOICON, &unplug_mode, &unplug_rw, &unplug_autoresume); #endif +MENUITEM_SETTING(study_mode, &global_settings.study_mode, NULL); +MENUITEM_SETTING(study_hop_step, &global_settings.study_hop_step, NULL); +MAKE_MENU(study_mode_menu, ID2P(LANG_STUDY_MODE), 0, Icon_NOICON, + &study_mode, &study_hop_step); + MAKE_MENU(playback_menu_item,ID2P(LANG_PLAYBACK),0, Icon_Playback_menu, &shuffle_item, &repeat_mode, &play_selected, @@ -194,6 +199,7 @@ MAKE_MENU(playback_menu_item,ID2P(LANG_PLAYBACK),0, #ifdef HAVE_HEADPHONE_DETECTION ,&unplug_menu #endif + ,&study_mode_menu ); static int playback_callback(int action,const struct menu_item_ex *this_item) diff --git a/apps/onplay.c b/apps/onplay.c index 45b18608e8..b65d2fe62f 100644 --- a/apps/onplay.c +++ b/apps/onplay.c @@ -1011,6 +1011,41 @@ MENUITEM_FUNCTION(eq_browse_presets_item, 0, ID2P(LANG_EQUALIZER_BROWSE), eq_browse_presets, NULL, NULL, Icon_Audio); #endif +/* study mode setting toggling */ + +static char* study_mode_toggle_get_name(int selected_item, void * data, + char *buffer) +{ + (void)selected_item; + (void)data; + snprintf(buffer, MAX_PATH, + global_settings.study_mode ? str(LANG_DISABLE_STUDY_MODE) + : str(LANG_ENABLE_STUDY_MODE)); + return buffer; +} + +static int study_mode_toggle_speak_item(int selected_item, void * data) +{ + (void)selected_item; + (void)data; + talk_id(global_settings.study_mode ? LANG_DISABLE_STUDY_MODE + : LANG_ENABLE_STUDY_MODE, false); + return 0; +} + +static int toggle_study_mode(void * param) +{ + (void)param; + global_settings.study_mode ^= 1; + return 0; +} + +MENUITEM_FUNCTION_DYNTEXT(study_mode_toggle, 0, + toggle_study_mode, NULL, + study_mode_toggle_get_name, + study_mode_toggle_speak_item, + NULL, NULL, Icon_NOICON); + /* CONTEXT_[TREE|ID3DB] items */ static int clipboard_callback(int action,const struct menu_item_ex *this_item); MENUITEM_FUNCTION(rename_file_item, 0, ID2P(LANG_RENAME), @@ -1152,6 +1187,7 @@ MAKE_ONPLAYMENU( wps_onplay_menu, ID2P(LANG_ONPLAY_MENU_TITLE), #if CONFIG_CODEC == SWCODEC &eq_menu_graphical_item, &eq_browse_presets_item, #endif + &study_mode_toggle, ); /* used when onplay() is not called in the CONTEXT_WPS context */ MAKE_ONPLAYMENU( tree_onplay_menu, ID2P(LANG_ONPLAY_MENU_TITLE), diff --git a/apps/playback.h b/apps/playback.h index 103361c507..5e1eb9865b 100644 --- a/apps/playback.h +++ b/apps/playback.h @@ -49,8 +49,8 @@ int audio_current_aa_hid(void); extern void audio_next_dir(void); extern void audio_prev_dir(void); #else -#define audio_next_dir() -#define audio_prev_dir() +#define audio_next_dir() ({ }) +#define audio_prev_dir() ({ }) #endif #endif diff --git a/apps/settings.h b/apps/settings.h index 7c32ba21e3..b21b404d9c 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -437,6 +437,8 @@ struct user_settings bool play_selected; /* Plays selected file even in shuffle mode */ int ff_rewind_min_step; /* FF/Rewind minimum step size */ int ff_rewind_accel; /* FF/Rewind acceleration (in seconds per doubling) */ + bool study_mode; /* study mode enabled */ + int study_hop_step; /* hop step in study mode, in seconds */ #ifndef HAVE_FLASH_STORAGE int disk_spindown; /* time until disk spindown, in seconds (0=off) */ diff --git a/apps/settings_list.c b/apps/settings_list.c index 78b73af149..94210ffbca 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c @@ -1163,6 +1163,10 @@ const struct settings_list settings[] = { #endif #endif OFFON_SETTING(0,cuesheet,LANG_CUESHEET_ENABLE,false,"cuesheet support", NULL), + OFFON_SETTING(0,study_mode,LANG_ENABLE_STUDY_MODE,false,"Study mode", + NULL), + INT_SETTING(0, study_hop_step, LANG_STUDY_HOP_STEP, 5, "Study hop step", + UNIT_SEC, 0, 250, 1, NULL, NULL, NULL), CHOICE_SETTING(0, start_in_screen, LANG_START_SCREEN, 1, "start in screen", "previous,root,files,db,wps,menu," #ifdef HAVE_RECORDING -- cgit v1.2.3