1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2004 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 ****************************************************************************/
23 static struct plugin_api
* rb
;
25 static char *audiobuf
;
26 static ssize_t audiobuflen
;
27 unsigned char xingbuf
[1500];
28 char tmpname
[MAX_PATH
];
30 static void xingupdate(int percent
)
34 rb
->snprintf(buf
, 32, "%d%%", percent
);
35 rb
->lcd_puts(0, 1, buf
);
39 static int insert_data_in_file(char *fname
, int fpos
, char *buf
, int num_bytes
)
45 rb
->snprintf(tmpname
, MAX_PATH
, "%s.tmp", fname
);
47 orig_fd
= rb
->open(fname
, O_RDONLY
);
49 return 10*orig_fd
- 1;
52 fd
= rb
->creat(tmpname
);
58 /* First, copy the initial portion (the ID3 tag) */
60 readlen
= rb
->read(orig_fd
, audiobuf
, fpos
);
64 return 10*readlen
- 3;
67 rc
= rb
->write(fd
, audiobuf
, readlen
);
75 /* Now insert the data into the file */
76 rc
= rb
->write(fd
, buf
, num_bytes
);
85 readlen
= rb
->read(orig_fd
, audiobuf
, audiobuflen
);
89 return 10*readlen
- 7;
92 rc
= rb
->write(fd
, audiobuf
, readlen
);
103 /* Remove the old file */
104 rc
= rb
->remove(fname
);
109 /* Replace the old file with the new */
110 rc
= rb
->rename(tmpname
, fname
);
118 static void fileerror(int rc
)
120 rb
->splash(HZ
*2, "File error: %d", rc
);
123 static const unsigned char empty_id3_header
[] =
125 'I', 'D', '3', 0x04, 0x00, 0x00,
126 0x00, 0x00, 0x1f, 0x76 /* Size is 4096 minus 10 bytes for the header */
129 static bool vbr_fix(char *selected_file
)
131 struct mp3entry entry
;
140 rb
->lcd_clear_display();
141 rb
->lcd_puts_scroll(0, 0, selected_file
);
146 rc
= rb
->mp3info(&entry
, selected_file
);
152 fd
= rb
->open(selected_file
, O_RDWR
);
158 flen
= rb
->lseek(fd
, 0, SEEK_END
);
162 num_frames
= rb
->count_mp3_frames(fd
, entry
.first_frame_offset
,
166 /* Note: We don't need to pass a template header because it will be
167 taken from the mpeg stream */
168 framelen
= rb
->create_xing_header(fd
, entry
.first_frame_offset
,
169 flen
, xingbuf
, num_frames
, 0,
170 0, xingupdate
, true);
172 /* Try to fit the Xing header first in the stream. Replace the existing
173 VBR header if there is one, else see if there is room between the
174 ID3 tag and the first MP3 frame. */
175 if(entry
.first_frame_offset
- entry
.id3v2len
>=
176 (unsigned int)framelen
) {
177 DEBUGF("Using existing space between ID3 and first frame\n");
179 /* Seek to the beginning of the unused space */
180 rc
= rb
->lseek(fd
, entry
.id3v2len
, SEEK_SET
);
188 entry
.first_frame_offset
- entry
.id3v2len
- framelen
;
190 /* Fill the unused space with 0's (using the MP3 buffer)
191 and write it to the file */
194 rb
->memset(audiobuf
, 0, unused_space
);
195 rc
= rb
->write(fd
, audiobuf
, unused_space
);
203 /* Then write the Xing header */
204 rc
= rb
->write(fd
, xingbuf
, framelen
);
213 /* If not, insert some space. If there is an ID3 tag in the
214 file we only insert just enough to squeeze the Xing header
215 in. If not, we insert an additional empty ID3 tag of 4K. */
219 /* Nasty trick alert! The insert_data_in_file() function
220 uses the MP3 buffer when copying the data. We assume
221 that the ID3 tag isn't longer than 1MB so the xing
222 buffer won't be overwritten. */
224 if(entry
.first_frame_offset
) {
225 DEBUGF("Inserting %d bytes\n", framelen
);
228 DEBUGF("Inserting 4096+%d bytes\n", framelen
);
229 numbytes
= 4096 + framelen
;
231 rb
->memset(audiobuf
+ 0x100000, 0, numbytes
);
233 /* Insert the ID3 header */
234 rb
->memcpy(audiobuf
+ 0x100000, empty_id3_header
,
235 sizeof(empty_id3_header
));
238 /* Copy the Xing header */
239 rb
->memcpy(audiobuf
+ 0x100000 + numbytes
- framelen
,
242 rc
= insert_data_in_file(selected_file
,
243 entry
.first_frame_offset
,
244 audiobuf
+ 0x100000, numbytes
);
257 DEBUGF("Not a VBR file\n");
258 rb
->splash(HZ
*2, "Not a VBR file");
264 enum plugin_status
plugin_start(struct plugin_api
* api
, void *parameter
)
271 audiobuf
= rb
->plugin_get_audio_buffer((size_t *)&audiobuflen
);
273 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
279 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
280 rb
->cpu_boost(false);