1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2004 Linus Nielsen Feltzing
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
25 static char *audiobuf
;
26 static size_t audiobuflen
;
27 unsigned char xingbuf
[1500];
28 char tmpname
[MAX_PATH
];
30 static void xingupdate(int percent
)
32 rb
->lcd_putsf(0, 1, "%d%%", percent
);
36 static int insert_data_in_file(const char *fname
, int fpos
, char *buf
, int num_bytes
)
42 rb
->snprintf(tmpname
, MAX_PATH
, "%s.tmp", fname
);
44 orig_fd
= rb
->open(fname
, O_RDONLY
);
46 return 10*orig_fd
- 1;
49 fd
= rb
->creat(tmpname
, 0666);
55 /* First, copy the initial portion (the ID3 tag) */
57 readlen
= rb
->read(orig_fd
, audiobuf
, fpos
);
61 return 10*readlen
- 3;
64 rc
= rb
->write(fd
, audiobuf
, readlen
);
72 /* Now insert the data into the file */
73 rc
= rb
->write(fd
, buf
, num_bytes
);
82 readlen
= rb
->read(orig_fd
, audiobuf
, audiobuflen
);
86 return 10*readlen
- 7;
89 rc
= rb
->write(fd
, audiobuf
, readlen
);
100 /* Remove the old file */
101 rc
= rb
->remove(fname
);
106 /* Replace the old file with the new */
107 rc
= rb
->rename(tmpname
, fname
);
115 static void fileerror(int rc
)
117 rb
->splashf(HZ
*2, "File error: %d", rc
);
120 static const unsigned char empty_id3_header
[] =
122 'I', 'D', '3', 0x04, 0x00, 0x00,
123 0x00, 0x00, 0x1f, 0x76 /* Size is 4096 minus 10 bytes for the header */
126 static bool vbr_fix(const char *selected_file
)
128 struct mp3entry entry
;
137 rb
->lcd_clear_display();
138 rb
->lcd_puts_scroll(0, 0, selected_file
);
143 rc
= rb
->mp3info(&entry
, selected_file
);
149 fd
= rb
->open(selected_file
, O_RDWR
);
155 flen
= rb
->lseek(fd
, 0, SEEK_END
);
159 num_frames
= rb
->count_mp3_frames(fd
, entry
.first_frame_offset
,
160 flen
, xingupdate
, audiobuf
, audiobuflen
);
163 /* Note: We don't need to pass a template header because it will be
164 taken from the mpeg stream */
165 framelen
= rb
->create_xing_header(fd
, entry
.first_frame_offset
,
166 flen
, xingbuf
, num_frames
, 0,
168 audiobuf
, audiobuflen
);
170 /* Try to fit the Xing header first in the stream. Replace the existing
171 VBR header if there is one, else see if there is room between the
172 ID3 tag and the first MP3 frame. */
173 if(entry
.first_frame_offset
- entry
.id3v2len
>=
174 (unsigned int)framelen
) {
175 DEBUGF("Using existing space between ID3 and first frame\n");
177 /* Seek to the beginning of the unused space */
178 rc
= rb
->lseek(fd
, entry
.id3v2len
, SEEK_SET
);
186 entry
.first_frame_offset
- entry
.id3v2len
- framelen
;
188 /* Fill the unused space with 0's (using the MP3 buffer)
189 and write it to the file */
192 rb
->memset(audiobuf
, 0, unused_space
);
193 rc
= rb
->write(fd
, audiobuf
, unused_space
);
201 /* Then write the Xing header */
202 rc
= rb
->write(fd
, xingbuf
, framelen
);
211 /* If not, insert some space. If there is an ID3 tag in the
212 file we only insert just enough to squeeze the Xing header
213 in. If not, we insert an additional empty ID3 tag of 4K. */
217 /* Nasty trick alert! The insert_data_in_file() function
218 uses the MP3 buffer when copying the data. We assume
219 that the ID3 tag isn't longer than 1MB so the xing
220 buffer won't be overwritten. */
222 if(entry
.first_frame_offset
) {
223 DEBUGF("Inserting %d bytes\n", framelen
);
226 DEBUGF("Inserting 4096+%d bytes\n", framelen
);
227 numbytes
= 4096 + framelen
;
229 rb
->memset(audiobuf
+ 0x100000, 0, numbytes
);
231 /* Insert the ID3 header */
232 rb
->memcpy(audiobuf
+ 0x100000, empty_id3_header
,
233 sizeof(empty_id3_header
));
236 /* Copy the Xing header */
237 rb
->memcpy(audiobuf
+ 0x100000 + numbytes
- framelen
,
240 rc
= insert_data_in_file(selected_file
,
241 entry
.first_frame_offset
,
242 audiobuf
+ 0x100000, numbytes
);
255 DEBUGF("Not a VBR file\n");
256 rb
->splash(HZ
*2, "Not a VBR file");
262 enum plugin_status
plugin_start(const void *parameter
)
268 audiobuf
= rb
->plugin_get_audio_buffer(&audiobuflen
);
270 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
276 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
277 rb
->cpu_boost(false);