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 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(const 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
->splashf(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(const 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(const void *parameter
)
270 audiobuf
= rb
->plugin_get_audio_buffer((size_t *)&audiobuflen
);
272 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
278 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
279 rb
->cpu_boost(false);