Index: apps/lang/english.lang
===================================================================
--- apps/lang/english.lang (revision 27817)
+++ apps/lang/english.lang (working copy)
@@ -12619,3 +12619,87 @@
*: "Update on Stop"
+
+ id: LANG_TRACKONLY
+ desc: used in track x of y constructs
+ user: core
+
+ *: "Track"
+
+
+ *: "Track"
+
+
+ *: "Track"
+
+
+
+ id: LANG_VOICEINFO
+ desc: progressively voice information on the wps hotkey
+ user: core
+
+ *: "Announce Information"
+
+
+ *: "Announce Information"
+
+
+ *: "Announce Information"
+
+
+
+ id: LANG_ELAPSED
+ desc: prefix for elapsed playtime announcement
+ user: core
+
+ *: "Elapsed"
+
+
+ *: "Elapsed"
+
+
+ *: "Elapsed"
+
+
+
+ id: LANG_WPS_ANNOUNCEMENT_FORMAT
+ desc: format for wps hotkey announcement
+ user: core
+
+ *: "WPS Announcement"
+
+
+ *: "WPS Announcement"
+
+
+ *: "WPS Announcement"
+
+
+
+ id: LANG_REMAINING
+ desc: for constructs such as number of tracks remaining etc
+ user: core
+
+ *: "Remaining"
+
+
+ *: "Remaining"
+
+
+ *: "Remaining"
+
+
+
+ id: LANG_DATE
+ desc: for constructing time and date announcements
+ user: core
+
+ *: "Date"
+
+
+ *: "Date"
+
+
+ *: "Date"
+
+
Index: apps/onplay.c
===================================================================
--- apps/onplay.c (revision 27817)
+++ apps/onplay.c (working copy)
@@ -64,6 +64,10 @@
#include "pitchscreen.h"
#include "viewport.h"
+#include "ctype.h"
+
+#include "powermgmt.h"
+
static int context;
static char* selected_file = NULL;
static int selected_file_attr = 0;
@@ -1216,6 +1220,295 @@
return ONPLAY_RELOAD_DIR;
}
+
+
+#define ANNOUNCEMENT_TIMEOUT 10
+
+static int target_info = 0;
+
+static int info_reset_timeout = 0;
+
+
+static unsigned char* voice_info_group(unsigned char* current_token);
+
+static int voice_general_info(void)
+{
+ unsigned char* infotemplate = global_settings.wps_announcement_format;
+
+ if (*infotemplate == 0)
+ {
+#if CONFIG_RTC
+ /* announce the time */
+ strcpy(infotemplate, "Ac");
+#else
+ /* announce elapsed play for this track */
+ strcpy(infotemplate, "Be");
+#endif
+ }
+
+ if (TIME_AFTER(current_tick, info_reset_timeout))
+ {
+ target_info = 0;
+ }
+
+ info_reset_timeout = current_tick + ANNOUNCEMENT_TIMEOUT * HZ;
+
+ talk_shutup();
+
+ /*
+ Consume announcement groups until we hit the target group
+ */
+ int test_info = 0;
+
+ while (*infotemplate != 0 && test_info != target_info)
+ {
+ if (*infotemplate == '.')
+ {
+ test_info++;
+ }
+
+ infotemplate++;
+ }
+
+
+ /*
+ On a match, voice the found group and move on to the next
+ */
+ if (test_info == target_info)
+ {
+ infotemplate = voice_info_group(infotemplate);
+
+ target_info++;
+ }
+
+ /*
+ If this was the last group, reset to the start
+ */
+ if (*infotemplate == 0)
+ {
+ target_info = 0;
+ }
+
+ return ONPLAY_OK;
+}
+
+
+static unsigned char* voice_info_group(unsigned char* current_token)
+{
+ unsigned char current_char;
+
+ while (*current_token != 0 && *current_token != '.')
+ {
+ current_char = toupper(*current_token);
+ if (current_char == 'A')
+ {
+ /*
+ Date and time functions
+ */
+ current_token++;
+
+ current_char = toupper(*current_token);
+
+#if CONFIG_RTC
+ struct tm *tm = get_time();
+
+ if (valid_time(tm))
+ {
+ if (current_char == 'A')
+ {
+ talk_time(tm, true);
+ }
+ else if (current_char == 'B')
+ {
+ talk_date(tm, true);
+ }
+ else if (current_char == 'C')
+ {
+ /* Time xxx */
+ (void)voice_info_group("SaAa");
+ }
+ else if (current_char == 'D')
+ {
+ /* Date xxx */
+ (void)voice_info_group("SbAb");
+ }
+ else if (current_char == 'E')
+ {
+ /* Date Time */
+ (void)voice_info_group("AbAa");
+ }
+#endif
+
+ int sleep_remaining = get_sleep_timer();
+
+ if (current_char == 'F')
+ {
+ talk_value_decimal(sleep_remaining, UNIT_TIME, 0, true);
+ }
+ else if (current_char == 'G')
+ {
+ /* SLEEPTIMER sleeptimer remaining */
+ (void)voice_info_group("ShDf");
+ }
+ }
+
+ }
+ else if (current_char == 'B')
+ {
+ /*
+ Current track information
+ */
+ current_token++;
+
+ current_char = toupper(*current_token);
+
+ struct mp3entry* id3 = audio_current_track();
+
+ int elapsed_length = id3->elapsed / 1000;
+ int track_length = id3->length / 1000;
+ int track_remaining = track_length - elapsed_length;
+
+ if (current_char == 'A')
+ {
+ talk_value_decimal(elapsed_length, UNIT_TIME, 0, true);
+ }
+ else if (current_char == 'B')
+ {
+ talk_value_decimal(track_length, UNIT_TIME, 0, true);
+ }
+ else if (current_char == 'C')
+ {
+ talk_value_decimal(track_remaining, UNIT_TIME, 0, true);
+ }
+ else if (current_char == 'D')
+ {
+ /* xxx elapsed yyy remaining */
+ (void)voice_info_group("BaSdBcSe");
+ }
+ else if (current_char == 'E')
+ {
+ /* xxx of yyy */
+ (void)voice_info_group("BaSfBb");
+ }
+ }
+ else if (current_char == 'C')
+ {
+ /*
+ Current playlist information
+ */
+ current_token++;
+
+ current_char = toupper(*current_token);
+
+ int current_track = playlist_get_display_index();
+ int total_tracks = playlist_amount();
+ int remaining_tracks = total_tracks - current_track;
+
+ if (current_char == 'A')
+ {
+ talk_number(current_track, true);
+ }
+ else if (current_char == 'B')
+ {
+ talk_number(total_tracks, true);
+ }
+ else if (current_char == 'C')
+ {
+ talk_number(remaining_tracks, true);
+ }
+ else if (current_char == 'D')
+ {
+ /* TRACK current track OF number of tracks */
+ (void)voice_info_group("ScCaSfCb");
+ }
+ }
+ else if (current_char == 'D')
+ {
+ /*
+ Battery, sleep timer and runtime
+ */
+ current_token++;
+
+ current_char = toupper(*current_token);
+
+ if (current_char == 'A')
+ {
+ talk_id(TALK_ID(battery_level(), UNIT_PERCENT), true);
+ }
+ else if (current_char == 'B')
+ {
+ talk_id(TALK_ID(battery_time() * 60, UNIT_TIME), true);
+ }
+ else if (current_char == 'C')
+ {
+ /* BATTERY LEVEL battery level percent */
+ (void)voice_info_group("SgDa");
+ }
+ else if (current_char == 'D')
+ {
+ /* BATTERY LEVEL battery level in minutes */
+ (void)voice_info_group("SgDb");
+ }
+
+ }
+ else if (current_char == 'S')
+ {
+ /*
+ Stock prefixes, suffixes and connectives
+ */
+ current_token++;
+
+ current_char = toupper(*current_token);
+
+ if (current_char == 'A')
+ {
+ talk_id(LANG_TIME, true);
+ }
+ else if (current_char == 'B')
+ {
+ talk_id(LANG_DATE, true);
+ }
+ else if (current_char == 'C')
+ {
+ talk_id(LANG_TRACKONLY, true);
+ }
+ else if (current_char == 'D')
+ {
+ talk_id(LANG_ELAPSED, true);
+ }
+ else if (current_char == 'E')
+ {
+ talk_id(LANG_REMAINING, true);
+ }
+ else if (current_char == 'F')
+ {
+ talk_id(LANG_OF, true);
+ }
+ else if (current_char == 'G')
+ {
+ talk_id(LANG_BATTERY_TIME, true);
+ }
+ else if (current_char == 'H')
+ {
+ talk_id(LANG_SLEEP_TIMER, true);
+ }
+ }
+ else if (current_char == ' ')
+ {
+ /*
+ Catch your breath
+ */
+ talk_id(VOICE_PAUSE, true);
+ }
+
+ current_token++;
+ }
+
+ return current_token;
+}
+
+
+
struct hotkey_assignment {
int action; /* hotkey_action */
int lang_id; /* Language ID */
@@ -1252,6 +1545,9 @@
{ HOTKEY_INSERT_SHUFFLED, LANG_INSERT_SHUFFLED,
HOTKEY_FUNC(playlist_insert_shuffled, NULL),
ONPLAY_OK },
+ { HOTKEY_VOICEINFO, LANG_VOICEINFO,
+ HOTKEY_FUNC(voice_general_info, NULL),
+ ONPLAY_OK },
#ifdef HAVE_PICTUREFLOW_INTEGRATION
{ HOTKEY_PICTUREFLOW, LANG_ONPLAY_PICTUREFLOW,
HOTKEY_FUNC(NULL, NULL),
Index: apps/settings.h
===================================================================
--- apps/settings.h (revision 27817)
+++ apps/settings.h (working copy)
@@ -42,8 +42,8 @@
/** Setting values defines **/
#define MAX_FILENAME 32
+#define MAX_ANNOUNCE_WPS 32
-
enum {
BOOKMARK_NO = 0,
BOOKMARK_YES,
@@ -611,6 +611,8 @@
bool talk_filetype; /* say file type */
bool talk_battery_level;
+ unsigned char wps_announcement_format[MAX_ANNOUNCE_WPS+1]; /* format for wps hotkey announcement */
+
/* file browser sorting */
bool sort_case; /* dir sort order: 0=case insensitive, 1=sensitive */
int sort_dir; /* 0=alpha, 1=date (old first), 2=date (new first) */
Index: apps/menus/settings_menu.c
===================================================================
--- apps/menus/settings_menu.c (revision 27817)
+++ apps/menus/settings_menu.c (working copy)
@@ -388,13 +388,27 @@
}
return action;
}
+
+
+void edit_wps_announce_format(void);
+
+void edit_wps_announce_format(void)
+{
+ kbd_input(global_settings.wps_announcement_format, MAX_ANNOUNCE_WPS);
+
+
+}
+
MENUITEM_SETTING(talk_filetype_item, &global_settings.talk_filetype, NULL);
MENUITEM_SETTING(talk_battery_level_item,
&global_settings.talk_battery_level, NULL);
+MENUITEM_FUNCTION(wps_announce_item, 0, ID2P(LANG_WPS_ANNOUNCEMENT_FORMAT),
+ (int(*)(void))edit_wps_announce_format,
+ NULL, NULL, Icon_NOICON);
MAKE_MENU(voice_settings_menu, ID2P(LANG_VOICE), 0, Icon_Voice,
&talk_menu_item, &talk_dir_item, &talk_dir_clip_item,
&talk_file_item, &talk_file_clip_item, &talk_filetype_item,
- &talk_battery_level_item);
+ &talk_battery_level_item, &wps_announce_item);
/* VOICE MENU */
/***********************************/
Index: apps/onplay.h
===================================================================
--- apps/onplay.h (revision 27817)
+++ apps/onplay.h (working copy)
@@ -44,6 +44,7 @@
HOTKEY_DELETE,
HOTKEY_INSERT,
HOTKEY_INSERT_SHUFFLED,
+ HOTKEY_VOICEINFO,
HOTKEY_PICTUREFLOW,
};
#endif
Index: apps/settings_list.c
===================================================================
--- apps/settings_list.c (revision 27817)
+++ apps/settings_list.c (working copy)
@@ -1078,6 +1078,7 @@
"talk filetype", NULL),
OFFON_SETTING(F_TEMPVAR, talk_battery_level, LANG_TALK_BATTERY_LEVEL, false,
"Announce Battery Level", NULL),
+ TEXT_SETTING(F_T_UCHARPTR, wps_announcement_format, "wps announcement format", "","", NULL),
#ifdef HAVE_RECORDING
/* recording */
@@ -1755,7 +1756,7 @@
#ifdef HAVE_HOTKEY
TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, hotkey_wps,
LANG_HOTKEY_WPS, HOTKEY_VIEW_PLAYLIST, "hotkey wps",
- "off,view playlist,show track info,pitchscreen,open with,delete"
+ "off,view playlist,show track info,pitchscreen,open with,delete,voiceinfo"
#ifdef HAVE_PICTUREFLOW_INTEGRATION
",pictureflow"
#endif
@@ -1767,7 +1768,7 @@
#endif
HOTKEY_OFF,
HOTKEY_VIEW_PLAYLIST, HOTKEY_SHOW_TRACK_INFO, HOTKEY_PITCHSCREEN,
- HOTKEY_OPEN_WITH, HOTKEY_DELETE
+ HOTKEY_OPEN_WITH, HOTKEY_DELETE,HOTKEY_VOICEINFO
#ifdef HAVE_PICTUREFLOW_INTEGRATION
, HOTKEY_PICTUREFLOW
#endif