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
,
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,
167 0, xingupdate
, true);
169 /* Try to fit the Xing header first in the stream. Replace the existing
170 VBR header if there is one, else see if there is room between the
171 ID3 tag and the first MP3 frame. */
172 if(entry
.first_frame_offset
- entry
.id3v2len
>=
173 (unsigned int)framelen
) {
174 DEBUGF("Using existing space between ID3 and first frame\n");
176 /* Seek to the beginning of the unused space */
177 rc
= rb
->lseek(fd
, entry
.id3v2len
, SEEK_SET
);
185 entry
.first_frame_offset
- entry
.id3v2len
- framelen
;
187 /* Fill the unused space with 0's (using the MP3 buffer)
188 and write it to the file */
191 rb
->memset(audiobuf
, 0, unused_space
);
192 rc
= rb
->write(fd
, audiobuf
, unused_space
);
200 /* Then write the Xing header */
201 rc
= rb
->write(fd
, xingbuf
, framelen
);
210 /* If not, insert some space. If there is an ID3 tag in the
211 file we only insert just enough to squeeze the Xing header
212 in. If not, we insert an additional empty ID3 tag of 4K. */
216 /* Nasty trick alert! The insert_data_in_file() function
217 uses the MP3 buffer when copying the data. We assume
218 that the ID3 tag isn't longer than 1MB so the xing
219 buffer won't be overwritten. */
221 if(entry
.first_frame_offset
) {
222 DEBUGF("Inserting %d bytes\n", framelen
);
225 DEBUGF("Inserting 4096+%d bytes\n", framelen
);
226 numbytes
= 4096 + framelen
;
228 rb
->memset(audiobuf
+ 0x100000, 0, numbytes
);
230 /* Insert the ID3 header */
231 rb
->memcpy(audiobuf
+ 0x100000, empty_id3_header
,
232 sizeof(empty_id3_header
));
235 /* Copy the Xing header */
236 rb
->memcpy(audiobuf
+ 0x100000 + numbytes
- framelen
,
239 rc
= insert_data_in_file(selected_file
,
240 entry
.first_frame_offset
,
241 audiobuf
+ 0x100000, numbytes
);
254 DEBUGF("Not a VBR file\n");
255 rb
->splash(HZ
*2, "Not a VBR file");
261 enum plugin_status
plugin_start(const void *parameter
)
267 audiobuf
= rb
->plugin_get_audio_buffer(&audiobuflen
);
269 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
275 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
276 rb
->cpu_boost(false);