From 7ef47ed87614d6100b491b2c0eb9f75d1fdc1f01 Mon Sep 17 00:00:00 2001 From: Martin Scarratt Date: Mon, 18 Sep 2006 10:06:03 +0000 Subject: Recording countdown timer: set timer in recording settings screen (max 1 week countdown), start/pause timer in recording screen by pressing the pause button. If you have a separate record button then this will override the timer and start to record. Icon at bottom right of screen indicates timer is ticking. If you are in the recording screen when the countdown is over, recording will start automatically, if not then the icon will flash to indicate you should return to the recording screen to begin recording. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10990 a1c6a512-1295-4272-9138-f99709370657 --- apps/keymaps/keymap-h1x0_h3x0.c | 11 ++- apps/lang/english.lang | 80 +++++++++++++++++++ apps/recorder/icons.c | 6 ++ apps/recorder/icons.h | 7 ++ apps/recorder/recording.c | 173 ++++++++++++++++++++++++++++++++++++++-- apps/settings.c | 168 +++++++++++++++++++++++++++++++++++++- apps/settings.h | 12 ++- apps/sound_menu.c | 23 +++++- 8 files changed, 470 insertions(+), 10 deletions(-) diff --git a/apps/keymaps/keymap-h1x0_h3x0.c b/apps/keymaps/keymap-h1x0_h3x0.c index 0c0b61d201..4ac671ff3c 100644 --- a/apps/keymaps/keymap-h1x0_h3x0.c +++ b/apps/keymaps/keymap-h1x0_h3x0.c @@ -415,6 +415,10 @@ const struct button_mapping button_context_settings_h100remote[] = { { ACTION_SETTINGS_INCREPEAT, BUTTON_RC_REW|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_SETTINGS_DEC, BUTTON_RC_FF, BUTTON_NONE }, { ACTION_SETTINGS_DECREPEAT, BUTTON_RC_FF|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_PREV, BUTTON_RC_SOURCE, BUTTON_NONE }, + { ACTION_STD_PREVREPEAT, BUTTON_RC_SOURCE|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_NEXT, BUTTON_RC_BITRATE, BUTTON_NONE }, + { ACTION_STD_NEXTREPEAT, BUTTON_RC_BITRATE|BUTTON_REPEAT, BUTTON_NONE }, /* { ACTION_NONE, BUTTON_RC_ON, BUTTON_NONE }, { ACTION_NONE, BUTTON_RC_STOP, BUTTON_NONE }, { ACTION_NONE, BUTTON_RC_MENU|BUTTON_REL, BUTTON_NONE }, @@ -427,8 +431,11 @@ const struct button_mapping button_context_settings_h300lcdremote[] = { { ACTION_SETTINGS_INCREPEAT, BUTTON_RC_VOL_UP|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_SETTINGS_DEC, BUTTON_RC_VOL_DOWN, BUTTON_NONE }, { ACTION_SETTINGS_DECREPEAT, BUTTON_RC_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_NONE, BUTTON_RC_REW, BUTTON_NONE }, - { ACTION_NONE, BUTTON_RC_FF, BUTTON_NONE }, + { ACTION_STD_PREV, BUTTON_RC_REW, BUTTON_NONE }, + { ACTION_STD_PREVREPEAT, BUTTON_RC_REW|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_NEXT, BUTTON_RC_FF, BUTTON_NONE }, + { ACTION_STD_NEXTREPEAT, BUTTON_RC_FF|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_SETTINGS_RESET, BUTTON_RC_ON, BUTTON_NONE }, LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) }; /* button_context_settings */ diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 320d4d0f2b..8dee255c8a 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -9806,3 +9806,83 @@ *: "" + + id: LANG_TIMER_CONFIRM + desc: Confirm string for recording countdown timer settings + user: + + *: "Press PLAY to confirm" + + + *: "Press PLAY to confirm" + h100,h120,h300: "Press NAVI to confirm" + + + *: "" + + + + id: LANG_TIMER_SET + desc: Recording timer menu + + *: "Set countdown timer" + + + *: "Set countdown timer" + + + *: "Set countdown timer" + + + + id: LANG_TIMER_DAYS + desc: recording timer settings string + + *: "Days" + + + *: "Days" + + + *: "Days" + + + + id: LANG_TIMER_HRS + desc: recording timer settings string + + *: "Hrs" + + + *: "Hrs" + + + *: "Hrs" + + + + id: LANG_TIMER_MINS + desc: recording timer settings string + + *: "Mins" + + + *: "Mins" + + + *: "Mins" + + + + id: LANG_REC_TIMER + desc: recording screen timer string + + *: "Timer" + + + *: "Timer" + + + *: "Timer" + + diff --git a/apps/recorder/icons.c b/apps/recorder/icons.c index 711df633f4..20a681fc81 100644 --- a/apps/recorder/icons.c +++ b/apps/recorder/icons.c @@ -36,6 +36,12 @@ const unsigned char bitmap_icons_5x8[][5] = [Icon_Mono]={0x00, 0x1c, 0x22, 0x1c, 0x00} /* Mono recording */ }; +const unsigned char bitmap_icons_7x7[][7] = +{ + [Icon_Timer]={0x1c, 0x22, 0x41, 0x4f, 0x49, 0x22, 0x1d}, /* Recording timer icon */ + [Icon_Blank]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* Blank for flashing */ +}; + const unsigned char bitmap_icons_6x8[][6] = { { 0x60, 0x7f, 0x03, 0x33, 0x3f, 0x00 }, /* Musical note */ diff --git a/apps/recorder/icons.h b/apps/recorder/icons.h index b4310aa90a..c68b281852 100644 --- a/apps/recorder/icons.h +++ b/apps/recorder/icons.h @@ -44,6 +44,12 @@ enum icons_5x8 { Icon5x8Last }; +enum icons_7x7 { + Icon_Timer, + Icon_Blank, + Icon7x7Last +}; + enum icons_6x8 { Icon_Audio, Icon_Folder, @@ -117,6 +123,7 @@ enum icons_18x8 { #endif extern const unsigned char bitmap_icons_5x8[Icon5x8Last][5]; +extern const unsigned char bitmap_icons_7x7[Icon7x7Last][7]; extern const unsigned char bitmap_icons_6x8[Icon6x8Last][6]; extern const unsigned char bitmap_icons_7x8[Icon7x8Last][7]; #if CONFIG_CODEC == SWCODEC diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c index 6ee71d2eee..4d0e226254 100644 --- a/apps/recorder/recording.c +++ b/apps/recorder/recording.c @@ -69,8 +69,18 @@ #include "screen_access.h" #include "action.h" #include "radio.h" +#include "timer.h" #ifdef HAVE_RECORDING +#ifdef SIMULATOR +bool timer_register(int reg_prio, void (*unregister_callback)(void), + long cycles, int int_prio, void (*timer_callback)(void)); +void timer_unregister(void); +#define TIMER_FREQ 0 +#endif +#define TIMER_ICON_WIDTH 7 +#define TIMER_ICON_HEIGHT 7 + #define PM_HEIGHT ((LCD_HEIGHT >= 72) ? 2 : 1) bool f2_rec_screen(void); @@ -78,6 +88,9 @@ bool f3_rec_screen(void); #define MAX_FILE_SIZE 0x7F800000 /* 2 GB - 4 MB */ +int days, hrs, mins, secs; +bool timer_icon; /* timer icon displayed? */ + int screen_update = NB_SCREENS; bool remote_display_on = true; const char* const freq_str[6] = @@ -779,6 +792,52 @@ static void trigger_listener(int trigger_status) } } +/* countdown timer callback function */ +void timer_callback(void) +{ + static int mini_tick = 0; + /* print icon at bottom right of main screen */ + if (timer_icon) + screens[0].mono_bitmap(bitmap_icons_7x7[Icon_Timer], + screens[0].width - TIMER_ICON_WIDTH, + screens[0].height - TIMER_ICON_HEIGHT, + TIMER_ICON_WIDTH, TIMER_ICON_HEIGHT); + else + screens[0].mono_bitmap(bitmap_icons_7x7[Icon_Blank], + screens[0].width - TIMER_ICON_WIDTH, + screens[0].height - TIMER_ICON_HEIGHT, + TIMER_ICON_WIDTH, TIMER_ICON_HEIGHT); + + screens[0].update_rect(screens[0].width - TIMER_ICON_WIDTH, + screens[0].height - TIMER_ICON_HEIGHT, + TIMER_ICON_WIDTH, TIMER_ICON_HEIGHT); + + mini_tick ++; + /* the countdown */ + if (mini_tick > 10) + { + secs -= 1; + if (secs < 0){ + mins -= 1; + secs = 59; + if (mins < 0){ + hrs -= 1; + mins = 59; + if (hrs < 0){ + days -= 1; + hrs = 23; + if (days < 0) + { + days = hrs = mins = secs = 0; + timer_icon = !timer_icon; /* flash icon when */ + } /* countdown finished */ + } + } + } + mini_tick = 0; + } +} + bool recording_screen(bool no_source) { long button; @@ -818,6 +877,8 @@ bool recording_screen(bool no_source) int i; int filename_offset[NB_SCREENS]; int pm_y[NB_SCREENS]; + static bool countdown; /* countdown in progress indicator */ + int countdown_offset = 0; static const unsigned char *byte_units[] = { ID2P(LANG_BYTE), @@ -827,6 +888,20 @@ bool recording_screen(bool no_source) }; global_settings.recscreen_on = true; + + /* Stop countdown if countdown settings changed */ + if ((mins != global_settings.ctdn_mins)|| + (hrs != global_settings.ctdn_hrs) || + (days != global_settings.ctdn_days)) + { + mins = global_settings.ctdn_mins; + hrs = global_settings.ctdn_hrs; + days = global_settings.ctdn_days; + secs = global_settings.ctdn_secs; + countdown = false; + timer_unregister(); + } + cursor = 0; #if (CONFIG_LED == LED_REAL) && !defined(SIMULATOR) ata_set_led_enabled(false); @@ -969,6 +1044,17 @@ bool recording_screen(bool no_source) last_audio_stat = audio_stat; } + /* When countdown timer reaches zero fake a new file button press */ + if (countdown && !days && !hrs && !mins && !secs) + { + timer_unregister(); + button = ACTION_REC_NEWFILE; + countdown = false; + global_settings.ctdn_days = days; + global_settings.ctdn_hrs = hrs; + global_settings.ctdn_mins = mins; + } + switch(button) { case ACTION_REC_LCD: @@ -1004,7 +1090,12 @@ bool recording_screen(bool no_source) #if CONFIG_CODEC != SWCODEC peak_meter_playback(true); peak_meter_enabled = false; -#endif +#endif + /* keeps settings the same as the countdown values */ + global_settings.ctdn_days = days; + global_settings.ctdn_hrs = hrs; + global_settings.ctdn_mins = mins; + global_settings.ctdn_secs = secs; done = true; } update_countdown = 1; /* Update immediately */ @@ -1014,7 +1105,27 @@ bool recording_screen(bool no_source) case ACTION_REC_NEWFILE: /* Only act if the mpeg is stopped */ if(!(audio_stat & AUDIO_STATUS_RECORD)) - { + { /* if countdown timer is set, start countdown */ + if (days || hrs || mins || secs) + { + if (button == ACTION_REC_PAUSE) + { + countdown = !countdown; + if (countdown) + timer_register(1, NULL, TIMER_FREQ/10, 1, timer_callback); + else + timer_unregister(); + break; + } + else + { + /* if newfile button pressed and countdown timer is on, + start new file and reset timer */ + timer_unregister(); + days = hrs = mins = secs = 0; + countdown = false; + } + } /* is this manual or triggered recording? */ if ((global_settings.rec_trigger_mode == TRIG_MODE_OFF) || (peak_meter_trigger_status() != TRIG_OFF)) @@ -1221,7 +1332,11 @@ bool recording_screen(bool no_source) #ifdef HAVE_FMRADIO_IN const int prev_rec_source = global_settings.rec_source; #endif - + /* maintain countdown values when entering menu */ + global_settings.ctdn_days = days; + global_settings.ctdn_hrs = hrs; + global_settings.ctdn_mins = mins; + global_settings.ctdn_secs = secs; #if CONFIG_LED == LED_REAL /* led is restored at begin of loop / end of function */ led(false); @@ -1245,6 +1360,19 @@ bool recording_screen(bool no_source) && prev_rec_source == AUDIO_SRC_FMRADIO) radio_status = FMRADIO_OFF; #endif + /* if countdown timer settings changed in menu, + stop counting and reset */ + if ((hrs != global_settings.ctdn_hrs) || + (mins != global_settings.ctdn_mins) || + (days != global_settings.ctdn_days)) + { + days = global_settings.ctdn_days; + hrs = global_settings.ctdn_hrs; + mins = global_settings.ctdn_mins; + secs = global_settings.ctdn_secs; + countdown = false; + timer_unregister(); + } #if CONFIG_CODEC == SWCODEC /* reinit after submenu exit */ @@ -1347,6 +1475,8 @@ bool recording_screen(bool no_source) break; } + timer_icon = countdown; /* display timer icon if countdown enabled */ + #ifdef HAVE_AGC peak_read = !peak_read; if (peak_read) { /* every 2nd run of loop */ @@ -1383,11 +1513,13 @@ bool recording_screen(bool no_source) if ((global_settings.rec_sizesplit) && (global_settings.rec_split_method)) { + countdown_offset = 1; dmb = dsize/1024/1024; snprintf(buf, sizeof(buf), "%s %dMB", str(LANG_SYSFONT_SPLIT_SIZE), dmb); } - else + /* only display recording time if countdown timer is off */ + else if (!days && !hrs && !mins && !secs) { hours = seconds / 3600; minutes = (seconds - (hours * 3600)) / 60; @@ -1395,6 +1527,11 @@ bool recording_screen(bool no_source) str(LANG_SYSFONT_RECORDING_TIME), hours, minutes, seconds%60); } + else + { + countdown_offset = 0; + snprintf(buf, 32, ""); + } for(i = 0; i < screen_update; i++) screens[i].puts(0, 0, buf); @@ -1418,7 +1555,8 @@ bool recording_screen(bool no_source) str(LANG_SYSFONT_RECORD_TIMESPLIT_REC), dhours, dminutes); } - else + /* only display recording size if countdown timer is off */ + else if (!days && !hrs && !mins && !secs) { output_dyn_value(buf2, sizeof buf2, num_recorded_bytes, @@ -1430,6 +1568,16 @@ bool recording_screen(bool no_source) for(i = 0; i < screen_update; i++) screens[i].puts(0, 1, buf); + /* display countdown timer if set */ + if (days || hrs || mins || secs) + { + snprintf(buf, 32, "%s %d:%02d:%02d:%02d", str(LANG_REC_TIMER), + days, hrs, mins, secs); + + for(i = 0; i < screen_update; i++) + screens[i].puts(0, countdown_offset, buf); + } + for(i = 0; i < screen_update; i++) { if (filename_offset[i] > 0) @@ -2123,6 +2271,21 @@ unsigned long pcm_rec_status(void) #endif /* #ifdef SIMULATOR */ #endif /* #ifdef CONFIG_CODEC == SWCODEC */ +#ifdef SIMULATOR +bool timer_register(int reg_prio, void (*unregister_callback)(void), + long cycles, int int_prio, void (*timer_callback)(void)) +{ + reg_prio = reg_prio; + unregister_callback = unregister_callback; + cycles = cycles; + int_prio = int_prio; + timer_callback = timer_callback; + return false; +} +void timer_unregister(void) +{ +} +#endif #endif /* HAVE_RECORDING */ diff --git a/apps/settings.c b/apps/settings.c index 3dc4ee1530..b2f7888a22 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -96,7 +96,7 @@ const char rec_base_directory[] = REC_BASE_DIR; #include "eq_menu.h" #endif -#define CONFIG_BLOCK_VERSION 52 +#define CONFIG_BLOCK_VERSION 53 #define CONFIG_BLOCK_SIZE 512 #define RTC_BLOCK_SIZE 44 @@ -477,6 +477,11 @@ static const struct bit_entry hd_bits[] = {1, S_O(rec_channels), 0, "rec channels", "stereo,mono" }, {1, S_O(rec_split_type), 0, "rec split type", "Split, Stop" }, {1, S_O(rec_split_method), 0, "rec split method", "Time,Filesize" }, + {6, S_O(ctdn_mins), 0, "countdown timer minutes", NULL }, /* 0 - 59 */ + {5, S_O(ctdn_hrs), 0, "countdown timer hours", NULL }, /* 0 - 23 */ + {6, S_O(ctdn_secs), 0, "countdown timer seconds", NULL }, /* 0 - 59 */ + {3, S_O(ctdn_days), 0, "countdown timer days", NULL }, /* 0 - 6 */ + { #if defined(HAVE_SPDIF_IN) || defined(HAVE_FMRADIO_IN) @@ -2032,6 +2037,167 @@ bool set_int(const unsigned char* string, (max-*variable)/step, &data,function); } +/* Useful for time and other multi integer settings */ +bool set_multi_int(const char* string, const struct opt_items * names, + struct opt_settings * variable, int varcount) +{ + int i, j; + char buf[32]; + long button; + int cursor = 0; + bool done = false; + int oldvalue[varcount]; + int pos = 0; + + for(j = 0; j < varcount; j++) + oldvalue[j] = *(int*)variable[j].setting; + + FOR_NB_SCREENS(i) + { + screens[i].clear_display(); +#ifdef HAVE_LCD_BITMAP + screens[i].setmargins(0, 8); +#endif + } + + snprintf(buf, sizeof(buf), "%s", string); + FOR_NB_SCREENS(i) + screens[i].puts(0, 0, buf); + + /* print variable names */ + for(j = 0; j < varcount ; j++) + { + if (j > 0) + { + snprintf(buf, sizeof(buf), ":"); + FOR_NB_SCREENS(i) + screens[i].puts(pos - 2, 1, buf); + } + + snprintf(buf, sizeof(buf), "%s", P2STR(names[j].string)); + FOR_NB_SCREENS(i) + screens[i].puts(pos, 1, buf); + + pos += strlen(buf) + 3; + } + + snprintf(buf, sizeof(buf), "%s", str(LANG_TIMER_CONFIRM)); + FOR_NB_SCREENS(i) + screens[i].puts(0, 5, buf); + + gui_syncstatusbar_draw(&statusbars, true); + + while(!done) + { + pos = 0; + + /* print variables */ + for(j = 0; j < varcount; j++) + { + if (j > 0) + { + snprintf(buf, sizeof(buf), " :"); + FOR_NB_SCREENS(i) + screens[i].puts(pos - 3, 3, buf); + } + + snprintf(buf, sizeof(buf), "%d", *(int*)variable[j].setting); + +#ifdef HAVE_LCD_BITMAP + if (cursor == j) + { + FOR_NB_SCREENS(i) + screens[i].puts_style_offset(pos, 3, buf, STYLE_INVERT, 0); + } + else +#endif + { + FOR_NB_SCREENS(i) + screens[i].puts(pos, 3, buf); + } + + snprintf(buf, sizeof(buf), "%d", variable[j].setting_max); + pos += strlen(buf) + 3; + } + + /* print empty char to terminate invert style */ + snprintf(buf, sizeof(buf), " "); + FOR_NB_SCREENS(i) + screens[i].puts(pos - 3, 3, buf); + +#ifdef HAVE_LCD_BITMAP + FOR_NB_SCREENS(i) + screens[i].update(); +#endif + + button = get_action(CONTEXT_SETTINGS, TIMEOUT_BLOCK); + + switch (button) + { + case ACTION_STD_NEXT: + cursor ++; + if (cursor >= varcount) + cursor = varcount - 1; + if (global_settings.talk_menu) + talk_id(names[cursor].voice_id, false); + break; + + case ACTION_STD_PREV: + if (cursor == 0) + { + /* cancel if pressing left when cursor + is already at the far left */ + for(j = 0; j < varcount; j++) + *(int*)variable[j].setting = oldvalue[j]; + gui_syncsplash(HZ/2, true, str(LANG_MENU_SETTING_CANCEL)); + done = true; + } + else + cursor --; + if (cursor < 0) + cursor = 0; + if (global_settings.talk_menu) + talk_id(names[cursor].voice_id, false); + break; + + case ACTION_SETTINGS_INC: + case ACTION_SETTINGS_INCREPEAT: + *(int*)variable[cursor].setting += 1; + if (*(int*)variable[cursor].setting > + variable[cursor].setting_max) + *(int*)variable[cursor].setting = 0; + if (global_settings.talk_menu) + talk_unit(INT, *(int*)variable[cursor].setting); + break; + + case ACTION_SETTINGS_DEC: + case ACTION_SETTINGS_DECREPEAT: + *(int*)variable[cursor].setting -= 1; + if (*(int*)variable[cursor].setting < 0) + *(int*)variable[cursor].setting = + variable[cursor].setting_max; + if (global_settings.talk_menu) + talk_unit(INT, *(int*)variable[cursor].setting); + break; + + case ACTION_STD_OK: + done = true; + break; + + case ACTION_STD_CANCEL: + for(j = 0; j < varcount; j++) + *(int*)variable[j].setting = oldvalue[j]; + gui_syncsplash(HZ/2, true, str(LANG_MENU_SETTING_CANCEL)); + return false; + + default: + if (default_event_handler(button) == SYS_USB_CONNECTED) + return true; + } + } + return false; +} + /* NOTE: the 'type' parameter specifies the actual type of the variable that 'variable' points to. not the value within. Only variables with type 'bool' should use parameter BOOL. diff --git a/apps/settings.h b/apps/settings.h index 561dc59375..fe00dce023 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -167,7 +167,10 @@ struct user_settings 13= 1GB, 14 = 1.5GB 15 = 1.75MB*/ int rec_split_type; /* split/stop */ int rec_split_method; /* time/filesize */ - + int ctdn_mins; /* 0 - 59 */ + int ctdn_hrs; /* 0 - 23 */ + int ctdn_secs; /* 0 - 59 */ + int ctdn_days; /* 0 - 6 */ int rec_prerecord_time; /* In seconds, 0-30, 0 means OFF */ int rec_directory; /* 0=base dir, 1=current dir */ bool rec_startup; /* true means start Rockbox in recording screen */ @@ -495,6 +498,11 @@ struct opt_items { long voice_id; }; +struct opt_settings { + int* setting; + int setting_max; +}; + /* prototypes */ void settings_calc_config_sector(void); @@ -516,6 +524,8 @@ bool set_bool_options(const char* string, bool* variable, bool set_bool(const char* string, bool* variable ); bool set_option(const char* string, void* variable, enum optiontype type, const struct opt_items* options, int numoptions, void (*function)(int)); +bool set_multi_int(const char* string, const struct opt_items * names, + struct opt_settings * variable, int varcount); bool set_int(const unsigned char* string, const char* unit, int voice_unit, int* variable, void (*function)(int), int step, int min, int max, diff --git a/apps/sound_menu.c b/apps/sound_menu.c index f220d26f8f..6537b5b171 100644 --- a/apps/sound_menu.c +++ b/apps/sound_menu.c @@ -7,7 +7,7 @@ * \/ \/ \/ \/ \/ * $Id$ * - * Copyright (C) 2002 Björn Stenberg + * Copyright (C) 2002 Bj�n Stenberg * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. @@ -591,6 +591,25 @@ static bool agc_cliptime(void) INT, names, 5, NULL ); } #endif /* HAVE_AGC */ + +/* Displays a menu for changing the countdown timer settings */ +static bool countdown_timer(void) +{ + static const struct opt_items names[] = { + { STR(LANG_TIMER_DAYS) }, + { STR(LANG_TIMER_HRS) }, + { STR(LANG_TIMER_MINS) } + }; + + struct opt_settings settings[] = { + { &global_settings.ctdn_days, 6 }, + { &global_settings.ctdn_hrs, 23 }, + { &global_settings.ctdn_mins, 59 } + }; + + return set_multi_int(str(LANG_TIMER_SET), names, settings, 3); +} + #endif /* HAVE_RECORDING */ static bool chanconf(void) @@ -1089,6 +1108,8 @@ bool recording_menu(bool no_source) items[i].desc = ID2P(LANG_RECORD_AGC_CLIPTIME); items[i++].function = agc_cliptime; #endif + items[i].desc = ID2P(LANG_TIMER_SET); + items[i++].function = countdown_timer; m=menu_init( items, i, NULL, NULL, NULL, NULL); result = menu_run(m); -- cgit v1.2.3