summaryrefslogtreecommitdiff
path: root/apps/recorder/recording.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/recorder/recording.c')
-rw-r--r--apps/recorder/recording.c257
1 files changed, 203 insertions, 54 deletions
diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c
index 7aa6aba98c..39e94739b5 100644
--- a/apps/recorder/recording.c
+++ b/apps/recorder/recording.c
@@ -50,6 +50,7 @@
50#include "talk.h" 50#include "talk.h"
51#include "atoi.h" 51#include "atoi.h"
52#include "sound.h" 52#include "sound.h"
53#include "ata.h"
53 54
54#ifdef HAVE_RECORDING 55#ifdef HAVE_RECORDING
55 56
@@ -240,6 +241,56 @@ int rec_create_directory(void)
240 return 0; 241 return 0;
241} 242}
242 243
244static char path_buffer[MAX_PATH];
245
246/* used in trigger_listerner and recording_screen */
247static unsigned int last_seconds = 0;
248
249/**
250 * Callback function so that the peak meter code can send an event
251 * to this application. This function can be passed to
252 * peak_meter_set_trigger_listener in order to activate the trigger.
253 */
254static void trigger_listener(int trigger_status)
255{
256 switch (trigger_status)
257 {
258 case TRIG_GO:
259 if((mpeg_status() & MPEG_STATUS_RECORD) != MPEG_STATUS_RECORD)
260 {
261 talk_buffer_steal(); /* we use the mp3 buffer */
262 mpeg_record(rec_create_filename(path_buffer));
263
264 /* give control to mpeg thread so that it can start recording */
265 yield(); yield(); yield();
266 }
267
268 /* if we're already recording this is a retrigger */
269 else
270 {
271 mpeg_new_file(rec_create_filename(path_buffer));
272 /* tell recording_screen to reset the time */
273 last_seconds = 0;
274 }
275 break;
276
277 /* A _change_ to TRIG_READY means the current recording has stopped */
278 case TRIG_READY:
279 if(mpeg_status() & MPEG_STATUS_RECORD)
280 {
281 mpeg_stop();
282 if (global_settings.rec_trigger_mode != TRIG_MODE_REARM)
283 {
284 peak_meter_set_trigger_listener(NULL);
285 peak_meter_trigger(false);
286 }
287 }
288 break;
289 }
290}
291
292#define BLINK_MASK 0x10
293
243bool recording_screen(void) 294bool recording_screen(void)
244{ 295{
245 long button; 296 long button;
@@ -252,12 +303,11 @@ bool recording_screen(void)
252 int update_countdown = 1; 303 int update_countdown = 1;
253 bool have_recorded = false; 304 bool have_recorded = false;
254 unsigned int seconds; 305 unsigned int seconds;
255 unsigned int last_seconds = 0;
256 int hours, minutes; 306 int hours, minutes;
257 char path_buffer[MAX_PATH]; 307 char path_buffer[MAX_PATH];
258 bool been_in_usb_mode = false; 308 bool been_in_usb_mode = false;
259 bool led_state; 309 int last_mpeg_stat = -1;
260 int led_delay; 310 bool last_led_stat = false;
261 311
262 const unsigned char *byte_units[] = { 312 const unsigned char *byte_units[] = {
263 ID2P(LANG_BYTE), 313 ID2P(LANG_BYTE),
@@ -267,6 +317,9 @@ bool recording_screen(void)
267 }; 317 };
268 318
269 cursor = 0; 319 cursor = 0;
320#ifndef SIMULATOR
321 ata_set_led_enabled(false);
322#endif
270 mpeg_init_recording(); 323 mpeg_init_recording();
271 324
272 sound_set(SOUND_VOLUME, global_settings.volume); 325 sound_set(SOUND_VOLUME, global_settings.volume);
@@ -288,6 +341,8 @@ bool recording_screen(void)
288 341
289 set_gain(); 342 set_gain();
290 343
344 settings_apply_trigger();
345
291 lcd_setfont(FONT_SYSFIXED); 346 lcd_setfont(FONT_SYSFIXED);
292 lcd_getstringsize("M", &w, &h); 347 lcd_getstringsize("M", &w, &h);
293 lcd_setmargins(global_settings.invert_cursor ? 0 : w, 8); 348 lcd_setmargins(global_settings.invert_cursor ? 0 : w, 8);
@@ -295,45 +350,93 @@ bool recording_screen(void)
295 if(rec_create_directory() > 0) 350 if(rec_create_directory() > 0)
296 have_recorded = true; 351 have_recorded = true;
297 352
298 led_state = false;
299 led_delay = 0;
300
301 while(!done) 353 while(!done)
302 { 354 {
355 int mpeg_stat = mpeg_status();
356
303 /* 357 /*
304 * Flash the LED while waiting to record. Turn it on while 358 * Flash the LED while waiting to record. Turn it on while
305 * recording. 359 * recording.
306 */ 360 */
307 if(mpeg_status() != MPEG_STATUS_RECORD) 361 if(mpeg_stat & MPEG_STATUS_RECORD)
308 { 362 {
309 if(led_delay++ >= 4) 363 if (mpeg_stat & MPEG_STATUS_PAUSE)
364 {
365 /*
366 This is supposed to be the same as
367 led(current_tick & BLINK_MASK)
368 But we do this hubub to prevent unnecessary hardware
369 communication when the led already has the desired state.
370 */
371 if (last_led_stat != ((current_tick & BLINK_MASK) == BLINK_MASK))
372 {
373 /* trigger is on in status TRIG_READY (no check needed) */
374 last_led_stat = !last_led_stat;
375 led(last_led_stat);
376 }
377 }
378 else
310 { 379 {
311 led_state = !led_state; 380 /* trigger is on in status TRIG_READY (no check needed) */
312 invert_led(led_state); 381 led(true);
313 led_delay = 0;
314 } 382 }
315 } 383 }
316 else 384 else
317 { 385 {
318 if(!led_state) 386 int trigStat = peak_meter_trigger_status();
387
388 // other trigger stati than trig_off and trig_steady
389 // already imply that we are recording.
390 if (trigStat == TRIG_STEADY)
319 { 391 {
320 led_state = true; 392 /* This is supposed to be the same as
321 invert_led(true); 393 led(current_tick & BLINK_MASK)
394 But we do this hubub to prevent unnecessary hardware
395 communication when the led already has the desired state.
396 */
397 if (last_led_stat != ((current_tick & BLINK_MASK) == BLINK_MASK))
398 {
399 /* trigger is on in status TRIG_READY (no check needed) */
400 last_led_stat = !last_led_stat;
401 led(last_led_stat);
402 }
403 }
404 else
405 {
406 /* trigger is on in status TRIG_READY (no check needed) */
407 led(false);
322 } 408 }
323 } 409 }
324 410
325 button = button_get_w_tmo(HZ / peak_meter_fps); 411 /* Wait for a button while drawing the peak meter */
412 button = peak_meter_draw_get_btn(0, 8 + h*2, LCD_WIDTH, h);
413
414 if (last_mpeg_stat != mpeg_stat)
415 {
416 if (mpeg_stat == MPEG_STATUS_RECORD)
417 {
418 have_recorded = true;
419 }
420 last_mpeg_stat = mpeg_stat;
421 }
422
326 switch(button) 423 switch(button)
327 { 424 {
328 case REC_STOPEXIT: 425 case REC_STOPEXIT:
329 if(mpeg_status() & MPEG_STATUS_RECORD) 426 if(mpeg_stat & MPEG_STATUS_RECORD)
330 { 427 {
428 /* turn off the trigger */
429 peak_meter_trigger(false);
430 peak_meter_set_trigger_listener(NULL);
331 mpeg_stop(); 431 mpeg_stop();
332 } 432 }
333 else 433 else
334 { 434 {
335 peak_meter_playback(true); 435 peak_meter_playback(true);
336 peak_meter_enabled = false; 436 peak_meter_enabled = false;
437 /* turn off the trigger */
438 peak_meter_set_trigger_listener(NULL);
439 peak_meter_trigger(false);
337 done = true; 440 done = true;
338 } 441 }
339 update_countdown = 1; /* Update immediately */ 442 update_countdown = 1; /* Update immediately */
@@ -341,8 +444,13 @@ bool recording_screen(void)
341 444
342 case REC_RECPAUSE: 445 case REC_RECPAUSE:
343 /* Only act if the mpeg is stopped */ 446 /* Only act if the mpeg is stopped */
344 if(!(mpeg_status() & MPEG_STATUS_RECORD)) 447 if(!(mpeg_stat & MPEG_STATUS_RECORD))
448 {
449 /* is this manual or triggered recording? */
450 if ((global_settings.rec_trigger_mode == TRIG_MODE_OFF) ||
451 (peak_meter_trigger_status() != TRIG_OFF))
345 { 452 {
453 /* manual recording */
346 have_recorded = true; 454 have_recorded = true;
347 talk_buffer_steal(); /* we use the mp3 buffer */ 455 talk_buffer_steal(); /* we use the mp3 buffer */
348 mpeg_record(rec_create_filename(path_buffer)); 456 mpeg_record(rec_create_filename(path_buffer));
@@ -353,9 +461,22 @@ bool recording_screen(void)
353 mpeg_beep(HZ/2); /* longer beep on start */ 461 mpeg_beep(HZ/2); /* longer beep on start */
354 } 462 }
355 } 463 }
464
465 /* this is triggered recording */
466 else
467 {
468 update_countdown = 1; /* Update immediately */
469
470 /* we don't start recording now, but enable the
471 trigger and let the callback function
472 trigger_listener control when the recording starts */
473 peak_meter_trigger(true);
474 peak_meter_set_trigger_listener(&trigger_listener);
475 }
476 }
356 else 477 else
357 { 478 {
358 if(mpeg_status() & MPEG_STATUS_PAUSE) 479 if(mpeg_stat & MPEG_STATUS_PAUSE)
359 { 480 {
360 mpeg_resume_recording(); 481 mpeg_resume_recording();
361 if (global_settings.talk_menu) 482 if (global_settings.talk_menu)
@@ -473,11 +594,14 @@ bool recording_screen(void)
473 594
474#ifdef REC_SETTINGS 595#ifdef REC_SETTINGS
475 case REC_SETTINGS: 596 case REC_SETTINGS:
476 if(mpeg_status() != MPEG_STATUS_RECORD) 597 if(mpeg_stat != MPEG_STATUS_RECORD)
477 { 598 {
478 invert_led(false); 599 /* led is restored at begin of loop / end of function */
600 led(false);
479 if (recording_menu(false)) 601 if (recording_menu(false))
602 {
480 return SYS_USB_CONNECTED; 603 return SYS_USB_CONNECTED;
604 }
481 settings_save(); 605 settings_save();
482 606
483 if (global_settings.rec_prerecord_time) 607 if (global_settings.rec_prerecord_time)
@@ -491,7 +615,6 @@ bool recording_screen(void)
491 global_settings.rec_prerecord_time); 615 global_settings.rec_prerecord_time);
492 616
493 set_gain(); 617 set_gain();
494
495 update_countdown = 1; /* Update immediately */ 618 update_countdown = 1; /* Update immediately */
496 619
497 lcd_setfont(FONT_SYSFIXED); 620 lcd_setfont(FONT_SYSFIXED);
@@ -502,9 +625,10 @@ bool recording_screen(void)
502 625
503#ifdef REC_F2 626#ifdef REC_F2
504 case REC_F2: 627 case REC_F2:
505 if(mpeg_status() != MPEG_STATUS_RECORD) 628 if(mpeg_stat != MPEG_STATUS_RECORD)
506 { 629 {
507 invert_led(false); 630 /* led is restored at begin of loop / end of function */
631 led(false);
508 if (f2_rec_screen()) 632 if (f2_rec_screen())
509 { 633 {
510 have_recorded = true; 634 have_recorded = true;
@@ -518,16 +642,17 @@ bool recording_screen(void)
518 642
519#ifdef REC_F3 643#ifdef REC_F3
520 case REC_F3: 644 case REC_F3:
521 if(mpeg_status() & MPEG_STATUS_RECORD) 645 if(mpeg_stat & MPEG_STATUS_RECORD)
522 { 646 {
523 mpeg_new_file(rec_create_filename(path_buffer)); 647 mpeg_new_file(rec_create_filename(path_buffer));
524 last_seconds = 0; 648 last_seconds = 0;
525 } 649 }
526 else 650 else
527 { 651 {
528 if(mpeg_status() != MPEG_STATUS_RECORD) 652 if(mpeg_stat != MPEG_STATUS_RECORD)
529 { 653 {
530 invert_led(false); 654 /* led is restored at begin of loop / end of function */
655 led(false);
531 if (f3_rec_screen()) 656 if (f3_rec_screen())
532 { 657 {
533 have_recorded = true; 658 have_recorded = true;
@@ -542,7 +667,7 @@ bool recording_screen(void)
542 667
543 case SYS_USB_CONNECTED: 668 case SYS_USB_CONNECTED:
544 /* Only accept USB connection when not recording */ 669 /* Only accept USB connection when not recording */
545 if(mpeg_status() != MPEG_STATUS_RECORD) 670 if(mpeg_stat != MPEG_STATUS_RECORD)
546 { 671 {
547 default_event_handler(SYS_USB_CONNECTED); 672 default_event_handler(SYS_USB_CONNECTED);
548 done = true; 673 done = true;
@@ -555,8 +680,6 @@ bool recording_screen(void)
555 break; 680 break;
556 } 681 }
557 682
558 peak_meter_peek();
559
560 if(TIME_AFTER(current_tick, timeout)) 683 if(TIME_AFTER(current_tick, timeout))
561 { 684 {
562 lcd_setfont(FONT_SYSFIXED); 685 lcd_setfont(FONT_SYSFIXED);
@@ -585,7 +708,7 @@ bool recording_screen(void)
585 708
586 dseconds = rec_timesplit_seconds(); 709 dseconds = rec_timesplit_seconds();
587 710
588 if(mpeg_status() & MPEG_STATUS_PRERECORD) 711 if(mpeg_stat & MPEG_STATUS_PRERECORD)
589 { 712 {
590 snprintf(buf, 32, "%s...", str(LANG_RECORD_PRERECORD)); 713 snprintf(buf, 32, "%s...", str(LANG_RECORD_PRERECORD));
591 } 714 }
@@ -618,15 +741,13 @@ bool recording_screen(void)
618 /* We will do file splitting regardless, since the OFF 741 /* We will do file splitting regardless, since the OFF
619 setting really means 24 hours. This is to make sure 742 setting really means 24 hours. This is to make sure
620 that the recorded files don't get too big. */ 743 that the recorded files don't get too big. */
621 if (mpeg_status() && (seconds >= dseconds)) 744 if (mpeg_stat && (seconds >= dseconds))
622 { 745 {
623 mpeg_new_file(rec_create_filename(path_buffer)); 746 mpeg_new_file(rec_create_filename(path_buffer));
624 update_countdown = 1; 747 update_countdown = 1;
625 last_seconds = 0; 748 last_seconds = 0;
626 } 749 }
627 750
628 peak_meter_draw(0, 8 + h*2, LCD_WIDTH, h);
629
630 /* Show mic gain if input source is Mic */ 751 /* Show mic gain if input source is Mic */
631 if(global_settings.rec_source == 0) 752 if(global_settings.rec_source == 0)
632 { 753 {
@@ -635,9 +756,9 @@ bool recording_screen(void)
635 global_settings.rec_mic_gain, 756 global_settings.rec_mic_gain,
636 buf2, sizeof(buf2))); 757 buf2, sizeof(buf2)));
637 if (global_settings.invert_cursor && (pos++ == cursor)) 758 if (global_settings.invert_cursor && (pos++ == cursor))
638 lcd_puts_style(0, 3, buf, STYLE_INVERT); 759 lcd_puts_style(0, 4, buf, STYLE_INVERT);
639 else 760 else
640 lcd_puts(0, 3, buf); 761 lcd_puts(0, 4, buf);
641 } 762 }
642 else 763 else
643 { 764 {
@@ -650,53 +771,58 @@ bool recording_screen(void)
650 fmt_gain(SOUND_LEFT_GAIN, gain, 771 fmt_gain(SOUND_LEFT_GAIN, gain,
651 buf2, sizeof(buf2))); 772 buf2, sizeof(buf2)));
652 if (global_settings.invert_cursor && (pos++ == cursor)) 773 if (global_settings.invert_cursor && (pos++ == cursor))
653 lcd_puts_style(0, 3, buf, STYLE_INVERT); 774 lcd_puts_style(0, 4, buf, STYLE_INVERT);
654 else 775 else
655 lcd_puts(0, 3, buf); 776 lcd_puts(0, 4, buf);
656 777
657 snprintf(buf, 32, "%s: %s", str(LANG_RECORDING_LEFT), 778 snprintf(buf, 32, "%s: %s", str(LANG_RECORDING_LEFT),
658 fmt_gain(SOUND_LEFT_GAIN, 779 fmt_gain(SOUND_LEFT_GAIN,
659 global_settings.rec_left_gain, 780 global_settings.rec_left_gain,
660 buf2, sizeof(buf2))); 781 buf2, sizeof(buf2)));
661 if (global_settings.invert_cursor && (pos++ == cursor)) 782 if (global_settings.invert_cursor && (pos++ == cursor))
662 lcd_puts_style(0, 4, buf, STYLE_INVERT); 783 lcd_puts_style(0, 5, buf, STYLE_INVERT);
663 else 784 else
664 lcd_puts(0, 4, buf); 785 lcd_puts(0, 5, buf);
665 786
666 snprintf(buf, 32, "%s: %s", str(LANG_RECORDING_RIGHT), 787 snprintf(buf, 32, "%s: %s", str(LANG_RECORDING_RIGHT),
667 fmt_gain(SOUND_RIGHT_GAIN, 788 fmt_gain(SOUND_RIGHT_GAIN,
668 global_settings.rec_right_gain, 789 global_settings.rec_right_gain,
669 buf2, sizeof(buf2))); 790 buf2, sizeof(buf2)));
670 if (global_settings.invert_cursor && (pos++ == cursor)) 791 if (global_settings.invert_cursor && (pos++ == cursor))
671 lcd_puts_style(0, 5, buf, STYLE_INVERT); 792 lcd_puts_style(0, 6, buf, STYLE_INVERT);
672 else 793 else
673 lcd_puts(0, 5, buf); 794 lcd_puts(0, 6, buf);
674 } 795 }
675 } 796 }
676 797
677 if(global_settings.rec_source != SOURCE_SPDIF) 798 if(global_settings.rec_source != SOURCE_SPDIF)
678 put_cursorxy(0, 3 + cursor, true); 799 put_cursorxy(0, 4 + cursor, true);
679 800
680 snprintf(buf, 32, "%s %s [%d]", 801 if (global_settings.rec_source != SOURCE_LINE) {
681 freq_str[global_settings.rec_frequency], 802 snprintf(buf, 32, "%s %s [%d]",
682 global_settings.rec_channels? 803 freq_str[global_settings.rec_frequency],
683 str(LANG_CHANNEL_MONO):str(LANG_CHANNEL_STEREO), 804 global_settings.rec_channels?
684 global_settings.rec_quality); 805 str(LANG_CHANNEL_MONO):str(LANG_CHANNEL_STEREO),
685 lcd_puts(0, 6, buf); 806 global_settings.rec_quality);
807 lcd_puts(0, 6, buf);
808 }
686 809
687 status_draw(true); 810 status_draw(true);
811 peak_meter_draw(0, 8 + h*2, LCD_WIDTH, h);
688 812
689 lcd_update(); 813 lcd_update();
690 } 814 }
691 else 815
816 /* draw the trigger status */
817 if (peak_meter_trigger_status() != TRIG_OFF)
692 { 818 {
693 lcd_clearrect(0, 8 + h*2, LCD_WIDTH, h); 819 peak_meter_draw_trig(LCD_WIDTH - TRIG_WIDTH, 4 * h);
694 peak_meter_draw(0, 8 + h*2, LCD_WIDTH, h); 820 lcd_update_rect(LCD_WIDTH - (TRIG_WIDTH + 2), 4 * h,
695 lcd_update_rect(0, 8 + h*2, LCD_WIDTH, h); 821 TRIG_WIDTH + 2, TRIG_HEIGHT);
696 } 822 }
697 } 823 }
698 824
699 if(mpeg_status() & MPEG_STATUS_ERROR) 825 if(mpeg_stat & MPEG_STATUS_ERROR)
700 { 826 {
701 done = true; 827 done = true;
702 } 828 }
@@ -721,6 +847,10 @@ bool recording_screen(void)
721 847
722 mpeg_init_playback(); 848 mpeg_init_playback();
723 849
850 /* make sure the trigger is really turned off */
851 peak_meter_trigger(false);
852 peak_meter_set_trigger_listener(NULL);
853
724 sound_settings_apply(); 854 sound_settings_apply();
725 855
726 lcd_setfont(FONT_UI); 856 lcd_setfont(FONT_UI);
@@ -728,6 +858,9 @@ bool recording_screen(void)
728 if (have_recorded) 858 if (have_recorded)
729 reload_directory(); 859 reload_directory();
730 860
861#ifndef SIMULATOR
862 ata_set_led_enabled(true);
863#endif
731 return been_in_usb_mode; 864 return been_in_usb_mode;
732/* 865/*
733#endif 866#endif
@@ -883,10 +1016,26 @@ bool f3_rec_screen(void)
883 lcd_bitmap(bitmap_icons_7x8[Icon_FastBackward], 1016 lcd_bitmap(bitmap_icons_7x8[Icon_FastBackward],
884 LCD_WIDTH/2 - 16, LCD_HEIGHT/2 - 4, 7, 8, true); 1017 LCD_WIDTH/2 - 16, LCD_HEIGHT/2 - 4, 7, 8, true);
885 1018
1019 /* trigger setup */
1020 ptr = str(LANG_RECORD_TRIGGER);
1021 lcd_getstringsize(ptr,&w,&h);
1022 lcd_putsxy((LCD_WIDTH-w)/2, LCD_HEIGHT - h*2, ptr);
1023 lcd_bitmap(bitmap_icons_7x8[Icon_DownArrow],
1024 LCD_WIDTH/2 - 3, LCD_HEIGHT - h*3, 7, 8, true);
1025
886 lcd_update(); 1026 lcd_update();
887 1027
888 button = button_get(true); 1028 button = button_get(true);
889 switch (button) { 1029 switch (button) {
1030 case BUTTON_DOWN:
1031 case BUTTON_F3 | BUTTON_DOWN:
1032#ifndef SIMULATOR
1033 rectrigger();
1034 settings_apply_trigger();
1035#endif
1036 exit = true;
1037 break;
1038
890 case BUTTON_LEFT: 1039 case BUTTON_LEFT:
891 case BUTTON_F3 | BUTTON_LEFT: 1040 case BUTTON_F3 | BUTTON_LEFT:
892 global_settings.rec_source++; 1041 global_settings.rec_source++;