mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-05-12 11:43:16 -04:00
Compare commits
5 commits
f83cb1f7d5
...
a1040cda5d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1040cda5d | ||
|
|
cc7418dd8b | ||
|
|
5ac105c837 | ||
|
|
e405858b9e | ||
|
|
e85f120190 |
19 changed files with 563 additions and 22 deletions
|
|
@ -829,6 +829,8 @@ long gui_wps_show(void)
|
||||||
if (retval == ONPLAY_MAINMENU
|
if (retval == ONPLAY_MAINMENU
|
||||||
|| !audio_status())
|
|| !audio_status())
|
||||||
return GO_TO_ROOT;
|
return GO_TO_ROOT;
|
||||||
|
else if (retval == ONPLAY_REVEAL_FILE)
|
||||||
|
return GO_TO_FILEBROWSER;
|
||||||
else if (retval == ONPLAY_PLAYLIST)
|
else if (retval == ONPLAY_PLAYLIST)
|
||||||
return GO_TO_PLAYLIST_VIEWER;
|
return GO_TO_PLAYLIST_VIEWER;
|
||||||
else if (retval == ONPLAY_PLUGIN)
|
else if (retval == ONPLAY_PLUGIN)
|
||||||
|
|
|
||||||
|
|
@ -16984,3 +16984,73 @@
|
||||||
*: "U S B"
|
*: "U S B"
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_COUNTDOWN_TIMER_SET
|
||||||
|
desc: countdown_timer plugin - header shown on the setup screen where the user enters the countdown duration
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "SET TIMER"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "SET TIMER"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Set timer"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_COUNTDOWN_TIMER_RUNNING
|
||||||
|
desc: countdown_timer plugin - status label shown while the countdown is active
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "RUNNING"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "RUNNING"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Running"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_COUNTDOWN_TIMER_PAUSED
|
||||||
|
desc: countdown_timer plugin - status label shown while the countdown is paused
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "PAUSED"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "PAUSED"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Paused"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_COUNTDOWN_TIMER_OVERTIME
|
||||||
|
desc: countdown_timer plugin - status label shown when the countdown has passed zero and is counting up
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "OVERTIME"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "OVERTIME"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Overtime"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_COUNTDOWN_TIMER_FINISHED
|
||||||
|
desc: countdown_timer plugin - status label shown at the moment the countdown expires
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "FINISHED"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "FINISHED"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Finished"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
|
|
||||||
|
|
@ -17057,3 +17057,115 @@
|
||||||
*: "U S B"
|
*: "U S B"
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_FILE_NOT_FOUND
|
||||||
|
desc: When file does not exist
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "File not found"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "File not found"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "File not found"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_SHOW_IN_FILES
|
||||||
|
desc: Reveal item in File Browser
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "Show in Files"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Show in Files"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Show in Files"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_CHANNEL_SWAP
|
||||||
|
desc: in sound_settings
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "Swap Left & Right"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Swap Left & Right"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Swap Left & Right"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_COUNTDOWN_TIMER_SET
|
||||||
|
desc: countdown_timer plugin - header shown on the setup screen where the user enters the countdown duration
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "SET TIMER"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "SET TIMER"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Set timer"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_COUNTDOWN_TIMER_RUNNING
|
||||||
|
desc: countdown_timer plugin - status label shown while the countdown is active
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "RUNNING"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "RUNNING"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Running"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_COUNTDOWN_TIMER_PAUSED
|
||||||
|
desc: countdown_timer plugin - status label shown while the countdown is paused
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "PAUSED"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "PAUSED"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Paused"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_COUNTDOWN_TIMER_OVERTIME
|
||||||
|
desc: countdown_timer plugin - status label shown when the countdown has passed zero and is counting up
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "OVERTIME"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "OVERTIME"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Overtime"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_COUNTDOWN_TIMER_FINISHED
|
||||||
|
desc: countdown_timer plugin - status label shown at the moment the countdown expires
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "FINISHED"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "FINISHED"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Finished"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
|
|
||||||
|
|
@ -897,6 +897,26 @@ static bool onplay_load_plugin(void *param)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int reveal(void)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_TAGCACHE
|
||||||
|
if (!prepare_database_sel(NULL))
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
if (!file_exists(selected_file.path))
|
||||||
|
{
|
||||||
|
splash(HZ*2, ID2P(LANG_FILE_NOT_FOUND));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
strmemccpy(global_status.browse_last_folder, selected_file.path,
|
||||||
|
sizeof global_status.browse_last_folder);
|
||||||
|
onplay_result = ONPLAY_REVEAL_FILE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MENUITEM_FUNCTION(reveal_item, 0, ID2P(LANG_SHOW_IN_FILES),
|
||||||
|
reveal, clipboard_callback, Icon_file_view_menu);
|
||||||
MENUITEM_FUNCTION(list_viewers_item, 0, ID2P(LANG_ONPLAY_OPEN_WITH),
|
MENUITEM_FUNCTION(list_viewers_item, 0, ID2P(LANG_ONPLAY_OPEN_WITH),
|
||||||
list_viewers, clipboard_callback, Icon_NOICON);
|
list_viewers, clipboard_callback, Icon_NOICON);
|
||||||
MENUITEM_FUNCTION_W_PARAM(properties_item, 0, ID2P(LANG_PROPERTIES),
|
MENUITEM_FUNCTION_W_PARAM(properties_item, 0, ID2P(LANG_PROPERTIES),
|
||||||
|
|
@ -1033,7 +1053,8 @@ static int clipboard_callback(int action,
|
||||||
if (selected_file.context == CONTEXT_ID3DB)
|
if (selected_file.context == CONTEXT_ID3DB)
|
||||||
{
|
{
|
||||||
if (this_item == &track_info_item ||
|
if (this_item == &track_info_item ||
|
||||||
this_item == &pictureflow_item)
|
this_item == &pictureflow_item ||
|
||||||
|
this_item == &reveal_item)
|
||||||
return action;
|
return action;
|
||||||
return ACTION_EXIT_MENUITEM;
|
return ACTION_EXIT_MENUITEM;
|
||||||
}
|
}
|
||||||
|
|
@ -1088,7 +1109,9 @@ static int clipboard_callback(int action,
|
||||||
if (*tree_get_context()->dirfilter != SHOW_M3U)
|
if (*tree_get_context()->dirfilter != SHOW_M3U)
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
else if (this_item == &delete_file_item)
|
else if (this_item == &delete_file_item ||
|
||||||
|
(this_item == &reveal_item &&
|
||||||
|
selected_file.context == CONTEXT_WPS))
|
||||||
return action;
|
return action;
|
||||||
#if LCD_DEPTH > 1
|
#if LCD_DEPTH > 1
|
||||||
else if (this_item == &set_backdrop_item)
|
else if (this_item == &set_backdrop_item)
|
||||||
|
|
@ -1124,8 +1147,8 @@ MAKE_ONPLAYMENU( wps_onplay_menu, ID2P(LANG_ONPLAY_MENU_TITLE),
|
||||||
#endif
|
#endif
|
||||||
&bookmark_menu,
|
&bookmark_menu,
|
||||||
&plugin_item,
|
&plugin_item,
|
||||||
&browse_id3_item, &list_viewers_item,
|
&browse_id3_item,
|
||||||
&delete_file_item, &view_cue_item,
|
&reveal_item, &view_cue_item,
|
||||||
#ifdef HAVE_PITCHCONTROL
|
#ifdef HAVE_PITCHCONTROL
|
||||||
&pitch_menu,
|
&pitch_menu,
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1162,6 +1185,7 @@ MAKE_ONPLAYMENU( tree_onplay_menu, ID2P(LANG_ONPLAY_MENU_TITLE),
|
||||||
&rename_file_item, &clipboard_cut_item, &clipboard_copy_item,
|
&rename_file_item, &clipboard_cut_item, &clipboard_copy_item,
|
||||||
&clipboard_paste_item, &delete_file_item, &delete_dir_item,
|
&clipboard_paste_item, &delete_file_item, &delete_dir_item,
|
||||||
&list_viewers_item, &create_dir_item, &properties_item, &track_info_item,
|
&list_viewers_item, &create_dir_item, &properties_item, &track_info_item,
|
||||||
|
&reveal_item,
|
||||||
#ifdef HAVE_TAGCACHE
|
#ifdef HAVE_TAGCACHE
|
||||||
&pictureflow_item,
|
&pictureflow_item,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ enum {
|
||||||
ONPLAY_MAINMENU = -1,
|
ONPLAY_MAINMENU = -1,
|
||||||
ONPLAY_OK = 0,
|
ONPLAY_OK = 0,
|
||||||
ONPLAY_RELOAD_DIR,
|
ONPLAY_RELOAD_DIR,
|
||||||
|
ONPLAY_REVEAL_FILE,
|
||||||
ONPLAY_START_PLAY,
|
ONPLAY_START_PLAY,
|
||||||
ONPLAY_PLAYLIST,
|
ONPLAY_PLAYLIST,
|
||||||
ONPLAY_PLUGIN,
|
ONPLAY_PLUGIN,
|
||||||
|
|
|
||||||
|
|
@ -515,9 +515,15 @@ static void format_line(struct playlist_entry* track, char* str,
|
||||||
int len)
|
int len)
|
||||||
{
|
{
|
||||||
char *id3viewc = NULL;
|
char *id3viewc = NULL;
|
||||||
char *skipped = "";
|
char *skipped, *prefix, *suffix;
|
||||||
|
skipped = prefix = suffix = "";
|
||||||
if (track->attr & PLAYLIST_ATTR_SKIPPED)
|
if (track->attr & PLAYLIST_ATTR_SKIPPED)
|
||||||
skipped = "(ERR) ";
|
skipped = "(ERR) ";
|
||||||
|
if (track->index == viewer.current_playing_track)
|
||||||
|
{
|
||||||
|
prefix = "[";
|
||||||
|
suffix = "]";
|
||||||
|
}
|
||||||
if (!(track->attr & PLAYLIST_ATTR_RETRIEVE_ID3_ATTEMPTED) &&
|
if (!(track->attr & PLAYLIST_ATTR_RETRIEVE_ID3_ATTEMPTED) &&
|
||||||
(global_settings.playlist_viewer_track_display ==
|
(global_settings.playlist_viewer_track_display ==
|
||||||
PLAYLIST_VIEWER_ENTRY_SHOW_ID3_TITLE_AND_ALBUM ||
|
PLAYLIST_VIEWER_ENTRY_SHOW_ID3_TITLE_AND_ALBUM ||
|
||||||
|
|
@ -591,9 +597,10 @@ static void format_line(struct playlist_entry* track, char* str,
|
||||||
format_name(name, track->name, sizeof(name));
|
format_name(name, track->name, sizeof(name));
|
||||||
if (global_settings.playlist_viewer_indices)
|
if (global_settings.playlist_viewer_indices)
|
||||||
/* Display playlist index */
|
/* Display playlist index */
|
||||||
snprintf(str, len, "%d. %s%s", track->display_index, skipped, name);
|
snprintf(str, len, "%s%d. %s%s%s",
|
||||||
|
prefix, track->display_index, skipped, name, suffix);
|
||||||
else
|
else
|
||||||
snprintf(str, len, "%s%s", skipped, name);
|
snprintf(str, len, "%s%s%s%s", prefix, skipped, name, suffix);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -603,9 +610,10 @@ static void format_line(struct playlist_entry* track, char* str,
|
||||||
}
|
}
|
||||||
if (global_settings.playlist_viewer_indices)
|
if (global_settings.playlist_viewer_indices)
|
||||||
/* Display playlist index */
|
/* Display playlist index */
|
||||||
snprintf(str, len, "%d. %s%s", track->display_index, skipped, id3viewc);
|
snprintf(str, len, "%s%d. %s%s%s",
|
||||||
|
prefix, track->display_index, skipped, id3viewc, suffix);
|
||||||
else
|
else
|
||||||
snprintf(str, len, "%s%s", skipped, id3viewc);
|
snprintf(str, len, "%s%s%s%s", prefix, skipped, id3viewc, suffix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ chopper,games
|
||||||
clix,games
|
clix,games
|
||||||
clock,apps
|
clock,apps
|
||||||
codebuster,games
|
codebuster,games
|
||||||
|
countdown_timer,apps
|
||||||
credits,viewers
|
credits,viewers
|
||||||
cube,demos
|
cube,demos
|
||||||
cue_playlist,viewers
|
cue_playlist,viewers
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ db_folder_select.c
|
||||||
tagcache/tagcache.c
|
tagcache/tagcache.c
|
||||||
#endif
|
#endif
|
||||||
chessclock.c
|
chessclock.c
|
||||||
|
countdown_timer.c
|
||||||
credits.c
|
credits.c
|
||||||
cube.c
|
cube.c
|
||||||
cue_playlist.c
|
cue_playlist.c
|
||||||
|
|
|
||||||
242
apps/plugins/countdown_timer.c
Normal file
242
apps/plugins/countdown_timer.c
Normal file
|
|
@ -0,0 +1,242 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2026 Teun van Dalen
|
||||||
|
*
|
||||||
|
* 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 "lib/pluginlib_actions.h"
|
||||||
|
#include "lib/pluginlib_exit.h"
|
||||||
|
|
||||||
|
const struct button_mapping *plugin_contexts[] = { pla_main_ctx };
|
||||||
|
|
||||||
|
#define MAX_MINUTES 99
|
||||||
|
#define MAX_SECONDS 59
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
STATE_SETUP,
|
||||||
|
STATE_RUNNING,
|
||||||
|
STATE_PAUSED,
|
||||||
|
STATE_FINISHED,
|
||||||
|
} timer_state_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int set_minutes;
|
||||||
|
int set_seconds;
|
||||||
|
int current_field;
|
||||||
|
long remaining_ticks;
|
||||||
|
long last_tick;
|
||||||
|
timer_state_t state;
|
||||||
|
} timer_ctx_t;
|
||||||
|
|
||||||
|
static inline int get_button(void)
|
||||||
|
{
|
||||||
|
return pluginlib_getaction(HZ / 10, plugin_contexts,
|
||||||
|
ARRAYLEN(plugin_contexts));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw(const timer_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
char time_str[12];
|
||||||
|
const char *status_str;
|
||||||
|
int disp_min, disp_sec;
|
||||||
|
int w, h, x, y;
|
||||||
|
|
||||||
|
rb->lcd_clear_display();
|
||||||
|
|
||||||
|
if (ctx->state == STATE_SETUP) {
|
||||||
|
disp_min = ctx->set_minutes;
|
||||||
|
disp_sec = ctx->set_seconds;
|
||||||
|
if (ctx->current_field == 0)
|
||||||
|
rb->snprintf(time_str, sizeof(time_str), "[%02d]:%02d",
|
||||||
|
disp_min, disp_sec);
|
||||||
|
else
|
||||||
|
rb->snprintf(time_str, sizeof(time_str), "%02d:[%02d]",
|
||||||
|
disp_min, disp_sec);
|
||||||
|
status_str = rb->str(LANG_COUNTDOWN_TIMER_SET);
|
||||||
|
} else if (ctx->state == STATE_FINISHED) {
|
||||||
|
rb->snprintf(time_str, sizeof(time_str), "00:00");
|
||||||
|
status_str = rb->str(LANG_COUNTDOWN_TIMER_FINISHED);
|
||||||
|
} else {
|
||||||
|
if (ctx->remaining_ticks >= 0) {
|
||||||
|
int remaining_secs = (ctx->remaining_ticks + HZ - 1) / HZ;
|
||||||
|
disp_min = remaining_secs / 60;
|
||||||
|
disp_sec = remaining_secs % 60;
|
||||||
|
rb->snprintf(time_str, sizeof(time_str), "%02d:%02d",
|
||||||
|
disp_min, disp_sec);
|
||||||
|
} else {
|
||||||
|
int over_secs = ((-ctx->remaining_ticks) + HZ - 1) / HZ;
|
||||||
|
disp_min = over_secs / 60;
|
||||||
|
disp_sec = over_secs % 60;
|
||||||
|
rb->snprintf(time_str, sizeof(time_str), "-%02d:%02d",
|
||||||
|
disp_min, disp_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->state == STATE_RUNNING && ctx->remaining_ticks < 0)
|
||||||
|
status_str = rb->str(LANG_COUNTDOWN_TIMER_OVERTIME);
|
||||||
|
else if (ctx->state == STATE_RUNNING)
|
||||||
|
status_str = rb->str(LANG_COUNTDOWN_TIMER_RUNNING);
|
||||||
|
else
|
||||||
|
status_str = rb->str(LANG_COUNTDOWN_TIMER_PAUSED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw status string above center */
|
||||||
|
rb->lcd_getstringsize(status_str, &w, &h);
|
||||||
|
x = (LCD_WIDTH - w) / 2;
|
||||||
|
y = (LCD_HEIGHT / 2) - h - 2;
|
||||||
|
rb->lcd_putsxy(x, y, status_str);
|
||||||
|
|
||||||
|
/* Draw time string at center */
|
||||||
|
rb->lcd_getstringsize(time_str, &w, &h);
|
||||||
|
x = (LCD_WIDTH - w) / 2;
|
||||||
|
y = LCD_HEIGHT / 2;
|
||||||
|
rb->lcd_putsxy(x, y, time_str);
|
||||||
|
|
||||||
|
rb->lcd_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
enum plugin_status plugin_start(const void *parameter)
|
||||||
|
{
|
||||||
|
timer_ctx_t ctx = {
|
||||||
|
.set_minutes = 10,
|
||||||
|
.set_seconds = 0,
|
||||||
|
.current_field = 0,
|
||||||
|
.remaining_ticks = 60 * HZ,
|
||||||
|
.last_tick = 0,
|
||||||
|
.state = STATE_SETUP,
|
||||||
|
};
|
||||||
|
bool overtime_alerted = false;
|
||||||
|
int button;
|
||||||
|
|
||||||
|
(void)parameter;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (ctx.state == STATE_RUNNING) {
|
||||||
|
long now = *rb->current_tick;
|
||||||
|
ctx.remaining_ticks -= now - ctx.last_tick;
|
||||||
|
ctx.last_tick = now;
|
||||||
|
|
||||||
|
if (ctx.remaining_ticks < 0 && !overtime_alerted) {
|
||||||
|
overtime_alerted = true;
|
||||||
|
ctx.state = STATE_FINISHED;
|
||||||
|
draw(&ctx);
|
||||||
|
rb->audio_pause();
|
||||||
|
#ifdef HAVE_BACKLIGHT
|
||||||
|
rb->backlight_on();
|
||||||
|
#endif
|
||||||
|
rb->beep_play(1000, 200, 1000);
|
||||||
|
rb->sleep(HZ / 4);
|
||||||
|
rb->beep_play(1000, 200, 1000);
|
||||||
|
rb->sleep(HZ / 4);
|
||||||
|
rb->beep_play(1000, 400, 1000);
|
||||||
|
rb->sleep(HZ + HZ / 2);
|
||||||
|
rb->audio_resume();
|
||||||
|
ctx.state = STATE_RUNNING;
|
||||||
|
/* Reset last_tick so the beep/sleep time is not counted
|
||||||
|
* against remaining_ticks on the next iteration. */
|
||||||
|
ctx.last_tick = *rb->current_tick;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(&ctx);
|
||||||
|
button = get_button();
|
||||||
|
|
||||||
|
switch (ctx.state) {
|
||||||
|
case STATE_SETUP: {
|
||||||
|
bool time_changed = false;
|
||||||
|
switch (button) {
|
||||||
|
#ifdef HAVE_SCROLLWHEEL
|
||||||
|
case PLA_SCROLL_FWD:
|
||||||
|
case PLA_SCROLL_FWD_REPEAT:
|
||||||
|
#endif
|
||||||
|
case PLA_UP:
|
||||||
|
case PLA_UP_REPEAT:
|
||||||
|
if (ctx.current_field == 0)
|
||||||
|
ctx.set_minutes = (ctx.set_minutes + 1) % (MAX_MINUTES + 1);
|
||||||
|
else
|
||||||
|
ctx.set_seconds = (ctx.set_seconds + 1) % (MAX_SECONDS + 1);
|
||||||
|
time_changed = true;
|
||||||
|
break;
|
||||||
|
#ifdef HAVE_SCROLLWHEEL
|
||||||
|
case PLA_SCROLL_BACK:
|
||||||
|
case PLA_SCROLL_BACK_REPEAT:
|
||||||
|
#endif
|
||||||
|
case PLA_DOWN:
|
||||||
|
case PLA_DOWN_REPEAT:
|
||||||
|
if (ctx.current_field == 0)
|
||||||
|
ctx.set_minutes = (ctx.set_minutes + MAX_MINUTES) % (MAX_MINUTES + 1);
|
||||||
|
else
|
||||||
|
ctx.set_seconds = (ctx.set_seconds + MAX_SECONDS) % (MAX_SECONDS + 1);
|
||||||
|
time_changed = true;
|
||||||
|
break;
|
||||||
|
case PLA_LEFT:
|
||||||
|
case PLA_LEFT_REPEAT:
|
||||||
|
case PLA_RIGHT:
|
||||||
|
case PLA_RIGHT_REPEAT:
|
||||||
|
ctx.current_field = (ctx.current_field + 1) % 2;
|
||||||
|
break;
|
||||||
|
case PLA_SELECT:
|
||||||
|
if (ctx.set_minutes > 0 || ctx.set_seconds > 0) {
|
||||||
|
ctx.remaining_ticks = (ctx.set_minutes * 60 + ctx.set_seconds) * HZ;
|
||||||
|
ctx.last_tick = *rb->current_tick;
|
||||||
|
ctx.state = STATE_RUNNING;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
exit_on_usb(button);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (time_changed)
|
||||||
|
ctx.remaining_ticks = (ctx.set_minutes * 60 + ctx.set_seconds) * HZ;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case STATE_RUNNING:
|
||||||
|
switch (button) {
|
||||||
|
case PLA_SELECT:
|
||||||
|
ctx.state = STATE_PAUSED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
exit_on_usb(button);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_FINISHED:
|
||||||
|
exit_on_usb(button);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_PAUSED:
|
||||||
|
switch (button) {
|
||||||
|
case PLA_SELECT:
|
||||||
|
ctx.last_tick = *rb->current_tick;
|
||||||
|
ctx.state = STATE_RUNNING;
|
||||||
|
break;
|
||||||
|
case PLA_UP:
|
||||||
|
case PLA_UP_REPEAT:
|
||||||
|
case PLA_CANCEL:
|
||||||
|
case PLA_EXIT:
|
||||||
|
return PLUGIN_OK;
|
||||||
|
default:
|
||||||
|
exit_on_usb(button);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1060,11 +1060,12 @@ const struct settings_list settings[] = {
|
||||||
/* 3-d enhancement effect */
|
/* 3-d enhancement effect */
|
||||||
CHOICE_SETTING(0, channel_config, LANG_CHANNEL_CONFIGURATION,
|
CHOICE_SETTING(0, channel_config, LANG_CHANNEL_CONFIGURATION,
|
||||||
0,"channels",
|
0,"channels",
|
||||||
"stereo,mono,custom,mono left,mono right,karaoke",
|
"stereo,mono,custom,mono left,mono right,karaoke,swap",
|
||||||
sound_set_channels, 6,
|
sound_set_channels, 7,
|
||||||
ID2P(LANG_CHANNEL_STEREO), ID2P(LANG_CHANNEL_MONO),
|
ID2P(LANG_CHANNEL_STEREO), ID2P(LANG_CHANNEL_MONO),
|
||||||
ID2P(LANG_CHANNEL_CUSTOM), ID2P(LANG_CHANNEL_LEFT),
|
ID2P(LANG_CHANNEL_CUSTOM), ID2P(LANG_CHANNEL_LEFT),
|
||||||
ID2P(LANG_CHANNEL_RIGHT), ID2P(LANG_CHANNEL_KARAOKE)),
|
ID2P(LANG_CHANNEL_RIGHT), ID2P(LANG_CHANNEL_KARAOKE),
|
||||||
|
ID2P(LANG_CHANNEL_SWAP)),
|
||||||
SOUND_SETTING(0, stereo_width, LANG_STEREO_WIDTH,
|
SOUND_SETTING(0, stereo_width, LANG_STEREO_WIDTH,
|
||||||
"stereo_width", SOUND_STEREO_WIDTH),
|
"stereo_width", SOUND_STEREO_WIDTH),
|
||||||
#ifdef AUDIOHW_HAVE_DEPTH_3D
|
#ifdef AUDIOHW_HAVE_DEPTH_3D
|
||||||
|
|
|
||||||
|
|
@ -975,6 +975,10 @@ static int dirbrowse(void)
|
||||||
return exit_to_new_screen(GO_TO_ROOT);
|
return exit_to_new_screen(GO_TO_ROOT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ONPLAY_REVEAL_FILE:
|
||||||
|
return exit_to_new_screen(GO_TO_FILEBROWSER);
|
||||||
|
break;
|
||||||
|
|
||||||
case ONPLAY_OK:
|
case ONPLAY_OK:
|
||||||
restore = do_restore_display;
|
restore = do_restore_display;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -760,6 +760,7 @@ Yegor Chernyshov
|
||||||
Javier Gutiérrez Gertrúdix
|
Javier Gutiérrez Gertrúdix
|
||||||
Sergey Puskov
|
Sergey Puskov
|
||||||
Eivind Ødegård
|
Eivind Ødegård
|
||||||
|
Teun van Dalen
|
||||||
|
|
||||||
The libmad team
|
The libmad team
|
||||||
The wavpack team
|
The wavpack team
|
||||||
|
|
|
||||||
|
|
@ -674,6 +674,7 @@ enum AUDIOHW_CHANNEL_CONFIG
|
||||||
SOUND_CHAN_MONO_LEFT,
|
SOUND_CHAN_MONO_LEFT,
|
||||||
SOUND_CHAN_MONO_RIGHT,
|
SOUND_CHAN_MONO_RIGHT,
|
||||||
SOUND_CHAN_KARAOKE,
|
SOUND_CHAN_KARAOKE,
|
||||||
|
SOUND_CHAN_SWAP,
|
||||||
SOUND_CHAN_NUM_MODES,
|
SOUND_CHAN_NUM_MODES,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ void channel_mode_proc_custom(struct dsp_proc_entry *this,
|
||||||
struct dsp_buffer **buf_p);
|
struct dsp_buffer **buf_p);
|
||||||
void channel_mode_proc_karaoke(struct dsp_proc_entry *this,
|
void channel_mode_proc_karaoke(struct dsp_proc_entry *this,
|
||||||
struct dsp_buffer **buf_p);
|
struct dsp_buffer **buf_p);
|
||||||
|
void channel_mode_proc_swap(struct dsp_proc_entry *this,
|
||||||
|
struct dsp_buffer **buf_p);
|
||||||
|
|
||||||
static struct channel_mode_data
|
static struct channel_mode_data
|
||||||
{
|
{
|
||||||
|
|
@ -131,6 +133,25 @@ void channel_mode_proc_karaoke(struct dsp_proc_entry *this,
|
||||||
}
|
}
|
||||||
#endif /* CPU */
|
#endif /* CPU */
|
||||||
|
|
||||||
|
void channel_mode_proc_swap(struct dsp_proc_entry *this,
|
||||||
|
struct dsp_buffer **buf_p)
|
||||||
|
{
|
||||||
|
struct dsp_buffer *buf = *buf_p;
|
||||||
|
int32_t *sl = buf->p32[0];
|
||||||
|
int32_t *sr = buf->p32[1];
|
||||||
|
int count = buf->remcount;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int32_t l = *sl;
|
||||||
|
*sl++ = *sr;
|
||||||
|
*sr++ = l;
|
||||||
|
}
|
||||||
|
while (--count > 0);
|
||||||
|
|
||||||
|
(void)this;
|
||||||
|
}
|
||||||
|
|
||||||
void channel_mode_proc_mono_left(struct dsp_proc_entry *this,
|
void channel_mode_proc_mono_left(struct dsp_proc_entry *this,
|
||||||
struct dsp_buffer **buf_p)
|
struct dsp_buffer **buf_p)
|
||||||
{
|
{
|
||||||
|
|
@ -194,6 +215,7 @@ static void update_process_fn(struct dsp_proc_entry *this)
|
||||||
[SOUND_CHAN_MONO_LEFT] = channel_mode_proc_mono_left,
|
[SOUND_CHAN_MONO_LEFT] = channel_mode_proc_mono_left,
|
||||||
[SOUND_CHAN_MONO_RIGHT] = channel_mode_proc_mono_right,
|
[SOUND_CHAN_MONO_RIGHT] = channel_mode_proc_mono_right,
|
||||||
[SOUND_CHAN_KARAOKE] = channel_mode_proc_karaoke,
|
[SOUND_CHAN_KARAOKE] = channel_mode_proc_karaoke,
|
||||||
|
[SOUND_CHAN_SWAP] = channel_mode_proc_swap,
|
||||||
};
|
};
|
||||||
|
|
||||||
this->process = fns[((struct channel_mode_data *)this->data)->mode];
|
this->process = fns[((struct channel_mode_data *)this->data)->mode];
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,9 @@ change to customise your listening experience.
|
||||||
to make the singer sound centrally placed, this often (but not
|
to make the singer sound centrally placed, this often (but not
|
||||||
always) has the effect of removing the voice track from a song. This
|
always) has the effect of removing the voice track from a song. This
|
||||||
setting also very often has other undesirable effects on the sound.
|
setting also very often has other undesirable effects on the sound.
|
||||||
|
\item[Swap Left \& Right.]
|
||||||
|
Plays the left channel in the right stereo channel, and the right
|
||||||
|
channel in the left stereo channel.
|
||||||
\end{description}
|
\end{description}
|
||||||
|
|
||||||
\section{Stereo Width}
|
\section{Stereo Width}
|
||||||
|
|
|
||||||
51
manual/plugins/countdown_timer.tex
Normal file
51
manual/plugins/countdown_timer.tex
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
% $Id$ %
|
||||||
|
\subsection{Countdown_timer}
|
||||||
|
|
||||||
|
A countdown timer. Set the desired duration, start the countdown, and the
|
||||||
|
\dap{} will alert you with a beep sequence when time is up. The timer
|
||||||
|
defaults to 10 minutes on launch.
|
||||||
|
|
||||||
|
\subsubsection{Setting the timer}
|
||||||
|
|
||||||
|
When the plugin starts, the display shows the time to count down from with
|
||||||
|
the active field highlighted in brackets (e.g.\ \texttt{[10]:00}).
|
||||||
|
|
||||||
|
\begin{btnmap}
|
||||||
|
\opt{scrollwheel}{\PluginScrollFwd{} / \PluginScrollBack{} or }
|
||||||
|
\PluginUp{} / \PluginDown
|
||||||
|
\opt{HAVEREMOTEKEYMAP}{& \PluginRCUp{} / \PluginRCDown}
|
||||||
|
& Increase / decrease the selected field \\
|
||||||
|
|
||||||
|
\PluginLeft{} / \PluginRight
|
||||||
|
\opt{HAVEREMOTEKEYMAP}{& \PluginRCLeft{} / \PluginRCRight}
|
||||||
|
& Switch between the minutes and seconds fields \\
|
||||||
|
|
||||||
|
\PluginSelect
|
||||||
|
\opt{HAVEREMOTEKEYMAP}{& \PluginRCSelect}
|
||||||
|
& Start the countdown \\
|
||||||
|
\end{btnmap}
|
||||||
|
|
||||||
|
Minutes can be set from 0 to 99 and seconds from 0 to 59. The timer cannot
|
||||||
|
be started if both fields are zero. Values wrap around when incremented or
|
||||||
|
decremented past their limits.
|
||||||
|
|
||||||
|
\subsubsection{Running the timer}
|
||||||
|
|
||||||
|
Once started, the remaining time counts down in \texttt{MM:SS} format.
|
||||||
|
|
||||||
|
\begin{btnmap}
|
||||||
|
\PluginSelect
|
||||||
|
\opt{HAVEREMOTEKEYMAP}{& \PluginRCSelect}
|
||||||
|
& Pause / resume the timer \\
|
||||||
|
|
||||||
|
\nopt{IPOD_4G_PAD,IPOD_3G_PAD}{\PluginCancel}
|
||||||
|
\opt{IPOD_4G_PAD,IPOD_3G_PAD}{\ButtonMenu}
|
||||||
|
\opt{HAVEREMOTEKEYMAP}{& \PluginRCCancel}
|
||||||
|
& Quit (only available while paused) \\
|
||||||
|
\end{btnmap}
|
||||||
|
|
||||||
|
When the countdown reaches zero the \dap{} pauses playback, turns on the
|
||||||
|
backlight, and plays three beeps. After the alert the timer continues
|
||||||
|
running into overtime, displaying the elapsed overtime as
|
||||||
|
\texttt{-MM:SS}. Playback resumes automatically after the beep sequence.
|
||||||
|
The timer can be quit by pausing it and pressing the quit button.
|
||||||
|
|
@ -297,3 +297,5 @@ option from the \setting{Context Menu} (see \reference{ref:Contextmenu}).}
|
||||||
\input{plugins/stopwatch.tex}
|
\input{plugins/stopwatch.tex}
|
||||||
|
|
||||||
\input{plugins/text_editor.tex}
|
\input{plugins/text_editor.tex}
|
||||||
|
|
||||||
|
\input{plugins/countdown_timer.tex}
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,9 @@ each option pertains both to files and directories):
|
||||||
Deletes the currently selected file. This option applies only to files, and
|
Deletes the currently selected file. This option applies only to files, and
|
||||||
not to directories. Rockbox will ask for confirmation before deleting a file.
|
not to directories. Rockbox will ask for confirmation before deleting a file.
|
||||||
Press \ActionYesNoAccept{}
|
Press \ActionYesNoAccept{}
|
||||||
to confirm deletion or any other key to cancel.
|
to confirm deletion or any other key to cancel. When deleting a currently
|
||||||
|
playing file, the part of the file that has already been buffered (i.e. read
|
||||||
|
into the \daps\ memory) will continue playing. This may even be the whole track.
|
||||||
\item [Delete Directory.]
|
\item [Delete Directory.]
|
||||||
Deletes the currently selected directory and all of the files and subdirectories
|
Deletes the currently selected directory and all of the files and subdirectories
|
||||||
it may contain. Deleted directories cannot be recovered. Use this feature with
|
it may contain. Deleted directories cannot be recovered. Use this feature with
|
||||||
|
|
|
||||||
|
|
@ -254,15 +254,8 @@ from the WPS, %
|
||||||
\setting{Context Menu}. Then select \setting{Show Track Info}. The same steps
|
\setting{Context Menu}. Then select \setting{Show Track Info}. The same steps
|
||||||
work in the Playlist Viewer as well.}
|
work in the Playlist Viewer as well.}
|
||||||
|
|
||||||
\subsubsection{Open With...}
|
\subsubsection{Show in Files}
|
||||||
This \setting{Open With} function is the same as the \setting{Open With}
|
Reveal the currently playing track in the \setting{File Browser}.
|
||||||
function in the file browser's \setting{Context Menu}.
|
|
||||||
|
|
||||||
\subsubsection{Delete}
|
|
||||||
Delete the currently playing file. The file will be deleted but the playback
|
|
||||||
of the file will not stop immediately. Instead, the part of the file that
|
|
||||||
has already been buffered (i.e. read into the \daps\ memory) will be played.
|
|
||||||
This may even be the whole track.
|
|
||||||
|
|
||||||
\opt{pitchscreen}{
|
\opt{pitchscreen}{
|
||||||
\subsubsection{\label{sec:pitchscreen}Pitch}
|
\subsubsection{\label{sec:pitchscreen}Pitch}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue