Index: apps/action.h =================================================================== --- apps/action.h (revision 14742) +++ apps/action.h (working copy) @@ -156,6 +156,7 @@ ACTION_REC_NEWFILE, ACTION_REC_F2, ACTION_REC_F3, + ACTION_REC_HIST_TOGGLE, /* main menu */ /* These are not strictly actions, but must be here Index: apps/recorder/icons.h =================================================================== --- apps/recorder/icons.h (revision 14742) +++ apps/recorder/icons.h (working copy) @@ -45,6 +45,12 @@ Icon5x8Last }; +enum icons_7x7 { + Icon_Timer, + Icon_Timer_rep, + Icon7x7Last +}; + enum icons_7x8 { Icon_Plug, Icon_USBPlug, @@ -100,6 +106,7 @@ #endif /* CONFIG_CODEC == SWCODEC && defined (HAVE_RECORDING) */ extern const unsigned char bitmap_icons_5x8[Icon5x8Last][5]; +extern const unsigned char bitmap_icons_7x7[Icon7x7Last][7]; extern const unsigned char bitmap_icons_7x8[Icon7x8Last][7]; extern const unsigned char bitmap_icon_disk[]; Index: apps/recorder/recording.h =================================================================== --- apps/recorder/recording.h (revision 14742) +++ apps/recorder/recording.h (working copy) @@ -26,6 +26,22 @@ int rec_create_directory(void); void settings_apply_trigger(void); +struct timer +{ + bool countdown; + bool timer_display; + unsigned int days; + unsigned int hrs; + unsigned int mins; + unsigned int secs; + unsigned int days_rpt; + unsigned int hrs_rpt; + unsigned int mins_rpt; + bool repeater; +}; + +struct timer *get_timerstat(void); + /* If true, start recording automatically when recording_sreen() is entered */ extern bool recording_start_automatic; @@ -34,6 +50,7 @@ void rec_set_source(int source, unsigned flags); #endif /* CONFIG_CODEC == SW_CODEC */ +struct audio_recording_options; /* Initializes a recording_options structure with global settings. pass returned data to audio_set_recording_options or rec_set_recording_options */ Index: apps/recorder/peakmeter.h =================================================================== --- apps/recorder/peakmeter.h (revision 14742) +++ apps/recorder/peakmeter.h (working copy) @@ -33,7 +33,7 @@ extern bool peak_meter_enabled; extern void peak_meter_playback(bool playback); -extern int peak_meter_draw_get_btn(int x, int y[], int height, int nb_screens); +extern int peak_meter_draw_get_btn(int x, int y[], int height[], int nb_screens); extern void peak_meter_set_clip_hold(int time); extern void peak_meter_peek(void); extern void peak_meter_init_range( bool dbfs, int range_min, int range_max); Index: apps/recorder/icons.c =================================================================== --- apps/recorder/icons.c (revision 14742) +++ apps/recorder/icons.c (working copy) @@ -44,6 +44,14 @@ #endif }; +const unsigned char bitmap_icons_7x7[][7] = +{ + [Icon_Timer] = + {0x1c, 0x22, 0x41, 0x4f, 0x49, 0x22, 0x1d}, /* Recording timer icon */ + [Icon_Timer_rep]= + {0x17, 0x26, 0x45, 0x41, 0x51, 0x32, 0x74} /* Recording repeat timer icon */ +}; + const unsigned char bitmap_icons_7x8[][7] = { {0x08,0x1c,0x3e,0x3e,0x3e,0x14,0x14}, /* Power plug */ @@ -121,7 +129,7 @@ #ifdef HAVE_MMC {0x15,0x3f,0x7d,0x7B,0x77,0x67,0x79,0x7b,0x57,0x4f,0x47,0x7f}; #else - {0x00,0x00,0x00,0x1c,0x2e,0x4f,0x77,0x79,0x3a,0x1c,0x00,0x00}; + {0x1c,0x2e,0x4f,0x77,0x79,0x3a,0x1c,0x00,0x00,0x00,0x00,0x00}; #endif /* Index: apps/recorder/recording.c =================================================================== --- apps/recorder/recording.c (revision 14742) +++ apps/recorder/recording.c (working copy) @@ -68,6 +68,11 @@ #include "screen_access.h" #include "action.h" #include "radio.h" +#include "fat.h" +#include "power.h" +#include "powermgmt.h" +#include "backlight.h" + #ifdef HAVE_RECORDING /* This array holds the record timer interval lengths, in seconds */ static const unsigned long rec_timer_seconds[] = @@ -165,14 +170,20 @@ return (rec_status & RCSTAT_IN_RECSCREEN) != 0; } -#define PM_HEIGHT ((LCD_HEIGHT >= 72) ? 2 : 1) +static struct timer timer; #if CONFIG_KEYPAD == RECORDER_PAD static bool f2_rec_screen(void); static bool f3_rec_screen(void); #endif +#if defined(HAVE_LCD_BITMAP) && (LCD_HEIGHT > 111) && defined(HAVE_AGC) +#define HAVE_HISTOGRAM /* only for bigger screens */ +#endif + #define MAX_FILE_SIZE 0x7F800000 /* 2 GB - 4 MB */ +#define MIN_DISK_SPACE 48 /* minimum remaining disk space */ +unsigned long disk_space = 0; static int screen_update = NB_SCREENS; #ifdef HAVE_REMOTE_LCD @@ -210,10 +221,11 @@ * peak_time is the counter of the peak hold read and agc process, * overflow every 13 years 8-) */ + static long peak_time = 0; +static short peak_valid_mem[4]; static long hist_time = 0; -static short peak_valid_mem[4]; #define BAL_MEM_SIZE 24 static short balance_mem[BAL_MEM_SIZE]; @@ -262,6 +274,43 @@ static short agc_maxgain; #endif /* HAVE_AGC */ +/* Histogram data, only for bigger screens */ +#ifdef HAVE_HISTOGRAM +#define HIST_Y (LCD_HEIGHT - 1) +#define HIST_W (LCD_WIDTH / 2 - 4) +static short history_mode; +static short hist_time_interval = 1; /* 1, 2, 4, 8 */ +static int hist_l = 0; +static int hist_r = 0; +static unsigned char history_l[HIST_W]; +static unsigned char history_r[HIST_W]; +#if LCD_DEPTH > 1 +#ifdef HAVE_LCD_COLOR +#define LCD_BATT_OK LCD_RGBPACK(63, 63, 63) +#define LCD_BATT_LO LCD_RGBPACK(159, 0, 0) +#define LCD_DISK_OK LCD_RGBPACK(0, 0, 143) +#define LCD_DISK_LO LCD_RGBPACK(127, 0, 0) +#define LCD_BAL_L LCD_RGBPACK(0, 0, 255) +#define LCD_BAL_R LCD_RGBPACK(204, 0, 0) +#define LCD_HIST_OVER LCD_RGBPACK(204, 0, 0) +#define LCD_HIST_HI LCD_RGBPACK(255, 204, 0) +#define LCD_HIST_OK LCD_RGBPACK(51, 153, 0) +#else +#define LCD_BATT_OK LCD_BLACK +#define LCD_BATT_LO LCD_DARKGRAY +#define LCD_DISK_OK LCD_BLACK +#define LCD_DISK_LO LCD_DARKGRAY +#define LCD_HIST_OVER LCD_BLACK +#define LCD_HIST_OK LCD_DARKGRAY +#define LCD_BAL LCD_DARKGRAY +#endif +#else +#define LCD_HIST_OVER LCD_DEFAULT_FG +#define LCD_HIST_OK LCD_DEFAULT_FG +#define LCD_BAL LCD_DEFAULT_FG +#endif +#endif /* HAVE_HISTOGRAM */ + static void set_gain(void) { if(global_settings.rec_source == AUDIO_SRC_MIC) @@ -307,6 +356,12 @@ for (i = 0; i < BAL_MEM_SIZE; i++) *balance += balance_mem[i]; *balance = *balance / BAL_MEM_SIZE; +#ifdef HAVE_HISTOGRAM + if (*peak_l > hist_l) + hist_l = *peak_l; + if (*peak_r > hist_r) + hist_r = *peak_r; +#endif return true; } @@ -548,8 +603,25 @@ { int max_cursor; - if(cursor < 0) + if(cursor < 0) { cursor = 0; +#ifdef HAVE_HISTOGRAM + int i; + history_mode++; + if (history_mode == 2) { + for (i=0; i < HIST_W; i++) { + history_l[i] = history_l[i] * 2; + history_r[i] = history_r[i] * 2; + } + } else if (history_mode == 4) { + for (i=0; i < HIST_W; i++) { + history_l[i] = history_l[i] / 2; + history_r[i] = history_r[i] / 2; + } + history_mode = 0; + } +#endif + } #ifdef HAVE_AGC switch(global_settings.rec_source) @@ -801,6 +873,37 @@ } } +/* countdown timer tick task */ +void timer_tick_task(void) +{ + static int mini_tick = 0; + + mini_tick ++; + /* the countdown */ + if ((mini_tick >= HZ) && (timer.countdown)) + { + mini_tick = 0; + if (timer.secs) timer.secs -= 1; + else{ + timer.secs = 59; + if (timer.mins) timer.mins -= 1; + else{ + timer.mins = 59; + if (timer.hrs) timer.hrs -= 1; + else{ + timer.hrs = 23; + if (timer.days) timer.days -= 1; + else{ + timer.days = timer.hrs = timer.mins = timer.secs = 0; + /* switch timer display on/off when countdown finished */ + timer.timer_display = !timer.timer_display; + } + } + } + } + } +} + bool recording_start_automatic = false; bool recording_screen(bool no_source) @@ -809,9 +912,18 @@ bool done = false; char buf[32]; char buf2[32]; - int w, h; + int w[NB_SCREENS], h[NB_SCREENS]; + int font[NB_SCREENS]; + int pm_h[NB_SCREENS]; int update_countdown = 1; - unsigned int seconds; +#ifndef SIMULATOR + bool disk_was_active = false; + bool warn_message = true; +#endif + unsigned long disk_free; + int bitrate; + int disk_time = 0; + unsigned int seconds, prerec = 0; int hours, minutes; char filename[13]; int last_audio_stat = -1; @@ -833,10 +945,10 @@ int led_countdown = 2; #endif #ifdef HAVE_AGC + bool peak_valid = false; + int balance = 0; bool peak_read = false; - bool peak_valid = false; int peak_l, peak_r; - int balance = 0; bool display_agc[NB_SCREENS]; #endif int line[NB_SCREENS]; @@ -849,6 +961,13 @@ /* pm_x = offset pm to put clipcount in front. Use lcd_getstringsize() when not using SYSFONT */ int pm_x = global_settings.peak_meter_clipcounter ? 30 : 0; + int agc_line = 0; + bool histogram_on = global_settings.hist_def; + bool font_check = true; + int pm_height[NB_SCREENS]; + int countdown_offset = 0; + bool repeat_timer_start = false; + unsigned int repeat_timer; static const unsigned char *byte_units[] = { ID2P(LANG_BYTE), @@ -869,6 +988,68 @@ } rec_status = RCSTAT_IN_RECSCREEN; + + + /* Stop countdown if countdown settings changed */ + if (!timer.countdown) + tick_remove_task(timer_tick_task); + +#ifdef HAVE_AGC + memset(balance_mem, 0x00, BAL_MEM_SIZE); +#endif + +#ifdef HAVE_HISTOGRAM + int history_pos = 0; + int hist_height; + const short hist_size_h[2] = {17, 31}; + /* + * Peak histogram linear to logarithmic [dB] table. + * The thresholds are scaled between the corresponding + * dispayed values, e.g. -6dB is -5.5dB < level <= 6.5dB + */ + const short hist_peak_lin2dB[2][31] = + { + /* Clip, 0, -2, -4, -6, -8, -10 */ + { 32767, 28539, 23197, 18427, 14637, 11627, 9236, + /* -12, -14, -16, -18, -20, -24, -30, -36, -48, -inf */ + 7336, 5828, 4629, 3677, 2602, 1642, 734, 328, 104, 0 }, + /* Clip, 0, -1, -2, -3, -4, -5, -6, -7, -8 */ + { 32767, 30579, 27569, 24573, 21901, 19519, 17397, 15505, 13819, 12316, + /* -9, -10, -11, -12, -13, -14, -15, -16, -18, -20, -22 */ + 10977, 9783, 8719, 7771, 6926, 6173, 5502, 4629, 3677, 2921, 2320, + /* -24, -27, -30, -33, -36, -39, -42, -48, -60, -inf */ + 1842, 1232, 872, 618, 437, 310, 207, 124, 33, 0 } + }; + const char hist_level_marks[4][6] = + { + /* linear: 0, -6, -12, -24, -inf [dB] */ + { 15, 8, 4, 1, 0, 0}, + /* logarithmic: 0, -6, -12, -24, -48 [dB] */ + { 15, 12, 9, 4, 1, 1}, + /* linear: 0, -3, -6, -12, -24, -inf [dB] */ + { 29, 21, 15, 7, 2, 0}, + /* logarithmic: 0, -3, -6, -12, -24, -48 [dB] */ + { 29, 26, 23, 17, 9, 2} + }; + const short hist_balance_marks[12] = + /* -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6 */ + {-4988, -4377, -3690, -2920, -2057, -1087, + 1087, 2057, 2920, 3690, 4377, 4988}; + + const unsigned char rec_icons_6x8[][6] = + { + {0x00,0x1c,0x3e,0x36,0x3e,0x1c} + }; + enum icons_6x8 + { + Icon_Disk, + Icon_6x8end + }; + + memset(history_l, 0x00, sizeof(history_l)); + memset(history_r, 0x00, sizeof(history_r)); +#endif /* HAVE_HISTOGRAM */ + cursor = 0; #if (CONFIG_LED == LED_REAL) && !defined(SIMULATOR) ata_set_led_enabled(false); @@ -884,7 +1065,7 @@ peak_meter_enabled = true; peak_meter_playback(true); #endif - + gui_syncsplash(1, "%s...", str(LANG_RECORDING)); audio_init_recording(0); sound_set_volume(global_settings.volume); @@ -926,29 +1107,109 @@ } #endif /* HAVE_AGC */ - FOR_NB_SCREENS(i) - { - screens[i].setfont(FONT_SYSFIXED); - screens[i].getstringsize("M", &w, &h); - screens[i].setmargins(global_settings.invert_cursor ? 0 : w, 8); - filename_offset[i] = ((screens[i].height >= 80) ? 1 : 0); - pm_y[i] = 8 + h * (2 + filename_offset[i]); - } - #ifdef HAVE_REMOTE_LCD if (!remote_display_on) { screens[1].clear_display(); snprintf(buf, sizeof(buf), str(LANG_REMOTE_LCD_ON)); - screens[1].puts((screens[1].width/w - strlen(buf))/2 + 1, - screens[1].height/(h*2) + 1, buf); + screens[1].puts((screens[1].width/w[1] - strlen(buf))/2 + 1, + screens[1].height/(h[1]*2) + 1, buf); screens[1].update(); gui_syncsplash(0, str(LANG_REMOTE_LCD_OFF)); } #endif + /* store the free disk space for this session [MBytes] */ + fat_size(IF_MV2(0,) NULL, &disk_free); /* free KBytes */ + disk_free = disk_free / 1024; + if (disk_free > disk_space) + disk_space = disk_free; + bitrate = 1411; /* [kbps] default for 44kHz stereo 16bit WAV */ + +#ifdef HAVE_HISTOGRAM + history_mode = global_settings.rec_histogram_mode; + hist_time_interval = 1 << global_settings.rec_histogram_interval; +#endif + while(!done) { + switch(global_settings.rec_source) + { + case AUDIO_SRC_LINEIN: +#ifdef HAVE_FMRADIO_IN + case AUDIO_SRC_FMRADIO: +#endif + FOR_NB_SCREENS(i) + line[i] = 5; + agc_line = 1; + break; + case AUDIO_SRC_MIC: + FOR_NB_SCREENS(i) + line[i] = 4; + agc_line = 1; + break; +#ifdef HAVE_SPDIF_IN + case AUDIO_SRC_SPDIF: + FOR_NB_SCREENS(i) + line[i] = 3; + agc_line = 0; /* no agc line for Spdif in */ + break; +#endif + default: + FOR_NB_SCREENS(i) + line[i] = 5; + break; + } + /* check and change font only if source has been changed */ + if (font_check) + { + FOR_NB_SCREENS(i) + pm_height[i] = global_settings.peak_size + 1; + + FOR_NB_SCREENS(i) + { + filename_offset[i] = ((screens[i].height >= 80) ? 1 : 0); + + while(screens[i].height < (line[i] + 1 + filename_offset[i] + pm_height[i]) * 8) + { + pm_height[i] -= 1; + if (pm_height[i] < 1) + { pm_height[i] = 1; + break; + } + } + + screens[i].setfont(FONT_UI); + screens[i].getstringsize("M", &w[i], &h[i]); + + if (i == SCREEN_MAIN) { + if (h[i] <= ((LCD_HEIGHT - (histogram_on ? 25 : 8)) / (line[i] + + filename_offset[0] + pm_height[i] + agc_line))) + font[i] = FONT_UI; + else + font[i] = FONT_SYSFIXED; + } + else if (h[i] <= ((screens[i].height - 8) / (line[i] + filename_offset[i] + pm_height[i]))) + font[i] = FONT_UI; + else + font[i] = FONT_SYSFIXED; + + screens[i].setfont(font[i]); + screens[i].getstringsize("M", &w[i], &h[i]); + screens[i].setmargins(global_settings.invert_cursor ? 0 : w[i], 8); + if (h[i] > 8) { + pm_y[i] = 9 + h[i] * (2 + filename_offset[i]); + pm_h[i] = (h[i] - 1) * pm_height[i]; + } + else { + pm_y[i] = 8 + h[i] * (2 + filename_offset[i]); + pm_h[i] = h[i] * pm_height[i]; + } + } + font_check = false; + } + + audio_stat = audio_status(); #if (CONFIG_LED == LED_REAL) @@ -999,7 +1260,7 @@ #endif /* CONFIG_LED */ /* Wait for a button a while (HZ/10) drawing the peak meter */ - button = peak_meter_draw_get_btn(pm_x, pm_y, h * PM_HEIGHT, screen_update); + button = peak_meter_draw_get_btn(pm_x, pm_y, pm_h, screen_update); if (last_audio_stat != audio_stat) { @@ -1010,7 +1271,6 @@ last_audio_stat = audio_stat; } - if (recording_start_automatic) { /* simulate a button press */ @@ -1018,9 +1278,33 @@ recording_start_automatic = false; } + /* repeat_timer is the repeat time in seconds */ + repeat_timer = (timer.mins_rpt * 60 + timer.hrs_rpt * + 3600 + timer.days_rpt * 3600 * 24); + + /* decide on repeat timer status */ + if ((repeat_timer > rec_timesplit_seconds()) && + global_settings.rec_timesplit) + timer.repeater = true; + else + timer.repeater = false; + + /* When countdown timer reaches zero fake a new file button press */ + if (timer.countdown && !timer.days && !timer.hrs && !timer.mins && + !timer.secs) + { + tick_remove_task(timer_tick_task); + button = ACTION_REC_NEWFILE; + timer.countdown = false; + } + switch(button) { #ifdef HAVE_REMOTE_LCD + case ACTION_REC_HIST_TOGGLE: + histogram_on = !histogram_on; + font_check = true; + break; case ACTION_REC_LCD: if (remote_display_on) { @@ -1028,8 +1312,8 @@ screen_update = 1; screens[1].clear_display(); snprintf(buf, sizeof(buf), str(LANG_REMOTE_LCD_ON)); - screens[1].puts((screens[1].width/w - strlen(buf))/2 + 1, - screens[1].height/(h*2) + 1, buf); + screens[1].puts((screens[1].width/w[1] - strlen(buf))/2 + 1, + screens[1].height/(h[1]*2) + 1, buf); screens[1].update(); gui_syncsplash(0, str(LANG_REMOTE_LCD_OFF)); } @@ -1064,7 +1348,27 @@ 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 (timer.days || timer.hrs || timer.mins || timer.secs) + { + if (button == ACTION_REC_PAUSE) + { + timer.countdown = !timer.countdown; + if (timer.countdown) + tick_add_task(timer_tick_task); + else + tick_remove_task(timer_tick_task); + break; + } + else + { + /* if newfile button pressed and countdown timer is on, + start new file and reset timer */ + tick_remove_task(timer_tick_task); + timer.days = timer.hrs = timer.mins = timer.secs = 0; + timer.countdown = false; + } + } /* is this manual or triggered recording? */ if ((global_settings.rec_trigger_mode == TRIG_MODE_OFF) || (peak_meter_trigger_status() != TRIG_OFF)) @@ -1072,6 +1376,11 @@ /* manual recording */ rec_status |= RCSTAT_HAVE_RECORDED; rec_command(RECORDING_CMD_START); + repeat_timer_start = true; /* allow access to repeat timer + code */ + /* amount of file that has been prerecorded - needed for + syncing repeat timer */ + prerec = audio_recorded_time() / HZ; last_seconds = 0; if (global_settings.talk_menu) { @@ -1272,7 +1581,6 @@ #ifdef HAVE_FMRADIO_REC const int prev_rec_source = global_settings.rec_source; #endif - #if (CONFIG_LED == LED_REAL) /* led is restored at begin of loop / end of function */ led(false); @@ -1294,6 +1602,10 @@ && prev_rec_source == AUDIO_SRC_FMRADIO) radio_status = FMRADIO_OFF; #endif + /* if countdown timer settings changed in menu, + stop counting and reset */ + if (!timer.countdown) + tick_remove_task(timer_tick_task); #if CONFIG_CODEC == SWCODEC /* reinit after submenu exit */ @@ -1326,14 +1638,17 @@ adjust_cursor(); set_gain(); update_countdown = 1; /* Update immediately */ +#ifdef HAVE_HISTOGRAM + hist_time_interval = 1 << global_settings.rec_histogram_interval; +#endif FOR_NB_SCREENS(i) { - screens[i].setfont(FONT_SYSFIXED); - screens[i].setmargins( - global_settings.invert_cursor ? 0 : w, 8); + screens[i].setfont(font[i]); + screens[i].setmargins(global_settings.invert_cursor ? 0 : w[i], 8); } } + font_check = true; } break; @@ -1396,6 +1711,9 @@ break; } /* end switch */ + /* display timer status in status bar if countdown enabled */ + timer.timer_display = timer.countdown; + #ifdef HAVE_AGC peak_read = !peak_read; if (peak_read) { /* every 2nd run of loop */ @@ -1409,7 +1727,7 @@ #endif FOR_NB_SCREENS(i) - screens[i].setfont(FONT_SYSFIXED); + screens[i].setfont(font[i]); seconds = audio_recorded_time() / HZ; @@ -1423,12 +1741,23 @@ update_countdown = 5; last_seconds = seconds; + /* Get free disk space and calculate remain time */ + fat_size( IF_MV2(0,) NULL, &disk_free ); /* [KBytes] */ + disk_free = disk_free / 1024; + if (disk_free < MIN_DISK_SPACE) + disk_free = MIN_DISK_SPACE; + disk_free -= MIN_DISK_SPACE; + disk_time = 140 * (int)disk_free / bitrate; /* rough estimation */ + dseconds = rec_timesplit_seconds(); dsize = rec_sizesplit_bytes(); num_recorded_bytes = audio_num_recorded_bytes(); for(i = 0; i < screen_update; i++) + { screens[i].clear_display(); + screens[i].setfont(font[i]); + } #if CONFIG_CODEC == SWCODEC if ((audio_stat & AUDIO_STATUS_WARNING) @@ -1446,11 +1775,13 @@ #endif /* CONFIG_CODEC == SWCODEC */ 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 (!timer.days && !timer.hrs && !timer.mins && !timer.secs) { hours = seconds / 3600; minutes = (seconds - (hours * 3600)) / 60; @@ -1458,6 +1789,11 @@ 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); @@ -1481,7 +1817,8 @@ str(LANG_SYSFONT_RECORD_TIMESPLIT_REC), dhours, dminutes); } - else + /* only display recording size if countdown timer is off */ + else if (!timer.days && !timer.hrs && !timer.mins && !timer.secs) { output_dyn_value(buf2, sizeof buf2, num_recorded_bytes, @@ -1493,6 +1830,16 @@ for(i = 0; i < screen_update; i++) screens[i].puts(0, 1, buf); + /* display countdown timer if set */ + if (timer.days || timer.hrs || timer.mins || timer.secs) + { + snprintf(buf, 32, "%s %d:%02d:%02d:%02d", str(LANG_REC_TIMER), + timer.days, timer.hrs, timer.mins, timer.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) @@ -1526,11 +1873,36 @@ rec_command(RECORDING_CMD_START_NEWFILE); last_seconds = 0; } - else + else if (repeat_timer_start) { peak_meter_trigger(false); peak_meter_set_trigger_listener(NULL); rec_command(RECORDING_CMD_STOP); + + /* stop any more attempts to access this code until a new + recording is started */ + repeat_timer_start = false; + + /* start repeat countdown if set and only if + stop time < repeat time */ + if (timer.repeater) + { + repeat_timer -= dseconds; + timer.days = repeat_timer / (3600 * 24); + timer.hrs = (repeat_timer - (timer.days * 3600 * 24)) / + 3600; + timer.mins = (repeat_timer - (timer.hrs * 3600)) / 60; + timer.secs = prerec; /* add prerecorded time to timer */ + + /* This is not really a toggle so much as a safety feature + so that it is impossible to start the timer more than + once */ + timer.countdown = !timer.countdown; + if (timer.countdown) + tick_add_task(timer_tick_task); + else + tick_remove_task(timer_tick_task); + } } update_countdown = 1; } @@ -1542,10 +1914,10 @@ snprintf(clpstr, 32, "%4d", pm_get_clipcount()); for(i = 0; i < screen_update; i++) { - if(PM_HEIGHT > 1) + if(pm_height[i] > 1) screens[i].puts(0, 2 + filename_offset[i], str(LANG_SYSFONT_PM_CLIPCOUNT)); - screens[i].puts(0, 1 + PM_HEIGHT + filename_offset[i], + screens[i].puts(0, 1 + pm_height[i] + filename_offset[i], clpstr); } } @@ -1559,12 +1931,12 @@ { for(i = 0; i < screen_update; i++) screens[i].puts_style_offset(0, filename_offset[i] + - PM_HEIGHT + 2, buf, STYLE_INVERT,0); + pm_height[i] + 2, buf, STYLE_INVERT,0); } else { for(i = 0; i < screen_update; i++) - screens[i].puts(0, filename_offset[i] + PM_HEIGHT + 2, buf); + screens[i].puts(0, filename_offset[i] + pm_height[i] + 2, buf); } if(global_settings.rec_source == AUDIO_SRC_MIC) @@ -1578,13 +1950,13 @@ { for(i = 0; i < screen_update; i++) screens[i].puts_style_offset(0, filename_offset[i] + - PM_HEIGHT + 3, buf, STYLE_INVERT,0); + pm_height[i] + 3, buf, STYLE_INVERT,0); } else { for(i = 0; i < screen_update; i++) screens[i].puts(0, filename_offset[i] + - PM_HEIGHT + 3, buf); + pm_height[i] + 3, buf); } } else if(0 @@ -1602,13 +1974,13 @@ { for(i = 0; i < screen_update; i++) screens[i].puts_style_offset(0, filename_offset[i] + - PM_HEIGHT + 3, buf, STYLE_INVERT,0); + pm_height[i] + 3, buf, STYLE_INVERT,0); } else { for(i = 0; i < screen_update; i++) screens[i].puts(0, filename_offset[i] + - PM_HEIGHT + 3, buf); + pm_height[i] + 3, buf); } snprintf(buf, sizeof(buf), "%s:%s", @@ -1620,16 +1992,18 @@ { for(i = 0; i < screen_update; i++) screens[i].puts_style_offset(0, filename_offset[i] + - PM_HEIGHT + 4, buf, STYLE_INVERT,0); + pm_height[i] + 4, buf, STYLE_INVERT,0); } else { for(i = 0; i < screen_update; i++) screens[i].puts(0, filename_offset[i] + - PM_HEIGHT + 4, buf); + pm_height[i] + 4, buf); } } + yield(); + FOR_NB_SCREENS(i) { switch (global_settings.rec_source) @@ -1653,7 +2027,7 @@ break; } /* end switch */ #ifdef HAVE_AGC - if (screens[i].height < h * (2 + filename_offset[i] + PM_HEIGHT + line[i])) + if (screens[i].height < 8 + h[i] * (1 + filename_offset[i] + pm_height[i] + line[i])) { line[i] -= 1; display_agc[i] = false; @@ -1705,7 +2079,7 @@ { for(i = 0; i < screen_update; i++) screens[i].puts_style_offset(0, filename_offset[i] + - PM_HEIGHT + line[i], buf, STYLE_INVERT,0); + pm_height[i] + line[i], buf, STYLE_INVERT,0); } else if ( global_settings.rec_source == AUDIO_SRC_MIC @@ -1716,7 +2090,7 @@ for(i = 0; i < screen_update; i++) { if (display_agc[i]) { screens[i].puts(0, filename_offset[i] + - PM_HEIGHT + line[i], buf); + pm_height[i] + line[i], buf); } } } @@ -1744,27 +2118,27 @@ for(i = 0; i < screen_update; i++) screen_put_cursorxy(&screens[i], 0, filename_offset[i] + - PM_HEIGHT + 3, true); + pm_height[i] + 3, true); if(global_settings.rec_source != AUDIO_SRC_MIC) { for(i = 0; i < screen_update; i++) screen_put_cursorxy(&screens[i], 0, filename_offset[i] + - PM_HEIGHT + 4, true); + pm_height[i] + 4, true); } break; case 2: for(i = 0; i < screen_update; i++) screen_put_cursorxy(&screens[i], 0, filename_offset[i] + - PM_HEIGHT + 3, true); + pm_height[i] + 3, true); break; case 3: for(i = 0; i < screen_update; i++) screen_put_cursorxy(&screens[i], 0, filename_offset[i] + - PM_HEIGHT + 4, true); + pm_height[i] + 4, true); break; #ifdef HAVE_AGC case 4: @@ -1772,14 +2146,14 @@ for(i = 0; i < screen_update; i++) screen_put_cursorxy(&screens[i], 0, filename_offset[i] + - PM_HEIGHT + line[i], true); + pm_height[i] + line[i], true); break; #endif /* HAVE_AGC */ default: for(i = 0; i < screen_update; i++) screen_put_cursorxy(&screens[i], 0, filename_offset[i] + - PM_HEIGHT + 2, true); + pm_height[i] + 2, true); } } @@ -1787,23 +2161,268 @@ hist_time++; #endif +#ifdef HAVE_HISTOGRAM + /* Draw histogram graphs (on main unit only). + * 4 modes: low size linear or logarithmic histogram with + * disk space usage, battery level and balance meter or + * high size linear or logarithmic peak histogram. + */ +#define HIST_BAL_X (LCD_WIDTH/2 + 4) +#define HIST_BAL_W (LCD_WIDTH/2 - 5) +#define BAL_MAX_R 4988 +#define BAL_MAX_L (-BAL_MAX_R * (HIST_BAL_W/2 + 1) / (HIST_BAL_W/2)) + int hist_bal_y; + if (histogram_on) + hist_bal_y = HIST_Y - hist_size_h[history_mode/2] - 11; + else + hist_bal_y = HIST_Y - 11; + + if((global_settings.rec_source == AUDIO_SRC_MIC)|| + (global_settings.rec_source == AUDIO_SRC_LINEIN)|| + (global_settings.rec_source == AUDIO_SRC_FMRADIO)) + agc_line = 1; + else + agc_line = 0; /* no agc line for Spdif in */ + + if ((hist_bal_y) > (8 + ((line[0] + filename_offset[0] + + pm_height[0] + agc_line + (global_settings.rec_trigger_mode > + 0 ? 1 : 0)) * h[0]))) + { + lcd_setfont(FONT_SYSFIXED); + lcd_set_drawmode(DRMODE_FG); +#if LCD_DEPTH > 1 + if (battery_level() > 10) + lcd_set_foreground(LCD_BATT_OK); + else + lcd_set_foreground(LCD_BATT_LO); +#else + lcd_set_foreground( +#ifdef HAVE_LCD_COLOR + global_settings.fg_color); +#else + LCD_DEFAULT_FG); +#endif +#endif /* LCD_DEPTH > 1 */ + lcd_fillrect(0, hist_bal_y, + (30 * battery_level() + 60) / 100, 9); +#if LCD_DEPTH > 1 + if (disk_time > 59) + lcd_set_foreground(LCD_DISK_OK); + else + lcd_set_foreground(LCD_DISK_LO); +#endif /* LCD_DEPTH > 1 */ + if ((LCD_WIDTH/2 - 36)*(disk_space-disk_free-3) / disk_space) + lcd_fillrect(35, hist_bal_y, (LCD_WIDTH/2 - 37) * + (disk_space - disk_free - 1) / disk_space, 9); + lcd_set_drawmode(DRMODE_COMPLEMENT); + lcd_set_foreground( +#ifdef HAVE_LCD_COLOR + global_settings.fg_color); +#else + LCD_DEFAULT_FG); +#endif +#ifndef SIMULATOR + if (charger_inserted()) + lcd_mono_bitmap(bitmap_icons_7x8[Icon_Plug], + 2 + 19*(battery_level() > 48), + hist_bal_y + 1, 7, 8); +#endif + if (battery_time() > 90) + snprintf(buf, 32, "%dh", (battery_time() + 10) / 60); + else + snprintf(buf,32, "%dm", battery_time()); + if (battery_level() > 48) + i = 1; + else if ((battery_time() < 590) && (battery_time() > 90)) + i = 15; + else + i = 10; + lcd_putsxy(i, hist_bal_y + 1, buf); + if (disk_time > 90) + snprintf(buf, 32, "%dh", (disk_time + 10) / 60); + else + snprintf(buf, 32, "%dm", disk_time); + i = ((disk_time < 91) || (disk_time > 589))? 30:26; + + if ((hist_time % 2) +#ifndef SIMULATOR + || !ata_disk_is_active() +#endif + ) + lcd_mono_bitmap(rec_icons_6x8[Icon_Disk], + LCD_WIDTH/2 - 11, + hist_bal_y + 1, 6, 8); + lcd_putsxy((5*disk_free > 3*disk_space) ? + (LCD_WIDTH/2 - i) : 37, + hist_bal_y + 1, buf); + lcd_drawrect(34, hist_bal_y - 1, LCD_WIDTH/2 - 36, 11); + lcd_set_drawmode(DRMODE_SOLID); + lcd_drawrect(0, hist_bal_y - 1, 30, 11); + lcd_vline(30, hist_bal_y + 2, hist_bal_y + 6); + lcd_vline(31, hist_bal_y + 2, hist_bal_y + 6); + + int bal; + lcd_drawrect(HIST_BAL_X-2, hist_bal_y-1, HIST_BAL_W+3, 11); + lcd_hline(HIST_BAL_X + HIST_BAL_W/2 - 1, + HIST_BAL_X + HIST_BAL_W/2 + 1, + hist_bal_y - 2); + lcd_hline(HIST_BAL_X + HIST_BAL_W/2 - 1, + HIST_BAL_X + HIST_BAL_W/2 + 1, + hist_bal_y + 10); + lcd_set_drawmode(DRMODE_FG); +#ifndef HAVE_LCD_COLOR + lcd_set_foreground(LCD_BAL); +#endif + for (i = 0; i < BAL_MEM_SIZE; i++) { + bal = MIN(balance_mem[i], BAL_MAX_R); + bal = MAX(bal, BAL_MAX_L); +#ifdef HAVE_LCD_COLOR + if (bal > 142) + lcd_set_foreground(LCD_BAL_L); + else if (bal < 142) + lcd_set_foreground(LCD_BAL_R); + else + lcd_set_foreground(LCD_DARKGRAY); +#endif + /* every 0.2 seconds a balance measure is taken, + draw a vline for each */ + lcd_vline(HIST_BAL_X + HIST_BAL_W/2 + + HIST_BAL_W * bal / 9976, + hist_bal_y + 1, hist_bal_y + 7); + } + lcd_set_foreground(LCD_BLACK); + bal = MAX(balance, BAL_MAX_L); + bal = MIN(bal, BAL_MAX_R); + /* draw the 3 pixel wide balance measure, + average measure of the last 24 measures (5 seconds) */ + lcd_fillrect(HIST_BAL_X-1 + HIST_BAL_W/2 + + HIST_BAL_W * bal / 9976, + hist_bal_y, 3, 9); + lcd_drawpixel(HIST_BAL_X + HIST_BAL_W/2, hist_bal_y + 4); + lcd_set_drawmode(DRMODE_COMPLEMENT); + lcd_drawpixel(HIST_BAL_X + HIST_BAL_W/2, hist_bal_y - 1); + lcd_drawpixel(HIST_BAL_X + HIST_BAL_W/2, hist_bal_y + 9); + for (i = 0; i < 12; i++) + lcd_drawpixel(HIST_BAL_X + HIST_BAL_W/2 + + HIST_BAL_W * hist_balance_marks[i] / 9976, + hist_bal_y + 4); + } + + if (histogram_on) + { + hist_height = hist_size_h[history_mode/2] - 1; + if (peak_valid && !(hist_time % hist_time_interval) && hist_l) + { + if (history_mode % 2) { + i = 0; + while (hist_l < hist_peak_lin2dB[history_mode / 2][i]) + i++; + history_l[history_pos] = hist_height - i; + i = 0; + while (hist_r < hist_peak_lin2dB[history_mode / 2][i]) + i++; + history_r[history_pos] = hist_height - i; + } else { + history_l[history_pos] = hist_l * hist_height / 32767; + history_r[history_pos] = hist_r * hist_height / 32767; + } + history_pos = (history_pos + 1) % HIST_W; + history_l[history_pos] = history_r[history_pos] = 0; + history_l[(history_pos + 1) % HIST_W] = 0; + history_r[(history_pos + 1) % HIST_W] = 0; + hist_l = 0; + hist_r = 0; + } + lcd_set_drawmode(DRMODE_SOLID); + lcd_drawrect(0, HIST_Y - hist_height, + HIST_W + 2, hist_height + 1); + lcd_drawrect(HIST_W + 6, HIST_Y - hist_height, + HIST_W + 2, hist_height + 1); + lcd_set_drawmode(DRMODE_FG); +#ifdef HAVE_LCD_COLOR + for (i = 0; i < HIST_W; i++) { + if (history_l[i]) { + if (history_l[i] == hist_height) + lcd_set_foreground(LCD_HIST_OVER); + else if (history_l[i] > hist_level_marks[history_mode][1]) + lcd_set_foreground(LCD_HIST_HI); + else + lcd_set_foreground(LCD_HIST_OK); + lcd_vline(1 + i, HIST_Y-1, HIST_Y - history_l[i]); + } + if (history_r[i]) { + if (history_r[i] == hist_height) + lcd_set_foreground(LCD_HIST_OVER); + else if (history_r[i] > hist_level_marks[history_mode][1]) + lcd_set_foreground(LCD_HIST_HI); + else + lcd_set_foreground(LCD_HIST_OK); + lcd_vline(HIST_W+7 + i, HIST_Y-1, HIST_Y - history_r[i]); + } + } +#else + for (i = 0; i < HIST_W; i++) { + if (history_l[i]) { + if (history_l[i] == hist_height) + lcd_set_foreground(LCD_HIST_OVER); + else + lcd_set_foreground(LCD_HIST_OK); + lcd_vline(1 + i, HIST_Y-1, HIST_Y - history_l[i]); + } + if (history_r[i]) { + if (history_r[i] == hist_height) + lcd_set_foreground(LCD_HIST_OVER); + else + lcd_set_foreground(LCD_HIST_OK); + lcd_vline(HIST_W+7 + i, HIST_Y-1, HIST_Y - history_r[i]); + } + } + lcd_set_foreground(LCD_WHITE); + for (i = 0; i < HIST_W; i++) { + if (history_l[i] == hist_height) + lcd_drawpixel(1 + i, HIST_Y - 1); + if (history_r[i] == hist_height) + lcd_drawpixel(HIST_W + 7 + i, HIST_Y - 1); + } +#endif /* HAVE_LCD_COLOR */ + lcd_set_foreground( +#ifdef HAVE_LCD_COLOR + global_settings.fg_color); +#else + LCD_DEFAULT_FG); +#endif + for (i = 0; i < 6; i++) + lcd_hline(HIST_W + 3, HIST_W + 4, + HIST_Y - hist_level_marks[history_mode][i]); + } +#endif /* HAVE_HISTOGRAM */ + +#ifdef HAVE_AGC + hist_time++; +#endif + for(i = 0; i < screen_update; i++) { gui_statusbar_draw(&(statusbars.statusbars[i]), true); - peak_meter_screen(&screens[i], pm_x, pm_y[i], h*PM_HEIGHT); + peak_meter_screen(&screens[i], pm_x, pm_y[i], pm_h[i]); + screens[i].update(); } /* draw the trigger status */ FOR_NB_SCREENS(i) { - trig_width[i] = ((screens[i].height < 64) || - ((screens[i].height < 72) && (PM_HEIGHT > 1))) ? - screens[i].width - 14 * w : screens[i].width; + trig_width[i] = (screens[i].height < (h[i] * (2 + + filename_offset[i] + pm_height[i] + + line[i]) + (histogram_on ? 25 : 8))) ? + screens[i].width - + 14 * w[i] : screens[i].width; trig_xpos[i] = screens[i].width - trig_width[i]; - trig_ypos[i] = ((screens[i].height < 72) && (PM_HEIGHT > 1)) ? - h*2 : - h*(1 + filename_offset[i] + PM_HEIGHT + line[i] + trig_ypos[i] = (screens[i].height < (h[i] * (2 + + filename_offset[i] + pm_height[i] + + line[i]) + (histogram_on ? 25 : 8))) ? h[i]*2 + : h[i]*(1 + filename_offset[i] + + pm_height[i] + line[i] #ifdef HAVE_AGC + 1 #endif @@ -1821,6 +2440,51 @@ } } + /* check battery level & free disk space */ +#ifndef SIMULATOR + if (ata_disk_is_active()) + disk_was_active = true; + else if (disk_was_active) + { + lcd_setfont(FONT_UI); + if (disk_time == 0) { + backlight_on(); +#ifdef HAVE_REMOTE_LCD + remote_backlight_on(); +#endif + if (audio_stat & AUDIO_STATUS_RECORD) { + gui_syncsplash(HZ, "%s %s", + str(LANG_WARNING_DISK_FULL), + str(LANG_WARNING_STOP_RECORDING)); + rec_command(RECORDING_CMD_STOP); + } + else { + gui_syncsplash(2*HZ, + str(LANG_WARNING_DISK_FULL)); + } + } + else if (warn_message && (battery_level() < 10)) { + backlight_on(); +#ifdef HAVE_REMOTE_LCD + remote_backlight_on(); +#endif + gui_syncsplash(3*HZ, + str(LANG_WARNING_BATTERY_LOW)); + } + else if (!warn_message && (disk_free < 512)) { + backlight_on(); +#ifdef HAVE_REMOTE_LCD + remote_backlight_on(); +#endif + gui_syncsplash(3*HZ, + str(LANG_WARNING_DISKSPACE_LOW)); + } + lcd_setfont(FONT_SYSFIXED); + warn_message = !warn_message; + disk_was_active = false; + } +#endif + if(audio_stat & AUDIO_STATUS_ERROR) { done = true; @@ -1881,6 +2545,10 @@ if (rec_status & (RCSTAT_CREATED_DIRECTORY | RCSTAT_HAVE_RECORDED)) reload_directory(); +#ifdef HAVE_HISTOGRAM + global_settings.rec_histogram_mode = history_mode; +#endif + #if (CONFIG_LED == LED_REAL) && !defined(SIMULATOR) ata_set_led_enabled(true); #endif @@ -2129,6 +2797,12 @@ } #endif /* CONFIG_KEYPAD == RECORDER_PAD */ +struct timer *get_timerstat(void) +{ + return &timer; +} + + #if CONFIG_CODEC == SWCODEC void audio_beep(int duration) { Index: apps/recorder/peakmeter.c =================================================================== --- apps/recorder/peakmeter.c (revision 14742) +++ apps/recorder/peakmeter.c (working copy) @@ -150,17 +150,17 @@ /* precalculated peak values that represent magical dBfs values. Used to draw the scale */ static const int db_scale_src_values[DB_SCALE_SRC_VALUES_SIZE] = { - 32736, /* 0 db */ - 22752, /* - 3 db */ - 16640, /* - 6 db */ - 11648, /* - 9 db */ - 8320, /* -12 db */ - 4364, /* -18 db */ - 2064, /* -24 db */ - 1194, /* -30 db */ - 363, /* -40 db */ - 101, /* -50 db */ - 34, /* -60 db */ + 32752, /* 0 db */ + 22784, /* - 3 db */ + 14256, /* - 6 db */ + 11752, /* - 9 db */ + 9256, /* -12 db */ + 4256, /* -18 db */ + 2186, /* -24 db */ + 1186, /* -30 db */ + 373, /* -40 db */ + 102, /* -50 db */ + 33, /* -60 db */ 0, /* -inf */ }; @@ -193,69 +193,81 @@ long m; int istart; - if (isample < 2308) { /* Range 1-5 */ + /* Range 1-4 */ + if (isample < 119) { - if (isample < 115) { /* Range 1-3 */ + /* Range 1-2 */ + if (isample < 5) { - if (isample < 24) { + /* Range 1 */ + if (isample < 1) { + istart = 0; + n = 0; + m = 5900; + } - if (isample < 5) { - istart = 1; /* Range 1 */ - n = 98; + /* Range 2 */ + else { + istart = 1; + n = 59; m = 34950; } + } + + /* Range 3-4 */ else { - istart = 5; /* Range 2 */ - n = 1496; + + /* Range 3 */ + if (isample < 24) { + istart = 5; + n = 1457; m = 7168; } - } - else { - istart = 24; /* Range 3 */ - n = 2858; - m = 1498; - } - } - else { /* Range 4-5 */ - if (isample < 534) { - istart = 114; /* Range 4 */ - n = 4207; - m = 319; - } + /* Range 4 */ else { - istart = 588; /* Range 5 */ - n = 5583; - m = 69; + istart = 24; + n = 2819; + m = 1464; } } } - else { /* Range 6-9 */ + /* Range 5-8 */ + else { - if (isample < 12932) { + /* Range 5-6 */ + if (isample < 2918) { - if (isample < 6394) { - istart = 2608; /* Range 6 */ - n = 6832; - m = 21; + /* Range 5 */ + if (isample < 592) { + istart = 119; + n = 4210; + m = 295; } + + /* Range 6 */ else { - istart = 7000; /* Range 7 */ - n = 7682; - m = 9; + istart = 592; + n = 5605; + m = 60; } } + + /* Range 7-8 */ else { - if (isample < 22450) { - istart = 13000; /* Range 8 */ - n = 8219; - m = 5; + /* Range 7 */ + if (isample < 15352) { + istart = 2918; + n = 7001; + m = 12; } + + /* Range 8 */ else { - istart = 22636; /* Range 9 */ - n = 8697; + istart = 15352; + n = 8439; m = 3; } } @@ -1309,12 +1321,13 @@ } #endif -int peak_meter_draw_get_btn(int x, int y[], int height, int nb_screens) +int peak_meter_draw_get_btn(int x, int y[], int height[], int nb_screens) { int button = BUTTON_NONE; long next_refresh = current_tick; long next_big_refresh = current_tick + HZ / 10; int i; + #ifndef SIMULATOR bool highperf = !ata_disk_is_active(); #else @@ -1337,8 +1350,8 @@ if (TIME_AFTER(current_tick, next_refresh)) { for(i = 0; i < nb_screens; i++) { - peak_meter_screen(&screens[i], x, y[i], height); - screens[i].update_rect(x, y[i], screens[i].width - x, height); + peak_meter_screen(&screens[i], x, y[i], height[i]); + screens[i].update_rect(x, y[i], screens[i].width - x, height[i]); } next_refresh += HZ / PEAK_METER_FPS; dopeek = true; Index: apps/lang/english.lang =================================================================== --- apps/lang/english.lang (revision 14742) +++ apps/lang/english.lang (working copy) @@ -1300,6 +1300,115 @@ + id: LANG_MULTIINT_CONFIRM + desc: Confirm string for multi_int settings + user: + + *: "Press PLAY to confirm" + + + *: "Press PLAY to confirm" + h100,h120,h300: "Press NAVI to confirm" + ipod*,x5,gigabeat: "Press SELECT to confirm" + ondio*: "Press MODE to confirm" + + + *: "" + + + + id: LANG_RECORD_TIMER + desc: Record timer menu + user: + + *: "Timer Options" + + + *: "Timer Options" + + + *: "Timer Options" + + + + id: LANG_TIMER_SET + desc: Recording timer menu + + *: "Set countdown timer" + + + *: "Set countdown timer" + + + *: "Set countdown timer" + + + + id: LANG_TIMER_REPEAT + desc: Recording timer menu + + *: "Record repeat timer" + + + *: "Record repeat timer" + + + *: "Record repeat 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" + + + id: LANG_DITHERING desc: in the sound settings menu user: @@ -2481,6 +2590,62 @@ + id: LANG_RECORDING_HISTOGRAM_INTERVAL + desc: in record settings menu + user: + + *: "Histogram interval" + + + *: "Histogram interval" + + + *: "" + + + + id: LANG_WARNING_DISKSPACE_LOW + desc: in recording screen + user: + + *: "WARNING! Low Disk-Space!" + + + *: "WARNING! Low Disk-Space!" + + + *: "" + + + + id: LANG_WARNING_DISK_FULL + desc: in recording screen + user: + + *: "Disk is full!" + + + *: "Disk is full!" + + + *: "" + + + + id: LANG_WARNING_STOP_RECORDING + desc: in recording screen + user: + + *: "Stopping Recording..." + + + *: "Stopping Recording..." + + + *: "" + + + id: LANG_TAGCACHE_UPDATE desc: in tag cache settings user: @@ -9462,6 +9627,45 @@ + id: LANG_RECORD_HIST_OPTIONS + desc: histogram on/off + + *: "Histogram options" + + + *: "Histogram options" + + + *: "Histogram options" + + + + id: LANG_RECORD_PEAKMETER_SIZE + desc: Size of peakmeter + + *: "Size of peakmeter" + + + *: "Size of peakmeter" + + + *: "Size of peakmeter" + + + + id: LANG_RECORD_HIST_DRAW + desc: Draw histogram default + + *: "Draw histogram default" + + + *: "Draw histogram default" + + + *: "Draw histogram default" + + + id: VOICE_KBIT_PER_SEC desc: spoken only, a unit postfix user: Index: apps/settings.c =================================================================== --- apps/settings.c (revision 14742) +++ apps/settings.c (working copy) @@ -989,7 +989,207 @@ step, min, max, formatter, NULL); } + /* The type separation is necessary since int and bool are fundamentally + different and bit-incompatible types and can not share the same access + code. */ +/* Useful for time and other multi integer settings */ +bool set_multi_int(const char* string, + const struct opt_items * names, + struct opt_settings * variable, + const int varcount, + bool *changes_accepted) +{ + int i, j, w, h, space_width; + char buf[32]; + long button; + int cursor = 0; + bool done = false; + int value[varcount]; + int pos = 0; + bool changed; + + if(changes_accepted) + changed = *changes_accepted; + else + changed = false; + + /* store current values in temp array */ + for(j = 0; j < varcount; j++) + value[j] = *(int*)variable[j].setting; + + /* initialize screen */ + FOR_NB_SCREENS(i) + screens[i].clear_display(); + + gui_syncstatusbar_draw(&statusbars, true); + screens[0].getstringsize(" ", &space_width, &h); + + /* print title */ + 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), ":"); + screens[0].getstringsize(buf, &w, &h); + FOR_NB_SCREENS(i) + screens[i].putsxy(pos, 8 + h, buf); + pos += w + space_width; + + } + + snprintf(buf, sizeof(buf), "%s", P2STR(names[j].string)); + FOR_NB_SCREENS(i) + screens[i].putsxy(pos, 8 + h, buf); + + screens[0].getstringsize(buf, &w, &h); + pos += w + space_width; + } + + /* print button instructions */ + snprintf(buf, sizeof(buf), "%s", str(LANG_MULTIINT_CONFIRM)); + FOR_NB_SCREENS(i) + screens[i].puts(0, 6, buf); + + while(!done) + { + /* print variables */ + pos = 0; + FOR_NB_SCREENS(i) + { + screens[i].set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + screens[i].fillrect(0, 8 + 3 * h, screens[i].width, h + 1); + screens[i].set_drawmode(DRMODE_SOLID); + } + + for(j = 0; j < varcount; j++) + { + if (j > 0) + { + snprintf(buf, sizeof(buf), ":"); + screens[0].getstringsize(buf, &w, &h); + FOR_NB_SCREENS(i) + screens[i].putsxy(pos, 8 + 3 * h, buf); + pos += w + space_width; + } + + snprintf(buf, sizeof(buf), "%d", value[j]); + + FOR_NB_SCREENS(i) + screens[i].putsxy(pos, 8 + 3 * h, buf); + + snprintf(buf, sizeof(buf), "%d", variable[j].setting_max); + screens[0].getstringsize(buf, &w, &h); + + /* highlight currently selected integer */ + if (cursor == j) + { + FOR_NB_SCREENS(i) + { + screens[i].set_drawmode(DRMODE_COMPLEMENT); + screens[i].fillrect(pos, 8 + 3 * h, w + 1, h + 1); + screens[i].set_drawmode(DRMODE_SOLID); + } + } + + pos += w + space_width; + } + +#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: + /* cancel if pressing left when cursor + is already at the far left */ + if (cursor == 0) + { + changed = false; + gui_syncsplash(HZ/2, str(LANG_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: + value[cursor] += 1; + + if (value[cursor] > variable[cursor].setting_max) + value[cursor] = 0; + + if (global_settings.talk_menu) + talk_id(value[cursor], false); + break; + + case ACTION_SETTINGS_DEC: + case ACTION_SETTINGS_DECREPEAT: + value[cursor] -= 1; + + if (value[cursor] < 0) + value[cursor] = variable[cursor].setting_max; + + if (global_settings.talk_menu) + talk_id(value[cursor], false); + break; + + case ACTION_STD_OK: + changed = true; + done = true; + break; + + case ACTION_STD_CANCEL: + changed = false; + gui_syncsplash(HZ/2, str(LANG_CANCEL)); + done = true; + + default: + if (default_event_handler(button) == SYS_USB_CONNECTED) + return true; + } + } + + /* store values if accepted */ + if(changed) + { + for(j = 0; j < varcount; j++) + *(int*)variable[j].setting = value[j]; + } + + if(changes_accepted) + *changes_accepted = changed; + return false; +} + /** extra stuff which is probably misplaced **/ void set_file(char* filename, char* setting, int maxlen) Index: apps/gui/statusbar.c =================================================================== --- apps/gui/statusbar.c (revision 14742) +++ apps/gui/statusbar.c (working copy) @@ -33,6 +33,7 @@ #include "action.h" /* for keys_locked */ #include "statusbar.h" #ifdef HAVE_RECORDING +#include "recording.h" #include "audio.h" #include "recording.h" #endif @@ -113,7 +114,11 @@ #define STATUSBAR_LOCKR_WIDTH 5 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD) +#ifdef HAVE_MMC #define STATUSBAR_DISK_WIDTH 12 +#else +#define STATUSBAR_DISK_WIDTH 7 +#endif #define STATUSBAR_DISK_X_POS(statusbar_width) statusbar_width - \ STATUSBAR_DISK_WIDTH #else @@ -121,6 +126,15 @@ #endif #define STATUSBAR_TIME_X_END(statusbar_width) statusbar_width - 1 - \ STATUSBAR_DISK_WIDTH +#if defined(HAVE_RECORDING) +#define TIMER_ICON_WIDTH 7 +#if CONFIG_RTC +#define CLOCK_WIDTH 35 +#else +#define CLOCK_WIDTH 0 +#endif +#endif + struct gui_syncstatusbar statusbars; /* Prototypes */ @@ -140,9 +154,11 @@ #endif #ifdef HAVE_RECORDING static void gui_statusbar_icon_recording_info(struct screen * display); +static void gui_statusbar_timer(struct screen * display, int dy, int hr, int mn, int sc, bool recscreen); +static void gui_statusbar_timer_rep(struct screen * display); #endif #if CONFIG_RTC -static void gui_statusbar_time(struct screen * display, struct tm *time); +static void gui_statusbar_time(struct screen * display, struct tm *time, bool timer_display); #endif #endif @@ -245,7 +261,22 @@ #if CONFIG_RTC bar->time = get_time(); #endif /* CONFIG_RTC */ +#ifdef HAVE_RECORDING + struct timer* timer = get_timerstat(); + bar->info.timer_day = timer->days; + bar->info.timer_hour = timer->hrs; + bar->info.timer_min = timer->mins; + /* avoid an update every second unless less than one + minute remains on the timer */ + if (!bar->info.timer_day && !bar->info.timer_hour && !bar->info.timer_min) + bar->info.timer_sec = timer->secs; + else + bar->info.timer_sec = 0; + bar->info.timer_display = timer->timer_display; + bar->info.timer_repeat = timer->repeater; +#endif + /* only redraw if forced to, or info has changed */ if (force_redraw || bar->redraw_volume || #if CONFIG_RTC @@ -319,8 +350,16 @@ if (bar->info.keylockremote) gui_statusbar_icon_lock_remote(display); #endif +#ifdef HAVE_RECORDING + if (bar->info.timer_display) + gui_statusbar_timer(display, bar->info.timer_day, bar->info.timer_hour, + bar->info.timer_min, bar->info.timer_sec, recscreen_on); + else if ((bar->info.timer_repeat) && (recscreen_on)) + gui_statusbar_timer_rep(display); +#endif #if CONFIG_RTC - gui_statusbar_time(display, bar->time); + gui_statusbar_time(display, bar->time, + bar->info.timer_display); bar->last_tm_min = bar->time->tm_min; #endif /* CONFIG_RTC */ #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD) @@ -581,10 +620,11 @@ /* * Print time to status bar */ -static void gui_statusbar_time(struct screen * display, struct tm *time) + +static void gui_statusbar_time(struct screen * display, struct tm *time, bool timer_display) { unsigned char buffer[6]; - unsigned int width, height; + int width, height; int hour, minute; if ( valid_time(time) ) { hour = time->tm_hour; @@ -603,15 +643,73 @@ display->setfont(FONT_SYSFIXED); display->getstringsize(buffer, &width, &height); if (height <= STATUSBAR_HEIGHT) { +#ifdef HAVE_RECORDING + if (timer_display) + display->set_drawmode(DRMODE_INVERSEVID); +#else + (void)timer_display; +#endif display->putsxy(STATUSBAR_TIME_X_END(display->width) - width, STATUSBAR_Y_POS, buffer); } + display->set_drawmode(DRMODE_SOLID); display->setfont(FONT_UI); } #endif #ifdef HAVE_RECORDING +static void gui_statusbar_timer(struct screen * display, int dy, int hr, int mn, + int sc, bool recscreen) +{ + unsigned char buffer[8]; + int width, height; + + /* vary the display depending on the remaining time to save space */ + if (dy) + snprintf(buffer, sizeof(buffer), " %dd%02dh", hr > 58 ? dy + 1 : dy, + hr > 58 ? 0 : hr + 1); + else if (!hr && !mn) + snprintf(buffer, sizeof(buffer), "%02ds", sc); + else + snprintf(buffer, sizeof(buffer), "%02dh%02dm", mn > 58 ? hr + 1: hr, + mn > 58 ? 0 : mn + 1); + + display->setfont(FONT_SYSFIXED); + display->getstringsize(buffer, &width, &height); + + if (height <= STATUSBAR_HEIGHT) + { + if(((display->width) >= (STATUSBAR_LOCKR_X_POS + STATUSBAR_LOCKR_WIDTH + + STATUSBAR_DISK_WIDTH + width + CLOCK_WIDTH + 1)) + && !recscreen) + display->putsxy(STATUSBAR_TIME_X_END(display->width) - width - + CLOCK_WIDTH, STATUSBAR_Y_POS, buffer); + /* display only an icon for small screens or when in recording screen*/ + else if ((display->width) >= (STATUSBAR_LOCKR_X_POS + + STATUSBAR_LOCKR_WIDTH + + STATUSBAR_DISK_WIDTH + + TIMER_ICON_WIDTH + CLOCK_WIDTH + 1)) + display->mono_bitmap(bitmap_icons_7x7[Icon_Timer], + STATUSBAR_TIME_X_END(display->width) - + TIMER_ICON_WIDTH - CLOCK_WIDTH, + STATUSBAR_Y_POS, + TIMER_ICON_WIDTH, STATUSBAR_HEIGHT); + } + + display->setfont(FONT_UI); + +} + +static void gui_statusbar_timer_rep(struct screen * display) +{ + display->mono_bitmap(bitmap_icons_7x7[Icon_Timer_rep], + STATUSBAR_TIME_X_END(display->width) - + TIMER_ICON_WIDTH - CLOCK_WIDTH, + STATUSBAR_Y_POS, + TIMER_ICON_WIDTH, STATUSBAR_HEIGHT); +} + #if CONFIG_CODEC == SWCODEC /** * Write a number to the display using bitmaps and return new position Index: apps/gui/statusbar.h =================================================================== --- apps/gui/statusbar.h (revision 14742) +++ apps/gui/statusbar.h (working copy) @@ -33,6 +33,15 @@ int volume; int playmode; int repeat; +#ifdef HAVE_RECORDING + int timer_day; + int timer_hour; + int timer_min; + int timer_sec; + int timer_repeat; +#endif + int timer_display; + #if CONFIG_CHARGING bool inserted; #endif Index: apps/settings.h =================================================================== --- apps/settings.h (revision 14742) +++ apps/settings.h (working copy) @@ -259,6 +259,12 @@ unsigned const char* string; long voice_id; }; + +struct opt_settings { + int* setting; + int setting_max; +}; + const struct settings_list* find_setting(void* variable, int *id); bool cfg_int_to_string(int setting_id, int val, char* buf, int buf_len); void talk_setting(void *global_settings_variable); @@ -276,6 +282,9 @@ int* variable, void (*function)(int), int step, int min, int max, void (*formatter)(char*, size_t, int, const char*) ); +bool set_multi_int(const char* string, const struct opt_items * names, + struct opt_settings * variable, int varcount, + bool * changes_accepted); /* use this one if you need to create a lang from the value (i.e with TALK_ID()) */ bool set_int_ex(const unsigned char* string, const char* unit, int voice_unit, int* variable, @@ -370,7 +379,6 @@ 13= 1GB, 14 = 1.5GB 15 = 1.75MB*/ int rec_split_type; /* split/stop */ int rec_split_method; /* time/filesize */ - int rec_prerecord_time; /* In seconds, 0-30, 0 means OFF */ char rec_directory[MAX_FILENAME+1]; int cliplight; /* 0 = off @@ -470,6 +478,15 @@ #endif bool car_adapter_mode; /* 0=off 1=on */ +#ifdef HAVE_RECORDING +#if defined(HAVE_LCD_BITMAP) && (LCD_WIDTH > 111) + int rec_histogram_mode; /* small lin/log /w balance, big lin/log */ + int rec_histogram_interval; /* interval: 0.5s, 1s, 2s, 4s */ + bool hist_def; +#endif + int peak_size; +#endif + /* show status bar */ bool statusbar; /* 0=hide, 1=show */ Index: apps/menus/recording_menu.c =================================================================== --- apps/menus/recording_menu.c (revision 14742) +++ apps/menus/recording_menu.c (working copy) @@ -43,6 +43,7 @@ #include "sound.h" #ifdef HAVE_RECORDING #include "audio.h" +#include "recording.h" #if CONFIG_TUNER #include "radio.h" #endif @@ -306,12 +307,78 @@ MENUITEM_SETTING(rec_editable, &global_settings.rec_editable, NULL); #endif +/* Displays a menu for changing the countdown timer settings */ +static int countdown_timer_func(void) +{ + bool retval; + bool changed = false; + struct timer* timer = get_timerstat(); + + static const struct opt_items names[] = { + { STR(LANG_TIMER_DAYS) }, + { STR(LANG_TIMER_HRS) }, + { STR(LANG_TIMER_MINS) } + }; + + struct opt_settings settings[] = { + { &timer->days, 6 }, + { &timer->hrs, 23 }, + { &timer->mins, 59 } + }; + + retval = set_multi_int(str(LANG_TIMER_SET), names, settings, 3, &changed); + + if (changed) + { + timer->countdown = false; + timer->secs = 0; + timer->timer_display = false; + } + + return retval; +} + +static int countdown_timer_repeat_func(void) +{ + struct timer* timer = get_timerstat(); + bool retval; + + static const struct opt_items names[] = { + { STR(LANG_TIMER_DAYS) }, + { STR(LANG_TIMER_HRS) }, + { STR(LANG_TIMER_MINS) } + }; + + struct opt_settings settings[] = { + { &timer->days_rpt, 6 }, + { &timer->hrs_rpt, 23 }, + { &timer->mins_rpt, 59 } + }; + retval = set_multi_int(str(LANG_TIMER_REPEAT), names, settings, 3, NULL); + + /* automatically select settings necessary for repeated recording */ + if (timer->days_rpt || timer->hrs_rpt || timer->mins_rpt) + { + global_settings.rec_split_type = 1; /* Stop */ + global_settings.rec_split_method = 0; /* Time */ + global_settings.rec_trigger_mode = 0; /* The repeat timer isn't + compatible with the trigger */ + } + + return retval; +} + +MENUITEM_FUNCTION(countdown_timer, 0, ID2P(LANG_TIMER_SET), + countdown_timer_func, NULL, NULL, Icon_Menu_setting); +MENUITEM_FUNCTION(countdown_timer_repeat, 0, ID2P(LANG_TIMER_REPEAT), + countdown_timer_repeat_func, NULL, NULL, Icon_Menu_setting); MENUITEM_SETTING(rec_split_type, &global_settings.rec_split_type, NULL); MENUITEM_SETTING(rec_split_method, &global_settings.rec_split_method, NULL); MENUITEM_SETTING(rec_timesplit, &global_settings.rec_timesplit, NULL); MENUITEM_SETTING(rec_sizesplit, &global_settings.rec_sizesplit, NULL); -MAKE_MENU(filesplitoptionsmenu, ID2P(LANG_RECORD_TIMESPLIT), NULL, Icon_NOICON, - &rec_split_method, &rec_split_type, &rec_timesplit, &rec_sizesplit); +MAKE_MENU(timermenu, ID2P(LANG_RECORD_TIMER), NULL, Icon_NOICON, + &countdown_timer, &countdown_timer_repeat, &rec_split_method, + &rec_split_type, &rec_timesplit, &rec_sizesplit); MENUITEM_SETTING(rec_prerecord_time, &global_settings.rec_prerecord_time, NULL); @@ -365,6 +432,9 @@ agc_preset_func, NULL, NULL, Icon_Menu_setting); MENUITEM_FUNCTION(agc_cliptime, 0, ID2P(LANG_RECORD_AGC_CLIPTIME), agc_cliptime_func, NULL, NULL, Icon_Menu_setting); +MAKE_MENU(agc_menu, ID2P(LANG_RECORD_AGC_PRESET), NULL, Icon_NOICON, + &agc_preset, &agc_cliptime); + #endif /* HAVE_AGC */ /** Rec trigger **/ @@ -481,7 +551,9 @@ int w, h, i; int stat_height = global_settings.statusbar ? STATUSBAR_HEIGHT : 0; int pm_y[NB_SCREENS]; + int pm_h[NB_SCREENS]; + int trig_xpos[NB_SCREENS]; int trig_ypos[NB_SCREENS]; int trig_width[NB_SCREENS]; @@ -492,6 +564,7 @@ trig_xpos[i] = 0; trig_ypos[i] = screens[i].height - stat_height - TRIG_HEIGHT; pm_y[i] = screens[i].height - stat_height; + pm_h[i] = 8; trig_width[i] = screens[i].width; } @@ -630,7 +703,7 @@ } peak_meter_draw_trig(trig_xpos, trig_ypos, trig_width, NB_SCREENS); - button = peak_meter_draw_get_btn(0, pm_y, 8, NB_SCREENS); + button = peak_meter_draw_get_btn(0, pm_y, pm_h, NB_SCREENS); FOR_NB_SCREENS(i) screens[i].update(); @@ -797,6 +870,43 @@ MENUITEM_FUNCTION(rectrigger_item, 0, ID2P(LANG_RECORD_TRIGGER), (int(*)(void))rectrigger, NULL, NULL, Icon_Menu_setting); +#if LCD_HEIGHT > 111 +static int history_int_func(void) +{ + static const struct opt_items names[] = { + { "0.5s", TALK_ID(500, UNIT_MS) }, + { "1s", TALK_ID(1, UNIT_SEC) }, + { "2s", TALK_ID(2, UNIT_SEC) }, + { "4s", TALK_ID(4, UNIT_SEC) } + }; + return set_option(str(LANG_RECORDING_HISTOGRAM_INTERVAL), + &global_settings.rec_histogram_interval, + INT, names, 4, NULL ); +} +MENUITEM_FUNCTION(history_interval, 0, ID2P(LANG_RECORDING_HISTOGRAM_INTERVAL), + history_int_func, NULL, NULL, Icon_Menu_setting); +MENUITEM_SETTING(hist_def, &global_settings.hist_def, NULL); +MAKE_MENU(hist_menu, ID2P(LANG_RECORD_HIST_OPTIONS), NULL, Icon_NOICON, + &history_interval, &hist_def); +#endif +static int peak_size_func(void) +{ + static const struct opt_items names[] = { + { "1x", TALK_ID(1, UNIT_INT) }, + { "2x", TALK_ID(2, UNIT_INT) }, + { "3x", TALK_ID(3, UNIT_INT) }, + { "4x", TALK_ID(4, UNIT_INT) }, + { "5x", TALK_ID(5, UNIT_INT) }, + { "6x", TALK_ID(6, UNIT_INT) }, + { "7x", TALK_ID(7, UNIT_INT) }, + { "8x", TALK_ID(8, UNIT_INT) } + }; + return set_option(str(LANG_RECORD_PEAKMETER_SIZE), + &global_settings.peak_size, + INT, names, 8, NULL ); +} +MENUITEM_FUNCTION(peak_size, 0, ID2P(LANG_RECORD_PEAKMETER_SIZE), + peak_size_func, NULL, NULL, Icon_Menu_setting); @@ -831,7 +941,7 @@ #if CONFIG_CODEC == MAS3587F &rec_editable, #endif - &filesplitoptionsmenu, + &timermenu, &rec_prerecord_time, &clear_rec_directory_item, #ifdef HAVE_BACKLIGHT @@ -839,8 +949,12 @@ #endif &rectrigger_item, #ifdef HAVE_AGC - &agc_preset, &agc_cliptime, + &agc_menu, #endif +#if LCD_HEIGHT > 111 + &hist_menu, +#endif + &peak_size, &browse_recconfigs, &save_recpresets_item ); Index: apps/settings_list.c =================================================================== --- apps/settings_list.c (revision 14742) +++ apps/settings_list.c (working copy) @@ -884,6 +884,17 @@ {F_T_INT|F_RECSETTING,&global_settings.rec_trigger_mode, LANG_RECORD_TRIGGER,INT(0), "trigger mode","off,once,repeat",UNUSED}, + +#if defined(HAVE_LCD_BITMAP) && (LCD_WIDTH > 111) + {F_T_INT,&global_settings.rec_histogram_mode,-1,INT(1), + "histogram mode",NULL,UNUSED}, + {F_T_INT,&global_settings.rec_histogram_interval,LANG_RECORDING_HISTOGRAM_INTERVAL,INT(0), + "histogram interval","0.5s,1s,2s,4s",UNUSED}, + OFFON_SETTING(0, hist_def, LANG_RECORD_HIST_DRAW, true, "default histogram status", NULL), +#endif + {F_T_INT,&global_settings.peak_size,LANG_RECORD_PEAKMETER_SIZE,INT(0), + "peakmeter size", "1x,2x,3x,4x,5x,6x,7x,8x",UNUSED}, + #endif /* HAVE_RECORDING */ #ifdef HAVE_SPDIF_POWER Index: apps/keymaps/keymap-x5.c =================================================================== --- apps/keymaps/keymap-x5.c (revision 14742) +++ apps/keymaps/keymap-x5.c (working copy) @@ -217,6 +217,9 @@ { ACTION_SETTINGS_DEC, BUTTON_DOWN, BUTTON_NONE }, { ACTION_SETTINGS_DECREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_STD_PREV, BUTTON_LEFT, BUTTON_NONE }, + { ACTION_STD_PREVREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_NEXT, BUTTON_RIGHT, BUTTON_NONE }, + { ACTION_STD_NEXTREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_STD_CANCEL, BUTTON_REC, BUTTON_NONE }, LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) Index: apps/keymaps/keymap-h1x0_h3x0.c =================================================================== --- apps/keymaps/keymap-h1x0_h3x0.c (revision 14742) +++ apps/keymaps/keymap-h1x0_h3x0.c (working copy) @@ -239,6 +239,7 @@ { ACTION_SETTINGS_INC, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_SETTINGS_DEC, BUTTON_LEFT, BUTTON_NONE }, { ACTION_SETTINGS_DEC, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_REC_HIST_TOGGLE, BUTTON_MODE|BUTTON_REPEAT, BUTTON_MODE }, LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) }; /* button_context_recscreen */ @@ -439,6 +440,10 @@ { 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 }, @@ -451,8 +456,13 @@ { 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_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 */ @@ -603,6 +613,7 @@ { ACTION_SETTINGS_INC, BUTTON_RC_BITRATE|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_SETTINGS_DEC, BUTTON_RC_SOURCE, BUTTON_NONE }, { ACTION_SETTINGS_DEC, BUTTON_RC_SOURCE|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_REC_HIST_TOGGLE, BUTTON_RC_MODE|BUTTON_REPEAT, BUTTON_RC_MODE }, LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) }; /* button_context_recscreen_h100remote */ @@ -615,6 +626,7 @@ { ACTION_SETTINGS_INC, BUTTON_RC_FF|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_SETTINGS_DEC, BUTTON_RC_REW, BUTTON_NONE }, { ACTION_SETTINGS_DEC, BUTTON_RC_REW|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_REC_HIST_TOGGLE, BUTTON_RC_MODE|BUTTON_REPEAT, BUTTON_RC_MODE }, LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) }; /* button_context_recscreen_h300lcdremote */ Index: apps/keymaps/keymap-ondio.c =================================================================== --- apps/keymaps/keymap-ondio.c (revision 14742) +++ apps/keymaps/keymap-ondio.c (working copy) @@ -73,9 +73,10 @@ { ACTION_SETTINGS_INCREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_SETTINGS_DEC, BUTTON_DOWN, BUTTON_NONE }, { ACTION_SETTINGS_DECREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_OK, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_STD_OK, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_MENU, BUTTON_NONE }, + { ACTION_STD_NEXT, BUTTON_RIGHT, BUTTON_NONE }, + { ACTION_NONE, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT }, + { ACTION_STD_PREV, BUTTON_LEFT, BUTTON_NONE }, + { ACTION_STD_OK, BUTTON_MENU, BUTTON_NONE }, LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) };