| /*************************************************************************** |
| * __________ __ ___. |
| * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| * \/ \/ \/ \/ \/ |
| * $Id$ |
| * |
| * Copyright (C) 2002 by Linus Nielsen Feltzing |
| * |
| * 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. |
| * |
| * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| * KIND, either express or implied. |
| * |
| ****************************************************************************/ |
| |
| #include "config.h" |
| |
| #include <stdio.h> |
| #include <stdbool.h> |
| #include <stdlib.h> |
| |
| #include "system.h" |
| #include "lcd.h" |
| #include "led.h" |
| #include "mpeg.h" |
| #include "audio.h" |
| #if CONFIG_CODEC == SWCODEC |
| #include "pcm_record.h" |
| #endif |
| #ifdef HAVE_UDA1380 |
| #include "uda1380.h" |
| #endif |
| |
| #include "mp3_playback.h" |
| #include "mas.h" |
| #include "button.h" |
| #include "kernel.h" |
| #include "settings.h" |
| #include "lang.h" |
| #include "font.h" |
| #include "icons.h" |
| #include "screens.h" |
| #include "peakmeter.h" |
| #include "status.h" |
| #include "menu.h" |
| #include "sound_menu.h" |
| #include "timefuncs.h" |
| #include "debug.h" |
| #include "misc.h" |
| #include "tree.h" |
| #include "string.h" |
| #include "dir.h" |
| #include "errno.h" |
| #include "talk.h" |
| #include "atoi.h" |
| #include "sound.h" |
| #include "ata.h" |
| #include "splash.h" |
| #ifdef HAVE_RECORDING |
| |
| |
| #if CONFIG_KEYPAD == RECORDER_PAD |
| #define REC_STOPEXIT BUTTON_OFF |
| #define REC_RECPAUSE BUTTON_PLAY |
| #define REC_INC BUTTON_RIGHT |
| #define REC_DEC BUTTON_LEFT |
| #define REC_NEXT BUTTON_DOWN |
| #define REC_PREV BUTTON_UP |
| #define REC_SETTINGS BUTTON_F1 |
| #define REC_F2 BUTTON_F2 |
| #define REC_F3 BUTTON_F3 |
| |
| #elif CONFIG_KEYPAD == ONDIO_PAD /* only limited features */ |
| #define REC_STOPEXIT BUTTON_OFF |
| #define REC_RECPAUSE_PRE BUTTON_MENU |
| #define REC_RECPAUSE (BUTTON_MENU | BUTTON_REL) |
| #define REC_INC BUTTON_RIGHT |
| #define REC_DEC BUTTON_LEFT |
| #define REC_NEXT BUTTON_DOWN |
| #define REC_PREV BUTTON_UP |
| #define REC_SETTINGS (BUTTON_MENU | BUTTON_REPEAT) |
| |
| #elif CONFIG_KEYPAD == IRIVER_H100_PAD |
| #define REC_STOPEXIT BUTTON_OFF |
| #define REC_RECPAUSE BUTTON_REC |
| #define REC_INC BUTTON_RIGHT |
| #define REC_DEC BUTTON_LEFT |
| #define REC_NEXT BUTTON_DOWN |
| #define REC_PREV BUTTON_UP |
| #define REC_SETTINGS BUTTON_MODE |
| |
| #elif CONFIG_KEYPAD == GMINI100_PAD |
| #define REC_STOPEXIT BUTTON_OFF |
| #define REC_RECPAUSE BUTTON_ON |
| #define REC_INC BUTTON_RIGHT |
| #define REC_DEC BUTTON_LEFT |
| #endif |
| |
| bool f2_rec_screen(void); |
| bool f3_rec_screen(void); |
| |
| #define SOURCE_MIC 0 |
| #define SOURCE_LINE 1 |
| #ifdef HAVE_SPDIF_IN |
| #define SOURCE_SPDIF 2 |
| #define MAX_SOURCE SOURCE_SPDIF |
| #else |
| #define MAX_SOURCE SOURCE_LINE |
| #endif |
| |
| #if CONFIG_CODEC == SWCODEC |
| #define REC_FILE_ENDING ".wav" |
| #else |
| #define REC_FILE_ENDING ".mp3" |
| #endif |
| |
| #define MAX_FILE_SIZE 0x7FF00000 /* 2 GB - 1 MB */ |
| |
| const char* const freq_str[6] = |
| { |
| "44.1kHz", |
| "48kHz", |
| "32kHz", |
| "22.05kHz", |
| "24kHz", |
| "16kHz" |
| }; |
| |
| static void set_gain(void) |
| { |
| if(global_settings.rec_source == SOURCE_MIC) |
| { |
| audio_set_recording_gain(global_settings.rec_mic_gain, 0, AUDIO_GAIN_MIC); |
| } |
| else |
| { |
| audio_set_recording_gain(global_settings.rec_left_gain, |
| global_settings.rec_right_gain, AUDIO_GAIN_LINEIN); |
| } |
| #ifdef HAVE_UDA1380 |
| audio_set_recording_gain(global_settings.rec_adc_left_gain, |
| global_settings.rec_adc_right_gain, |
| AUDIO_GAIN_ADC); |
| #endif |
| } |
| |
| static const char* const fmtstr[] = |
| { |
| "%d %s", /* no decimals */ |
| "%d.%d %s ", /* 1 decimal */ |
| "%d.%02d %s " /* 2 decimals */ |
| }; |
| |
| char *fmt_gain(int snd, int val, char *str, int len) |
| { |
| int tmp, i, d, numdec; |
| const char *unit; |
| |
| tmp = sound_val2phys(snd, val); |
| numdec = sound_numdecimals(snd); |
| unit = sound_unit(snd); |
| |
| if(numdec) |
| { |
| i = tmp / (10*numdec); |
| d = abs(tmp % (10*numdec)); |
| snprintf(str, len, fmtstr[numdec], i, d, unit); |
| } |
| else |
| snprintf(str, len, fmtstr[numdec], tmp, unit); |
| |
| return str; |
| } |
| |
| static int cursor; |
| |
| void adjust_cursor(void) |
| { |
| int max_cursor; |
| |
| if(cursor < 0) |
| cursor = 0; |
| |
| switch(global_settings.rec_source) |
| { |
| case SOURCE_MIC: |
| max_cursor = 1; |
| break; |
| |
| case SOURCE_LINE: |
| max_cursor = 3; |
| break; |
| default: |
| max_cursor = 0; |
| break; |
| } |
| |
| if(cursor > max_cursor) |
| cursor = max_cursor; |
| } |
| |
| char *rec_create_filename(char *buffer) |
| { |
| if(global_settings.rec_directory) |
| getcwd(buffer, MAX_PATH); |
| else |
| strncpy(buffer, rec_base_directory, MAX_PATH); |
| |
| #ifdef HAVE_RTC |
| create_datetime_filename(buffer, buffer, "R", REC_FILE_ENDING); |
| #else |
| create_numbered_filename(buffer, buffer, "rec_", REC_FILE_ENDING, 4); |
| #endif |
| return buffer; |
| } |
| |
| int rec_create_directory(void) |
| { |
| int rc; |
| |
| /* Try to create the base directory if needed */ |
| if(global_settings.rec_directory == 0) |
| { |
| rc = mkdir(rec_base_directory, 0); |
| if(rc < 0 && errno != EEXIST) |
| { |
| gui_syncsplash(HZ * 2, true, |
| "Can't create the %s directory. Error code %d.", |
| rec_base_directory, rc); |
| return -1; |
| } |
| else |
| { |
| /* If we have created the directory, we want the dir browser to |
| be refreshed even if we haven't recorded anything */ |
| if(errno != EEXIST) |
| return 1; |
| } |
| } |
| return 0; |
| } |
| |
| static char path_buffer[MAX_PATH]; |
| |
| /* used in trigger_listerner and recording_screen */ |
| static unsigned int last_seconds = 0; |
| |
| /** |
| * Callback function so that the peak meter code can send an event |
| * to this application. This function can be passed to |
| * peak_meter_set_trigger_listener in order to activate the trigger. |
| */ |
| static void trigger_listener(int trigger_status) |
| { |
| switch (trigger_status) |
| { |
| case TRIG_GO: |
| if((audio_status() & AUDIO_STATUS_RECORD) != AUDIO_STATUS_RECORD) |
| { |
| talk_buffer_steal(); /* we use the mp3 buffer */ |
| audio_record(rec_create_filename(path_buffer)); |
| |
| /* give control to mpeg thread so that it can start recording */ |
| yield(); yield(); yield(); |
| } |
| |
| /* if we're already recording this is a retrigger */ |
| else |
| { |
| audio_new_file(rec_create_filename(path_buffer)); |
| /* tell recording_screen to reset the time */ |
| last_seconds = 0; |
| } |
| break; |
| |
| /* A _change_ to TRIG_READY means the current recording has stopped */ |
| case TRIG_READY: |
| if(audio_status() & AUDIO_STATUS_RECORD) |
| { |
| audio_stop(); |
| if (global_settings.rec_trigger_mode != TRIG_MODE_REARM) |
| { |
| peak_meter_set_trigger_listener(NULL); |
| peak_meter_trigger(false); |
| } |
| } |
| break; |
| } |
| } |
| |
| bool recording_screen(void) |
| { |
| long button; |
| long lastbutton = BUTTON_NONE; |
| bool done = false; |
| char buf[32]; |
| char buf2[32]; |
| int gain; |
| int w, h; |
| int update_countdown = 1; |
| bool have_recorded = false; |
| unsigned int seconds; |
| int hours, minutes; |
| char path_buffer[MAX_PATH]; |
| bool been_in_usb_mode = false; |
| int last_audio_stat = -1; |
| int audio_stat; |
| #if CONFIG_LED == LED_REAL |
| bool led_state = false; |
| int led_countdown = 2; |
| #endif |
| |
| const unsigned char *byte_units[] = { |
| ID2P(LANG_BYTE), |
| ID2P(LANG_KILOBYTE), |
| ID2P(LANG_MEGABYTE), |
| ID2P(LANG_GIGABYTE) |
| }; |
| |
| cursor = 0; |
| #if (CONFIG_LED == LED_REAL) && !defined(SIMULATOR) |
| ata_set_led_enabled(false); |
| #endif |
| audio_init_recording(); |
| |
| sound_set_volume(global_settings.volume); |
| |
| /* Yes, we use the D/A for monitoring */ |
| peak_meter_playback(true); |
| |
| peak_meter_enabled = true; |
| |
| #if CONFIG_CODEC == SWCODEC |
| audio_stop(); |
| #endif |
| |
| if (global_settings.rec_prerecord_time) |
| talk_buffer_steal(); /* will use the mp3 buffer */ |
| |
| audio_set_recording_options(global_settings.rec_frequency, |
| global_settings.rec_quality, |
| global_settings.rec_source, |
| global_settings.rec_channels, |
| global_settings.rec_editable, |
| global_settings.rec_prerecord_time); |
| |
| set_gain(); |
| |
| settings_apply_trigger(); |
| |
| lcd_setfont(FONT_SYSFIXED); |
| lcd_getstringsize("M", &w, &h); |
| lcd_setmargins(global_settings.invert_cursor ? 0 : w, 8); |
| |
| if(rec_create_directory() > 0) |
| have_recorded = true; |
| |
| while(!done) |
| { |
| #if CONFIG_CODEC == SWCODEC |
| audio_stat = pcm_rec_status(); |
| #else |
| audio_stat = audio_status(); |
| #endif |
| |
| #if CONFIG_LED == LED_REAL |
| |
| /* |
| * Flash the LED while waiting to record. Turn it on while |
| * recording. |
| */ |
| if(audio_stat & AUDIO_STATUS_RECORD) |
| { |
| if (audio_stat & AUDIO_STATUS_PAUSE) |
| { |
| if (--led_countdown <= 0) |
| { |
| led_state = !led_state; |
| led(led_state); |
| led_countdown = 2; |
| } |
| } |
| else |
| { |
| /* trigger is on in status TRIG_READY (no check needed) */ |
| led(true); |
| } |
| } |
| else |
| { |
| int trigStat = peak_meter_trigger_status(); |
| /* |
| * other trigger stati than trig_off and trig_steady |
| * already imply that we are recording. |
| */ |
| if (trigStat == TRIG_STEADY) |
| { |
| if (--led_countdown <= 0) |
| { |
| led_state = !led_state; |
| led(led_state); |
| led_countdown = 2; |
| } |
| } |
| else |
| { |
| /* trigger is on in status TRIG_READY (no check needed) */ |
| led(false); |
| } |
| } |
| #endif /* CONFIG_LED */ |
| |
| /* Wait for a button a while (HZ/10) drawing the peak meter */ |
| button = peak_meter_draw_get_btn(0, 8 + h*2, LCD_WIDTH, h); |
| |
| if (last_audio_stat != audio_stat) |
| { |
| if (audio_stat == AUDIO_STATUS_RECORD) |
| { |
| have_recorded = true; |
| } |
| last_audio_stat = audio_stat; |
| } |
| |
| switch(button) |
| { |
| case REC_STOPEXIT: |
| /* turn off the trigger */ |
| peak_meter_trigger(false); |
| peak_meter_set_trigger_listener(NULL); |
| |
| if(audio_stat & AUDIO_STATUS_RECORD) |
| { |
| audio_stop_recording(); |
| } |
| else |
| { |
| peak_meter_playback(true); |
| peak_meter_enabled = false; |
| done = true; |
| } |
| update_countdown = 1; /* Update immediately */ |
| break; |
| |
| case REC_RECPAUSE: |
| #ifdef REC_RECPAUSE_PRE |
| if (lastbutton != REC_RECPAUSE_PRE) |
| break; |
| #endif |
| /* Only act if the mpeg is stopped */ |
| if(!(audio_stat & AUDIO_STATUS_RECORD)) |
| { |
| /* is this manual or triggered recording? */ |
| if ((global_settings.rec_trigger_mode == TRIG_MODE_OFF) || |
| (peak_meter_trigger_status() != TRIG_OFF)) |
| { |
| /* manual recording */ |
| have_recorded = true; |
| talk_buffer_steal(); /* we use the mp3 buffer */ |
| audio_record(rec_create_filename(path_buffer)); |
| last_seconds = 0; |
| if (global_settings.talk_menu) |
| { /* no voice possible here, but a beep */ |
| audio_beep(HZ/2); /* longer beep on start */ |
| } |
| } |
| |
| /* this is triggered recording */ |
| else |
| { |
| /* we don't start recording now, but enable the |
| trigger and let the callback function |
| trigger_listener control when the recording starts */ |
| peak_meter_trigger(true); |
| peak_meter_set_trigger_listener(&trigger_listener); |
| } |
| } |
| else |
| { |
| if(audio_stat & AUDIO_STATUS_PAUSE) |
| { |
| audio_resume_recording(); |
| if (global_settings.talk_menu) |
| { /* no voice possible here, but a beep */ |
| audio_beep(HZ/4); /* short beep on resume */ |
| } |
| } |
| else |
| { |
| audio_pause_recording(); |
| } |
| } |
| update_countdown = 1; /* Update immediately */ |
| break; |
| |
| #ifdef REC_PREV |
| case REC_PREV: |
| cursor--; |
| adjust_cursor(); |
| update_countdown = 1; /* Update immediately */ |
| break; |
| #endif |
| |
| #ifdef REC_NEXT |
| case REC_NEXT: |
| cursor++; |
| adjust_cursor(); |
| update_countdown = 1; /* Update immediately */ |
| break; |
| #endif |
| |
| case REC_INC: |
| case REC_INC | BUTTON_REPEAT: |
| switch(cursor) |
| { |
| case 0: |
| if(global_settings.volume < |
| sound_max(SOUND_VOLUME)) |
| global_settings.volume++; |
| sound_set_volume(global_settings.volume); |
| break; |
| |
| case 1: |
| if(global_settings.rec_source == SOURCE_MIC) |
| { |
| if(global_settings.rec_mic_gain < |
| sound_max(SOUND_MIC_GAIN)) |
| global_settings.rec_mic_gain++; |
| } |
| else |
| { |
| gain = MAX(global_settings.rec_left_gain, |
| global_settings.rec_right_gain); |
| if(gain < sound_max(SOUND_LEFT_GAIN)) |
| gain++; |
| global_settings.rec_left_gain = gain; |
| global_settings.rec_right_gain = gain; |
| } |
| break; |
| case 2: |
| if(global_settings.rec_left_gain < |
| sound_max(SOUND_LEFT_GAIN)) |
| global_settings.rec_left_gain++; |
| break; |
| case 3: |
| if(global_settings.rec_right_gain < |
| sound_max(SOUND_RIGHT_GAIN)) |
| global_settings.rec_right_gain++; |
| break; |
| } |
| set_gain(); |
| update_countdown = 1; /* Update immediately */ |
| break; |
| |
| case REC_DEC: |
| case REC_DEC | BUTTON_REPEAT: |
| switch(cursor) |
| { |
| case 0: |
| if(global_settings.volume > |
| sound_min(SOUND_VOLUME)) |
| global_settings.volume--; |
| sound_set_volume(global_settings.volume); |
| break; |
| |
| case 1: |
| if(global_settings.rec_source == SOURCE_MIC) |
| { |
| if(global_settings.rec_mic_gain > |
| sound_min(SOUND_MIC_GAIN)) |
| global_settings.rec_mic_gain--; |
| } |
| else |
| { |
| gain = MAX(global_settings.rec_left_gain, |
| global_settings.rec_right_gain); |
| if(gain > sound_min(SOUND_LEFT_GAIN)) |
| gain--; |
| global_settings.rec_left_gain = gain; |
| global_settings.rec_right_gain = gain; |
| } |
| break; |
| case 2: |
| if(global_settings.rec_left_gain > |
| sound_min(SOUND_LEFT_GAIN)) |
| global_settings.rec_left_gain--; |
| break; |
| case 3: |
| if(global_settings.rec_right_gain > |
| sound_min(SOUND_RIGHT_GAIN)) |
| global_settings.rec_right_gain--; |
| break; |
| } |
| set_gain(); |
| update_countdown = 1; /* Update immediately */ |
| break; |
| |
| #ifdef REC_SETTINGS |
| case REC_SETTINGS: |
| if(audio_stat != AUDIO_STATUS_RECORD) |
| { |
| #if CONFIG_LED == LED_REAL |
| /* led is restored at begin of loop / end of function */ |
| led(false); |
| #endif |
| if (recording_menu(false)) |
| { |
| return SYS_USB_CONNECTED; |
| } |
| settings_save(); |
| |
| if (global_settings.rec_prerecord_time) |
| talk_buffer_steal(); /* will use the mp3 buffer */ |
| |
| audio_set_recording_options(global_settings.rec_frequency, |
| global_settings.rec_quality, |
| global_settings.rec_source, |
| global_settings.rec_channels, |
| global_settings.rec_editable, |
| global_settings.rec_prerecord_time); |
| |
| adjust_cursor(); |
| set_gain(); |
| update_countdown = 1; /* Update immediately */ |
| |
| lcd_setfont(FONT_SYSFIXED); |
| lcd_setmargins(global_settings.invert_cursor ? 0 : w, 8); |
| } |
| break; |
| #endif |
| |
| #ifdef REC_F2 |
| case REC_F2: |
| if(audio_stat != AUDIO_STATUS_RECORD) |
| { |
| #if CONFIG_LED == LED_REAL |
| /* led is restored at begin of loop / end of function */ |
| led(false); |
| #endif |
| if (f2_rec_screen()) |
| { |
| have_recorded = true; |
| done = true; |
| } |
| else |
| update_countdown = 1; /* Update immediately */ |
| } |
| break; |
| #endif |
| |
| #ifdef REC_F3 |
| case REC_F3: |
| if(audio_stat & AUDIO_STATUS_RECORD) |
| { |
| audio_new_file(rec_create_filename(path_buffer)); |
| last_seconds = 0; |
| } |
| else |
| { |
| if(audio_stat != AUDIO_STATUS_RECORD) |
| { |
| #if CONFIG_LED == LED_REAL |
| /* led is restored at begin of loop / end of function */ |
| led(false); |
| #endif |
| if (f3_rec_screen()) |
| { |
| have_recorded = true; |
| done = true; |
| } |
| else |
| update_countdown = 1; /* Update immediately */ |
| } |
| } |
| break; |
| #endif |
| |
| case SYS_USB_CONNECTED: |
| /* Only accept USB connection when not recording */ |
| if(audio_stat != AUDIO_STATUS_RECORD) |
| { |
| default_event_handler(SYS_USB_CONNECTED); |
| done = true; |
| been_in_usb_mode = true; |
| } |
| break; |
| |
| default: |
| default_event_handler(button); |
| break; |
| } |
| if (button != BUTTON_NONE) |
| lastbutton = button; |
| |
| lcd_setfont(FONT_SYSFIXED); |
| |
| seconds = audio_recorded_time() / HZ; |
| |
| update_countdown--; |
| if(update_countdown == 0 || seconds > last_seconds) |
| { |
| unsigned int dseconds, dhours, dminutes; |
| unsigned long num_recorded_bytes; |
| int pos = 0; |
| |
| update_countdown = 5; |
| last_seconds = seconds; |
| |
| lcd_clear_display(); |
| |
| hours = seconds / 3600; |
| minutes = (seconds - (hours * 3600)) / 60; |
| snprintf(buf, 32, "%s %02d:%02d:%02d", |
| str(LANG_RECORDING_TIME), |
| hours, minutes, seconds%60); |
| lcd_puts(0, 0, buf); |
| |
| dseconds = rec_timesplit_seconds(); |
| num_recorded_bytes = audio_num_recorded_bytes(); |
| |
| if(audio_stat & AUDIO_STATUS_PRERECORD) |
| { |
| snprintf(buf, 32, "%s...", str(LANG_RECORD_PRERECORD)); |
| } |
| else |
| { |
| /* Display the split interval if the record timesplit |
| is active */ |
| if (global_settings.rec_timesplit) |
| { |
| /* Display the record timesplit interval rather |
| than the file size if the record timer is |
| active */ |
| dhours = dseconds / 3600; |
| dminutes = (dseconds - (dhours * 3600)) / 60; |
| snprintf(buf, 32, "%s %02d:%02d", |
| str(LANG_RECORD_TIMESPLIT_REC), |
| dhours, dminutes); |
| } |
| else |
| { |
| output_dyn_value(buf2, sizeof buf2, |
| num_recorded_bytes, |
| byte_units, true); |
| snprintf(buf, 32, "%s %s", |
| str(LANG_RECORDING_SIZE), buf2); |
| } |
| } |
| lcd_puts(0, 1, buf); |
| |
| /* We will do file splitting regardless, either at the end of |
| a split interval, or when the filesize approaches the 2GB |
| FAT file size (compatibility) limit. */ |
| if (audio_stat && |
| ((global_settings.rec_timesplit && (seconds >= dseconds)) |
| || (num_recorded_bytes >= MAX_FILE_SIZE))) |
| { |
| audio_new_file(rec_create_filename(path_buffer)); |
| update_countdown = 1; |
| last_seconds = 0; |
| } |
| |
| snprintf(buf, 32, "%s: %s", str(LANG_VOLUME), |
| fmt_gain(SOUND_VOLUME, |
| global_settings.volume, |
| buf2, sizeof(buf2))); |
| |
| if (global_settings.invert_cursor && (pos++ == cursor)) |
| lcd_puts_style(0, 3, buf, STYLE_INVERT); |
| else |
| lcd_puts(0, 3, buf); |
| |
| if(global_settings.rec_source == SOURCE_MIC) |
| { |
| snprintf(buf, 32, "%s: %s", str(LANG_RECORDING_GAIN), |
| fmt_gain(SOUND_MIC_GAIN, |
| global_settings.rec_mic_gain, |
| buf2, sizeof(buf2))); |
| if (global_settings.invert_cursor && (pos++ == cursor)) |
| lcd_puts_style(0, 4, buf, STYLE_INVERT); |
| else |
| lcd_puts(0, 4, buf); |
| } |
| else |
| { |
| if(global_settings.rec_source == SOURCE_LINE) |
| { |
| gain = MAX(global_settings.rec_left_gain, |
| global_settings.rec_right_gain); |
| |
| snprintf(buf, 32, "%s: %s", str(LANG_RECORDING_GAIN), |
| fmt_gain(SOUND_LEFT_GAIN, gain, |
| buf2, sizeof(buf2))); |
| if (global_settings.invert_cursor && (pos++ == cursor)) |
| lcd_puts_style(0, 4, buf, STYLE_INVERT); |
| else |
| lcd_puts(0, 4, buf); |
| |
| snprintf(buf, 32, "%s: %s", str(LANG_RECORDING_LEFT), |
| fmt_gain(SOUND_LEFT_GAIN, |
| global_settings.rec_left_gain, |
| buf2, sizeof(buf2))); |
| if (global_settings.invert_cursor && (pos++ == cursor)) |
| lcd_puts_style(0, 5, buf, STYLE_INVERT); |
| else |
| lcd_puts(0, 5, buf); |
| |
| snprintf(buf, 32, "%s: %s", str(LANG_RECORDING_RIGHT), |
| fmt_gain(SOUND_RIGHT_GAIN, |
| global_settings.rec_right_gain, |
| buf2, sizeof(buf2))); |
| if (global_settings.invert_cursor && (pos == cursor)) |
| lcd_puts_style(0, 6, buf, STYLE_INVERT); |
| else |
| lcd_puts(0, 6, buf); |
| } |
| } |
| |
| put_cursorxy(0, 3 + cursor, true); |
| |
| if (global_settings.rec_source != SOURCE_LINE) { |
| snprintf(buf, 32, "%s %s [%d]", |
| freq_str[global_settings.rec_frequency], |
| global_settings.rec_channels? |
| str(LANG_CHANNEL_MONO):str(LANG_CHANNEL_STEREO), |
| global_settings.rec_quality); |
| lcd_puts(0, 6, buf); |
| } |
| |
| status_draw(true); |
| peak_meter_draw(0, 8 + h*2, LCD_WIDTH, h); |
| |
| lcd_update(); |
| |
| /* draw the trigger status */ |
| if (peak_meter_trigger_status() != TRIG_OFF) |
| { |
| peak_meter_draw_trig(LCD_WIDTH - TRIG_WIDTH, 4 * h); |
| lcd_update_rect(LCD_WIDTH - (TRIG_WIDTH + 2), 4 * h, |
| TRIG_WIDTH + 2, TRIG_HEIGHT); |
| } |
| } |
| |
| if(audio_stat & AUDIO_STATUS_ERROR) |
| { |
| done = true; |
| } |
| } |
| |
| |
| #if CONFIG_CODEC == SWCODEC |
| audio_stat = pcm_rec_status(); |
| #else |
| audio_stat = audio_status(); |
| #endif |
| if (audio_stat & AUDIO_STATUS_ERROR) |
| { |
| gui_syncsplash(0, true, str(LANG_DISK_FULL)); |
| status_draw(true); |
| lcd_update(); |
| audio_error_clear(); |
| |
| while(1) |
| { |
| button = button_get(true); |
| if(button == (REC_STOPEXIT | BUTTON_REL)) |
| break; |
| } |
| } |
| |
| #if CONFIG_CODEC == SWCODEC |
| audio_stop_recording(); |
| audio_close_recording(); |
| #else |
| audio_init_playback(); |
| #endif |
| |
| /* make sure the trigger is really turned off */ |
| peak_meter_trigger(false); |
| peak_meter_set_trigger_listener(NULL); |
| |
| sound_settings_apply(); |
| |
| lcd_setfont(FONT_UI); |
| |
| if (have_recorded) |
| reload_directory(); |
| |
| #if (CONFIG_LED == LED_REAL) && !defined(SIMULATOR) |
| ata_set_led_enabled(true); |
| #endif |
| return been_in_usb_mode; |
| /* |
| #endif |
| */ |
| } |
| |
| #ifdef REC_F2 |
| bool f2_rec_screen(void) |
| { |
| bool exit = false; |
| bool used = false; |
| int w, h; |
| char buf[32]; |
| int button; |
| |
| lcd_setfont(FONT_SYSFIXED); |
| lcd_getstringsize("A",&w,&h); |
| |
| while (!exit) { |
| const char* ptr=NULL; |
| |
| lcd_clear_display(); |
| |
| /* Recording quality */ |
| lcd_putsxy(0, LCD_HEIGHT/2 - h*2, str(LANG_RECORDING_QUALITY)); |
| snprintf(buf, 32, "%d", global_settings.rec_quality); |
| lcd_putsxy(0, LCD_HEIGHT/2-h, buf); |
| lcd_mono_bitmap(bitmap_icons_7x8[Icon_FastBackward], |
| LCD_WIDTH/2 - 16, LCD_HEIGHT/2 - 4, 7, 8); |
| |
| /* Frequency */ |
| snprintf(buf, sizeof buf, "%s:", str(LANG_RECORDING_FREQUENCY)); |
| lcd_getstringsize(buf,&w,&h); |
| lcd_putsxy((LCD_WIDTH-w)/2, LCD_HEIGHT - h*2, buf); |
| ptr = freq_str[global_settings.rec_frequency]; |
| lcd_getstringsize(ptr, &w, &h); |
| lcd_putsxy((LCD_WIDTH-w)/2, LCD_HEIGHT - h, ptr); |
| lcd_mono_bitmap(bitmap_icons_7x8[Icon_DownArrow], |
| LCD_WIDTH/2 - 3, LCD_HEIGHT - h*3, 7, 8); |
| |
| /* Channel mode */ |
| switch ( global_settings.rec_channels ) { |
| case 0: |
| ptr = str(LANG_CHANNEL_STEREO); |
| break; |
| |
| case 1: |
| ptr = str(LANG_CHANNEL_MONO); |
| break; |
| } |
| |
| lcd_getstringsize(str(LANG_RECORDING_CHANNELS), &w, &h); |
| lcd_putsxy(LCD_WIDTH - w, LCD_HEIGHT/2 - h*2, |
| str(LANG_RECORDING_CHANNELS)); |
| lcd_getstringsize(str(LANG_F2_MODE), &w, &h); |
| lcd_putsxy(LCD_WIDTH - w, LCD_HEIGHT/2 - h, str(LANG_F2_MODE)); |
| lcd_getstringsize(ptr, &w, &h); |
| lcd_putsxy(LCD_WIDTH - w, LCD_HEIGHT/2, ptr); |
| lcd_mono_bitmap(bitmap_icons_7x8[Icon_FastForward], |
| LCD_WIDTH/2 + 8, LCD_HEIGHT/2 - 4, 7, 8); |
| |
| lcd_update(); |
| |
| button = button_get(true); |
| switch (button) { |
| case BUTTON_LEFT: |
| case BUTTON_F2 | BUTTON_LEFT: |
| global_settings.rec_quality++; |
| if(global_settings.rec_quality > 7) |
| global_settings.rec_quality = 0; |
| used = true; |
| break; |
| |
| case BUTTON_DOWN: |
| case BUTTON_F2 | BUTTON_DOWN: |
| global_settings.rec_frequency++; |
| if(global_settings.rec_frequency > 5) |
| global_settings.rec_frequency = 0; |
| used = true; |
| break; |
| |
| case BUTTON_RIGHT: |
| case BUTTON_F2 | BUTTON_RIGHT: |
| global_settings.rec_channels++; |
| if(global_settings.rec_channels > 1) |
| global_settings.rec_channels = 0; |
| used = true; |
| break; |
| |
| case BUTTON_F2 | BUTTON_REL: |
| if ( used ) |
| exit = true; |
| used = true; |
| break; |
| |
| case BUTTON_F2 | BUTTON_REPEAT: |
| used = true; |
| break; |
| |
| default: |
| if(default_event_handler(button) == SYS_USB_CONNECTED) |
| return true; |
| break; |
| } |
| } |
| |
| if (global_settings.rec_prerecord_time) |
| talk_buffer_steal(); /* will use the mp3 buffer */ |
| |
| audio_set_recording_options(global_settings.rec_frequency, |
| global_settings.rec_quality, |
| global_settings.rec_source, |
| global_settings.rec_channels, |
| global_settings.rec_editable, |
| global_settings.rec_prerecord_time); |
| |
| set_gain(); |
| |
| settings_save(); |
| lcd_setfont(FONT_UI); |
| |
| return false; |
| } |
| #endif /* #ifdef REC_F2 */ |
| |
| #ifdef REC_F3 |
| bool f3_rec_screen(void) |
| { |
| bool exit = false; |
| bool used = false; |
| int w, h; |
| int button; |
| char *src_str[] = |
| { |
| str(LANG_RECORDING_SRC_MIC), |
| str(LANG_RECORDING_SRC_LINE), |
| str(LANG_RECORDING_SRC_DIGITAL) |
| }; |
| |
| lcd_setfont(FONT_SYSFIXED); |
| lcd_getstringsize("A",&w,&h); |
| |
| while (!exit) { |
| char* ptr=NULL; |
| |
| lcd_clear_display(); |
| |
| /* Recording source */ |
| lcd_putsxy(0, LCD_HEIGHT/2 - h*2, str(LANG_RECORDING_SOURCE)); |
| ptr = src_str[global_settings.rec_source]; |
| lcd_getstringsize(ptr, &w, &h); |
| lcd_putsxy(0, LCD_HEIGHT/2-h, ptr); |
| lcd_mono_bitmap(bitmap_icons_7x8[Icon_FastBackward], |
| LCD_WIDTH/2 - 16, LCD_HEIGHT/2 - 4, 7, 8); |
| |
| /* trigger setup */ |
| ptr = str(LANG_RECORD_TRIGGER); |
| lcd_getstringsize(ptr,&w,&h); |
| lcd_putsxy((LCD_WIDTH-w)/2, LCD_HEIGHT - h*2, ptr); |
| lcd_mono_bitmap(bitmap_icons_7x8[Icon_DownArrow], |
| LCD_WIDTH/2 - 3, LCD_HEIGHT - h*3, 7, 8); |
| |
| lcd_update(); |
| |
| button = button_get(true); |
| switch (button) { |
| case BUTTON_DOWN: |
| case BUTTON_F3 | BUTTON_DOWN: |
| #ifndef SIMULATOR |
| rectrigger(); |
| settings_apply_trigger(); |
| #endif |
| exit = true; |
| break; |
| |
| case BUTTON_LEFT: |
| case BUTTON_F3 | BUTTON_LEFT: |
| global_settings.rec_source++; |
| if(global_settings.rec_source > MAX_SOURCE) |
| global_settings.rec_source = 0; |
| used = true; |
| break; |
| |
| case BUTTON_F3 | BUTTON_REL: |
| if ( used ) |
| exit = true; |
| used = true; |
| break; |
| |
| case BUTTON_F3 | BUTTON_REPEAT: |
| used = true; |
| break; |
| |
| default: |
| if(default_event_handler(button) == SYS_USB_CONNECTED) |
| return true; |
| break; |
| } |
| } |
| |
| if (global_settings.rec_prerecord_time) |
| talk_buffer_steal(); /* will use the mp3 buffer */ |
| |
| audio_set_recording_options(global_settings.rec_frequency, |
| global_settings.rec_quality, |
| global_settings.rec_source, |
| global_settings.rec_channels, |
| global_settings.rec_editable, |
| global_settings.rec_prerecord_time); |
| |
| |
| set_gain(); |
| |
| settings_save(); |
| lcd_setfont(FONT_UI); |
| |
| return false; |
| } |
| #endif /* #ifdef REC_F3 */ |
| |
| #if CONFIG_CODEC == SWCODEC |
| void audio_beep(int duration) |
| { |
| /* dummy */ |
| (void)duration; |
| } |
| #endif |
| |
| |
| #endif /* HAVE_RECORDING */ |