summaryrefslogtreecommitdiff
path: root/apps
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
parent5fc1b64ae051e454d2b3bf3a20be5d88937e55e7 (diff)
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')
-rw-r--r--apps/plugin.c16
-rw-r--r--apps/plugin.h20
-rw-r--r--apps/plugins/Makefile2
-rw-r--r--apps/plugins/vbrfix.c280
-rw-r--r--apps/plugins/viewers.config1
5 files changed, 312 insertions, 7 deletions
diff --git a/apps/plugin.c b/apps/plugin.c
index c7758afbcf..8d8d25fc99 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <atoi.h>
#include <timefuncs.h>
+#include "debug.h"
#include "button.h"
#include "lcd.h"
#include "dir.h"
@@ -39,6 +40,7 @@
#include "backlight.h"
#include "ata.h"
#include "talk.h"
+#include "mp3data.h"
#ifdef HAVE_LCD_BITMAP
#include "widgets.h"
@@ -48,11 +50,10 @@
#include <debug.h>
#ifdef WIN32
#include "plugin-win32.h"
- #define PREFIX(_x_) _x_
#else
#include <dlfcn.h>
- #define PREFIX(_x_) x11_ ## _x_
#endif
+ #define PREFIX(_x_) sim_ ## _x_
#else
#define PREFIX(_x_) _x_
#endif
@@ -213,6 +214,12 @@ static struct plugin_api rockbox_api = {
#ifdef HAVE_LCD_BITMAP
font_get,
#endif
+#if defined(DEBUG) || defined(SIMULATOR)
+ debugf,
+#endif
+ mp3info,
+ count_mp3_frames,
+ create_xing_header,
};
int plugin_load(char* plugin, void* parameter)
@@ -246,11 +253,8 @@ int plugin_load(char* plugin, void* parameter)
lcd_clear_display();
#endif
#ifdef SIMULATOR
-#ifdef WIN32
- snprintf(path, sizeof path, "%s", plugin);
-#else
snprintf(path, sizeof path, "archos%s", plugin);
-#endif
+
pd = dlopen(path, RTLD_NOW);
if (!pd) {
snprintf(buf, sizeof buf, "Can't open %s", plugin);
diff --git a/apps/plugin.h b/apps/plugin.h
index f539c3ef3a..c67f49ebda 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -45,6 +45,16 @@
#include "settings.h"
#include "thread.h"
+#ifdef PLUGIN
+#if defined(DEBUG) || defined(SIMULATOR)
+#define DEBUGF rb->debugf
+#define LDEBUGF rb->debugf
+#else
+#define DEBUGF(...)
+#define LDEBUGF(...)
+#endif
+#endif
+
/* increase this every time the api struct changes */
#define PLUGIN_API_VERSION 14
@@ -235,6 +245,16 @@ struct plugin_api {
#ifdef HAVE_LCD_BITMAP
struct font* (*font_get)(int font);
#endif
+#if defined(DEBUG) || defined(SIMULATOR)
+ void (*debugf)(char *fmt, ...);
+#endif
+ bool (*mp3info)(struct mp3entry *entry, char *filename) ;
+ int (*count_mp3_frames)(int fd, int startpos, int filesize,
+ void (*progressfunc)(int));
+ int (*create_xing_header)(int fd, int startpos, int filesize,
+ unsigned char *buf, int num_frames,
+ unsigned long header_template,
+ void (*progressfunc)(int), bool generate_toc);
};
/* defined by the plugin loader (plugin.c) */
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
INCLUDES = -I$(FIRMWARE)/include -I$(FIRMWARE)/export -I$(FIRMWARE)/common \
-I$(FIRMWARE)/drivers -I.. -Ilib
CFLAGS = -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes \
-$(INCLUDES) $(TARGET) $(EXTRA_DEFINES) -DMEM=${MEM}
+$(INCLUDES) $(TARGET) $(EXTRA_DEFINES) -DMEM=${MEM} -DPLUGIN
LDS := plugin.lds
LINKFILE := $(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 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2004 Linus Nielsen Feltzing
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "plugin.h"
+
+static struct plugin_api* rb;
+
+static char *mp3buf;
+static int mp3buflen;
+
+static void xingupdate(int percent)
+{
+ char buf[32];
+
+ rb->snprintf(buf, 32, "%d%%", percent);
+ rb->lcd_puts(0, 1, buf);
+#ifdef HAVE_LCD_BITMAP
+ rb->lcd_update();
+#endif
+}
+
+static int insert_data_in_file(char *fname, int fpos, char *buf, int num_bytes)
+{
+ int readlen;
+ int rc;
+ int orig_fd, fd;
+ char tmpname[MAX_PATH];
+
+ rb->snprintf(tmpname, MAX_PATH, "%s.tmp", fname);
+
+ orig_fd = rb->open(fname, O_RDONLY);
+ if(orig_fd < 0) {
+ return 10*orig_fd - 1;
+ }
+
+ fd = rb->creat(tmpname, O_WRONLY);
+ if(fd < 0) {
+ rb->close(orig_fd);
+ return 10*fd - 2;
+ }
+
+ /* First, copy the initial portion (the ID3 tag) */
+ if(fpos) {
+ readlen = rb->read(orig_fd, mp3buf, fpos);
+ if(readlen < 0) {
+ rb->close(fd);
+ rb->close(orig_fd);
+ return 10*readlen - 3;
+ }
+
+ rc = rb->write(fd, mp3buf, readlen);
+ if(rc < 0) {
+ rb->close(fd);
+ rb->close(orig_fd);
+ return 10*rc - 4;
+ }
+ }
+
+ /* Now insert the data into the file */
+ rc = rb->write(fd, buf, num_bytes);
+ if(rc < 0) {
+ rb->close(orig_fd);
+ rb->close(fd);
+ return 10*rc - 5;
+ }
+
+ /* Copy the file */
+ do {
+ readlen = rb->read(orig_fd, mp3buf, mp3buflen);
+ if(readlen < 0) {
+ rb->close(fd);
+ rb->close(orig_fd);
+ return 10*readlen - 7;
+ }
+
+ rc = rb->write(fd, mp3buf, readlen);
+ if(rc < 0) {
+ rb->close(fd);
+ rb->close(orig_fd);
+ return 10*rc - 8;
+ }
+ } while(readlen > 0);
+
+ rb->close(fd);
+ rb->close(orig_fd);
+
+ /* Remove the old file */
+ rc = rb->remove(fname);
+ if(rc < 0) {
+ return 10*rc - 9;
+ }
+
+ /* Replace the old file with the new */
+ rc = rb->rename(tmpname, fname);
+ if(rc < 0) {
+ return 10*rc - 9;
+ }
+
+ return 0;
+}
+
+static void fileerror(int rc)
+{
+ rb->splash(HZ*2, true, "File error: %d", rc);
+}
+
+static const unsigned char empty_id3_header[] =
+{
+ 'I', 'D', '3', 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x1f, 0x76 /* Size is 4096 minus 10 bytes for the header */
+};
+
+static bool vbr_fix(char *selected_file)
+{
+ unsigned char xingbuf[1500];
+ struct mp3entry entry;
+ int fd;
+ int rc;
+ int flen;
+ int num_frames;
+ int numbytes;
+ int framelen;
+ int unused_space;
+
+ rb->lcd_clear_display();
+ rb->lcd_puts_scroll(0, 0, selected_file);
+#ifdef HAVE_LCD_BITMAP
+ rb->lcd_update();
+#endif
+
+ xingupdate(0);
+
+ rc = rb->mp3info(&entry, selected_file);
+ if(rc < 0) {
+ fileerror(rc);
+ return true;
+ }
+
+ fd = rb->open(selected_file, O_RDWR);
+ if(fd < 0) {
+ fileerror(fd);
+ return true;
+ }
+
+ flen = rb->lseek(fd, 0, SEEK_END);
+
+ xingupdate(0);
+
+ num_frames = rb->count_mp3_frames(fd, entry.first_frame_offset,
+ flen, xingupdate);
+
+ if(num_frames) {
+ /* Note: We don't need to pass a template header because it will be
+ taken from the mpeg stream */
+ framelen = rb->create_xing_header(fd, entry.first_frame_offset,
+ flen, xingbuf, num_frames,
+ 0, xingupdate, true);
+
+ /* Try to fit the Xing header first in the stream. Replace the existing
+ VBR header if there is one, else see if there is room between the
+ ID3 tag and the first MP3 frame. */
+ if(entry.first_frame_offset - entry.id3v2len >=
+ (unsigned int)framelen) {
+ DEBUGF("Using existing space between ID3 and first frame\n");
+
+ /* Seek to the beginning of the unused space */
+ rc = rb->lseek(fd, entry.id3v2len, SEEK_SET);
+ if(rc < 0) {
+ rb->close(fd);
+ fileerror(rc);
+ return true;
+ }
+
+ unused_space =
+ entry.first_frame_offset - entry.id3v2len - framelen;
+
+ /* Fill the unused space with 0's (using the MP3 buffer)
+ and write it to the file */
+ if(unused_space)
+ {
+ rb->memset(mp3buf, 0, unused_space);
+ rc = rb->write(fd, mp3buf, unused_space);
+ if(rc < 0) {
+ rb->close(fd);
+ fileerror(rc);
+ return true;
+ }
+ }
+
+ /* Then write the Xing header */
+ rc = rb->write(fd, xingbuf, framelen);
+ if(rc < 0) {
+ rb->close(fd);
+ fileerror(rc);
+ return true;
+ }
+
+ rb->close(fd);
+ } else {
+ /* If not, insert some space. If there is an ID3 tag in the
+ file we only insert just enough to squeeze the Xing header
+ in. If not, we insert an additional empty ID3 tag of 4K. */
+
+ rb->close(fd);
+
+ /* Nasty trick alert! The insert_data_in_file() function
+ uses the MP3 buffer when copying the data. We assume
+ that the ID3 tag isn't longer than 1MB so the xing
+ buffer won't be overwritten. */
+
+ if(entry.first_frame_offset) {
+ DEBUGF("Inserting %d bytes\n", framelen);
+ numbytes = framelen;
+ } else {
+ DEBUGF("Inserting 4096+%d bytes\n", framelen);
+ numbytes = 4096 + framelen;
+
+ rb->memset(mp3buf + 0x100000, 0, numbytes);
+
+ /* Insert the ID3 header */
+ rb->memcpy(mp3buf + 0x100000, empty_id3_header,
+ sizeof(empty_id3_header));
+ }
+
+ /* Copy the Xing header */
+ rb->memcpy(mp3buf + 0x100000 + numbytes - framelen,
+ xingbuf, framelen);
+
+ rc = insert_data_in_file(selected_file,
+ entry.first_frame_offset,
+ mp3buf + 0x100000, numbytes);
+
+ if(rc < 0) {
+ fileerror(rc);
+ return true;
+ }
+ }
+
+ xingupdate(100);
+ }
+ else
+ {
+ /* Not a VBR file */
+ DEBUGF("Not a VBR file\n");
+ rb->splash(HZ*2, true, "Not a VBR file");
+ }
+
+ return false;
+}
+
+enum plugin_status plugin_start(struct plugin_api* api, void *parameter)
+{
+ TEST_PLUGIN_API(api);
+
+ rb = api;
+
+ if (!parameter)
+ return PLUGIN_ERROR;
+
+ mp3buf = rb->plugin_get_mp3_buffer(&mp3buflen);
+
+ vbr_fix(parameter);
+
+ return PLUGIN_OK;
+}
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
jpg,jpeg.rock,18 24 3C 3C 24 18
ucl,rockbox_flash.rock,2A 7F 41 41 7F 2A
rvf,video.rock,5D 7F 5D 7F 5D 7F
+mp3,vbrfix.rock,10 08 58 38 04 02