summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2003-04-20 22:00:30 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2003-04-20 22:00:30 +0000
commit478da628f0eb5fb3b5163dab459927ada52badfc (patch)
tree04e27d8bd6122a23c0fe483c4d35e149d1953179
parentc6fb565dd98d2da0cd5ba0e29b73c49617edcb9c (diff)
downloadrockbox-478da628f0eb5fb3b5163dab459927ada52badfc.tar.gz
rockbox-478da628f0eb5fb3b5163dab459927ada52badfc.zip
Xing headers now support mono better, added the 'editable files' option
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3572 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/lang/english.lang5
-rw-r--r--apps/onplay.c6
-rw-r--r--apps/recorder/recording.c30
-rw-r--r--apps/settings.c26
-rw-r--r--apps/settings.h1
-rw-r--r--apps/sound_menu.c7
-rw-r--r--firmware/export/mp3data.h2
-rw-r--r--firmware/export/mpeg.h6
-rw-r--r--firmware/mp3data.c133
-rw-r--r--firmware/mpeg.c26
10 files changed, 152 insertions, 90 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index e080491e2c..15d9039018 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -1467,3 +1467,8 @@ id: LANG_INVERT_CURSOR
1467desc: in settings_menu 1467desc: in settings_menu
1468eng: "Invert cursor" 1468eng: "Invert cursor"
1469new: 1469new:
1470
1471id: LANG_RECORDING_EDITABLE
1472desc: Editable recordings setting
1473eng: "Editable files"
1474new:
diff --git a/apps/onplay.c b/apps/onplay.c
index 3ba4c1b49c..14e3cdd7a7 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -251,11 +251,11 @@ static bool vbr_fix(void)
251 flen, xingupdate); 251 flen, xingupdate);
252 252
253 if(num_frames) { 253 if(num_frames) {
254 /* Note: We don't need to pass any values for mpeg_version and 254 /* Note: We don't need to pass a template header because it will be
255 sample_rate because they will be extracted from the mpeg stream */ 255 taken from the mpeg stream */
256 framelen = create_xing_header(fd, entry.first_frame_offset, 256 framelen = create_xing_header(fd, entry.first_frame_offset,
257 flen, xingbuf, num_frames, 257 flen, xingbuf, num_frames,
258 0, 0, xingupdate, true); 258 0, xingupdate, true);
259 259
260 /* Try to fit the Xing header first in the stream. Replace the existing 260 /* Try to fit the Xing header first in the stream. Replace the existing
261 VBR header if there is one, else see if there is room between the 261 VBR header if there is one, else see if there is room between the
diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c
index cf295db19c..14bd37d950 100644
--- a/apps/recorder/recording.c
+++ b/apps/recorder/recording.c
@@ -169,7 +169,8 @@ bool recording_screen(void)
169 mpeg_set_recording_options(global_settings.rec_frequency, 169 mpeg_set_recording_options(global_settings.rec_frequency,
170 global_settings.rec_quality, 170 global_settings.rec_quality,
171 global_settings.rec_source, 171 global_settings.rec_source,
172 global_settings.rec_channels); 172 global_settings.rec_channels,
173 global_settings.rec_editable);
173 174
174 set_gain(); 175 set_gain();
175 176
@@ -312,22 +313,29 @@ bool recording_screen(void)
312 mpeg_set_recording_options(global_settings.rec_frequency, 313 mpeg_set_recording_options(global_settings.rec_frequency,
313 global_settings.rec_quality, 314 global_settings.rec_quality,
314 global_settings.rec_source, 315 global_settings.rec_source,
315 global_settings.rec_channels); 316 global_settings.rec_channels,
317 global_settings.rec_editable);
316 318
317 set_gain(); 319 set_gain();
318 update_countdown = 1; /* Update immediately */ 320 update_countdown = 1; /* Update immediately */
319 break; 321 break;
320 322
321 case BUTTON_F2: 323 case BUTTON_F2:
322 if (f2_rec_screen()) 324 if(mpeg_status())
323 return SYS_USB_CONNECTED; 325 {
324 update_countdown = 1; /* Update immediately */ 326 if (f2_rec_screen())
327 return SYS_USB_CONNECTED;
328 update_countdown = 1; /* Update immediately */
329 }
325 break; 330 break;
326 331
327 case BUTTON_F3: 332 case BUTTON_F3:
328 if (f3_rec_screen()) 333 if(mpeg_status())
329 return SYS_USB_CONNECTED; 334 {
330 update_countdown = 1; /* Update immediately */ 335 if (f3_rec_screen())
336 return SYS_USB_CONNECTED;
337 update_countdown = 1; /* Update immediately */
338 }
331 break; 339 break;
332 340
333 } 341 }
@@ -537,7 +545,8 @@ bool f2_rec_screen(void)
537 mpeg_set_recording_options(global_settings.rec_frequency, 545 mpeg_set_recording_options(global_settings.rec_frequency,
538 global_settings.rec_quality, 546 global_settings.rec_quality,
539 global_settings.rec_source, 547 global_settings.rec_source,
540 global_settings.rec_channels); 548 global_settings.rec_channels,
549 global_settings.rec_editable);
541 550
542 set_gain(); 551 set_gain();
543 552
@@ -621,7 +630,8 @@ bool f3_rec_screen(void)
621 mpeg_set_recording_options(global_settings.rec_frequency, 630 mpeg_set_recording_options(global_settings.rec_frequency,
622 global_settings.rec_quality, 631 global_settings.rec_quality,
623 global_settings.rec_source, 632 global_settings.rec_source,
624 global_settings.rec_channels); 633 global_settings.rec_channels,
634 global_settings.rec_editable);
625 635
626 set_gain(); 636 set_gain();
627 637
diff --git a/apps/settings.c b/apps/settings.c
index 8c132c5f9b..8b74df852b 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -96,8 +96,8 @@ offset abs
960x16 0x2a <(int) Byte offset into resume file> 960x16 0x2a <(int) Byte offset into resume file>
970x1a 0x2e <time until disk spindown> 970x1a 0x2e <time until disk spindown>
980x1b 0x2f <browse current, play selected, queue_resume> 980x1b 0x2f <browse current, play selected, queue_resume>
990x1c 0x30 <peak meter hold timeout (bit 0-4)>, 990x1c 0x30 <peak meter hold timeout (bit 0-4),
100 peak_meter_performance (bit 7) 100 rec_editable (bit 7)>
1010x1d 0x31 <(int) queue resume index> 1010x1d 0x31 <(int) queue resume index>
1020x21 0x35 <repeat mode (bit 0-1), rec. channels (bit 2), 1020x21 0x35 <repeat mode (bit 0-1), rec. channels (bit 2),
103 mic gain (bit 4-7)> 103 mic gain (bit 4-7)>
@@ -125,7 +125,7 @@ modified unless the header & checksum test fails.
125 125
126Rest of config block, only saved to disk: 126Rest of config block, only saved to disk:
1270xAE fade on pause/unpause/stop setting (bit 0) 1270xAE fade on pause/unpause/stop setting (bit 0)
1280xB0 peak meter clip hold timeout (bit 0-4) 1280xB0 peak meter clip hold timeout (bit 0-4), peak meter performance (bit 7)
1290xB1 peak meter release step size, peak_meter_dbfs (bit 7) 1290xB1 peak meter release step size, peak_meter_dbfs (bit 7)
1300xB2 peak meter min either in -db or in percent 1300xB2 peak meter min either in -db or in percent
1310xB3 peak meter max either in -db or in percent 1310xB3 peak meter max either in -db or in percent
@@ -341,7 +341,8 @@ int settings_save( void )
341 ((global_settings.play_selected & 1) << 1) | 341 ((global_settings.play_selected & 1) << 1) |
342 ((global_settings.queue_resume & 3) << 2)); 342 ((global_settings.queue_resume & 3) << 2));
343 343
344 config_block[0x1c] = (unsigned char)global_settings.peak_meter_hold; 344 config_block[0x1c] = (unsigned char)global_settings.peak_meter_hold |
345 (global_settings.rec_editable?0x80:0);
345 346
346 memcpy(&config_block[0x1d], &global_settings.queue_resume_index, 4); 347 memcpy(&config_block[0x1d], &global_settings.queue_resume_index, 4);
347 348
@@ -617,8 +618,11 @@ void settings_load(void)
617 global_settings.queue_resume = (config_block[0x1b] >> 2) & 3; 618 global_settings.queue_resume = (config_block[0x1b] >> 2) & 3;
618 } 619 }
619 620
620 if (config_block[0x1c] != 0xFF) 621 if (config_block[0x1c] != 0xFF) {
621 global_settings.peak_meter_hold = (config_block[0x1c]) & 0x1f; 622 global_settings.peak_meter_hold = (config_block[0x1c]) & 0x1f;
623 global_settings.rec_editable =
624 config_block[0x1c]?true:false;
625 }
622 626
623 if (config_block[0x1d] != 0xFF) 627 if (config_block[0x1d] != 0xFF)
624 memcpy(&global_settings.queue_resume_index, &config_block[0x1d], 628 memcpy(&global_settings.queue_resume_index, &config_block[0x1d],
@@ -1029,6 +1033,9 @@ bool settings_load_config(char* file)
1029 static char* options[] = {"stereo", "mono"}; 1033 static char* options[] = {"stereo", "mono"};
1030 set_cfg_option(&global_settings.rec_channels, value, options, 2); 1034 set_cfg_option(&global_settings.rec_channels, value, options, 2);
1031 } 1035 }
1036 else if (!strcasecmp(name, "editable recordings")) {
1037 set_cfg_bool(&global_settings.rec_editable, value);
1038 }
1032#endif 1039#endif
1033 else if (!strcasecmp(name, "idle poweroff")) { 1040 else if (!strcasecmp(name, "idle poweroff")) {
1034 static char* options[] = {"off","1","2","3","4","5","6","7","8", 1041 static char* options[] = {"off","1","2","3","4","5","6","7","8",
@@ -1434,6 +1441,14 @@ bool settings_save_config(void)
1434 global_settings.rec_left_gain, 1441 global_settings.rec_left_gain,
1435 global_settings.rec_right_gain); 1442 global_settings.rec_right_gain);
1436 write(fd, buf, strlen(buf)); 1443 write(fd, buf, strlen(buf));
1444
1445 {
1446 static char* options[] = {"off", "on"};
1447 snprintf(buf, sizeof(buf), "editable recordings: %s\r\n",
1448 options[global_settings.rec_editable]);
1449 write(fd, buf, strlen(buf));
1450 }
1451
1437#endif 1452#endif
1438 close(fd); 1453 close(fd);
1439 1454
@@ -1467,6 +1482,7 @@ void settings_reset(void) {
1467 global_settings.rec_mic_gain = 8; 1482 global_settings.rec_mic_gain = 8;
1468 global_settings.rec_left_gain = 2; /* 0dB */ 1483 global_settings.rec_left_gain = 2; /* 0dB */
1469 global_settings.rec_right_gain = 2; /* 0dB */ 1484 global_settings.rec_right_gain = 2; /* 0dB */
1485 global_settings.rec_editable = false;
1470 global_settings.resume = RESUME_ASK; 1486 global_settings.resume = RESUME_ASK;
1471 global_settings.contrast = DEFAULT_CONTRAST_SETTING; 1487 global_settings.contrast = DEFAULT_CONTRAST_SETTING;
1472 global_settings.invert = DEFAULT_INVERT_SETTING; 1488 global_settings.invert = DEFAULT_INVERT_SETTING;
diff --git a/apps/settings.h b/apps/settings.h
index 7876a18afa..0ff7cb2102 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -74,6 +74,7 @@ struct user_settings
74 int rec_mic_gain; /* 0-15 */ 74 int rec_mic_gain; /* 0-15 */
75 int rec_left_gain; /* 0-15 */ 75 int rec_left_gain; /* 0-15 */
76 int rec_right_gain; /* 0-15 */ 76 int rec_right_gain; /* 0-15 */
77 bool rec_editable; /* true means that the bit reservoir is off */
77 78
78 /* device settings */ 79 /* device settings */
79 80
diff --git a/apps/sound_menu.c b/apps/sound_menu.c
index 9ac95e46b8..84d389a47a 100644
--- a/apps/sound_menu.c
+++ b/apps/sound_menu.c
@@ -219,6 +219,12 @@ static bool recquality(void)
219 &global_settings.rec_quality, 219 &global_settings.rec_quality,
220 NULL, 1, 0, 7 ); 220 NULL, 1, 0, 7 );
221} 221}
222
223static bool receditable(void)
224{
225 return set_bool(str(LANG_RECORDING_EDITABLE),
226 &global_settings.rec_editable);
227}
222#endif /* HAVE_MAS3587F */ 228#endif /* HAVE_MAS3587F */
223 229
224static void set_chanconf(int val) 230static void set_chanconf(int val)
@@ -275,6 +281,7 @@ bool recording_menu(void)
275 { str(LANG_RECORDING_FREQUENCY), recfrequency }, 281 { str(LANG_RECORDING_FREQUENCY), recfrequency },
276 { str(LANG_RECORDING_SOURCE), recsource }, 282 { str(LANG_RECORDING_SOURCE), recsource },
277 { str(LANG_RECORDING_CHANNELS), recchannels }, 283 { str(LANG_RECORDING_CHANNELS), recchannels },
284 { str(LANG_RECORDING_EDITABLE), receditable },
278 }; 285 };
279 286
280 m=menu_init( items, sizeof items / sizeof(struct menu_items) ); 287 m=menu_init( items, sizeof items / sizeof(struct menu_items) );
diff --git a/firmware/export/mp3data.h b/firmware/export/mp3data.h
index d180935aa4..6b3ff83b1a 100644
--- a/firmware/export/mp3data.h
+++ b/firmware/export/mp3data.h
@@ -61,7 +61,7 @@ int count_mp3_frames(int fd, int startpos, int filesize,
61 void (*progressfunc)(int)); 61 void (*progressfunc)(int));
62int create_xing_header(int fd, int startpos, int filesize, 62int create_xing_header(int fd, int startpos, int filesize,
63 unsigned char *buf, int num_frames, 63 unsigned char *buf, int num_frames,
64 int mpeg_version, int sample_rate, 64 unsigned long header_template,
65 void (*progressfunc)(int), bool generate_toc); 65 void (*progressfunc)(int), bool generate_toc);
66 66
67#endif 67#endif
diff --git a/firmware/export/mpeg.h b/firmware/export/mpeg.h
index e971aaac33..d939567f3d 100644
--- a/firmware/export/mpeg.h
+++ b/firmware/export/mpeg.h
@@ -32,6 +32,9 @@
32#define MPEG_PLAY_PENDING_THRESHOLD 0x10000 32#define MPEG_PLAY_PENDING_THRESHOLD 0x10000
33#define MPEG_PLAY_PENDING_SWAPSIZE 0x10000 33#define MPEG_PLAY_PENDING_SWAPSIZE 0x10000
34 34
35/* For ID3 info and VBR header */
36#define MPEG_RESERVED_HEADER_SPACE (4096 + 1500)
37
35struct mpeg_debug 38struct mpeg_debug
36{ 39{
37 int mp3buflen; 40 int mp3buflen;
@@ -84,7 +87,8 @@ void mpeg_init_recording(void);
84void mpeg_init_playback(void); 87void mpeg_init_playback(void);
85void mpeg_record(char *filename); 88void mpeg_record(char *filename);
86void mpeg_set_recording_options(int frequency, int quality, 89void mpeg_set_recording_options(int frequency, int quality,
87 int source, int channel_mode); 90 int source, int channel_mode,
91 bool editable);
88void mpeg_set_recording_gain(int left, int right, int mic); 92void mpeg_set_recording_gain(int left, int right, int mic);
89unsigned long mpeg_recorded_time(void); 93unsigned long mpeg_recorded_time(void);
90unsigned long mpeg_num_recorded_bytes(void); 94unsigned long mpeg_num_recorded_bytes(void);
diff --git a/firmware/mp3data.c b/firmware/mp3data.c
index 415d3bf3d1..1cbf8e54ee 100644
--- a/firmware/mp3data.c
+++ b/firmware/mp3data.c
@@ -530,14 +530,6 @@ int get_mp3file_info(int fd, struct mp3info *info)
530 return bytecount; 530 return bytecount;
531} 531}
532 532
533/* This is an MP3 header, 128kbit/s, with silence
534 MPEG version and sample frequency are not set */
535static const unsigned char xing_frame_header[] = {
536 0xff, 0xe2, 0x90, 0x64, 0x86, 0x1f
537};
538
539static const char cooltext[] = "Rockbox rocks";
540
541static void int2bytes(unsigned char *buf, int val) 533static void int2bytes(unsigned char *buf, int val)
542{ 534{
543 buf[0] = (val >> 24) & 0xff; 535 buf[0] = (val >> 24) & 0xff;
@@ -602,55 +594,30 @@ int count_mp3_frames(int fd, int startpos, int filesize,
602 } 594 }
603} 595}
604 596
605/* Note: mpeg_version and sample_rate are 2-bit values, as specified by the 597static const char cooltext[] = "Rockbox - rocks your box";
606 MPEG frame standard. See the tables above. */ 598
607int create_xing_header(int fd, int startpos, int filesize, 599int create_xing_header(int fd, int startpos, int filesize,
608 unsigned char *buf, int num_frames, 600 unsigned char *buf, int num_frames,
609 int mpeg_version, int sample_rate, 601 unsigned long header_template,
610 void (*progressfunc)(int), bool generate_toc) 602 void (*progressfunc)(int), bool generate_toc)
611{ 603{
612 unsigned long header = 0; 604 unsigned long header = 0;
613 unsigned long saved_header = 0;
614 struct mp3info info; 605 struct mp3info info;
615 int pos, last_pos; 606 int pos, last_pos;
616 int i, j; 607 int i, j;
617 int bytes; 608 int bytes;
618 int filepos; 609 int filepos;
619 int tocentry;
620 int x; 610 int x;
621 int index; 611 int index;
612 unsigned char toc[100];
622 613
623 DEBUGF("create_xing_header()\n"); 614 DEBUGF("create_xing_header()\n");
624 615
625 /* Create the frame header */
626 memset(buf, 0, 1500);
627 memcpy(buf, xing_frame_header, 6);
628
629 lseek(fd, startpos, SEEK_SET);
630 buf_init();
631
632 buf[36] = 'X';
633 buf[36+1] = 'i';
634 buf[36+2] = 'n';
635 buf[36+3] = 'g';
636 int2bytes(&buf[36+4], ((num_frames?VBR_FRAMES_FLAG:0) |
637 (filesize?VBR_BYTES_FLAG:0) |
638 (generate_toc?VBR_TOC_FLAG:0)));
639 index = 36+8;
640 if(num_frames)
641 {
642 int2bytes(&buf[index], num_frames);
643 index += 4;
644 }
645
646 if(filesize)
647 {
648 int2bytes(&buf[index], filesize - startpos);
649 index += 4;
650 }
651
652 if(generate_toc) 616 if(generate_toc)
653 { 617 {
618 lseek(fd, startpos, SEEK_SET);
619 buf_init();
620
654 /* Generate filepos table */ 621 /* Generate filepos table */
655 last_pos = 0; 622 last_pos = 0;
656 filepos = 0; 623 filepos = 0;
@@ -670,48 +637,90 @@ int create_xing_header(int fd, int startpos, int filesize,
670 filepos += info.frame_size; 637 filepos += info.frame_size;
671 } 638 }
672 639
673 /* Save one header for later use */ 640 /* Save a header for later use. Yes, we may be passed a header
641 template in the header_template argument, but since we are
642 reading headers from the stream anyway, we might as well
643 use the ones we find. However, we only save one header, and
644 we want to save one in te middle of the stream, just in case
645 the first and the last headers are corrupt. */
674 if(i == 1) 646 if(i == 1)
675 saved_header = header; 647 header_template = header;
676 648
677 if(progressfunc) 649 if(progressfunc)
678 { 650 {
679 progressfunc(50 + i/2); 651 progressfunc(50 + i/2);
680 } 652 }
681 653
682 tocentry = filepos * 256 / filesize; 654 /* Fill in the TOC entry */
655 toc[i] = filepos * 256 / filesize;
683 656
684 DEBUGF("Pos %d: %d relpos: %d filepos: %x tocentry: %x\n", 657 DEBUGF("Pos %d: %d relpos: %d filepos: %x tocentry: %x\n",
685 i, pos, pos-last_pos, filepos, tocentry); 658 i, pos, pos-last_pos, filepos, toc[i]);
686
687 /* Fill in the TOC entry */
688 buf[index + i] = tocentry;
689 659
690 last_pos = pos; 660 last_pos = pos;
691 } 661 }
662 }
663
664 /* Clear the frame */
665 memset(buf, 0, 1500);
692 666
693 /* Copy the MPEG version and sample rate from the mpeg stream into 667 /* Use the template header and create a new one */
694 the Xing header */ 668 mp3headerinfo(&info, header_template);
695 saved_header &= (VERSION_MASK | SAMPLERATE_MASK); 669
670 /* calculate position of VBR header */
671 if ( info.version == MPEG_VERSION1 ) {
672 if (info.channel_mode == 3) /* mono */
673 index = 21;
674 else
675 index = 36;
676 }
677 else {
678 if (info.channel_mode == 3) /* mono */
679 index = 13;
680 else
681 index = 21;
682 }
683
684 /* We ignore the Protection bit even if the rest of the stream is
685 protected. (fixme?) */
686 header = header_template & ~(BITRATE_MASK | PROTECTION_MASK);
687 header |= 8 << 12; /* This gives us plenty of space, at least 192 bytes */
688
689 /* Write the header to the buffer */
690 int2bytes(buf, header);
696 691
697 buf[1] |= (saved_header >> 16) & 0xff; 692 /* Now get the length of the newly created frame */
698 buf[2] |= (saved_header >> 8) & 0xff; 693 mp3headerinfo(&info, header);
694
695 /* Create the Xing data */
696 buf[index] = 'X';
697 buf[index+1] = 'i';
698 buf[index+2] = 'n';
699 buf[index+3] = 'g';
700 int2bytes(&buf[index+4], ((num_frames?VBR_FRAMES_FLAG:0) |
701 (filesize?VBR_BYTES_FLAG:0) |
702 (generate_toc?VBR_TOC_FLAG:0)));
703 index = index+8;
704 if(num_frames)
705 {
706 int2bytes(&buf[index], num_frames);
707 index += 4;
699 } 708 }
700 else 709
710 if(filesize)
701 { 711 {
702 /* Fill in the MPEG version and sample rate into the Xing header */ 712 int2bytes(&buf[index], filesize - startpos);
703 buf[1] |= mpeg_version << 3; 713 index += 4;
704 buf[2] |= sample_rate << 2;
705 } 714 }
706 715
716 /* Copy the TOC */
717 memcpy(buf + index, toc, 100);
718
719 /* And some extra cool info */
707 memcpy(buf + index + 100, cooltext, sizeof(cooltext)); 720 memcpy(buf + index + 100, cooltext, sizeof(cooltext));
708 721
709 /* Now get the length of the newly created frame */
710 header = BYTES2INT(buf[0], buf[1], buf[2], buf[3]);
711 mp3headerinfo(&info, header);
712
713#ifdef DEBUG 722#ifdef DEBUG
714 for(i = 0;i < 417;i++) 723 for(i = 0;i < info.framesize;i++)
715 { 724 {
716 if(i && !(i % 16)) 725 if(i && !(i % 16))
717 DEBUGF("\n"); 726 DEBUGF("\n");
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index 7e48040da2..11837d608e 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -1266,6 +1266,7 @@ static void mpeg_thread(void)
1266 int amount_to_save; 1266 int amount_to_save;
1267 int writelen; 1267 int writelen;
1268 int framelen; 1268 int framelen;
1269 unsigned long saved_header;
1269#endif 1270#endif
1270 1271
1271 is_playing = false; 1272 is_playing = false;
@@ -1840,10 +1841,10 @@ static void mpeg_thread(void)
1840 DEBUGF("Recording...\n"); 1841 DEBUGF("Recording...\n");
1841 reset_mp3_buffer(); 1842 reset_mp3_buffer();
1842 1843
1843 /* Advance the write pointer 4096+1500 bytes to make 1844 /* Advance the write pointer to make
1844 room for an ID3 tag plus a VBR header */ 1845 room for an ID3 tag plus a VBR header */
1845 mp3buf_write = 4096+1500; 1846 mp3buf_write = MPEG_RESERVED_HEADER_SPACE;
1846 memset(mp3buf, 0, 4096+1500); 1847 memset(mp3buf, 0, MPEG_RESERVED_HEADER_SPACE);
1847 1848
1848 /* Insert the ID3 header */ 1849 /* Insert the ID3 header */
1849 memcpy(mp3buf, empty_id3_header, sizeof(empty_id3_header)); 1850 memcpy(mp3buf, empty_id3_header, sizeof(empty_id3_header));
@@ -1883,14 +1884,17 @@ static void mpeg_thread(void)
1883 we can no longer trust it */ 1884 we can no longer trust it */
1884 if(num_recorded_frames == 0x7ffff) 1885 if(num_recorded_frames == 0x7ffff)
1885 num_recorded_frames = 0; 1886 num_recorded_frames = 0;
1887
1888 /* Read the first MP3 frame from the recorded stream */
1889 lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE, SEEK_SET);
1890 read(mpeg_file, &saved_header, 4);
1886 1891
1887 framelen = create_xing_header(mpeg_file, 0, num_rec_bytes, 1892 framelen = create_xing_header(mpeg_file, 0, num_rec_bytes,
1888 mp3buf, num_recorded_frames, 1893 mp3buf, num_recorded_frames,
1889 rec_version_index, 1894 saved_header, NULL, false);
1890 rec_frequency_index,
1891 NULL, false);
1892 1895
1893 lseek(mpeg_file, 4096+1500-framelen, SEEK_SET); 1896 lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE-framelen,
1897 SEEK_SET);
1894 write(mpeg_file, mp3buf, framelen); 1898 write(mpeg_file, mp3buf, framelen);
1895 close(mpeg_file); 1899 close(mpeg_file);
1896 1900
@@ -2823,7 +2827,8 @@ void mpeg_set_pitch(int pitch)
2823 2827
2824#ifdef HAVE_MAS3587F 2828#ifdef HAVE_MAS3587F
2825void mpeg_set_recording_options(int frequency, int quality, 2829void mpeg_set_recording_options(int frequency, int quality,
2826 int source, int channel_mode) 2830 int source, int channel_mode,
2831 bool editable)
2827{ 2832{
2828 bool is_mpeg1; 2833 bool is_mpeg1;
2829 unsigned long val; 2834 unsigned long val;
@@ -2844,6 +2849,11 @@ void mpeg_set_recording_options(int frequency, int quality,
2844 2849
2845 DEBUGF("mas_writemem(MAS_BANK_D0, 0x7f0, %x)\n", val); 2850 DEBUGF("mas_writemem(MAS_BANK_D0, 0x7f0, %x)\n", val);
2846 2851
2852 val = editable?4:0;
2853 mas_writemem(MAS_BANK_D0, 0x7f9, &val,1);
2854
2855 DEBUGF("mas_writemem(MAS_BANK_D0, 0x7f9, %x)\n", val);
2856
2847 val = ((!is_recording << 10) | /* Monitoring */ 2857 val = ((!is_recording << 10) | /* Monitoring */
2848 ((source < 2)?1:2) << 8) | /* Input select */ 2858 ((source < 2)?1:2) << 8) | /* Input select */
2849 (1 << 5) | /* SDO strobe invert */ 2859 (1 << 5) | /* SDO strobe invert */