diff --git a/apps/misc.c b/apps/misc.c index d7a64b3..481dc2a 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -27,9 +27,7 @@ #ifdef __PCTOOL__ #include #include -#ifdef WPSEDITOR -#include "string.h" -#endif +#include #else #include "sprintf.h" #include "appevents.h" @@ -765,26 +763,6 @@ char* strrsplt(char* str, int c) return s; } -/* Test file existence, using dircache of possible */ -bool file_exists(const char *file) -{ - int fd; - - if (!file || strlen(file) <= 0) - return false; - -#ifdef HAVE_DIRCACHE - if (dircache_is_enabled()) - return (dircache_get_entry_ptr(file) != NULL); -#endif - - fd = open(file, O_RDONLY); - if (fd < 0) - return false; - close(fd); - return true; -} - bool dir_exists(const char *path) { DIR* d = opendir(path); @@ -838,6 +816,26 @@ char* skip_whitespace(char* const str) return s; } +/* Test file existence, using dircache of possible */ +bool file_exists(const char *file) +{ + int fd; + + if (!file || strlen(file) <= 0) + return false; + +#ifdef HAVE_DIRCACHE + if (dircache_is_enabled()) + return (dircache_get_entry_ptr(file) != NULL); +#endif + + fd = open(file, O_RDONLY); + if (fd < 0) + return false; + close(fd); + return true; +} + /* Format time into buf. * * buf - buffer to format to. diff --git a/apps/tagcache.c b/apps/tagcache.c old mode 100644 new mode 100755 index 84e8875..51a2590 --- a/apps/tagcache.c +++ b/apps/tagcache.c @@ -62,12 +62,9 @@ #include #include "config.h" #include "ata_idle_notify.h" -#include "thread.h" -#include "kernel.h" #include "system.h" #include "logf.h" #include "string.h" -#include "usb.h" #include "metadata.h" #include "metadata.h" #include "tagcache.h" @@ -82,11 +79,14 @@ #ifndef __PCTOOL__ #include "lang.h" #include "eeprom_settings.h" +#include "thread.h" +#include "kernel.h" +#include "usb.h" #endif #ifdef __PCTOOL__ #define yield() do { } while(0) -#define sim_sleep(timeout) do { } while(0) +#define sleep(timeout) do { } while(0) #define do_timed_yield() do { } while(0) #endif @@ -328,7 +328,7 @@ static int open_tag_fd(struct tagcache_header *hdr, int tag, bool write) snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, tag); - fd = open(buf, write ? O_RDWR : O_RDONLY); + fd = db_open(buf, write ? O_RDWR : O_RDONLY); if (fd < 0) { logf("tag file open failed: tag=%d write=%d file=%s", tag, write, buf); @@ -354,7 +354,7 @@ static int open_master_fd(struct master_header *hdr, bool write) int fd; int rc; - fd = open(TAGCACHE_FILE_MASTER, write ? O_RDWR : O_RDONLY); + fd = db_open(TAGCACHE_FILE_MASTER, write ? O_RDWR : O_RDONLY); if (fd < 0) { logf("master file open failed for R/W"); @@ -690,7 +690,7 @@ static bool open_files(struct tagcache_search *tcs, int tag) char fn[MAX_PATH]; snprintf(fn, sizeof fn, TAGCACHE_FILE_INDEX, tag); - tcs->idxfd[tag] = open(fn, O_RDONLY); + tcs->idxfd[tag] = db_open(fn, O_RDONLY); } if (tcs->idxfd[tag] < 0) @@ -1153,17 +1153,24 @@ static void remove_files(void) tc_stat.ready = false; tc_stat.ramcache = false; tc_stat.econ = false; - remove(TAGCACHE_FILE_MASTER); + db_remove(TAGCACHE_FILE_MASTER); for (i = 0; i < TAG_COUNT; i++) { if (tagcache_is_numeric_tag(i)) continue; snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, i); - remove(buf); + db_remove(buf); } } +#ifdef __PCTOOL__ +void tagcache_remove_database(void) +{ + remove_files(); + db_remove(TAGCACHE_FILE_TEMP); +} +#endif static bool check_all_headers(void) { @@ -1306,7 +1313,7 @@ bool tagcache_search_add_clause(struct tagcache_search *tcs, char buf[MAX_PATH]; snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, clause->tag); - tcs->idxfd[clause->tag] = open(buf, O_RDONLY); + tcs->idxfd[clause->tag] = db_open(buf, O_RDONLY); } tcs->clause[tcs->clause_count] = clause; @@ -2459,7 +2466,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd) * anything whether the index type is sorted or not. */ snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, index_type); - fd = open(buf, O_WRONLY | O_CREAT | O_TRUNC); + fd = db_open(buf, O_WRONLY | O_CREAT | O_TRUNC); if (fd < 0) { logf("%s open fail", buf); @@ -2481,12 +2488,12 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd) /* Loading the tag lookup file as "master file". */ logf("Loading index file"); - masterfd = open(TAGCACHE_FILE_MASTER, O_RDWR); + masterfd = db_open(TAGCACHE_FILE_MASTER, O_RDWR); if (masterfd < 0) { logf("Creating new DB"); - masterfd = open(TAGCACHE_FILE_MASTER, O_WRONLY | O_CREAT | O_TRUNC); + masterfd = db_open(TAGCACHE_FILE_MASTER, O_WRONLY | O_CREAT | O_TRUNC); if (masterfd < 0) { @@ -2804,7 +2811,7 @@ static bool commit(void) while (write_lock) sleep(1); - tmpfd = open(TAGCACHE_FILE_TEMP, O_RDONLY); + tmpfd = db_open(TAGCACHE_FILE_TEMP, O_RDONLY); if (tmpfd < 0) { logf("nothing to commit"); @@ -2820,7 +2827,7 @@ static bool commit(void) { logf("incorrect header"); close(tmpfd); - remove(TAGCACHE_FILE_TEMP); + db_remove(TAGCACHE_FILE_TEMP); return false; } @@ -2828,7 +2835,7 @@ static bool commit(void) { logf("nothing to commit"); close(tmpfd); - remove(TAGCACHE_FILE_TEMP); + db_remove(TAGCACHE_FILE_TEMP); return true; } @@ -2923,7 +2930,7 @@ static bool commit(void) } close(tmpfd); - remove(TAGCACHE_FILE_TEMP); + db_remove(TAGCACHE_FILE_TEMP); tc_stat.commit_step = 0; @@ -3019,6 +3026,7 @@ static bool modify_numeric_entry(int masterfd, int idx_id, int tag, long data) return write_index(masterfd, idx_id, &idx); } +#endif #if 0 bool tagcache_modify_numeric_entry(struct tagcache_search *tcs, @@ -3036,6 +3044,7 @@ bool tagcache_modify_numeric_entry(struct tagcache_search *tcs, } #endif +#ifndef __PCTOOL__ #define COMMAND_QUEUE_IS_EMPTY (command_queue_ridx == command_queue_widx) static bool command_queue_is_full(void) @@ -3161,7 +3170,6 @@ void tagcache_update_numeric(int idx_id, int tag, long data) { queue_command(CMD_UPDATE_NUMERIC, idx_id, tag, data); } -#endif /* !__PCTOOL__ */ long tagcache_get_serial(void) { @@ -3172,6 +3180,7 @@ long tagcache_get_commitid(void) { return current_tcmh.commitid; } +#endif /* !__PCTOOL__ */ static bool write_tag(int fd, const char *tagstr, const char *datastr) { @@ -3820,7 +3829,7 @@ static bool load_tagcache(void) logf("loading tagcache to ram..."); - fd = open(TAGCACHE_FILE_MASTER, O_RDONLY); + fd = db_open(TAGCACHE_FILE_MASTER, O_RDONLY); if (fd < 0) { logf("tagcache open failed"); @@ -4035,7 +4044,7 @@ static bool check_deleted_files(void) logf("reverse scan..."); snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, tag_filename); - fd = open(buf, O_RDONLY); + fd = db_open(buf, O_RDONLY); if (fd < 0) { @@ -4194,7 +4203,7 @@ void tagcache_build(const char *path) logf("updating tagcache"); - cachefd = open(TAGCACHE_FILE_TEMP, O_RDONLY); + cachefd = db_open(TAGCACHE_FILE_TEMP, O_RDONLY); if (cachefd >= 0) { logf("skipping, cache already waiting for commit"); @@ -4202,7 +4211,7 @@ void tagcache_build(const char *path) return ; } - cachefd = open(TAGCACHE_FILE_TEMP, O_RDWR | O_CREAT | O_TRUNC); + cachefd = db_open(TAGCACHE_FILE_TEMP, O_RDWR | O_CREAT | O_TRUNC); if (cachefd < 0) { logf("master file open failed: %s", TAGCACHE_FILE_TEMP); @@ -4210,9 +4219,9 @@ void tagcache_build(const char *path) } filenametag_fd = open_tag_fd(&header, tag_filename, false); - +#ifndef __PCTOOL__ cpu_boost(true); - +#endif logf("Scanning files..."); /* Scan for new files. */ memset(&header, 0, sizeof(struct tagcache_header)); @@ -4239,7 +4248,9 @@ void tagcache_build(const char *path) if (!ret) { logf("Aborted."); +#ifndef __PCTOOL__ cpu_boost(false); +#endif return ; } @@ -4249,7 +4260,7 @@ void tagcache_build(const char *path) #endif if (commit()) { - remove(TAGCACHE_FILE_TEMP); + db_remove(TAGCACHE_FILE_TEMP); logf("tagcache built!"); } #ifdef __PCTOOL__ @@ -4265,7 +4276,9 @@ void tagcache_build(const char *path) } #endif +#ifndef __PCTOOL__ cpu_boost(false); +#endif } #ifdef HAVE_TC_RAMCACHE @@ -4274,7 +4287,9 @@ static void load_ramcache(void) if (!hdr) return ; +#ifndef __PCTOOL__ cpu_boost(true); +#endif /* At first we should load the cache (if exists). */ tc_stat.ramcache = load_tagcache(); @@ -4287,7 +4302,9 @@ static void load_ramcache(void) hdr = NULL; } +#ifndef __PCTOOL__ cpu_boost(false); +#endif } void tagcache_unload_ramcache(void) @@ -4346,7 +4363,7 @@ static void tagcache_thread(void) case Q_REBUILD: remove_files(); - remove(TAGCACHE_FILE_TEMP); + db_remove(TAGCACHE_FILE_TEMP); tagcache_build("/"); break; diff --git a/apps/tagcache.h b/apps/tagcache.h old mode 100644 new mode 100755 index e995784..831df6c --- a/apps/tagcache.h +++ b/apps/tagcache.h @@ -179,6 +179,7 @@ void tagcache_build(const char *path); #ifdef __PCTOOL__ void tagcache_reverse_scan(void); +void tagcache_remove_database(void); #endif const char* tagcache_tag_to_str(int tag); @@ -231,4 +232,13 @@ bool tagcache_update(void); bool tagcache_rebuild(void); int tagcache_get_max_commit_step(void); #endif + +#ifdef __PCTOOL__ +extern int db_open(const char *name, int o); +extern int db_remove(const char *name); +#else +#define db_open(x,y) open(x,y) +#define db_remove(x) remove(x) +#endif + #endif diff --git a/firmware/common/unicode.c b/firmware/common/unicode.c index 61989e5..4764c9a 100644 --- a/firmware/common/unicode.c +++ b/firmware/common/unicode.c @@ -30,21 +30,24 @@ #include "file.h" #include "debug.h" #include "rbunicode.h" -#include "config.h" #ifndef O_BINARY #define O_BINARY 0 #endif +#ifndef CODEPAGE_FILES_IS_NOT_USED #define CODEPAGE_DIR ROCKBOX_DIR"/codepages" +#endif + static int default_codepage = 0; static int loaded_cp_table = 0; -#ifdef HAVE_LCD_BITMAP +#if defined(HAVE_LCD_BITMAP) || defined(__PCTOOL__) #define MAX_CP_TABLE_SIZE 32768 #define NUM_TABLES 5 +#ifndef CODEPAGE_FILES_IS_NOT_USED static const char *filename[NUM_TABLES] = { CODEPAGE_DIR"/iso.cp", @@ -53,6 +56,7 @@ static const char *filename[NUM_TABLES] = CODEPAGE_DIR"/949.cp", /* KSX1001 */ CODEPAGE_DIR"/950.cp" /* BIG5 */ }; +#endif static const char cp_2_table[NUM_CODEPAGES] = { @@ -83,9 +87,11 @@ static const char *name_codepages[NUM_CODEPAGES+1] = #define MAX_CP_TABLE_SIZE 640 #define NUM_TABLES 1 +#ifndef CODEPAGE_FILES_IS_NOT_USED static const char *filename[NUM_TABLES] = { CODEPAGE_DIR"/isomini.cp" }; +#endif static const char cp_2_table[NUM_CODEPAGES] = { @@ -118,12 +124,15 @@ static int load_cp_table(int cp) { int i=0; int table = cp_2_table[cp]; - int file, tablesize; - unsigned char tmp[2]; + int tablesize; if (table == 0 || table == loaded_cp_table) return 1; +#ifndef CODEPAGE_FILES_IS_NOT_USED + int file; + unsigned char tmp[2]; + file = open(filename[table-1], O_RDONLY|O_BINARY); if (file < 0) { @@ -148,9 +157,15 @@ static int load_cp_table(int cp) } codepage_table[i++] = (tmp[1] << 8) | tmp[0]; } + close(file); +#else + const unsigned short *uni_table = get_codepage_table(cp, &tablesize); + + for (i = 0; i < tablesize; i++) + codepage_table[i] = uni_table[i]; +#endif loaded_cp_table = table; - close(file); return 1; } @@ -194,7 +209,7 @@ unsigned char* iso_decode(const unsigned char *iso, unsigned char *utf8, case ISO_8859_9: /* Turkish */ case ISO_8859_2: /* Latin Extended */ case WIN_1250: /* Central European */ -#ifdef HAVE_LCD_BITMAP +#if defined(HAVE_LCD_BITMAP) || defined(__PCTOOL__) case ISO_8859_8: /* Hebrew */ case ISO_8859_11: /* Thai */ case WIN_1256: /* Arabic */ @@ -203,7 +218,7 @@ unsigned char* iso_decode(const unsigned char *iso, unsigned char *utf8, ucs = codepage_table[tmp]; break; -#ifdef HAVE_LCD_BITMAP +#if defined(HAVE_LCD_BITMAP) || defined(__PCTOOL__) case SJIS: /* Japanese */ if (*iso > 0xA0 && *iso < 0xE0) { tmp = *iso++ | (0xA100 - 0x8000); diff --git a/firmware/export/config.h b/firmware/export/config.h index 17b3c1c..18c081a 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -368,6 +368,14 @@ Lyre prototype 1*/ /* no known platform */ #endif +#ifdef __PCTOOL__ +/* + * config-pctool.h is not included in the Rockbox source tree. + * It is necessary to prepare each application. + */ +#include "config-pctool.h" +#endif + /* setup basic macros from capability masks */ #include "config_caps.h" diff --git a/firmware/export/system.h b/firmware/export/system.h old mode 100644 new mode 100755 index b44600d..54f53ef --- a/firmware/export/system.h +++ b/firmware/export/system.h @@ -24,7 +24,11 @@ #include "cpu.h" #include "stdbool.h" +#ifndef THREAD_IS_NOT_USED #include "kernel.h" +#else +#include +#endif extern void system_reboot (void); /* Called from any UIE handler and panicf - wait for a key and return @@ -228,9 +232,9 @@ enum { MAXMEMGUARD }; -#ifndef SIMULATOR +#if !defined(SIMULATOR) && !defined(__PCTOOL__) #include "system-target.h" -#else /* SIMULATOR */ +#else /* SIMULATOR and __PCTOOL__ */ static inline uint16_t swap16(uint16_t value) /* @@ -264,7 +268,7 @@ static inline uint32_t swap_odd_even32(uint32_t value) return (t >> 8) | ((t ^ value) << 8); } -#endif /* !SIMULATOR */ +#endif /* !SIMULATOR and __PCTOOL__ */ /* Declare this as HIGHEST_IRQ_LEVEL if they don't differ */ #ifndef DISABLE_INTERRUPTS diff --git a/firmware/export/thread.h b/firmware/export/thread.h index 7fe128d..bd8f4ae 100644 --- a/firmware/export/thread.h +++ b/firmware/export/thread.h @@ -78,7 +78,7 @@ #define DEFAULT_STACK_SIZE 0x400 /* Bytes */ -#ifndef SIMULATOR +#if !defined(SIMULATOR) && !defined(__PCTOOL__) /* Need to keep structures inside the header file because debug_menu * needs them. */ #ifdef CPU_COLDFIRE @@ -122,7 +122,7 @@ struct regs void *s; /* Semaphore for blocking and wakeup */ void (*start)(void); /* Start function */ }; -#endif /* !SIMULATOR */ +#endif /* !SIMULATOR and __PCTOOL__ */ /* NOTE: The use of the word "queue" may also refer to a linked list of threads being maintained that are normally dealt with in FIFO order diff --git a/firmware/include/_ansi.h b/firmware/include/_ansi.h index 0002816..52c16e5 100644 --- a/firmware/include/_ansi.h +++ b/firmware/include/_ansi.h @@ -9,8 +9,8 @@ "comment out" the non-ANSI parts of the ANSI header files (non-ANSI header files aren't affected). */ -#ifndef _ANSIDECL_H_ -#define _ANSIDECL_H_ +#ifndef _ANSI_DECL_H_ +#define _ANSI_DECL_H_ /* First try to figure out whether we really are in an ANSI C environment. */ /* FIXME: This probably needs some work. Perhaps sys/config.h can be @@ -75,4 +75,4 @@ #define ATTRIBUTE_PRINTF(fmt, arg1) _ATTRIBUTE( ( format( printf, fmt, arg1 ) ) ) #define ATTRIBUTE_SCANF(fmt, arg1) _ATTRIBUTE( ( format( scanf, fmt, arg1 ) ) ) -#endif /* _ANSIDECL_H_ */ +#endif /* _ANSI_DECL_H_ */ diff --git a/firmware/include/dir_uncached.h b/firmware/include/dir_uncached.h index e198833..9c5302f 100644 --- a/firmware/include/dir_uncached.h +++ b/firmware/include/dir_uncached.h @@ -32,7 +32,7 @@ #define ATTR_ARCHIVE 0x20 #define ATTR_VOLUME 0x40 /* this is a volume, not a real directory */ -#ifdef SIMULATOR +#if defined(SIMULATOR) || defined(__PCTOOL__) #define dirent_uncached sim_dirent #define DIR_UNCACHED SIM_DIR #define opendir_uncached sim_opendir @@ -57,7 +57,7 @@ struct dirent_uncached { #include "fat.h" typedef struct { -#ifndef SIMULATOR +#if !defined(SIMULATOR) && !defined(__PCTOOL__) bool busy; long startcluster; struct fat_dir fatdir; diff --git a/firmware/include/file.h b/firmware/include/file.h index 9a9548f..f46f51c 100644 --- a/firmware/include/file.h +++ b/firmware/include/file.h @@ -48,7 +48,7 @@ #define O_TRUNC 0x10 #endif -#if defined(SIMULATOR) && !defined(PLUGIN) && !defined(CODEC) +#if (defined(SIMULATOR) && !defined(PLUGIN) && !defined(CODEC)) || defined(__PCTOOL__) #define open(x,y) sim_open(x,y) #define creat(x) sim_creat(x) #define remove(x) sim_remove(x) diff --git a/firmware/include/rbunicode.h b/firmware/include/rbunicode.h index 39fe253..621c468 100644 --- a/firmware/include/rbunicode.h +++ b/firmware/include/rbunicode.h @@ -28,14 +28,12 @@ #ifndef _RBUNICODE_H_ #define _RBUNICODE_H_ -#ifndef __PCTOOL__ #include "config.h" -#endif #define MASK 0xC0 /* 11000000 */ #define COMP 0x80 /* 10x */ -#ifdef HAVE_LCD_BITMAP +#if defined(HAVE_LCD_BITMAP) || defined(__PCTOOL__) enum codepages { ISO_8859_1 = 0, ISO_8859_7, ISO_8859_8, WIN_1251, @@ -62,4 +60,7 @@ const unsigned char* utf8decode(const unsigned char *utf8, unsigned short *ucs); void set_codepage(int cp); int utf8seek(const unsigned char* utf8, int offset); const char* get_codepage_name(int cp); +#ifdef CODEPAGE_FILES_IS_NOT_USED +extern const unsigned short *get_codepage_table(int cp, int *tablesize); +#endif #endif /* _RBUNICODE_H_ */ diff --git a/firmware/include/stdio.h b/firmware/include/stdio.h index 968bd59..6c315ef 100644 --- a/firmware/include/stdio.h +++ b/firmware/include/stdio.h @@ -45,4 +45,8 @@ int vfprintf(FILE *stream, const char *format, __VALIST ap); #endif #endif +#ifdef __PCTOOL__ +extern int printf(const char *format, __VALIST ap); +#endif + #endif /* _STDIO_H_ */ diff --git a/tools/database/Makefile b/tools/database/Makefile index 2c20bb7..e2d8125 100644 --- a/tools/database/Makefile +++ b/tools/database/Makefile @@ -1,42 +1,140 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id$ +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# ifndef V -SILENT = @ +SILENT:=@ endif -INCLUDE = -I../../firmware/export \ - -I../../apps -I../../uisimulator/sdl -I/usr/include/SDL -FIRMINC = -I../../firmware/include -fno-builtin -DEFINES = -D__PCTOOL__ -DHAVE_TAGCACHE -DSIMULATOR -DCONFIG_CODEC=1 \ - -DROCKBOX_LITTLE_ENDIAN -DROCKBOX_DIR=\".rockbox\" -DROCKBOX_HAS_LOGF \ - -DCONFIG_CODEC=1 -CFLAGS = -g $(INCLUDE) $(DEFINES) -Wno-pointer-sign +CC:=gcc +MAKE:=make +RM:=rm +AR:=ar -SRC = database.o tagcache.o replaygain.o \ - metadata.o metadata_common.o mp3data.o \ - a52.o mp3.o adx.o mp4.o aiff.o mpc.o ape.o ogg.o \ - asap.o sid.o asf.o spc.o flac.o vorbis.o wave.o \ - mod.o wavpack.o monkeys.o \ - logf.o unicode.o ctype.o structec.o crc32.o io.o misc.o +ifneq "$(MAKECMDGOALS)" "clean" + VERSION:=$(shell ../../tools/version.sh ../../) + BUILDDATE:=$(shell date -u +'-DYEAR=%Y -DMONTH=%m -DDAY=%d') +endif + +GCC_VER := $(shell $(CC) -dumpversion | sed -e 's/\..*//') + +GCCOPTS := -O -W -Wall -fno-builtin +DEBUG := -g +DEFINES := -D__PCTOOL__ +INCLUDES := -I. -I../../apps -I../../apps/metadata -I../../firmware/export +FIRMINC := -I../../firmware/include +LIBS := -lsdb + +ifeq ($(findstring CYGWIN,$(shell uname)),CYGWIN) + ifneq "$(GCC_VER)" "4" + GCCOPTS += -mno-cygwin + endif +else + ifneq ($(findstring MINGW,$(shell uname)),MINGW) + LIBS += -ldl + endif +endif +ifeq "$(GCC_VER)" "4" + GCCOPTS += -Wno-pointer-sign +endif + +# set the endian of the build environment +ifdef ROCKBOX_BUILD_ENDIAN + DEFINES += -D$(ROCKBOX_BUILD_ENDIAN) +else + # checked the endian of the build environment. + # It is necessary to install perl. + # Please execute make after exporting ROCKBOX_BUILD_ENDIAN=ROCKBOX_BIG_ENDIAN + # or ROCKBOX_BUILD_ENDIAN=ROCKBOX_LITTLE_ENDIAN when you make database tool + # in the environment in which perl is not installed. + ENDIAN := $(shell perl -e 'print unpack("I*", "\x00\x00\x00\x01")') + ifeq "$(ENDIAN)" "1" + DEFINES += -DROCKBOX_BIG_ENDIAN + else + DEFINES += -DROCKBOX_LITTLE_ENDIAN + endif +endif + +APP_CFLAGS := $(GCCOPTS) $(DEBUG) -DAPP_VERSION=\"$(VERSION)\" $(BUILDDATE) -I. -L. +SIM_CFLAGS := $(GCCOPTS) $(DEBUG) $(DEFINES) $(INCLUDES) +LIB_CFLAGS := $(GCCOPTS) $(DEBUG) $(DEFINES) $(INCLUDES) $(FIRMINC) -OBJ = $(SRC:.c=.o) +.PHONY: all clean +all: database -# source code search path -VPATH = ../../apps ../../apps/metadata ../../firmware/common ../../firmware/ \ - ../../uisimulator/common +APP_SRCS := codepage.c dbfile.c file.c database.c +SIM_SRCS := ../../uisimulator/common/io.c +LIB_SRCS := ../../firmware/common/crc32.c \ +../../firmware/common/ctype.c \ +../../firmware/common/errno.c \ +../../firmware/common/strcasestr.c \ +../../firmware/common/structec.c \ +../../firmware/common/unicode.c \ +../../apps/metadata.c \ +../../apps/misc.c \ +../../apps/mp3data.c \ +../../apps/replaygain.c \ +../../apps/tagcache.c \ +../../tools/codepage_tables.c -TARGET= database +# append metadata files +LIB_SRCS += $(wildcard ../../apps/metadata/*.c) -all: $(TARGET) +APP_OBJS := $(patsubst %.c,%.o, $(notdir $(APP_SRCS))) +SIM_OBJS := $(patsubst %.c,%.o, $(notdir $(SIM_SRCS))) +LIB_OBJS := $(patsubst %.c,%.o, $(notdir $(LIB_SRCS))) -%.o : ../../uisimulator/common/%.c +DEPFILE = database.d + +$(DEPFILE): $(SRCS) + $(SILENT)(for each in $(APP_SRCS); do \ + obj=`echo $$each | sed -e 's/\.c/.o/' -e 's/^.*\///'`; \ + $(CC) -MG -MM -MT "$$obj" $(APP_CFLAGS) $$each 2>/dev/null; \ + done) >> $(DEPFILE) + $(SILENT)(for each in $(SIM_SRCS); do \ + obj=`echo $$each | sed -e 's/\.c/.o/' -e 's/^.*\///'`; \ + $(CC) -MG -MM -MT "$$obj" $(SIM_CFLAGS) $$each 2>/dev/null; \ + done) >> $(DEPFILE) + $(SILENT)(for each in $(LIB_SRCS); do \ + obj=`echo $$each | sed -e 's/\.c/.o/' -e 's/^.*\///'`; \ + $(CC) -MG -MM -MT "$$obj" $(LIB_CFLAGS) $$each 2>/dev/null; \ + done) >> $(DEPFILE) + + +database: libsdb.a $(APP_OBJS) + @echo LD database + $(SILENT)$(CC) $(APP_CFLAGS) -o $@ $(APP_OBJS) $(LIBS) + +libsdb.a: $(SIM_OBJS) $(LIB_OBJS) + @echo AR libsdb.a + $(SILENT)$(AR) ruv $@ $+ > /dev/null 2>&1 + +$(APP_OBJS):%.o: $(shell grep %.c $(APP_SRCS)) @echo CC $( ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 Yoshihisa Uchida + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ #include -#include "tagcache.h" +#include +#include "database.h" -int main(int argc, char **argv) +/* Rockbox functions */ + +/* implemented by firmware/common/unicode.c */ +extern void set_codepage(int cp); + +/* implemented by apps/tagcache.c */ +extern void tagcache_build(const char *path); +extern void tagcache_init(void); +extern void tagcache_remove_database(void); +extern void tagcache_reverse_scan(void); + +#define DEFAULT_ROCKBOX_DIRECTORY "/.rockbox" + +const char *sim_root_dir = NULL; +const char *sim_rockbox_dir = DEFAULT_ROCKBOX_DIRECTORY; + + +#define DB_MODE_CREATE_STR "create" +#define DB_MODE_UPDATE_STR "update" +#define DB_MODE_APPEND_STR "append" + +enum {DB_MODE_CREATE, DB_MODE_UPDATE, DB_MODE_APPEND}; + +const unsigned char *usage_messages[] = { - tagcache_init(); - tagcache_build("."); - tagcache_reverse_scan(); - - return 0; -} + "Usage: database -r|--root-path \n", + " -m|--mode \n", + " [-s|--song-directory ]\n", + " [-c|--codepage ]\n", + " [-i|--input-path ]\n", + " [-o|--output-path ]\n", + " [-h|--help]\n", + " [-V|--version]\n", + "\n", + "Options\n", + " -r|--root-path \n", + " Rockbox root path.\n", + " -m|--mode \n", + " create: build database newly.\n", + " update: update database.\n", + " append: append non registered files.\n", + " -s|--song-directory \n", + " song storage directory.\n", + " -c|--codepage \n", + " metadata codepage\n", + " -i|--input-path \n", + " database input path\n", + " -o|--output-path \n", + " database output path\n", + " -h|--help\n", + " show this help message and exit.\n", + " -V|--version\n", + " show version information and exit.\n", + NULL, +}; + +struct database_params +{ + int mode; + char rootdir[MAX_PATH]; + char songdir[MAX_PATH]; + int cp; + char db_input_path[MAX_PATH]; + char db_output_path[MAX_PATH]; + bool is_show_usage; + bool is_show_version; +}; + +static struct database_params param; -/* stub to avoid including all of apps/misc.c */ -bool file_exists(const char *file) +static void show_usage(void) { - if (!stat(file)) - return true; - return false; + int i; + + for (i = 0; usage_messages[i] != NULL; i++) + fprintf(stdout, usage_messages[i]); + return; } -/* stubs to avoid including thread-sdl.c */ -#include "kernel.h" -void mutex_init(struct mutex *m) +static void show_version(void) { - (void)m; -} + fprintf(stdout, "database tool version %s\n", APP_VERSION); + fprintf(stdout, "Copyright (C) 2009 The Rockbox Team., Yoshihisa Uchida\n"); + fprintf(stdout, "Released under the GNU General Public License v2+\n"); + return; +} -void mutex_lock(struct mutex *m) +static bool check_opt(const char *arg, const char *short_opt, const char *long_opt) { - (void)m; -} + return (strcmp(arg, short_opt) == 0) || (strcmp(arg, long_opt) == 0); +} -void mutex_unlock(struct mutex *m) +static bool check_path(int argc, char **argv, int idx, const char *opt_name, + char *value) { - (void)m; -} + if ((idx == argc-1) || (argv[idx+1][0] == '-')) + return false; -void thread_sdl_thread_lock(void *me) + if (strlen(argv[idx+1]) >= MAX_PATH) + { + fprintf(stderr, "%s is too long.\n", opt_name); + param.is_show_usage = false; + return false; + } + strcpy(value, argv[idx+1]); + return true; +} + +static bool get_params(int argc, char **argv) { - (void)me; -} + int idx = 0; + + param.mode = -1; + param.rootdir[0] = '\0'; + strcpy(param.songdir, "/"); + param.cp = 0; /* ISO-8859-1 */ + param.db_input_path[0] = '\0'; + param.db_output_path[0] = '\0'; + param.is_show_usage = true; + param.is_show_version = false; -void * thread_sdl_thread_unlock(void) + for (idx = 1; idx < argc; idx++) + { + if (check_opt(argv[idx], "-h", "--help")) + return true; + else if (check_opt(argv[idx], "-V", "--version")) + { + param.is_show_version = true; + return true; + } + else if (check_opt(argv[idx], "-r", "--root-path")) + { + if (!check_path(argc, argv, idx++, "root path", param.rootdir)) + return false; + } + else if (check_opt(argv[idx], "-s", "--song-directory")) + { + if (!check_path(argc, argv, idx++, "song storage directory", + param.songdir)) + return false; + } + else if (check_opt(argv[idx], "-m", "--mode")) + { + if (idx == argc-1) + return false; + + idx++; + if (strcmp(argv[idx],DB_MODE_CREATE_STR)==0) + param.mode = DB_MODE_CREATE; + else if (strcmp(argv[idx],DB_MODE_UPDATE_STR)==0) + param.mode = DB_MODE_UPDATE; + else if (strcmp(argv[idx],DB_MODE_APPEND_STR)==0) + param.mode = DB_MODE_APPEND; + else + { + fprintf(stderr, "%s: --mode is invalid.\n", argv[idx]); + param.is_show_usage = false; + return false; + } + } + else if (check_opt(argv[idx], "-c", "--codepage")) + { + if (idx == argc-1) + return false; + + param.cp = get_codepage(argv[++idx]); + if (param.cp < 0) + { + fprintf(stderr, "%s: codepage is invalid.\n", argv[idx]); + param.is_show_usage = false; + return false; + } + } + else if (check_opt(argv[idx], "-i", "--input-path")) + { + if (!check_path(argc, argv, idx++, "database input path", + param.db_input_path)) + return false; + } + else if (check_opt(argv[idx], "-o", "--output-path")) + { + if (!check_path(argc, argv, idx++, "database output path", + param.db_output_path)) + return false; + } + else + return false; + } + + if (param.rootdir[0] == '\0' || param.mode < 0) + return false; + + param.is_show_usage = false; + return true; +} + +int main(int argc, char **argv) { - return (void*)1; -} - + if (!get_params(argc, argv) || param.is_show_usage) + { + show_usage(); + return 1; + } + + if (param.is_show_version) + { + show_version(); + return 0; + } + + sim_root_dir = param.rootdir; + + if (param.db_input_path[0] == '\0') + snprintf(param.db_input_path, MAX_PATH, "%s%s", + param.rootdir, DEFAULT_ROCKBOX_DIRECTORY); + + if (param.db_output_path[0] == '\0') + strcpy(param.db_output_path, param.db_input_path); + + mkdirs(param.db_output_path); + + if (param.mode != DB_MODE_CREATE) + copy_database_files(param.db_input_path, param.db_output_path); + + set_db_root_path(param.db_output_path); + + set_codepage(param.cp); + + tagcache_init(); + + if (param.mode == DB_MODE_CREATE) + { + tagcache_remove_database(); + tagcache_build(param.songdir); + } + else if (param.mode == DB_MODE_UPDATE) + { + tagcache_build(param.songdir); + tagcache_reverse_scan(); + } + else if (param.mode == DB_MODE_APPEND) + { + tagcache_build(param.songdir); + } + + return 0; +} diff --git a/uisimulator/common/io.c b/uisimulator/common/io.c index d87e331..e62a477 100644 --- a/uisimulator/common/io.c +++ b/uisimulator/common/io.c @@ -50,14 +50,16 @@ #define MAX_OPEN_FILES 11 #include +#include "config.h" +#ifndef THREAD_IS_NOT_USED #include #include #include "thread.h" #include "kernel.h" +#include "thread-sdl.h" +#endif #include "debug.h" -#include "config.h" #include "ata.h" /* for IF_MV2 et al. */ -#include "thread-sdl.h" /* Windows (and potentially other OSes) distinguish binary and text files. @@ -147,6 +149,12 @@ void dircache_rename(const char *oldname, const char *newname); #define SIMULATOR_DEFAULT_ROOT "simdisk" extern const char *sim_root_dir; +#ifdef __PCTOOL__ +#define PCTOOL_DEFAULT_ROOT "./" +#define PCTOOL_DEFAULT_ROCKBOX_DIR "/.rockbox" +extern const char *sim_rockbox_dir; +#endif + static int num_openfiles = 0; struct sim_dirent { @@ -171,7 +179,7 @@ struct mydir { typedef struct mydir MYDIR; #if 1 /* maybe this needs disabling for MSVC... */ -static unsigned int rockbox2sim(int opt) +unsigned int rockbox2sim(int opt) { int newopt = O_BINARY; @@ -201,7 +209,9 @@ enum struct sim_io { +#ifndef THREAD_IS_NOT_USED struct mutex sim_mutex; /* Rockbox mutex */ +#endif int cmd; /* The command to perform */ int ready; /* I/O ready flag - 1= ready */ int fd; /* The file to read/write */ @@ -214,22 +224,29 @@ static struct sim_io io; int ata_init(void) { +#ifndef THREAD_IS_NOT_USED /* Initialize the rockbox kernel objects on a rockbox thread */ mutex_init(&io.sim_mutex); +#endif io.accum = 0; return 1; } +#ifndef __PCTOOL__ int ata_spinup_time(void) { return HZ; } +#endif static ssize_t io_trigger_and_wait(int cmd) { +#ifndef THREAD_IS_NOT_USED void *mythread = NULL; - ssize_t result; +#endif + ssize_t result = 0; +#ifndef THREAD_IS_NOT_USED if (io.count > IO_YIELD_THRESHOLD || (io.accum += io.count) >= IO_YIELD_THRESHOLD) { @@ -237,6 +254,7 @@ static ssize_t io_trigger_and_wait(int cmd) io.accum = 0; mythread = thread_sdl_thread_unlock(); } +#endif switch (cmd) { @@ -247,21 +265,21 @@ static ssize_t io_trigger_and_wait(int cmd) result = write(io.fd, io.buf, io.count); break; } - +#ifndef THREAD_IS_NOT_USED /* Regain our status as current */ if (mythread != NULL) { thread_sdl_thread_lock(mythread); } - +#endif return result; } -#ifndef __PCTOOL__ static const char *get_sim_pathname(const char *name) { static char buffer[MAX_PATH]; /* sufficiently big */ +#ifndef __PCTOOL__ if(name[0] == '/') { snprintf(buffer, sizeof(buffer), "%s%s", @@ -270,10 +288,22 @@ static const char *get_sim_pathname(const char *name) } fprintf(stderr, "WARNING, bad file name lacks slash: %s\n", name); return name; -} #else -#define get_sim_pathname(name) name + if(name[0] == '/') + { + snprintf(buffer, sizeof(buffer), "%s%s", + sim_root_dir != NULL ? sim_root_dir : PCTOOL_DEFAULT_ROOT, name); + } + else + { + snprintf(buffer, sizeof(buffer), "%s%s/%s", + sim_root_dir != NULL ? sim_root_dir : PCTOOL_DEFAULT_ROOT, + sim_rockbox_dir != NULL ? sim_rockbox_dir : PCTOOL_DEFAULT_ROCKBOX_DIR, + name); + } + return buffer; #endif +} MYDIR *sim_opendir(const char *name) { @@ -366,35 +396,35 @@ int sim_creat(const char *name) ssize_t sim_read(int fd, void *buf, size_t count) { ssize_t result; - +#ifndef THREAD_IS_NOT_USED mutex_lock(&io.sim_mutex); - +#endif /* Setup parameters */ io.fd = fd; io.buf = buf; io.count = count; result = io_trigger_and_wait(IO_READ); - +#ifndef THREAD_IS_NOT_USED mutex_unlock(&io.sim_mutex); - +#endif return result; } ssize_t sim_write(int fd, const void *buf, size_t count) { ssize_t result; - +#ifndef THREAD_IS_NOT_USED mutex_lock(&io.sim_mutex); - +#endif io.fd = fd; io.buf = (void*)buf; io.count = count; result = io_trigger_and_wait(IO_WRITE); - +#ifndef THREAD_IS_NOT_USED mutex_unlock(&io.sim_mutex); - +#endif return result; } diff --git a/tools/database/codepage.c b/tools/database/codepage.c new file mode 100644 index 0000000..6d52e0a --- /dev/null +++ b/tools/database/codepage.c @@ -0,0 +1,183 @@ +/**************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 Yoshihisa Uchida + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include +#include "../../tools/codepage_tables.h" + +/* implemented by firmware/common/unicode.c */ +extern const char* get_codepage_name(int cp); + +static const unsigned short *codetable_map[] = +{ + cp932_table, + cp936_table, + cp949_table, + cp950_table, +}; + +/* this function based on iso_decode (in tools/codepages.c) */ +static unsigned short decode_iso_character(unsigned char latin1, int cp) +{ + unsigned short ucs = 0; + + /* cp tells us which codepage to convert from */ + switch (cp) { + case 1: /* Greek (ISO-8859-7) */ + /* first convert to unicode */ + if (latin1 < 0xa1) + ucs = latin1; + else if (latin1 > 0xb7) + ucs = latin1 + 0x02d0; + else + ucs = iso8859_7_to_uni[latin1 - 0xa1]; + break; + + case 2: /* Hebrew (ISO-8859-8) */ + /* first convert to unicode */ + if (latin1 == 0xaa) + ucs = 0xd7; + else if (latin1 == 0xba) + ucs = 0xf7; + else if (latin1 == 0xdf) + ucs = 0x2017; + else if (latin1 < 0xc0) + ucs = latin1; + else + ucs = latin1 + 0x04f0; + break; + + case 3: /* Cyrillic (CP1251) */ + /* first convert to unicode */ + if (latin1 < 0x80) + ucs = latin1; + else if (latin1 > 0xbf) + ucs = latin1 + 0x0350; + else + ucs = cp1251_to_uni[latin1 - 0x80]; + break; + + case 4: /* Thai (ISO-8859-11) */ + /* first convert to unicode */ + if (latin1 < 0xa1) + ucs = latin1; + else + ucs = latin1 + 0x0d60; + break; + + case 5: /* Arabic (CP1256) */ + /* first convert to unicode */ + if (latin1 < 0x80) + ucs = latin1; + else + ucs = cp1256_to_uni[latin1 - 0x80]; + break; + + case 6: /* Turkish (ISO-8859-9) */ + /* first convert to unicode */ + switch (latin1) { + case 0xd0: + ucs = 0x011e; + break; + case 0xdd: + ucs = 0x0130; + break; + case 0xde: + ucs = 0x015e; + break; + case 0xf0: + ucs = 0x011f; + break; + case 0xfd: + ucs = 0x0131; + break; + case 0xfe: + ucs = 0x015f; + break; + default: + ucs = latin1; + break; + } + break; + + case 7: /* Latin Extended (ISO-8859-2) */ + /* first convert to unicode */ + if (latin1 < 0xa1) + ucs = latin1; + else + ucs = iso8859_2_to_uni[latin1 - 0xa1]; + break; + + case 8: /* Central European (CP1250) */ + /* first convert to unicode */ + if (latin1 < 0x80) + ucs = latin1; + else + ucs = cp1250_to_uni[latin1 - 0x80]; + break; + + default: + break; + } + return ucs; +} + +const unsigned short *get_codepage_table(int cp, int *tablesize) +{ + int i, j; + static unsigned short iso_table[1024]; /* 128 * 8 codepages */ + static int is_iso = 0; + + if (cp >= 9) + { + *tablesize = 32768; + return codetable_map[cp - 9]; + } + + *tablesize = 1024; + + if (is_iso) + return iso_table; + + for (i = 1; i < 9; i++) + { + for (j = 0; j < 128; i++) + iso_table[i * 128 + j] = decode_iso_character(i+128, cp); + } + is_iso = 1; + + return iso_table; +} + +int get_codepage(const char *cp) +{ + int code; + const char *name; + + for (code = 0; ; code++) + { + name = get_codepage_name(code); + if (strcmp(name, "unknown") == 0) + break; + if (strcmp(cp, name) == 0) + return code; + } + + return -1; +} diff --git a/tools/database/config-pctool.h b/tools/database/config-pctool.h new file mode 100644 index 0000000..3311fb7 --- /dev/null +++ b/tools/database/config-pctool.h @@ -0,0 +1,17 @@ +/* + * This config file is for the database tool + */ + +/* Please never change the following items. */ + +/* define this if you would like tagcache to build on this target */ +#define HAVE_TAGCACHE + +/* define this if you do software codec */ +#define CONFIG_CODEC SWCODEC + +/* define this if thread functions is not used */ +#define THREAD_IS_NOT_USED + +/* define this if codepage files (*.cp) is not used */ +#define CODEPAGE_FILES_IS_NOT_USED diff --git a/tools/database/dbfile.c b/tools/database/dbfile.c new file mode 100644 index 0000000..8373615 --- /dev/null +++ b/tools/database/dbfile.c @@ -0,0 +1,57 @@ +/**************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 Yoshihisa Uchida + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include +#include +#include +#include "database.h" + +/* Rockbox functions */ + +/* implemented by uisimulator/common/io.c */ +extern unsigned int rockbox2sim(int opt); + +static unsigned char root_path[MAX_PATH]; + +/* database files access helper functions */ + +void set_db_root_path(const unsigned char *path) +{ + strncpy(root_path, path, MAX_PATH-1); +} + +static const char *db_path(const char *name) +{ + static char path[MAX_PATH]; + + snprintf(path, MAX_PATH, "%s/%s", root_path, name); + + return path; +} + +int db_open(const char *name, int o) +{ + return open(db_path(name), rockbox2sim(o), 0666); +} + +int db_remove(const char *name) +{ + return remove(db_path(name)); +} diff --git a/tools/database/file.c b/tools/database/file.c new file mode 100644 index 0000000..9537fc8 --- /dev/null +++ b/tools/database/file.c @@ -0,0 +1,131 @@ +/**************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 Yoshihisa Uchida + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include +#include +#include +#include +#include "database.h" + +bool mkdirs(const char *path) +{ + int i; + int len = strlen(path); + char parent[MAX_PATH]; + struct stat sbuf; + + if (!stat(path, &sbuf)) + { + if (S_ISDIR(sbuf.st_mode)) + return true; + + fprintf(stderr, "%s: does not directory\n", path); + return false; + } + + for (i = len-1; i > 0; i--) + { +#ifdef __MINGW32__ + if (path[i] == '\\' || path[i] == '/') +#else + if (path[i] == '/') +#endif + { + strncpy(parent, path, i); + parent[i] = '\0'; + if (!mkdirs(parent)) + return false; + break; + } + } + +#ifdef __MINGW32__ + mkdir(path); +#else + mkdir(path, 0777); +#endif + + if (stat(path, &sbuf)) + { + fprintf(stderr, "%s: does not create directories\n", path); + return false; + } + return true; +} + +static bool copy_file(const char *src, const char *dst, const char *file) +{ + char buf[4096]; + char spath[MAX_PATH]; + char dpath[MAX_PATH]; + FILE *sfp; + FILE *dfp; + size_t rsz; + + snprintf(spath, MAX_PATH, "%s/%s", src, file); + snprintf(dpath, MAX_PATH, "%s/%s", dst, file); + + sfp = fopen(spath, "rb"); + if (sfp == NULL) + { + fprintf(stderr, "%s/%s: does not open.\n", src, file); + return false; + } + + dfp = fopen(dpath, "wb"); + if (dfp == NULL) + { + fclose(sfp); + fprintf(stderr, "%s/%s: does not open.\n", dst, file); + return false; + } + + do { + rsz = fread(buf, 1, sizeof(buf), sfp); + fwrite(buf, 1, rsz, dfp); + } while (rsz == sizeof(buf)); + + fclose(sfp); + fclose(dfp); + + return true; +} + +bool copy_database_files(const char *src, const char *dst) +{ + DIR *dir = opendir(src); + struct dirent *dp; + int len; + + if (dir == NULL) + { + fprintf(stderr, "%s: No such directory exists\n", src); + return false; + } + + while ((dp = readdir(dir)) != NULL) + { + len = strlen(dp->d_name); + if (len > 5 && strcmp(dp->d_name + len - 4, ".tcd") == 0) + copy_file(src, dst, dp->d_name); + } + closedir(dir); + return true; +} diff --git a/tools/database/readme.txt b/tools/database/readme.txt new file mode 100755 index 0000000..7245712 --- /dev/null +++ b/tools/database/readme.txt @@ -0,0 +1,136 @@ + __________ __ ___. + Open \______ \ ____ ____ | | _\_ |__ _______ ___ + Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + \/ \/ \/ \/ \/ +$Id$ + +Copyright (C) 2009 Yoshihisa Uchida + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + KIND, either express or implied. + +========================================================================== +database tool + Create the song database (database_*.tcd) application. + + +================================================= +Usage +================================================= +database -r|--root-path + -m|--mode + [-s|--song-directory ] + [-c|--codepage ] + [-i|--input-path ] + [-o|--output-path ] + [-h|--help] + [-V|--version] + +-r|--root-path + set Rockbox root directory. + + When the database tool is used on Windows, the drive letter is written + Windows style (such as "C:\\path\of\root" or "C:/path/of/root"). + + When using database tool on MinGW+MSYS shell, it should be set not /foo but //foo. + +-m|--mode + create: build database newly. + + update: Files not registered in the database are added to the database. + And deleted files are deleted from the database. + + append: Files not registered in the database are added to the database. + But deleted files are not deleted from the database. + +-s|--song-directory + set song storage directory. + If begins with a "/", then it looks for the song file + from <--root-path>/. + If does not begin with a "/", then it looks for the song + file from <--root-path>/.rockbox/. + + If this option is not given, then = "/". + + When using database tool on MinGW+MSYS shell, it should be set not /foo but //foo. + +-c|--codepage + set metadata codepage. + If this option is not given, then metadata codepage is "ISO-8859-1". + When the player is the codepage not supported, "ISO-8859-1" is selected. + + codepage list + option value codepage + ----------------------------------------------- + ISO-8859-1 Latin1 (ISO-8859-1) + ISO-8859-2 Latin Extended (ISO-8859-2) + ISO-8859-7 Greek (ISO-8859-7) + ISO-8859-8 Hebrew (ISO-8859-8) + ISO-8859-9 Turkish (ISO-8859-9) + ISO-8859-11 Thai (ISO-8859-11) + CP1250 Central European (CP1250) + CP1251 Cyrillic (CP1251) + CP1256 Arabic (CP1256) + SJIS Japanese (SJIS) + GB-2312 Simple Chinese (GB2312) + KSX-1001 Korean (KSX1001) + BIG-5 Traditional Chinese (BIG5) + UTF-8 Unicode (UTF-8) + +-i|--input-path + The directory where database files read when <--mode> is update or append. + If does not begin with a "/" or the drive letter, then it considered + the relative path from the directory that executes the database tool. + + If this option is not given, song database (database_*.tcd) are read from + <--root-path>/.rockbox directory. + +-o|--output-path + The directory of output of database files. + If does not begin with a "/" or the drive letter, then it considered + the relative path from the directory that executes the database tool. + + If this option is not given, song database (database_*.tcd) are saved in + <--root-path>/.rockbox directory. + +-h|--help + show help message and exit. + +-V|--version + show version information and exit. + +================================================= +Requirement +================================================= +OS + 1) Windows + - Cygwin + When the database tool is built by using gcc 3.X.X on Cygwin, + to execute the database tool, cygwin1.dll is not needed. + But if it is built by using gcc 4.X.X, cygwin1.dll is needed. + + - MinGW + It is necessary to install msys. + + 2) Linux + + Other OS do not checked. + +When the database tool does not use the SDL library, then the SDL library +may not be installed. + +================================================= +Build +================================================= +1) make + +================================================= +TODO +=================================================