summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2004-06-10 13:29:52 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2004-06-10 13:29:52 +0000
commita6142ab7ab58f69a3f1a034db4bdf1eff24d3dd6 (patch)
treeef00c3ec8074ccb080b221c7d1dd4b3d03c8fd87 /apps/plugins
parent5fc1b64ae051e454d2b3bf3a20be5d88937e55e7 (diff)
downloadrockbox-a6142ab7ab58f69a3f1a034db4bdf1eff24d3dd6.tar.gz
rockbox-a6142ab7ab58f69a3f1a034db4bdf1eff24d3dd6.zip
Finally, the archos directory sandbox works in the same way for both X11 and win32 simulators. Unfortunately, this breaks the VC++ compatibility. Also, the plugin API now supports DEBUGF. Last, but not least, we have a new plugin, vbrfix.rock.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4726 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/Makefile2
-rw-r--r--apps/plugins/vbrfix.c280
-rw-r--r--apps/plugins/viewers.config1
3 files changed, 282 insertions, 1 deletions
diff --git a/apps/plugins/Makefile b/apps/plugins/Makefile
index 367103be67..1c703f2573 100644
--- a/apps/plugins/Makefile
+++ b/apps/plugins/Makefile
@@ -15,7 +15,7 @@ FIRMWARE = ../../firmware
15INCLUDES = -I$(FIRMWARE)/include -I$(FIRMWARE)/export -I$(FIRMWARE)/common \ 15INCLUDES = -I$(FIRMWARE)/include -I$(FIRMWARE)/export -I$(FIRMWARE)/common \
16-I$(FIRMWARE)/drivers -I.. -Ilib 16-I$(FIRMWARE)/drivers -I.. -Ilib
17CFLAGS = -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes \ 17CFLAGS = -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes \
18$(INCLUDES) $(TARGET) $(EXTRA_DEFINES) -DMEM=${MEM} 18$(INCLUDES) $(TARGET) $(EXTRA_DEFINES) -DMEM=${MEM} -DPLUGIN
19 19
20LDS := plugin.lds 20LDS := plugin.lds
21LINKFILE := $(OBJDIR)/pluginlink.lds 21LINKFILE := $(OBJDIR)/pluginlink.lds
diff --git a/apps/plugins/vbrfix.c b/apps/plugins/vbrfix.c
new file mode 100644
index 0000000000..1beca2669d
--- /dev/null
+++ b/apps/plugins/vbrfix.c
@@ -0,0 +1,280 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2004 Linus Nielsen Feltzing
11 *
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.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "plugin.h"
20
21static struct plugin_api* rb;
22
23static char *mp3buf;
24static int mp3buflen;
25
26static void xingupdate(int percent)
27{
28 char buf[32];
29
30 rb->snprintf(buf, 32, "%d%%", percent);
31 rb->lcd_puts(0, 1, buf);
32#ifdef HAVE_LCD_BITMAP
33 rb->lcd_update();
34#endif
35}
36
37static int insert_data_in_file(char *fname, int fpos, char *buf, int num_bytes)
38{
39 int readlen;
40 int rc;
41 int orig_fd, fd;
42 char tmpname[MAX_PATH];
43
44 rb->snprintf(tmpname, MAX_PATH, "%s.tmp", fname);
45
46 orig_fd = rb->open(fname, O_RDONLY);
47 if(orig_fd < 0) {
48 return 10*orig_fd - 1;
49 }
50
51 fd = rb->creat(tmpname, O_WRONLY);
52 if(fd < 0) {
53 rb->close(orig_fd);
54 return 10*fd - 2;
55 }
56
57 /* First, copy the initial portion (the ID3 tag) */
58 if(fpos) {
59 readlen = rb->read(orig_fd, mp3buf, fpos);
60 if(readlen < 0) {
61 rb->close(fd);
62 rb->close(orig_fd);
63 return 10*readlen - 3;
64 }
65
66 rc = rb->write(fd, mp3buf, readlen);
67 if(rc < 0) {
68 rb->close(fd);
69 rb->close(orig_fd);
70 return 10*rc - 4;
71 }
72 }
73
74 /* Now insert the data into the file */
75 rc = rb->write(fd, buf, num_bytes);
76 if(rc < 0) {
77 rb->close(orig_fd);
78 rb->close(fd);
79 return 10*rc - 5;
80 }
81
82 /* Copy the file */
83 do {
84 readlen = rb->read(orig_fd, mp3buf, mp3buflen);
85 if(readlen < 0) {
86 rb->close(fd);
87 rb->close(orig_fd);
88 return 10*readlen - 7;
89 }
90
91 rc = rb->write(fd, mp3buf, readlen);
92 if(rc < 0) {
93 rb->close(fd);
94 rb->close(orig_fd);
95 return 10*rc - 8;
96 }
97 } while(readlen > 0);
98
99 rb->close(fd);
100 rb->close(orig_fd);
101
102 /* Remove the old file */
103 rc = rb->remove(fname);
104 if(rc < 0) {
105 return 10*rc - 9;
106 }
107
108 /* Replace the old file with the new */
109 rc = rb->rename(tmpname, fname);
110 if(rc < 0) {
111 return 10*rc - 9;
112 }
113
114 return 0;
115}
116
117static void fileerror(int rc)
118{
119 rb->splash(HZ*2, true, "File error: %d", rc);
120}
121
122static const unsigned char empty_id3_header[] =
123{
124 'I', 'D', '3', 0x04, 0x00, 0x00,
125 0x00, 0x00, 0x1f, 0x76 /* Size is 4096 minus 10 bytes for the header */
126};
127
128static bool vbr_fix(char *selected_file)
129{
130 unsigned char xingbuf[1500];
131 struct mp3entry entry;
132 int fd;
133 int rc;
134 int flen;
135 int num_frames;
136 int numbytes;
137 int framelen;
138 int unused_space;
139
140 rb->lcd_clear_display();
141 rb->lcd_puts_scroll(0, 0, selected_file);
142#ifdef HAVE_LCD_BITMAP
143 rb->lcd_update();
144#endif
145
146 xingupdate(0);
147
148 rc = rb->mp3info(&entry, selected_file);
149 if(rc < 0) {
150 fileerror(rc);
151 return true;
152 }
153
154 fd = rb->open(selected_file, O_RDWR);
155 if(fd < 0) {
156 fileerror(fd);
157 return true;
158 }
159
160 flen = rb->lseek(fd, 0, SEEK_END);
161
162 xingupdate(0);
163
164 num_frames = rb->count_mp3_frames(fd, entry.first_frame_offset,
165 flen, xingupdate);
166
167 if(num_frames) {
168 /* Note: We don't need to pass a template header because it will be
169 taken from the mpeg stream */
170 framelen = rb->create_xing_header(fd, entry.first_frame_offset,
171 flen, xingbuf, num_frames,
172 0, xingupdate, true);
173
174 /* Try to fit the Xing header first in the stream. Replace the existing
175 VBR header if there is one, else see if there is room between the
176 ID3 tag and the first MP3 frame. */
177 if(entry.first_frame_offset - entry.id3v2len >=
178 (unsigned int)framelen) {
179 DEBUGF("Using existing space between ID3 and first frame\n");
180
181 /* Seek to the beginning of the unused space */
182 rc = rb->lseek(fd, entry.id3v2len, SEEK_SET);
183 if(rc < 0) {
184 rb->close(fd);
185 fileerror(rc);
186 return true;
187 }
188
189 unused_space =
190 entry.first_frame_offset - entry.id3v2len - framelen;
191
192 /* Fill the unused space with 0's (using the MP3 buffer)
193 and write it to the file */
194 if(unused_space)
195 {
196 rb->memset(mp3buf, 0, unused_space);
197 rc = rb->write(fd, mp3buf, unused_space);
198 if(rc < 0) {
199 rb->close(fd);
200 fileerror(rc);
201 return true;
202 }
203 }
204
205 /* Then write the Xing header */
206 rc = rb->write(fd, xingbuf, framelen);
207 if(rc < 0) {
208 rb->close(fd);
209 fileerror(rc);
210 return true;
211 }
212
213 rb->close(fd);
214 } else {
215 /* If not, insert some space. If there is an ID3 tag in the
216 file we only insert just enough to squeeze the Xing header
217 in. If not, we insert an additional empty ID3 tag of 4K. */
218
219 rb->close(fd);
220
221 /* Nasty trick alert! The insert_data_in_file() function
222 uses the MP3 buffer when copying the data. We assume
223 that the ID3 tag isn't longer than 1MB so the xing
224 buffer won't be overwritten. */
225
226 if(entry.first_frame_offset) {
227 DEBUGF("Inserting %d bytes\n", framelen);
228 numbytes = framelen;
229 } else {
230 DEBUGF("Inserting 4096+%d bytes\n", framelen);
231 numbytes = 4096 + framelen;
232
233 rb->memset(mp3buf + 0x100000, 0, numbytes);
234
235 /* Insert the ID3 header */
236 rb->memcpy(mp3buf + 0x100000, empty_id3_header,
237 sizeof(empty_id3_header));
238 }
239
240 /* Copy the Xing header */
241 rb->memcpy(mp3buf + 0x100000 + numbytes - framelen,
242 xingbuf, framelen);
243
244 rc = insert_data_in_file(selected_file,
245 entry.first_frame_offset,
246 mp3buf + 0x100000, numbytes);
247
248 if(rc < 0) {
249 fileerror(rc);
250 return true;
251 }
252 }
253
254 xingupdate(100);
255 }
256 else
257 {
258 /* Not a VBR file */
259 DEBUGF("Not a VBR file\n");
260 rb->splash(HZ*2, true, "Not a VBR file");
261 }
262
263 return false;
264}
265
266enum plugin_status plugin_start(struct plugin_api* api, void *parameter)
267{
268 TEST_PLUGIN_API(api);
269
270 rb = api;
271
272 if (!parameter)
273 return PLUGIN_ERROR;
274
275 mp3buf = rb->plugin_get_mp3_buffer(&mp3buflen);
276
277 vbr_fix(parameter);
278
279 return PLUGIN_OK;
280}
diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config
index ad1e696957..2acbe17af3 100644
--- a/apps/plugins/viewers.config
+++ b/apps/plugins/viewers.config
@@ -3,3 +3,4 @@ txt,viewer.rock,55 55 55 55 55 55
3jpg,jpeg.rock,18 24 3C 3C 24 18 3jpg,jpeg.rock,18 24 3C 3C 24 18
4ucl,rockbox_flash.rock,2A 7F 41 41 7F 2A 4ucl,rockbox_flash.rock,2A 7F 41 41 7F 2A
5rvf,video.rock,5D 7F 5D 7F 5D 7F 5rvf,video.rock,5D 7F 5D 7F 5D 7F
6mp3,vbrfix.rock,10 08 58 38 04 02