1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
31 #if CONFIG_CODEC == SWCODEC
32 #include "pcm_record.h"
38 #include "mp3_playback.h"
48 #include "peakmeter.h"
49 #include "statusbar.h"
51 #include "sound_menu.h"
52 #include "timefuncs.h"
64 #include "screen_access.h"
68 #if CONFIG_KEYPAD == RECORDER_PAD
69 #define REC_SHUTDOWN (BUTTON_OFF | BUTTON_REPEAT)
70 #define REC_STOPEXIT BUTTON_OFF
71 #define REC_RECPAUSE BUTTON_PLAY
72 #define REC_INC BUTTON_RIGHT
73 #define REC_DEC BUTTON_LEFT
74 #define REC_NEXT BUTTON_DOWN
75 #define REC_PREV BUTTON_UP
76 #define REC_SETTINGS BUTTON_F1
77 #define REC_F2 BUTTON_F2
78 #define REC_F3 BUTTON_F3
80 #elif CONFIG_KEYPAD == ONDIO_PAD /* only limited features */
81 #define REC_SHUTDOWN (BUTTON_OFF | BUTTON_REPEAT)
82 #define REC_STOPEXIT BUTTON_OFF
83 #define REC_RECPAUSE_PRE BUTTON_MENU
84 #define REC_RECPAUSE (BUTTON_MENU | BUTTON_REL)
85 #define REC_INC BUTTON_RIGHT
86 #define REC_DEC BUTTON_LEFT
87 #define REC_NEXT BUTTON_DOWN
88 #define REC_PREV BUTTON_UP
89 #define REC_SETTINGS (BUTTON_MENU | BUTTON_REPEAT)
91 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
92 #define REC_SHUTDOWN (BUTTON_OFF | BUTTON_REPEAT)
93 #define REC_STOPEXIT BUTTON_OFF
94 #define REC_RECPAUSE BUTTON_REC
95 #define REC_INC BUTTON_RIGHT
96 #define REC_DEC BUTTON_LEFT
97 #define REC_NEXT BUTTON_DOWN
98 #define REC_PREV BUTTON_UP
99 #define REC_SETTINGS BUTTON_MODE
101 #elif CONFIG_KEYPAD == GMINI100_PAD
102 #define REC_SHUTDOWN (BUTTON_OFF | BUTTON_REPEAT)
103 #define REC_STOPEXIT BUTTON_OFF
104 #define REC_RECPAUSE BUTTON_ON
105 #define REC_INC BUTTON_RIGHT
106 #define REC_DEC BUTTON_LEFT
109 #if (CONFIG_REMOTE_KEYPAD == H100_REMOTE) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
110 #define REC_RC_SHUTDOWN (BUTTON_RC_STOP | BUTTON_REPEAT)
111 #define REC_RC_STOPEXIT BUTTON_RC_STOP
112 #define REC_RC_RECPAUSE BUTTON_RC_ON
113 #define REC_RC_INC BUTTON_RC_BITRATE
114 #define REC_RC_DEC BUTTON_RC_SOURCE
115 #define REC_RC_NEXT BUTTON_RC_FF
116 #define REC_RC_PREV BUTTON_RC_REW
117 #define REC_RC_SETTINGS BUTTON_RC_MODE
120 bool f2_rec_screen(void);
121 bool f3_rec_screen(void);
124 #define SOURCE_LINE 1
126 #define SOURCE_SPDIF 2
127 #define MAX_SOURCE SOURCE_SPDIF
129 #define MAX_SOURCE SOURCE_LINE
132 #if CONFIG_CODEC == SWCODEC
133 #define REC_FILE_ENDING ".wav"
135 #define REC_FILE_ENDING ".mp3"
138 #define MAX_FILE_SIZE 0x7FF00000 /* 2 GB - 1 MB */
140 const char* const freq_str
[6] =
150 static void set_gain(void)
152 if(global_settings
.rec_source
== SOURCE_MIC
)
154 audio_set_recording_gain(global_settings
.rec_mic_gain
,
157 audio_set_recording_gain(global_settings
.rec_mic_decimator_left_gain
,
158 global_settings
.rec_mic_decimator_right_gain
,
159 AUDIO_GAIN_DECIMATOR
);
164 audio_set_recording_gain(global_settings
.rec_left_gain
,
165 global_settings
.rec_right_gain
,
168 audio_set_recording_gain(global_settings
.rec_linein_decimator_left_gain
,
169 global_settings
.rec_linein_decimator_right_gain
,
170 AUDIO_GAIN_DECIMATOR
);
175 static const char* const fmtstr
[] =
177 "%c%d %s", /* no decimals */
178 "%c%d.%d %s ", /* 1 decimal */
179 "%c%d.%02d %s " /* 2 decimals */
182 char *fmt_gain(int snd
, int val
, char *str
, int len
)
187 val
= sound_val2phys(snd
, val
);
194 numdec
= sound_numdecimals(snd
);
195 unit
= sound_unit(snd
);
199 i
= val
/ (10*numdec
);
200 d
= val
% (10*numdec
);
201 snprintf(str
, len
, fmtstr
[numdec
], sign
, i
, d
, unit
);
204 snprintf(str
, len
, fmtstr
[numdec
], sign
, val
, unit
);
209 char *fmt_gain2(int snd1
, int val1
, int snd2
, int val2
, char *str
, int len
)
211 /* same as above but for combined (added) values (recording gain) */
215 int val
= sound_val2phys(snd1
, val1
) + sound_val2phys(snd2
, val2
);
222 numdec
= MAX(sound_numdecimals(snd1
), sound_numdecimals(snd2
));
223 unit
= sound_unit(snd1
); /* should be same! */
227 i
= val
/ (10*numdec
);
228 d
= val
% (10*numdec
);
229 snprintf(str
, len
, fmtstr
[numdec
], sign
, i
, d
, unit
);
232 snprintf(str
, len
, fmtstr
[numdec
], sign
, val
, unit
);
239 void adjust_cursor(void)
246 switch(global_settings
.rec_source
)
259 if(cursor
> max_cursor
)
263 char *rec_create_filename(char *buffer
)
265 if(global_settings
.rec_directory
)
266 getcwd(buffer
, MAX_PATH
);
268 strncpy(buffer
, rec_base_directory
, MAX_PATH
);
271 create_datetime_filename(buffer
, buffer
, "R", REC_FILE_ENDING
);
273 create_numbered_filename(buffer
, buffer
, "rec_", REC_FILE_ENDING
, 4);
278 int rec_create_directory(void)
282 /* Try to create the base directory if needed */
283 if(global_settings
.rec_directory
== 0)
285 rc
= mkdir(rec_base_directory
, 0);
286 if(rc
< 0 && errno
!= EEXIST
)
288 gui_syncsplash(HZ
* 2, true,
289 "Can't create the %s directory. Error code %d.",
290 rec_base_directory
, rc
);
295 /* If we have created the directory, we want the dir browser to
296 be refreshed even if we haven't recorded anything */
304 static char path_buffer
[MAX_PATH
];
306 /* used in trigger_listerner and recording_screen */
307 static unsigned int last_seconds
= 0;
310 * Callback function so that the peak meter code can send an event
311 * to this application. This function can be passed to
312 * peak_meter_set_trigger_listener in order to activate the trigger.
314 static void trigger_listener(int trigger_status
)
316 switch (trigger_status
)
319 if((audio_status() & AUDIO_STATUS_RECORD
) != AUDIO_STATUS_RECORD
)
321 talk_buffer_steal(); /* we use the mp3 buffer */
322 audio_record(rec_create_filename(path_buffer
));
324 /* give control to mpeg thread so that it can start recording */
325 yield(); yield(); yield();
328 /* if we're already recording this is a retrigger */
331 audio_new_file(rec_create_filename(path_buffer
));
332 /* tell recording_screen to reset the time */
337 /* A _change_ to TRIG_READY means the current recording has stopped */
339 if(audio_status() & AUDIO_STATUS_RECORD
)
342 if (global_settings
.rec_trigger_mode
!= TRIG_MODE_REARM
)
344 peak_meter_set_trigger_listener(NULL
);
345 peak_meter_trigger(false);
353 /* Handles combined recording gain changes.
354 GAIN RANGE = negative digital / analog / positive digital
356 void change_recording_gain(bool increment
, bool left
, bool right
,
357 int ana_mic_size
, int ana_line_size
)
361 if(global_settings
.rec_source
== SOURCE_MIC
)
363 /* always changed as stereo */
364 if(global_settings
.rec_mic_decimator_left_gain
<
365 sound_max(SOUND_DECIMATOR_LEFT_GAIN
))
367 /* increase digital gain by 1 if below max */
368 global_settings
.rec_mic_decimator_left_gain
++;
369 global_settings
.rec_mic_decimator_right_gain
=
370 global_settings
.rec_mic_decimator_left_gain
;
374 if((global_settings
.rec_mic_decimator_left_gain
>= ana_mic_size
) &&
375 (global_settings
.rec_mic_gain
< sound_max(SOUND_MIC_GAIN
)))
377 /* in analogue range, cycle digital gain for each analogue */
378 global_settings
.rec_mic_decimator_left_gain
= 0;
379 global_settings
.rec_mic_decimator_right_gain
=
380 global_settings
.rec_mic_decimator_left_gain
;
381 global_settings
.rec_mic_gain
++;
386 if(((left
) && (right
)) &&
387 (global_settings
.rec_linein_decimator_left_gain
<
388 sound_max(SOUND_DECIMATOR_LEFT_GAIN
)) &&
389 (global_settings
.rec_linein_decimator_right_gain
<
390 sound_max(SOUND_DECIMATOR_RIGHT_GAIN
)) )
392 /* increase digital gain by 1 if below max*/
393 global_settings
.rec_linein_decimator_left_gain
++;
394 global_settings
.rec_linein_decimator_right_gain
++;
396 else if((right
) && (!left
) &&
397 (global_settings
.rec_linein_decimator_right_gain
<
398 sound_max(SOUND_DECIMATOR_RIGHT_GAIN
)))
400 global_settings
.rec_linein_decimator_right_gain
++;
402 else if((left
) && (!right
) &&
403 (global_settings
.rec_linein_decimator_left_gain
<
404 sound_max(SOUND_DECIMATOR_LEFT_GAIN
)))
406 global_settings
.rec_linein_decimator_left_gain
++;
409 /* Stereo increase */
411 (global_settings
.rec_linein_decimator_left_gain
>=
413 (global_settings
.rec_left_gain
< sound_max(SOUND_LEFT_GAIN
)))
415 /* if analogue range cycle left digital gain for each */
416 global_settings
.rec_linein_decimator_left_gain
= 0;
417 global_settings
.rec_left_gain
++;
420 (global_settings
.rec_linein_decimator_right_gain
>=
422 (global_settings
.rec_right_gain
< sound_max(SOUND_RIGHT_GAIN
)))
424 /* if analogue range cycle right digital for each */
425 global_settings
.rec_linein_decimator_right_gain
= 0;
426 global_settings
.rec_right_gain
++;
432 if(global_settings
.rec_source
== SOURCE_MIC
)
434 /* always changed as stereo */
435 if(global_settings
.rec_mic_decimator_left_gain
>
436 sound_min(SOUND_DECIMATOR_LEFT_GAIN
))
438 /* decrease digital gain by 1 if above minimum */
439 global_settings
.rec_mic_decimator_left_gain
--;
440 global_settings
.rec_mic_decimator_right_gain
=
441 global_settings
.rec_mic_decimator_left_gain
;
445 if((global_settings
.rec_mic_decimator_left_gain
< 0) &&
446 (global_settings
.rec_mic_gain
> sound_min(SOUND_MIC_GAIN
)))
448 /* if analogue in range, cycle digital gain for each */
449 global_settings
.rec_mic_decimator_left_gain
= ana_mic_size
- 1;
450 global_settings
.rec_mic_decimator_right_gain
=
451 global_settings
.rec_mic_decimator_left_gain
;
452 global_settings
.rec_mic_gain
--;
457 if( ((left
) && (right
)) &&
458 (global_settings
.rec_linein_decimator_left_gain
>
459 sound_min(SOUND_DECIMATOR_LEFT_GAIN
)) &&
460 (global_settings
.rec_linein_decimator_right_gain
>
461 sound_min(SOUND_DECIMATOR_RIGHT_GAIN
)) )
463 /* decrease digital gain by 1 if above minimum */
464 global_settings
.rec_linein_decimator_left_gain
--;
465 global_settings
.rec_linein_decimator_right_gain
--;
467 else if((right
) && (!left
) &&
468 (global_settings
.rec_linein_decimator_right_gain
>
469 sound_min(SOUND_DECIMATOR_RIGHT_GAIN
)))
471 global_settings
.rec_linein_decimator_right_gain
--;
473 else if((left
) && (!right
) &&
474 (global_settings
.rec_linein_decimator_left_gain
>
475 sound_min(SOUND_DECIMATOR_LEFT_GAIN
)))
477 global_settings
.rec_linein_decimator_left_gain
--;
480 /* Stereo decrease */
482 (global_settings
.rec_linein_decimator_left_gain
< 0) &&
483 (global_settings
.rec_left_gain
> sound_min(SOUND_LEFT_GAIN
)))
485 /* if in analogue range cycle left digital gain for each */
486 global_settings
.rec_left_gain
--;
487 global_settings
.rec_linein_decimator_left_gain
=
491 (global_settings
.rec_linein_decimator_right_gain
< 0) &&
492 (global_settings
.rec_right_gain
> sound_min(SOUND_RIGHT_GAIN
)))
494 /* if in analogue range cycle right digital gain for each */
495 global_settings
.rec_right_gain
--;
496 global_settings
.rec_linein_decimator_right_gain
=
504 bool recording_screen(void)
507 long lastbutton
= BUTTON_NONE
;
512 int update_countdown
= 1;
513 bool have_recorded
= false;
514 unsigned int seconds
;
516 char path_buffer
[MAX_PATH
];
517 bool been_in_usb_mode
= false;
518 int last_audio_stat
= -1;
520 #if CONFIG_LED == LED_REAL
521 bool led_state
= false;
522 int led_countdown
= 2;
527 /*calculate no. of digital steps to each analogue step. Assuming
528 left dig step = right dig step, and there is an integer no. of digital steps
530 int ana_mic_size
= sound_val2phys(SOUND_MIC_GAIN
, 1) /
531 sound_val2phys(SOUND_DECIMATOR_LEFT_GAIN
, 1);
532 int ana_line_size
= sound_val2phys(SOUND_LEFT_GAIN
, 1) /
533 sound_val2phys(SOUND_DECIMATOR_LEFT_GAIN
, 1);
535 if(global_settings
.rec_source
== SOURCE_MIC
)
537 global_settings
.rec_mic_decimator_left_gain
=
538 global_settings
.rec_mic_decimator_right_gain
;
542 const unsigned char *byte_units
[] = {
550 #if (CONFIG_LED == LED_REAL) && !defined(SIMULATOR)
551 ata_set_led_enabled(false);
553 audio_init_recording();
555 sound_set_volume(global_settings
.volume
);
557 #if CONFIG_CODEC == SWCODEC
559 /* Set peak meter to recording mode */
560 peak_meter_playback(false);
563 /* Yes, we use the D/A for monitoring */
564 peak_meter_playback(true);
566 peak_meter_enabled
= true;
568 if (global_settings
.rec_prerecord_time
)
569 talk_buffer_steal(); /* will use the mp3 buffer */
571 audio_set_recording_options(global_settings
.rec_frequency
,
572 global_settings
.rec_quality
,
573 global_settings
.rec_source
,
574 global_settings
.rec_channels
,
575 global_settings
.rec_editable
,
576 global_settings
.rec_prerecord_time
);
580 settings_apply_trigger();
584 screens
[i
].setfont(FONT_SYSFIXED
);
585 screens
[i
].getstringsize("M", &w
, &h
);
586 screens
[i
].setmargins(global_settings
.invert_cursor
? 0 : w
, 8);
589 if(rec_create_directory() > 0)
590 have_recorded
= true;
594 #if CONFIG_CODEC == SWCODEC
595 audio_stat
= pcm_rec_status();
597 audio_stat
= audio_status();
600 #if CONFIG_LED == LED_REAL
603 * Flash the LED while waiting to record. Turn it on while
606 if(audio_stat
& AUDIO_STATUS_RECORD
)
608 if (audio_stat
& AUDIO_STATUS_PAUSE
)
610 if (--led_countdown
<= 0)
612 led_state
= !led_state
;
619 /* trigger is on in status TRIG_READY (no check needed) */
625 int trigStat
= peak_meter_trigger_status();
627 * other trigger stati than trig_off and trig_steady
628 * already imply that we are recording.
630 if (trigStat
== TRIG_STEADY
)
632 if (--led_countdown
<= 0)
634 led_state
= !led_state
;
641 /* trigger is on in status TRIG_READY (no check needed) */
645 #endif /* CONFIG_LED */
647 /* Wait for a button a while (HZ/10) drawing the peak meter */
648 button
= peak_meter_draw_get_btn(0, 8 + h
*2, h
*2);
650 if (last_audio_stat
!= audio_stat
)
652 if (audio_stat
== AUDIO_STATUS_RECORD
)
654 have_recorded
= true;
656 last_audio_stat
= audio_stat
;
663 #ifdef REC_RC_STOPEXIT
664 case REC_RC_STOPEXIT
:
666 #ifdef REC_RC_SHUTDOWN
667 case REC_RC_SHUTDOWN
:
669 /* turn off the trigger */
670 peak_meter_trigger(false);
671 peak_meter_set_trigger_listener(NULL
);
673 if(audio_stat
& AUDIO_STATUS_RECORD
)
675 audio_stop_recording();
679 peak_meter_playback(true);
680 #if CONFIG_CODEC != SWCODEC
681 peak_meter_enabled
= false;
685 update_countdown
= 1; /* Update immediately */
689 #ifdef REC_RC_RECPAUSE
690 case REC_RC_RECPAUSE
:
692 #ifdef REC_RECPAUSE_PRE
693 if (lastbutton
!= REC_RECPAUSE_PRE
)
696 /* Only act if the mpeg is stopped */
697 if(!(audio_stat
& AUDIO_STATUS_RECORD
))
699 /* is this manual or triggered recording? */
700 if ((global_settings
.rec_trigger_mode
== TRIG_MODE_OFF
) ||
701 (peak_meter_trigger_status() != TRIG_OFF
))
703 /* manual recording */
704 have_recorded
= true;
705 talk_buffer_steal(); /* we use the mp3 buffer */
706 audio_record(rec_create_filename(path_buffer
));
708 if (global_settings
.talk_menu
)
709 { /* no voice possible here, but a beep */
710 audio_beep(HZ
/2); /* longer beep on start */
714 /* this is triggered recording */
717 /* we don't start recording now, but enable the
718 trigger and let the callback function
719 trigger_listener control when the recording starts */
720 peak_meter_trigger(true);
721 peak_meter_set_trigger_listener(&trigger_listener
);
726 if(audio_stat
& AUDIO_STATUS_PAUSE
)
728 audio_resume_recording();
729 if (global_settings
.talk_menu
)
730 { /* no voice possible here, but a beep */
731 audio_beep(HZ
/4); /* short beep on resume */
736 audio_pause_recording();
739 update_countdown
= 1; /* Update immediately */
749 update_countdown
= 1; /* Update immediately */
760 update_countdown
= 1; /* Update immediately */
765 case REC_INC
| BUTTON_REPEAT
:
768 case REC_RC_INC
| BUTTON_REPEAT
:
773 if(global_settings
.volume
<
774 sound_max(SOUND_VOLUME
))
775 global_settings
.volume
++;
776 sound_set_volume(global_settings
.volume
);
780 change_recording_gain(true, true, true,
781 ana_mic_size
, ana_line_size
);
784 change_recording_gain(true, true, false,
785 ana_mic_size
, ana_line_size
);
788 change_recording_gain(true, false, true,
789 ana_mic_size
, ana_line_size
);
793 if(global_settings
.rec_source
== SOURCE_MIC
)
795 if(global_settings
.rec_mic_gain
<
796 sound_max(SOUND_MIC_GAIN
))
797 global_settings
.rec_mic_gain
++;
801 if(global_settings
.rec_left_gain
<
802 sound_max(SOUND_LEFT_GAIN
))
803 global_settings
.rec_left_gain
++;
804 if(global_settings
.rec_right_gain
<
805 sound_max(SOUND_RIGHT_GAIN
))
806 global_settings
.rec_right_gain
++;
810 if(global_settings
.rec_left_gain
<
811 sound_max(SOUND_LEFT_GAIN
))
812 global_settings
.rec_left_gain
++;
815 if(global_settings
.rec_right_gain
<
816 sound_max(SOUND_RIGHT_GAIN
))
817 global_settings
.rec_right_gain
++;
822 update_countdown
= 1; /* Update immediately */
826 case REC_DEC
| BUTTON_REPEAT
:
829 case REC_RC_DEC
| BUTTON_REPEAT
:
834 if(global_settings
.volume
>
835 sound_min(SOUND_VOLUME
))
836 global_settings
.volume
--;
837 sound_set_volume(global_settings
.volume
);
842 change_recording_gain(false, true, true,
843 ana_mic_size
, ana_line_size
);
847 change_recording_gain(false, true, false,
848 ana_mic_size
, ana_line_size
);
852 change_recording_gain(false, false, true,
853 ana_mic_size
, ana_line_size
);
857 if(global_settings
.rec_source
== SOURCE_MIC
)
859 if(global_settings
.rec_mic_gain
>
860 sound_min(SOUND_MIC_GAIN
))
861 global_settings
.rec_mic_gain
--;
865 if(global_settings
.rec_left_gain
>
866 sound_min(SOUND_LEFT_GAIN
))
867 global_settings
.rec_left_gain
--;
868 if(global_settings
.rec_right_gain
>
869 sound_min(SOUND_RIGHT_GAIN
))
870 global_settings
.rec_right_gain
--;
874 if(global_settings
.rec_left_gain
>
875 sound_min(SOUND_LEFT_GAIN
))
876 global_settings
.rec_left_gain
--;
879 if(global_settings
.rec_right_gain
>
880 sound_min(SOUND_RIGHT_GAIN
))
881 global_settings
.rec_right_gain
--;
886 update_countdown
= 1; /* Update immediately */
891 #ifdef REC_RC_SETTINGS
892 case REC_RC_SETTINGS
:
894 if(audio_stat
!= AUDIO_STATUS_RECORD
)
896 #if CONFIG_LED == LED_REAL
897 /* led is restored at begin of loop / end of function */
900 if (recording_menu(false))
902 return SYS_USB_CONNECTED
;
906 if (global_settings
.rec_prerecord_time
)
907 talk_buffer_steal(); /* will use the mp3 buffer */
909 audio_set_recording_options(global_settings
.rec_frequency
,
910 global_settings
.rec_quality
,
911 global_settings
.rec_source
,
912 global_settings
.rec_channels
,
913 global_settings
.rec_editable
,
914 global_settings
.rec_prerecord_time
);
918 update_countdown
= 1; /* Update immediately */
922 screens
[i
].setfont(FONT_SYSFIXED
);
923 screens
[i
].setmargins(global_settings
.invert_cursor
? 0 : w
, 8);
931 if(audio_stat
!= AUDIO_STATUS_RECORD
)
933 #if CONFIG_LED == LED_REAL
934 /* led is restored at begin of loop / end of function */
939 have_recorded
= true;
943 update_countdown
= 1; /* Update immediately */
950 if(audio_stat
& AUDIO_STATUS_RECORD
)
952 audio_new_file(rec_create_filename(path_buffer
));
957 if(audio_stat
!= AUDIO_STATUS_RECORD
)
959 #if CONFIG_LED == LED_REAL
960 /* led is restored at begin of loop / end of function */
965 have_recorded
= true;
969 update_countdown
= 1; /* Update immediately */
975 case SYS_USB_CONNECTED
:
976 /* Only accept USB connection when not recording */
977 if(audio_stat
!= AUDIO_STATUS_RECORD
)
979 default_event_handler(SYS_USB_CONNECTED
);
981 been_in_usb_mode
= true;
986 default_event_handler(button
);
989 if (button
!= BUTTON_NONE
)
993 screens
[i
].setfont(FONT_SYSFIXED
);
995 seconds
= audio_recorded_time() / HZ
;
998 if(update_countdown
== 0 || seconds
> last_seconds
)
1000 unsigned int dseconds
, dhours
, dminutes
;
1001 unsigned long num_recorded_bytes
;
1004 update_countdown
= 5;
1005 last_seconds
= seconds
;
1008 screens
[i
].clear_display();
1010 hours
= seconds
/ 3600;
1011 minutes
= (seconds
- (hours
* 3600)) / 60;
1012 snprintf(buf
, 32, "%s %02d:%02d:%02d",
1013 str(LANG_RECORDING_TIME
),
1014 hours
, minutes
, seconds
%60);
1016 screens
[i
].puts(0, 0, buf
);
1018 dseconds
= rec_timesplit_seconds();
1019 num_recorded_bytes
= audio_num_recorded_bytes();
1021 if(audio_stat
& AUDIO_STATUS_PRERECORD
)
1023 snprintf(buf
, 32, "%s...", str(LANG_RECORD_PRERECORD
));
1027 /* Display the split interval if the record timesplit
1029 if (global_settings
.rec_timesplit
)
1031 /* Display the record timesplit interval rather
1032 than the file size if the record timer is
1034 dhours
= dseconds
/ 3600;
1035 dminutes
= (dseconds
- (dhours
* 3600)) / 60;
1036 snprintf(buf
, 32, "%s %02d:%02d",
1037 str(LANG_RECORD_TIMESPLIT_REC
),
1042 output_dyn_value(buf2
, sizeof buf2
,
1045 snprintf(buf
, 32, "%s %s",
1046 str(LANG_RECORDING_SIZE
), buf2
);
1050 screens
[i
].puts(0, 1, buf
);
1052 /* We will do file splitting regardless, either at the end of
1053 a split interval, or when the filesize approaches the 2GB
1054 FAT file size (compatibility) limit. */
1056 ((global_settings
.rec_timesplit
&& (seconds
>= dseconds
))
1057 || (num_recorded_bytes
>= MAX_FILE_SIZE
)))
1059 audio_new_file(rec_create_filename(path_buffer
));
1060 update_countdown
= 1;
1064 snprintf(buf
, 32, "%s: %s", str(LANG_VOLUME
),
1065 fmt_gain(SOUND_VOLUME
,
1066 global_settings
.volume
,
1067 buf2
, sizeof(buf2
)));
1069 if (global_settings
.invert_cursor
&& (pos
++ == cursor
))
1072 screens
[i
].puts_style_offset(0, 4, buf
, STYLE_INVERT
,0);
1077 screens
[i
].puts(0, 4, buf
);
1080 if(global_settings
.rec_source
== SOURCE_MIC
)
1084 /*****************test info code***********************
1085 snprintf(buf, 32, "Aa:(2x) %d DigL:(0.5x) %d ",
1086 global_settings.rec_mic_gain,
1087 global_settings.rec_mic_decimator_left_gain);
1088 lcd_puts(0, 10, buf);
1089 snprintf(buf, 32, "DigR:(0.5x) %d",
1090 global_settings.rec_mic_decimator_right_gain);
1091 lcd_puts(9, 12, buf);
1092 *****************test info code***********************/
1094 snprintf(buf
, 32, "%s:%s (%s)",
1095 str(LANG_RECORDING_GAIN
),
1096 fmt_gain2(SOUND_MIC_GAIN
,
1097 global_settings
.rec_mic_gain
,
1098 SOUND_DECIMATOR_LEFT_GAIN
,
1099 global_settings
.rec_mic_decimator_left_gain
,
1100 buf2
, sizeof(buf2
)),
1101 (((global_settings
.rec_mic_gain
==
1102 sound_max(SOUND_MIC_GAIN
)) &&
1103 (global_settings
.rec_mic_decimator_left_gain
> 0))||
1104 ((global_settings
.rec_mic_gain
==
1105 sound_min(SOUND_MIC_GAIN
)) &&
1106 (global_settings
.rec_mic_decimator_left_gain
< 0)))?
1107 str(LANG_RECORDING_GAIN_DIGITAL
) :
1108 str(LANG_RECORDING_GAIN_ANALOG
)
1110 #else /* HAVE_UDA1380 */
1111 snprintf(buf
, 32, "%s:%s", str(LANG_RECORDING_GAIN
),
1112 fmt_gain(SOUND_MIC_GAIN
,
1113 global_settings
.rec_mic_gain
,
1114 buf2
, sizeof(buf2
)));
1116 if(global_settings
.invert_cursor
&& ((1==cursor
)||(2==cursor
)))
1119 screens
[i
].puts_style_offset(0, 5, buf
, STYLE_INVERT
,0);
1124 screens
[i
].puts(0, 5, buf
);
1127 else if(global_settings
.rec_source
== SOURCE_LINE
)
1131 /*****************test info code***********************
1132 snprintf(buf, 32, "AL:(3x) %d DigL:(0.5x) %d",
1133 global_settings.rec_left_gain,
1134 global_settings.rec_linein_decimator_left_gain);
1135 lcd_puts(0, 10, buf);
1136 snprintf(buf, 32, "AR:(3x) %d DigR:(0.5x) %d",
1137 global_settings.rec_right_gain,
1138 global_settings.rec_linein_decimator_right_gain);
1139 lcd_puts(0, 12, buf);
1140 *****************test info code***********************/
1142 snprintf(buf
, 32, "%s:%s (%s)",
1143 str(LANG_RECORDING_LEFT
),
1144 fmt_gain2(SOUND_LEFT_GAIN
,
1145 global_settings
.rec_left_gain
,
1146 SOUND_DECIMATOR_LEFT_GAIN
,
1147 global_settings
.rec_linein_decimator_left_gain
,
1148 buf2
, sizeof(buf2
)),
1149 (((global_settings
.rec_left_gain
==
1150 sound_max(SOUND_LEFT_GAIN
)) &&
1151 (global_settings
.rec_linein_decimator_left_gain
1153 ((global_settings
.rec_left_gain
==
1154 sound_min(SOUND_LEFT_GAIN
)) &&
1155 (global_settings
.rec_linein_decimator_left_gain
1157 str(LANG_RECORDING_GAIN_DIGITAL
) :
1158 str(LANG_RECORDING_GAIN_ANALOG
)
1160 #else /* HAVE_UDA1380 */
1161 snprintf(buf
, 32, "%s:%s",
1162 str(LANG_RECORDING_LEFT
),
1163 fmt_gain(SOUND_LEFT_GAIN
,
1164 global_settings
.rec_left_gain
,
1165 buf2
, sizeof(buf2
)));
1166 #endif /* HAVE_UDA1380 */
1167 if(global_settings
.invert_cursor
&& ((1==cursor
)||(2==cursor
)))
1170 screens
[i
].puts_style_offset(0, 5, buf
, STYLE_INVERT
,0);
1175 screens
[i
].puts(0, 5, buf
);
1179 snprintf(buf
, 32, "%s:%s (%s)",
1180 str(LANG_RECORDING_RIGHT
),
1181 fmt_gain2(SOUND_RIGHT_GAIN
,
1182 global_settings
.rec_right_gain
,
1183 SOUND_DECIMATOR_RIGHT_GAIN
,
1184 global_settings
.rec_linein_decimator_right_gain
,
1185 buf2
, sizeof(buf2
)),
1186 (((global_settings
.rec_right_gain
==
1187 sound_max(SOUND_RIGHT_GAIN
)) &&
1188 (global_settings
.rec_linein_decimator_right_gain
1190 ((global_settings
.rec_right_gain
==
1191 sound_min(SOUND_RIGHT_GAIN
)) &&
1192 (global_settings
.rec_linein_decimator_right_gain
1194 str(LANG_RECORDING_GAIN_DIGITAL
) :
1195 str(LANG_RECORDING_GAIN_ANALOG
)
1197 #else /* HAVE_UDA1380 */
1198 snprintf(buf
, 32, "%s:%s",
1199 str(LANG_RECORDING_RIGHT
),
1200 fmt_gain(SOUND_RIGHT_GAIN
,
1201 global_settings
.rec_right_gain
,
1202 buf2
, sizeof(buf2
)));
1203 #endif /* HAVE_UDA1380 */
1204 if(global_settings
.invert_cursor
&& ((1==cursor
)||(3==cursor
)))
1207 screens
[i
].puts_style_offset(0, 6, buf
, STYLE_INVERT
,0);
1212 screens
[i
].puts(0, 6, buf
);
1216 if(!global_settings
.invert_cursor
){
1221 screen_put_cursorxy(&screens
[i
], 0, 5, true);
1223 if(global_settings
.rec_source
!= SOURCE_MIC
)
1226 screen_put_cursorxy(&screens
[i
], 0, 6, true);
1231 screen_put_cursorxy(&screens
[i
], 0, 5, true);
1235 screen_put_cursorxy(&screens
[i
], 0, 6, true);
1239 screen_put_cursorxy(&screens
[i
], 0, 4, true);
1243 snprintf(buf
, 32, "%s %s",
1244 freq_str
[global_settings
.rec_frequency
],
1245 global_settings
.rec_channels
?
1246 str(LANG_CHANNEL_MONO
):str(LANG_CHANNEL_STEREO
));
1248 /* Main screen only for this info */
1249 lcd_puts(0, 8, buf
);
1251 gui_syncstatusbar_draw(&statusbars
, true);
1255 peak_meter_screen(&screens
[i
], 0, 8 + h
*2, h
*2);
1256 screens
[i
].update();
1259 /* draw the trigger status */
1260 if (peak_meter_trigger_status() != TRIG_OFF
)
1262 peak_meter_draw_trig(LCD_WIDTH
- TRIG_WIDTH
, 4 * h
);
1263 lcd_update_rect(LCD_WIDTH
- (TRIG_WIDTH
+ 2), 4 * h
,
1264 TRIG_WIDTH
+ 2, TRIG_HEIGHT
);
1268 if(audio_stat
& AUDIO_STATUS_ERROR
)
1275 #if CONFIG_CODEC == SWCODEC
1276 audio_stat
= pcm_rec_status();
1278 audio_stat
= audio_status();
1280 if (audio_stat
& AUDIO_STATUS_ERROR
)
1282 gui_syncsplash(0, true, str(LANG_DISK_FULL
));
1283 gui_syncstatusbar_draw(&statusbars
, true);
1285 audio_error_clear();
1289 button
= button_get(true);
1290 if(button
== (REC_STOPEXIT
| BUTTON_REL
))
1295 #if CONFIG_CODEC == SWCODEC
1296 audio_stop_recording();
1297 audio_close_recording();
1300 audio_init_playback();
1303 /* make sure the trigger is really turned off */
1304 peak_meter_trigger(false);
1305 peak_meter_set_trigger_listener(NULL
);
1307 sound_settings_apply();
1309 lcd_setfont(FONT_UI
);
1314 #if (CONFIG_LED == LED_REAL) && !defined(SIMULATOR)
1315 ata_set_led_enabled(true);
1317 return been_in_usb_mode
;
1321 bool f2_rec_screen(void)
1329 lcd_setfont(FONT_SYSFIXED
);
1330 lcd_getstringsize("A",&w
,&h
);
1333 const char* ptr
=NULL
;
1335 lcd_clear_display();
1337 /* Recording quality */
1338 lcd_putsxy(0, LCD_HEIGHT
/2 - h
*2, str(LANG_RECORDING_QUALITY
));
1339 snprintf(buf
, 32, "%d", global_settings
.rec_quality
);
1340 lcd_putsxy(0, LCD_HEIGHT
/2-h
, buf
);
1341 lcd_mono_bitmap(bitmap_icons_7x8
[Icon_FastBackward
],
1342 LCD_WIDTH
/2 - 16, LCD_HEIGHT
/2 - 4, 7, 8);
1345 snprintf(buf
, sizeof buf
, "%s:", str(LANG_RECORDING_FREQUENCY
));
1346 lcd_getstringsize(buf
,&w
,&h
);
1347 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
*2, buf
);
1348 ptr
= freq_str
[global_settings
.rec_frequency
];
1349 lcd_getstringsize(ptr
, &w
, &h
);
1350 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
, ptr
);
1351 lcd_mono_bitmap(bitmap_icons_7x8
[Icon_DownArrow
],
1352 LCD_WIDTH
/2 - 3, LCD_HEIGHT
- h
*3, 7, 8);
1355 switch ( global_settings
.rec_channels
) {
1357 ptr
= str(LANG_CHANNEL_STEREO
);
1361 ptr
= str(LANG_CHANNEL_MONO
);
1365 lcd_getstringsize(str(LANG_RECORDING_CHANNELS
), &w
, &h
);
1366 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 - h
*2,
1367 str(LANG_RECORDING_CHANNELS
));
1368 lcd_getstringsize(str(LANG_F2_MODE
), &w
, &h
);
1369 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 - h
, str(LANG_F2_MODE
));
1370 lcd_getstringsize(ptr
, &w
, &h
);
1371 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2, ptr
);
1372 lcd_mono_bitmap(bitmap_icons_7x8
[Icon_FastForward
],
1373 LCD_WIDTH
/2 + 8, LCD_HEIGHT
/2 - 4, 7, 8);
1377 button
= button_get(true);
1380 case BUTTON_F2
| BUTTON_LEFT
:
1381 global_settings
.rec_quality
++;
1382 if(global_settings
.rec_quality
> 7)
1383 global_settings
.rec_quality
= 0;
1388 case BUTTON_F2
| BUTTON_DOWN
:
1389 global_settings
.rec_frequency
++;
1390 if(global_settings
.rec_frequency
> 5)
1391 global_settings
.rec_frequency
= 0;
1396 case BUTTON_F2
| BUTTON_RIGHT
:
1397 global_settings
.rec_channels
++;
1398 if(global_settings
.rec_channels
> 1)
1399 global_settings
.rec_channels
= 0;
1403 case BUTTON_F2
| BUTTON_REL
:
1409 case BUTTON_F2
| BUTTON_REPEAT
:
1414 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
1420 if (global_settings
.rec_prerecord_time
)
1421 talk_buffer_steal(); /* will use the mp3 buffer */
1423 audio_set_recording_options(global_settings
.rec_frequency
,
1424 global_settings
.rec_quality
,
1425 global_settings
.rec_source
,
1426 global_settings
.rec_channels
,
1427 global_settings
.rec_editable
,
1428 global_settings
.rec_prerecord_time
);
1433 lcd_setfont(FONT_UI
);
1437 #endif /* #ifdef REC_F2 */
1440 bool f3_rec_screen(void)
1448 str(LANG_RECORDING_SRC_MIC
),
1449 str(LANG_RECORDING_SRC_LINE
),
1450 str(LANG_RECORDING_SRC_DIGITAL
)
1453 lcd_setfont(FONT_SYSFIXED
);
1454 lcd_getstringsize("A",&w
,&h
);
1459 lcd_clear_display();
1461 /* Recording source */
1462 lcd_putsxy(0, LCD_HEIGHT
/2 - h
*2, str(LANG_RECORDING_SOURCE
));
1463 ptr
= src_str
[global_settings
.rec_source
];
1464 lcd_getstringsize(ptr
, &w
, &h
);
1465 lcd_putsxy(0, LCD_HEIGHT
/2-h
, ptr
);
1466 lcd_mono_bitmap(bitmap_icons_7x8
[Icon_FastBackward
],
1467 LCD_WIDTH
/2 - 16, LCD_HEIGHT
/2 - 4, 7, 8);
1470 ptr
= str(LANG_RECORD_TRIGGER
);
1471 lcd_getstringsize(ptr
,&w
,&h
);
1472 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
*2, ptr
);
1473 lcd_mono_bitmap(bitmap_icons_7x8
[Icon_DownArrow
],
1474 LCD_WIDTH
/2 - 3, LCD_HEIGHT
- h
*3, 7, 8);
1478 button
= button_get(true);
1481 case BUTTON_F3
| BUTTON_DOWN
:
1484 settings_apply_trigger();
1490 case BUTTON_F3
| BUTTON_LEFT
:
1491 global_settings
.rec_source
++;
1492 if(global_settings
.rec_source
> MAX_SOURCE
)
1493 global_settings
.rec_source
= 0;
1497 case BUTTON_F3
| BUTTON_REL
:
1503 case BUTTON_F3
| BUTTON_REPEAT
:
1508 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
1514 if (global_settings
.rec_prerecord_time
)
1515 talk_buffer_steal(); /* will use the mp3 buffer */
1517 audio_set_recording_options(global_settings
.rec_frequency
,
1518 global_settings
.rec_quality
,
1519 global_settings
.rec_source
,
1520 global_settings
.rec_channels
,
1521 global_settings
.rec_editable
,
1522 global_settings
.rec_prerecord_time
);
1528 lcd_setfont(FONT_UI
);
1532 #endif /* #ifdef REC_F3 */
1534 #if CONFIG_CODEC == SWCODEC
1535 void audio_beep(int duration
)
1542 /* stubs for recording sim */
1543 void audio_init_recording(void)
1547 void audio_close_recording(void)
1551 unsigned long audio_recorded_time(void)
1556 unsigned long audio_num_recorded_bytes(void)
1558 return 5 * 1024 * 1024;
1561 void audio_set_recording_options(int frequency
, int quality
,
1562 int source
, int channel_mode
,
1563 bool editable
, int prerecord_time
)
1565 frequency
= frequency
;
1568 channel_mode
= channel_mode
;
1569 editable
= editable
;
1570 prerecord_time
= prerecord_time
;
1573 void audio_set_recording_gain(int left
, int right
, int type
)
1580 void audio_stop_recording(void)
1584 void audio_pause_recording(void)
1588 void audio_resume_recording(void)
1592 void pcm_rec_get_peaks(int *left
, int *right
)
1600 void audio_record(const char *filename
)
1602 filename
= filename
;
1605 void audio_new_file(const char *filename
)
1607 filename
= filename
;
1610 unsigned long pcm_rec_status(void)
1615 #endif /* #ifdef SIMULATOR */
1616 #endif /* #ifdef CONFIG_CODEC == SWCODEC */
1619 #endif /* HAVE_RECORDING */