summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2023-10-04 08:51:10 -0400
committerWilliam Wilgus <wilgus.william@gmail.com>2023-10-05 21:24:37 -0400
commit1ed640da24eb97255328c4498035ba524f6265fc (patch)
treee89771f51a031cc114d36f6dd9c261b04cd4667d
parent6634a60bf0750159ffc34bdff548fac0817e72bc (diff)
downloadrockbox-1ed640da24.tar.gz
rockbox-1ed640da24.zip
[Feature] db_commit plugin allows a more verbose commit
prints logf messages to the screen buffer and dumps the output to .rockbox/db_commit_log.txt logs warnings about tags that can't be displayed by the current font adds an option to the tagcache using the file .rockbox/database_commit.ignore to prevent auto commit Change-Id: Ib381b3b6d9dd19d76c95d0e87e605f7378e29674
-rw-r--r--apps/plugin.c2
-rw-r--r--apps/plugin.h2
-rw-r--r--apps/plugins/CATEGORIES1
-rw-r--r--apps/plugins/SOURCES1
-rw-r--r--apps/plugins/SUBDIRS1
-rw-r--r--apps/plugins/SUBDIRS.app_build1
-rw-r--r--apps/plugins/tagcache/SOURCES2
-rw-r--r--apps/plugins/tagcache/tagcache.c581
-rw-r--r--apps/plugins/tagcache/tagcache.h25
-rw-r--r--apps/plugins/tagcache/tagcache.make30
-rw-r--r--apps/tagcache.c70
-rw-r--r--apps/tagcache.h1
-rw-r--r--manual/rockbox_interface/tagcache.tex9
13 files changed, 707 insertions, 19 deletions
diff --git a/apps/plugin.c b/apps/plugin.c
index b1188fc183..e916918f23 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -832,7 +832,7 @@ static const struct plugin_api rockbox_api = {
/* new stuff at the end, sort into place next time
the API gets incompatible */
-
+ tagcache_commit_finalize,
};
static int plugin_buffer_handle;
diff --git a/apps/plugin.h b/apps/plugin.h
index 11adf61e9c..4f9027987f 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -969,7 +969,7 @@ struct plugin_api {
#endif
/* new stuff at the end, sort into place next time
the API gets incompatible */
-
+ void (*tagcache_commit_finalize)(void);
};
/* plugin header */
diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES
index 9ec38ab76b..49016fef13 100644
--- a/apps/plugins/CATEGORIES
+++ b/apps/plugins/CATEGORIES
@@ -22,6 +22,7 @@ clock,apps
codebuster,games
credits,viewers
cube,demos
+db_commit,apps
db_folder_select,viewers
demystify,demos
dice,games
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index 7edc8a3c51..b857f26ba5 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -4,6 +4,7 @@ battery_bench.c
#endif
#ifdef HAVE_TAGCACHE
db_folder_select.c
+tagcache/tagcache.c
#endif
chessclock.c
credits.c
diff --git a/apps/plugins/SUBDIRS b/apps/plugins/SUBDIRS
index 4cb57edb1b..b9c18b5fd9 100644
--- a/apps/plugins/SUBDIRS
+++ b/apps/plugins/SUBDIRS
@@ -31,6 +31,7 @@ rockboy
#if defined(HAVE_TAGCACHE)
pictureflow
+tagcache
#endif
#if PLUGIN_BUFFER_SIZE > 0x20000
diff --git a/apps/plugins/SUBDIRS.app_build b/apps/plugins/SUBDIRS.app_build
index 1fc283d6c4..fbf83f01da 100644
--- a/apps/plugins/SUBDIRS.app_build
+++ b/apps/plugins/SUBDIRS.app_build
@@ -17,6 +17,7 @@ reversi
#ifdef HAVE_TAGCACHE
pictureflow
+tagcache
#endif
/* For all the swcodec targets */
diff --git a/apps/plugins/tagcache/SOURCES b/apps/plugins/tagcache/SOURCES
new file mode 100644
index 0000000000..2541f3e87c
--- /dev/null
+++ b/apps/plugins/tagcache/SOURCES
@@ -0,0 +1,2 @@
+tagcache.c
+
diff --git a/apps/plugins/tagcache/tagcache.c b/apps/plugins/tagcache/tagcache.c
new file mode 100644
index 0000000000..25ba9bc301
--- /dev/null
+++ b/apps/plugins/tagcache/tagcache.c
@@ -0,0 +1,581 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2023 by William Wilgus
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/*Plugin Includes*/
+
+#include "plugin.h"
+/* Redefinitons of ANSI C functions. */
+#include "lib/wrappers.h"
+#include "lib/helper.h"
+
+static void thread_create(void);
+static void thread(void); /* the thread running it all */
+static void allocate_tempbuf(void);
+static void free_tempbuf(void);
+static bool do_timed_yield(void);
+static void _log(const char *fmt, ...);
+/*Aliases*/
+#if 0
+#ifdef ROCKBOX_HAS_LOGF
+ #define logf rb->logf
+#else
+ #define logf(...) {}
+#endif
+#endif
+
+
+#define logf _log
+#define sleep rb->sleep
+#define qsort rb->qsort
+
+#define write(x,y,z) rb->write(x,y,z)
+#define ftruncate rb->ftruncate
+#define remove rb->remove
+
+#define vsnprintf rb->vsnprintf
+#define mkdir rb->mkdir
+#define filesize rb->filesize
+
+#define strtok_r rb->strtok_r
+#define strncasecmp rb->strncasecmp
+#define strcasecmp rb->strcasecmp
+
+#define current_tick (*rb->current_tick)
+#define crc_32(x,y,z) rb->crc_32(x,y,z)
+
+
+#ifndef SIMULATOR
+#define errno (*rb->__errno())
+#endif
+#define ENOENT 2 /* No such file or directory */
+#define EEXIST 17 /* File exists */
+#define MAX_LOG_SIZE 16384
+
+#define EV_EXIT MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0xFF)
+#define EV_ACTION MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0x02)
+#define EV_STARTUP MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0x01)
+
+/* communication to the worker thread */
+static struct
+{
+ int user_index;
+ bool exiting; /* signal to the thread that we want to exit */
+ bool resume;
+ unsigned int id; /* worker thread id */
+ struct event_queue queue; /* thread event queue */
+ long last_useraction_tick;
+} gThread;
+
+
+/*Support Fns*/
+/* open but with a builtin printf for assembling the path */
+int open_pathfmt(char *buf, size_t size, int oflag, const char *pathfmt, ...)
+{
+ va_list ap;
+ va_start(ap, pathfmt);
+ vsnprintf(buf, size, pathfmt, ap);
+ va_end(ap);
+ if ((oflag & O_PATH) == O_PATH)
+ return -1;
+ int handle = open(buf, oflag, 0666);
+ //logf("Open: %s %d flag: %x", buf, handle, oflag);
+ return handle;
+}
+
+static void sleep_yield(void)
+{
+ rb->queue_remove_from_head(&gThread.queue, EV_ACTION);
+ rb->queue_post(&gThread.queue, EV_ACTION, 0);
+ sleep(1);
+ #undef yield
+ rb->yield();
+ #define yield sleep_yield
+}
+
+/* make sure tag can be displayed by font pf*/
+static bool text_is_displayable(struct font *pf, unsigned char *src)
+{
+ unsigned short code;
+ const unsigned char *ptr = src;
+ while(*ptr)
+ {
+ ptr = rb->utf8decode(ptr, &code);
+
+ if(!rb->font_get_bits(pf, code))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+/* callback for each tag if false returned tag will not be added */
+bool user_check_tag(int index_type, char* build_idx_buf)
+{
+ static struct font *pf = NULL;
+ if (!pf)
+ pf = rb->font_get(FONT_UI);
+
+ if (index_type == tag_artist || index_type == tag_album ||
+ index_type == tag_genre || index_type == tag_title ||
+ index_type == tag_composer || index_type == tag_comment ||
+ index_type == tag_albumartist || index_type == tag_virt_canonicalartist)
+ {
+ /* this could be expanded with more rules / transformations */
+ if (rb->utf8length(build_idx_buf) != strlen(build_idx_buf))
+ {
+ if (!text_is_displayable(pf, build_idx_buf))
+ {
+ logf("Can't display (%d) %s", index_type, build_idx_buf);
+ }
+ }
+ }
+ return true;
+}
+
+/* undef features we don't need */
+#undef HAVE_DIRCACHE
+#undef HAVE_TC_RAMCACHE
+#undef HAVE_EEPROM_SETTINGS
+/* paste the whole tagcache.c file */
+#include "../tagcache.c"
+
+static bool logdump(bool append);
+static unsigned char logbuffer[MAX_LOG_SIZE + 1];
+static int logindex;
+static bool logwrap;
+static bool logenabled = true;
+
+static void check_logindex(void)
+{
+ if(logindex >= MAX_LOG_SIZE)
+ {
+ /* wrap */
+ logdump(true);
+ //logwrap = true;
+ logindex = 0;
+ }
+}
+
+static int log_push(void *userp, int c)
+{
+ (void)userp;
+
+ logbuffer[logindex++] = c;
+ check_logindex();
+
+ return 1;
+}
+
+/* our logf function */
+static void _log(const char *fmt, ...)
+{
+ if (!logenabled)
+ {
+ rb->splash(10, "log not enabled");
+ return;
+ }
+
+
+ #ifdef USB_ENABLE_SERIAL
+ int old_logindex = logindex;
+ #endif
+ va_list ap;
+
+ va_start(ap, fmt);
+
+#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
+ char buf[1024];
+ vsnprintf(buf, sizeof buf, fmt, ap);
+ DEBUGF("%s\n", buf);
+ /* restart va_list otherwise the result if undefined when vuprintf is called */
+ va_end(ap);
+ va_start(ap, fmt);
+#endif
+
+ rb->vuprintf(log_push, NULL, fmt, ap);
+ va_end(ap);
+
+ /* add trailing zero */
+ log_push(NULL, '\0');
+}
+
+
+int compute_nb_lines(int w, struct font* font)
+{
+ int i, nb_lines;
+ int cur_x, delta_x;
+
+ if(logindex>= MAX_LOG_SIZE || (logindex == 0 && !logwrap))
+ return 0;
+
+ if(logwrap)
+ i = logindex;
+ else
+ i = 0;
+
+ cur_x = 0;
+ nb_lines = 0;
+
+ do {
+ if(logbuffer[i] == '\0')
+ {
+ cur_x = 0;
+ nb_lines++;
+ }
+ else
+ {
+ /* does character fit on this line ? */
+ delta_x = rb->font_get_width(font, logbuffer[i]);
+
+ if(cur_x + delta_x > w)
+ {
+ cur_x = 0;
+ nb_lines++;
+ }
+
+ /* update pointer */
+ cur_x += delta_x;
+ }
+
+ i++;
+ if(i >= MAX_LOG_SIZE)
+ i = 0;
+ } while(i != logindex);
+
+ return nb_lines;
+}
+
+static bool logdisplay(void)
+{
+
+ int w, h, i, index;
+ int fontnr;
+ static int delta_y = -1;
+ int cur_x, cur_y, delta_x;
+ struct font* font;
+
+ char buf[2];
+
+ fontnr = FONT_FIRSTUSERFONT;
+ font = rb->font_get(fontnr);
+ buf[1] = '\0';
+ w = LCD_WIDTH;
+ h = LCD_HEIGHT;
+
+ if (delta_y < 0) /* init, get the horizontal size of each line */
+ {
+ rb->font_getstringsize("A", NULL, &delta_y, fontnr);
+ /* start at the end of the log */
+ gThread.user_index = compute_nb_lines(w, font) - h/delta_y -1;
+ /* user_index will be number of the first line to display (warning: line!=log entry) */
+ /* if negative, will be set 0 to zero later */
+ }
+
+
+ rb->lcd_clear_display();
+
+ if(gThread.user_index < 0 || gThread.user_index >= MAX_LOG_SIZE)
+ gThread.user_index = 0;
+
+
+ if(logwrap)
+ i = logindex;
+ else
+ i = 0;
+
+ index = 0;
+ cur_x = 0;
+ cur_y = 0;
+
+ /* nothing to print ? */
+ if(logindex == 0 && !logwrap)
+ goto end_print;
+
+ do {
+ if(logbuffer[i] == '\0')
+ {
+ /* should be display a newline ? */
+ if(index >= gThread.user_index)
+ cur_y += delta_y;
+ cur_x = 0;
+ index++;
+ }
+ else
+ {
+ /* does character fit on this line ? */
+ delta_x = rb->font_get_width(font, logbuffer[i]);
+
+ if(cur_x + delta_x > w)
+ {
+ /* should be display a newline ? */
+ if(index >= gThread.user_index)
+ cur_y += delta_y;
+ cur_x = 0;
+ index++;
+ }
+
+ /* should we print character ? */
+ if(index >= gThread.user_index)
+ {
+ buf[0] = logbuffer[i];
+ rb->lcd_putsxy(cur_x, cur_y, buf);
+ }
+
+ /* update pointer */
+ cur_x += delta_x;
+ }
+ i++;
+ /* did we fill the screen ? */
+ if(cur_y > h - delta_y)
+ {
+ if (TIME_AFTER(current_tick, gThread.last_useraction_tick + HZ))
+ gThread.user_index++;
+ break;
+ }
+
+ if(i >= MAX_LOG_SIZE)
+ i = 0;
+ } while(i != logindex);
+
+ end_print:
+ rb->lcd_update();
+
+ return false;
+}
+
+static bool logdump(bool append)
+{
+ int fd;
+ int flags = O_CREAT|O_WRONLY|O_TRUNC;
+ /* nothing to print ? */
+ if(!logenabled || (logindex == 0 && !logwrap))
+ {
+ /* nothing is logged just yet */
+ return false;
+ }
+ if (!append)
+ {
+ flags = O_CREAT|O_WRONLY|O_APPEND;
+ }
+
+ fd = open(ROCKBOX_DIR "/db_commit_log.txt", flags, 0666);
+ logenabled = false;
+ if(-1 != fd) {
+ int i;
+
+ if(logwrap)
+ i = logindex;
+ else
+ i = 0;
+
+ do {
+ if(logbuffer[i]=='\0')
+ rb->fdprintf(fd, "\n");
+ else
+ rb->fdprintf(fd, "%c", logbuffer[i]);
+
+ i++;
+ if(i >= MAX_LOG_SIZE)
+ i = 0;
+ } while(i != logindex);
+
+ close(fd);
+ }
+
+ logenabled = true;
+
+ return false;
+}
+
+static void allocate_tempbuf(void)
+{
+ tempbuf_size = 0;
+ tempbuf = rb->plugin_get_audio_buffer(&tempbuf_size);
+ tempbuf_size &= ~0x03;
+
+}
+
+static void free_tempbuf(void)
+{
+ if (tempbuf_size == 0)
+ return ;
+
+ rb->plugin_release_audio_buffer();
+ tempbuf = NULL;
+ tempbuf_size = 0;
+}
+
+static bool do_timed_yield(void)
+{
+ /* Sorting can lock up for quite a while, so yield occasionally */
+ static long wakeup_tick = 0;
+ if (TIME_AFTER(current_tick, wakeup_tick))
+ {
+
+ yield();
+
+ wakeup_tick = current_tick + (HZ/5);
+ return true;
+ }
+ return false;
+}
+
+/*-----------------------------------------------------------------------------*/
+/******* plugin_start ******* */
+/*-----------------------------------------------------------------------------*/
+
+enum plugin_status plugin_start(const void* parameter)
+{
+ (void) parameter;
+
+ /* Turn off backlight timeout */
+ backlight_ignore_timeout();
+
+ memset(&tc_stat, 0, sizeof(struct tagcache_stat));
+ memset(&current_tcmh, 0, sizeof(struct master_header));
+ filenametag_fd = -1;
+
+ strlcpy(tc_stat.db_path, rb->global_settings->tagcache_db_path, sizeof(tc_stat.db_path));
+ if (!rb->dir_exists(tc_stat.db_path)) /* on fail use default DB path */
+ strlcpy(tc_stat.db_path, ROCKBOX_DIR, sizeof(tc_stat.db_path));
+ tc_stat.initialized = true;
+
+ memset(&gThread, 0, sizeof(gThread));
+ logf("started");
+ logdump(false);
+
+ thread_create();
+ gThread.user_index = 0;
+ logdisplay(); /* get something on the screen while user waits */
+
+ allocate_tempbuf();
+
+ commit();
+
+ if (tc_stat.ready)
+ rb->tagcache_commit_finalize();
+
+ free_tempbuf();
+
+ logdump(true);
+ gThread.user_index++;
+ logdisplay();
+ rb->thread_wait(gThread.id);
+ rb->queue_delete(&gThread.queue);
+
+ /* Turn on backlight timeout (revert to settings) */
+ backlight_use_settings();
+ return PLUGIN_OK;
+}
+
+/****************** main thread + helper ******************/
+static void thread(void)
+{
+ struct queue_event ev;
+ while (!gThread.exiting)
+ {
+ rb->queue_wait_w_tmo(&gThread.queue, &ev, 1);
+ switch (ev.id)
+ {
+ case SYS_USB_CONNECTED:
+ rb->usb_acknowledge(SYS_USB_CONNECTED_ACK);
+ logenabled = false;
+ break;
+ case SYS_USB_DISCONNECTED:
+ logenabled = true;
+ /*fall through*/
+ case EV_STARTUP:
+ logf("Thread Started");
+ break;
+ case EV_EXIT:
+ return;
+ default:
+ break;
+ }
+ logdisplay();
+
+ int action = rb->get_action(CONTEXT_STD, HZ/10);
+
+ switch( action )
+ {
+ case ACTION_NONE:
+ break;
+ case ACTION_STD_NEXT:
+ case ACTION_STD_NEXTREPEAT:
+ gThread.last_useraction_tick = current_tick;
+ gThread.user_index++;
+ break;
+ case ACTION_STD_PREV:
+ case ACTION_STD_PREVREPEAT:
+ gThread.last_useraction_tick = current_tick;
+ gThread.user_index--;
+ break;
+ case ACTION_STD_OK:
+ gThread.last_useraction_tick = current_tick;
+ gThread.user_index = 0;
+ break;
+ case SYS_POWEROFF:
+ case ACTION_STD_CANCEL:
+ gThread.exiting = true;
+ return;
+#ifdef HAVE_TOUCHSCREEN
+ case ACTION_TOUCHSCREEN:
+ {
+ gThread.last_useraction_tick = current_tick;
+ short x, y;
+ static int prev_y;
+
+ action = action_get_touchscreen_press(&x, &y);
+
+ if(action & BUTTON_REL)
+ prev_y = 0;
+ else
+ {
+ if(prev_y != 0)
+ gThread.user_index += (prev_y - y) / delta_y;
+
+ prev_y = y;
+ }
+ }
+#endif
+ default:
+ break;
+ }
+
+
+ yield();
+ }
+}
+
+static void thread_create(void)
+{
+ /* put the thread's queue in the bcast list */
+ rb->queue_init(&gThread.queue, true);
+ /*Note: tagcache_stack is defined in apps/tagcache.c */
+ gThread.last_useraction_tick = current_tick;
+ gThread.id = rb->create_thread(thread, tagcache_stack, sizeof(tagcache_stack),
+ 0, "db_commit"
+ IF_PRIO(, PRIORITY_USER_INTERFACE)
+ IF_COP(, CPU));
+ rb->queue_post(&gThread.queue, EV_STARTUP, 0);
+ yield();
+}
diff --git a/apps/plugins/tagcache/tagcache.h b/apps/plugins/tagcache/tagcache.h
new file mode 100644
index 0000000000..e416289741
--- /dev/null
+++ b/apps/plugins/tagcache/tagcache.h
@@ -0,0 +1,25 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C)
+ *
+ * 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 _TC_PLUGIN_
+#define _TC_PLUGIN_
+#endif /*_TC_PLUGIN_ */
+
+
diff --git a/apps/plugins/tagcache/tagcache.make b/apps/plugins/tagcache/tagcache.make
new file mode 100644
index 0000000000..5d6d65cb0e
--- /dev/null
+++ b/apps/plugins/tagcache/tagcache.make
@@ -0,0 +1,30 @@
+# __________ __ ___.
+# Open \______ \ ____ ____ | | _\_ |__ _______ ___
+# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+# \/ \/ \/ \/ \/
+# $Id$
+#
+
+TCPLUG_SRCDIR := $(APPSDIR)/plugins/tagcache
+TCPLUG_BUILDDIR := $(BUILDDIR)/apps/plugins/tagcache
+
+ROCKS += $(TCPLUG_BUILDDIR)/db_commit.rock
+
+TCPLUG_FLAGS = $(PLUGINFLAGS) -fno-strict-aliasing -Wno-unused \
+ -I$(TCPLUG_SRCDIR) -ffunction-sections \
+ -fdata-sections -Wl,--gc-sections
+TCPLUG_SRC := $(call preprocess, $(TCPLUG_SRCDIR)/SOURCES)
+TCPLUG_OBJ := $(call c2obj, $(TCPLUG_SRC))
+
+# add source files to OTHER_SRC to get automatic dependencies
+OTHER_SRC += $(APPSDIR)/tagcache.c $(TCPLUG_SRC)
+
+$(TCPLUG_BUILDDIR)/db_commit.rock: $(TCPLUG_OBJ)
+
+# special pattern rule for compiling with extra flags
+$(TCPLUG_BUILDDIR)/%.o: $(TCPLUG_SRCDIR)/%.c $(TCPLUG_SRCDIR)/tagcache.make
+ $(SILENT)mkdir -p $(dir $@)
+ $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) -I$(dir $<) $(TCPLUG_FLAGS) -c $< -o $@
+
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 170a066a36..b0c2eac28f 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -55,6 +55,7 @@
*
*/
+#if !defined(PLUGIN)
/*#define LOGF_ENABLE*/
/*#define LOGF_CLAUSES define to enable logf clause matching (LOGF_ENABLE req'd) */
@@ -91,7 +92,7 @@
#include "lang.h"
#include "eeprom_settings.h"
#endif
-
+#endif /*!defined(PLUGIN)*/
/*
* Define this to support non-native endian tagcache files.
* Databases are always written in native endian so this is
@@ -132,6 +133,9 @@
/* Idle time before committing events in the command queue. */
#define TAGCACHE_COMMAND_QUEUE_COMMIT_DELAY HZ*2
+/* Dont commit database_tmp data. */
+#define TAGCACHE_FILE_NOCOMMIT "database_commit.ignore"
+
/* Temporary database containing new tags to be committed to the main db. */
#define TAGCACHE_FILE_TEMP "database_tmp.tcd"
@@ -730,7 +734,7 @@ static bool update_master_header(void)
return true;
}
-
+#if !defined(PLUGIN)
#ifndef __PCTOOL__
static bool do_timed_yield(void)
{
@@ -2355,6 +2359,8 @@ static void NO_INLINE add_tagcache(char *path, unsigned long mtime)
#undef ADD_TAG
}
+#endif /*!defined(PLUGIN)*/
+
static bool tempbuf_insert(char *str, int id, int idx_id, bool unique)
{
@@ -3064,18 +3070,22 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
}
str_setlen(build_idx_buf, entry.tag_length[index_type]);
- if (TAGCACHE_IS_UNIQUE(index_type))
- error = !tempbuf_insert(build_idx_buf, i, -1, true);
- else
- error = !tempbuf_insert(build_idx_buf, i,
- tcmh.tch.entry_count + i, false);
-
- if (error)
+#if defined(PLUGIN)
+ if (user_check_tag(index_type, build_idx_buf))
+#endif /*defined(PLUGIN)*/
{
- logf("insert error");
- goto error_exit;
- }
+ if (TAGCACHE_IS_UNIQUE(index_type))
+ error = !tempbuf_insert(build_idx_buf, i, -1, true);
+ else
+ error = !tempbuf_insert(build_idx_buf, i,
+ tcmh.tch.entry_count + i, false);
+ if (error)
+ {
+ logf("insert error");
+ goto error_exit;
+ }
+ }
/* Skip to next. */
lseek(tmpfd, entry.data_length - entry.tag_offset[index_type] -
entry.tag_length[index_type], SEEK_CUR);
@@ -3299,7 +3309,20 @@ static bool commit(void)
while (write_lock)
sleep(1);
- tmpfd = open_db_fd(TAGCACHE_FILE_TEMP, O_RDONLY);
+#if !defined(PLUGIN)
+ int fd = open_db_fd(TAGCACHE_FILE_NOCOMMIT, O_RDONLY);
+ if (fd >= 0)
+ {
+ logf("canceling commit");
+ tc_stat.commit_delayed = true;
+ close(fd);
+ tmpfd = -1;
+ }
+ else
+#endif /*!defined(PLUGIN)*/
+ {
+ tmpfd = open_db_fd(TAGCACHE_FILE_TEMP, O_RDONLY);
+ }
if (tmpfd < 0)
{
logf("nothing to commit");
@@ -3361,6 +3384,14 @@ static bool commit(void)
}
#endif /* HAVE_TC_RAMCACHE */
+#if defined(PLUGIN)
+ if (tempbuf_size == 0)
+ {
+ tempbuf = rb->plugin_get_audio_buffer(&tempbuf_size);
+ tempbuf_size &= ~0x03;
+ }
+#endif /*defined(PLUGIN)*/
+
/* And finally fail if there are no buffers available. */
if (tempbuf_size == 0)
{
@@ -3433,8 +3464,7 @@ static bool commit(void)
close(masterfd);
logf("tagcache committed");
- tc_stat.ready = check_all_headers();
- tc_stat.readyvalid = true;
+ tagcache_commit_finalize();
#if defined(HAVE_TC_RAMCACHE)
if (ramcache_buffer_stolen)
@@ -3476,7 +3506,13 @@ commit_error:
return rc;
}
+void tagcache_commit_finalize(void)
+{
+ tc_stat.ready = check_all_headers();
+ tc_stat.readyvalid = true;
+}
+#if !defined(PLUGIN)
#ifndef __PCTOOL__
static bool modify_numeric_entry(int masterfd, int idx_id, int tag, long data)
@@ -5116,8 +5152,7 @@ static void tagcache_thread(void)
if (!tc_stat.ready)
{
sleep(HZ);
- tc_stat.ready = check_all_headers();
- tc_stat.readyvalid = true;
+ tagcache_commit_finalize();
}
while (1)
@@ -5351,3 +5386,4 @@ int tagcache_get_max_commit_step(void)
{
return (int)(SORTED_TAGS_COUNT)+1;
}
+#endif /*!defined(PLUGIN)*/
diff --git a/apps/tagcache.h b/apps/tagcache.h
index 9cf796fafd..a20a13900a 100644
--- a/apps/tagcache.h
+++ b/apps/tagcache.h
@@ -204,6 +204,7 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename);
#endif
void tagcache_unload_ramcache(void);
#endif
+void tagcache_commit_finalize(void);
void tagcache_init(void) INIT_ATTR;
bool tagcache_is_initialized(void);
bool tagcache_is_fully_initialized(void);
diff --git a/manual/rockbox_interface/tagcache.tex b/manual/rockbox_interface/tagcache.tex
index 3fae3c5c04..a0d9834779 100644
--- a/manual/rockbox_interface/tagcache.tex
+++ b/manual/rockbox_interface/tagcache.tex
@@ -31,6 +31,15 @@ If a subdirectory of an `ignored' directory should still be scanned, place a
file named \fname{database.unignore} in it. The files in that directory and
its subdirectories will be scanned and added to the database.
+\subsubsection{Issues During Database Commit}
+
+You may have files on your \dap{} whose contents might not be displayed
+correctly or even crash the database.
+Placing a file named \fname{/.rockbox/database_commit.ignore}
+will prevent the device from committing the database automatically
+you can manually commit the database using the db_commit plugin in APPS
+with logging
+
\subsection{\label{ref:databasemenu}The Database Menu}
\begin{description}