A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

[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

+707 -19
+1 -1
apps/plugin.c
··· 832 832 833 833 /* new stuff at the end, sort into place next time 834 834 the API gets incompatible */ 835 - 835 + tagcache_commit_finalize, 836 836 }; 837 837 838 838 static int plugin_buffer_handle;
+1 -1
apps/plugin.h
··· 969 969 #endif 970 970 /* new stuff at the end, sort into place next time 971 971 the API gets incompatible */ 972 - 972 + void (*tagcache_commit_finalize)(void); 973 973 }; 974 974 975 975 /* plugin header */
+1
apps/plugins/CATEGORIES
··· 22 22 codebuster,games 23 23 credits,viewers 24 24 cube,demos 25 + db_commit,apps 25 26 db_folder_select,viewers 26 27 demystify,demos 27 28 dice,games
+1
apps/plugins/SOURCES
··· 4 4 #endif 5 5 #ifdef HAVE_TAGCACHE 6 6 db_folder_select.c 7 + tagcache/tagcache.c 7 8 #endif 8 9 chessclock.c 9 10 credits.c
+1
apps/plugins/SUBDIRS
··· 31 31 32 32 #if defined(HAVE_TAGCACHE) 33 33 pictureflow 34 + tagcache 34 35 #endif 35 36 36 37 #if PLUGIN_BUFFER_SIZE > 0x20000
+1
apps/plugins/SUBDIRS.app_build
··· 17 17 18 18 #ifdef HAVE_TAGCACHE 19 19 pictureflow 20 + tagcache 20 21 #endif 21 22 22 23 /* For all the swcodec targets */
+2
apps/plugins/tagcache/SOURCES
··· 1 + tagcache.c 2 +
+581
apps/plugins/tagcache/tagcache.c
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2023 by William Wilgus 11 + * 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. 16 + * 17 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 + * KIND, either express or implied. 19 + * 20 + ****************************************************************************/ 21 + 22 + /*Plugin Includes*/ 23 + 24 + #include "plugin.h" 25 + /* Redefinitons of ANSI C functions. */ 26 + #include "lib/wrappers.h" 27 + #include "lib/helper.h" 28 + 29 + static void thread_create(void); 30 + static void thread(void); /* the thread running it all */ 31 + static void allocate_tempbuf(void); 32 + static void free_tempbuf(void); 33 + static bool do_timed_yield(void); 34 + static void _log(const char *fmt, ...); 35 + /*Aliases*/ 36 + #if 0 37 + #ifdef ROCKBOX_HAS_LOGF 38 + #define logf rb->logf 39 + #else 40 + #define logf(...) {} 41 + #endif 42 + #endif 43 + 44 + 45 + #define logf _log 46 + #define sleep rb->sleep 47 + #define qsort rb->qsort 48 + 49 + #define write(x,y,z) rb->write(x,y,z) 50 + #define ftruncate rb->ftruncate 51 + #define remove rb->remove 52 + 53 + #define vsnprintf rb->vsnprintf 54 + #define mkdir rb->mkdir 55 + #define filesize rb->filesize 56 + 57 + #define strtok_r rb->strtok_r 58 + #define strncasecmp rb->strncasecmp 59 + #define strcasecmp rb->strcasecmp 60 + 61 + #define current_tick (*rb->current_tick) 62 + #define crc_32(x,y,z) rb->crc_32(x,y,z) 63 + 64 + 65 + #ifndef SIMULATOR 66 + #define errno (*rb->__errno()) 67 + #endif 68 + #define ENOENT 2 /* No such file or directory */ 69 + #define EEXIST 17 /* File exists */ 70 + #define MAX_LOG_SIZE 16384 71 + 72 + #define EV_EXIT MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0xFF) 73 + #define EV_ACTION MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0x02) 74 + #define EV_STARTUP MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0x01) 75 + 76 + /* communication to the worker thread */ 77 + static struct 78 + { 79 + int user_index; 80 + bool exiting; /* signal to the thread that we want to exit */ 81 + bool resume; 82 + unsigned int id; /* worker thread id */ 83 + struct event_queue queue; /* thread event queue */ 84 + long last_useraction_tick; 85 + } gThread; 86 + 87 + 88 + /*Support Fns*/ 89 + /* open but with a builtin printf for assembling the path */ 90 + int open_pathfmt(char *buf, size_t size, int oflag, const char *pathfmt, ...) 91 + { 92 + va_list ap; 93 + va_start(ap, pathfmt); 94 + vsnprintf(buf, size, pathfmt, ap); 95 + va_end(ap); 96 + if ((oflag & O_PATH) == O_PATH) 97 + return -1; 98 + int handle = open(buf, oflag, 0666); 99 + //logf("Open: %s %d flag: %x", buf, handle, oflag); 100 + return handle; 101 + } 102 + 103 + static void sleep_yield(void) 104 + { 105 + rb->queue_remove_from_head(&gThread.queue, EV_ACTION); 106 + rb->queue_post(&gThread.queue, EV_ACTION, 0); 107 + sleep(1); 108 + #undef yield 109 + rb->yield(); 110 + #define yield sleep_yield 111 + } 112 + 113 + /* make sure tag can be displayed by font pf*/ 114 + static bool text_is_displayable(struct font *pf, unsigned char *src) 115 + { 116 + unsigned short code; 117 + const unsigned char *ptr = src; 118 + while(*ptr) 119 + { 120 + ptr = rb->utf8decode(ptr, &code); 121 + 122 + if(!rb->font_get_bits(pf, code)) 123 + { 124 + return false; 125 + } 126 + } 127 + return true; 128 + } 129 + 130 + /* callback for each tag if false returned tag will not be added */ 131 + bool user_check_tag(int index_type, char* build_idx_buf) 132 + { 133 + static struct font *pf = NULL; 134 + if (!pf) 135 + pf = rb->font_get(FONT_UI); 136 + 137 + if (index_type == tag_artist || index_type == tag_album || 138 + index_type == tag_genre || index_type == tag_title || 139 + index_type == tag_composer || index_type == tag_comment || 140 + index_type == tag_albumartist || index_type == tag_virt_canonicalartist) 141 + { 142 + /* this could be expanded with more rules / transformations */ 143 + if (rb->utf8length(build_idx_buf) != strlen(build_idx_buf)) 144 + { 145 + if (!text_is_displayable(pf, build_idx_buf)) 146 + { 147 + logf("Can't display (%d) %s", index_type, build_idx_buf); 148 + } 149 + } 150 + } 151 + return true; 152 + } 153 + 154 + /* undef features we don't need */ 155 + #undef HAVE_DIRCACHE 156 + #undef HAVE_TC_RAMCACHE 157 + #undef HAVE_EEPROM_SETTINGS 158 + /* paste the whole tagcache.c file */ 159 + #include "../tagcache.c" 160 + 161 + static bool logdump(bool append); 162 + static unsigned char logbuffer[MAX_LOG_SIZE + 1]; 163 + static int logindex; 164 + static bool logwrap; 165 + static bool logenabled = true; 166 + 167 + static void check_logindex(void) 168 + { 169 + if(logindex >= MAX_LOG_SIZE) 170 + { 171 + /* wrap */ 172 + logdump(true); 173 + //logwrap = true; 174 + logindex = 0; 175 + } 176 + } 177 + 178 + static int log_push(void *userp, int c) 179 + { 180 + (void)userp; 181 + 182 + logbuffer[logindex++] = c; 183 + check_logindex(); 184 + 185 + return 1; 186 + } 187 + 188 + /* our logf function */ 189 + static void _log(const char *fmt, ...) 190 + { 191 + if (!logenabled) 192 + { 193 + rb->splash(10, "log not enabled"); 194 + return; 195 + } 196 + 197 + 198 + #ifdef USB_ENABLE_SERIAL 199 + int old_logindex = logindex; 200 + #endif 201 + va_list ap; 202 + 203 + va_start(ap, fmt); 204 + 205 + #if (CONFIG_PLATFORM & PLATFORM_HOSTED) 206 + char buf[1024]; 207 + vsnprintf(buf, sizeof buf, fmt, ap); 208 + DEBUGF("%s\n", buf); 209 + /* restart va_list otherwise the result if undefined when vuprintf is called */ 210 + va_end(ap); 211 + va_start(ap, fmt); 212 + #endif 213 + 214 + rb->vuprintf(log_push, NULL, fmt, ap); 215 + va_end(ap); 216 + 217 + /* add trailing zero */ 218 + log_push(NULL, '\0'); 219 + } 220 + 221 + 222 + int compute_nb_lines(int w, struct font* font) 223 + { 224 + int i, nb_lines; 225 + int cur_x, delta_x; 226 + 227 + if(logindex>= MAX_LOG_SIZE || (logindex == 0 && !logwrap)) 228 + return 0; 229 + 230 + if(logwrap) 231 + i = logindex; 232 + else 233 + i = 0; 234 + 235 + cur_x = 0; 236 + nb_lines = 0; 237 + 238 + do { 239 + if(logbuffer[i] == '\0') 240 + { 241 + cur_x = 0; 242 + nb_lines++; 243 + } 244 + else 245 + { 246 + /* does character fit on this line ? */ 247 + delta_x = rb->font_get_width(font, logbuffer[i]); 248 + 249 + if(cur_x + delta_x > w) 250 + { 251 + cur_x = 0; 252 + nb_lines++; 253 + } 254 + 255 + /* update pointer */ 256 + cur_x += delta_x; 257 + } 258 + 259 + i++; 260 + if(i >= MAX_LOG_SIZE) 261 + i = 0; 262 + } while(i != logindex); 263 + 264 + return nb_lines; 265 + } 266 + 267 + static bool logdisplay(void) 268 + { 269 + 270 + int w, h, i, index; 271 + int fontnr; 272 + static int delta_y = -1; 273 + int cur_x, cur_y, delta_x; 274 + struct font* font; 275 + 276 + char buf[2]; 277 + 278 + fontnr = FONT_FIRSTUSERFONT; 279 + font = rb->font_get(fontnr); 280 + buf[1] = '\0'; 281 + w = LCD_WIDTH; 282 + h = LCD_HEIGHT; 283 + 284 + if (delta_y < 0) /* init, get the horizontal size of each line */ 285 + { 286 + rb->font_getstringsize("A", NULL, &delta_y, fontnr); 287 + /* start at the end of the log */ 288 + gThread.user_index = compute_nb_lines(w, font) - h/delta_y -1; 289 + /* user_index will be number of the first line to display (warning: line!=log entry) */ 290 + /* if negative, will be set 0 to zero later */ 291 + } 292 + 293 + 294 + rb->lcd_clear_display(); 295 + 296 + if(gThread.user_index < 0 || gThread.user_index >= MAX_LOG_SIZE) 297 + gThread.user_index = 0; 298 + 299 + 300 + if(logwrap) 301 + i = logindex; 302 + else 303 + i = 0; 304 + 305 + index = 0; 306 + cur_x = 0; 307 + cur_y = 0; 308 + 309 + /* nothing to print ? */ 310 + if(logindex == 0 && !logwrap) 311 + goto end_print; 312 + 313 + do { 314 + if(logbuffer[i] == '\0') 315 + { 316 + /* should be display a newline ? */ 317 + if(index >= gThread.user_index) 318 + cur_y += delta_y; 319 + cur_x = 0; 320 + index++; 321 + } 322 + else 323 + { 324 + /* does character fit on this line ? */ 325 + delta_x = rb->font_get_width(font, logbuffer[i]); 326 + 327 + if(cur_x + delta_x > w) 328 + { 329 + /* should be display a newline ? */ 330 + if(index >= gThread.user_index) 331 + cur_y += delta_y; 332 + cur_x = 0; 333 + index++; 334 + } 335 + 336 + /* should we print character ? */ 337 + if(index >= gThread.user_index) 338 + { 339 + buf[0] = logbuffer[i]; 340 + rb->lcd_putsxy(cur_x, cur_y, buf); 341 + } 342 + 343 + /* update pointer */ 344 + cur_x += delta_x; 345 + } 346 + i++; 347 + /* did we fill the screen ? */ 348 + if(cur_y > h - delta_y) 349 + { 350 + if (TIME_AFTER(current_tick, gThread.last_useraction_tick + HZ)) 351 + gThread.user_index++; 352 + break; 353 + } 354 + 355 + if(i >= MAX_LOG_SIZE) 356 + i = 0; 357 + } while(i != logindex); 358 + 359 + end_print: 360 + rb->lcd_update(); 361 + 362 + return false; 363 + } 364 + 365 + static bool logdump(bool append) 366 + { 367 + int fd; 368 + int flags = O_CREAT|O_WRONLY|O_TRUNC; 369 + /* nothing to print ? */ 370 + if(!logenabled || (logindex == 0 && !logwrap)) 371 + { 372 + /* nothing is logged just yet */ 373 + return false; 374 + } 375 + if (!append) 376 + { 377 + flags = O_CREAT|O_WRONLY|O_APPEND; 378 + } 379 + 380 + fd = open(ROCKBOX_DIR "/db_commit_log.txt", flags, 0666); 381 + logenabled = false; 382 + if(-1 != fd) { 383 + int i; 384 + 385 + if(logwrap) 386 + i = logindex; 387 + else 388 + i = 0; 389 + 390 + do { 391 + if(logbuffer[i]=='\0') 392 + rb->fdprintf(fd, "\n"); 393 + else 394 + rb->fdprintf(fd, "%c", logbuffer[i]); 395 + 396 + i++; 397 + if(i >= MAX_LOG_SIZE) 398 + i = 0; 399 + } while(i != logindex); 400 + 401 + close(fd); 402 + } 403 + 404 + logenabled = true; 405 + 406 + return false; 407 + } 408 + 409 + static void allocate_tempbuf(void) 410 + { 411 + tempbuf_size = 0; 412 + tempbuf = rb->plugin_get_audio_buffer(&tempbuf_size); 413 + tempbuf_size &= ~0x03; 414 + 415 + } 416 + 417 + static void free_tempbuf(void) 418 + { 419 + if (tempbuf_size == 0) 420 + return ; 421 + 422 + rb->plugin_release_audio_buffer(); 423 + tempbuf = NULL; 424 + tempbuf_size = 0; 425 + } 426 + 427 + static bool do_timed_yield(void) 428 + { 429 + /* Sorting can lock up for quite a while, so yield occasionally */ 430 + static long wakeup_tick = 0; 431 + if (TIME_AFTER(current_tick, wakeup_tick)) 432 + { 433 + 434 + yield(); 435 + 436 + wakeup_tick = current_tick + (HZ/5); 437 + return true; 438 + } 439 + return false; 440 + } 441 + 442 + /*-----------------------------------------------------------------------------*/ 443 + /******* plugin_start ******* */ 444 + /*-----------------------------------------------------------------------------*/ 445 + 446 + enum plugin_status plugin_start(const void* parameter) 447 + { 448 + (void) parameter; 449 + 450 + /* Turn off backlight timeout */ 451 + backlight_ignore_timeout(); 452 + 453 + memset(&tc_stat, 0, sizeof(struct tagcache_stat)); 454 + memset(&current_tcmh, 0, sizeof(struct master_header)); 455 + filenametag_fd = -1; 456 + 457 + strlcpy(tc_stat.db_path, rb->global_settings->tagcache_db_path, sizeof(tc_stat.db_path)); 458 + if (!rb->dir_exists(tc_stat.db_path)) /* on fail use default DB path */ 459 + strlcpy(tc_stat.db_path, ROCKBOX_DIR, sizeof(tc_stat.db_path)); 460 + tc_stat.initialized = true; 461 + 462 + memset(&gThread, 0, sizeof(gThread)); 463 + logf("started"); 464 + logdump(false); 465 + 466 + thread_create(); 467 + gThread.user_index = 0; 468 + logdisplay(); /* get something on the screen while user waits */ 469 + 470 + allocate_tempbuf(); 471 + 472 + commit(); 473 + 474 + if (tc_stat.ready) 475 + rb->tagcache_commit_finalize(); 476 + 477 + free_tempbuf(); 478 + 479 + logdump(true); 480 + gThread.user_index++; 481 + logdisplay(); 482 + rb->thread_wait(gThread.id); 483 + rb->queue_delete(&gThread.queue); 484 + 485 + /* Turn on backlight timeout (revert to settings) */ 486 + backlight_use_settings(); 487 + return PLUGIN_OK; 488 + } 489 + 490 + /****************** main thread + helper ******************/ 491 + static void thread(void) 492 + { 493 + struct queue_event ev; 494 + while (!gThread.exiting) 495 + { 496 + rb->queue_wait_w_tmo(&gThread.queue, &ev, 1); 497 + switch (ev.id) 498 + { 499 + case SYS_USB_CONNECTED: 500 + rb->usb_acknowledge(SYS_USB_CONNECTED_ACK); 501 + logenabled = false; 502 + break; 503 + case SYS_USB_DISCONNECTED: 504 + logenabled = true; 505 + /*fall through*/ 506 + case EV_STARTUP: 507 + logf("Thread Started"); 508 + break; 509 + case EV_EXIT: 510 + return; 511 + default: 512 + break; 513 + } 514 + logdisplay(); 515 + 516 + int action = rb->get_action(CONTEXT_STD, HZ/10); 517 + 518 + switch( action ) 519 + { 520 + case ACTION_NONE: 521 + break; 522 + case ACTION_STD_NEXT: 523 + case ACTION_STD_NEXTREPEAT: 524 + gThread.last_useraction_tick = current_tick; 525 + gThread.user_index++; 526 + break; 527 + case ACTION_STD_PREV: 528 + case ACTION_STD_PREVREPEAT: 529 + gThread.last_useraction_tick = current_tick; 530 + gThread.user_index--; 531 + break; 532 + case ACTION_STD_OK: 533 + gThread.last_useraction_tick = current_tick; 534 + gThread.user_index = 0; 535 + break; 536 + case SYS_POWEROFF: 537 + case ACTION_STD_CANCEL: 538 + gThread.exiting = true; 539 + return; 540 + #ifdef HAVE_TOUCHSCREEN 541 + case ACTION_TOUCHSCREEN: 542 + { 543 + gThread.last_useraction_tick = current_tick; 544 + short x, y; 545 + static int prev_y; 546 + 547 + action = action_get_touchscreen_press(&x, &y); 548 + 549 + if(action & BUTTON_REL) 550 + prev_y = 0; 551 + else 552 + { 553 + if(prev_y != 0) 554 + gThread.user_index += (prev_y - y) / delta_y; 555 + 556 + prev_y = y; 557 + } 558 + } 559 + #endif 560 + default: 561 + break; 562 + } 563 + 564 + 565 + yield(); 566 + } 567 + } 568 + 569 + static void thread_create(void) 570 + { 571 + /* put the thread's queue in the bcast list */ 572 + rb->queue_init(&gThread.queue, true); 573 + /*Note: tagcache_stack is defined in apps/tagcache.c */ 574 + gThread.last_useraction_tick = current_tick; 575 + gThread.id = rb->create_thread(thread, tagcache_stack, sizeof(tagcache_stack), 576 + 0, "db_commit" 577 + IF_PRIO(, PRIORITY_USER_INTERFACE) 578 + IF_COP(, CPU)); 579 + rb->queue_post(&gThread.queue, EV_STARTUP, 0); 580 + yield(); 581 + }
+25
apps/plugins/tagcache/tagcache.h
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 11 + * 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. 16 + * 17 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 + * KIND, either express or implied. 19 + * 20 + ****************************************************************************/ 21 + #ifndef _TC_PLUGIN_ 22 + #define _TC_PLUGIN_ 23 + #endif /*_TC_PLUGIN_ */ 24 + 25 +
+30
apps/plugins/tagcache/tagcache.make
··· 1 + # __________ __ ___. 2 + # Open \______ \ ____ ____ | | _\_ |__ _______ ___ 3 + # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 4 + # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 5 + # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 6 + # \/ \/ \/ \/ \/ 7 + # $Id$ 8 + # 9 + 10 + TCPLUG_SRCDIR := $(APPSDIR)/plugins/tagcache 11 + TCPLUG_BUILDDIR := $(BUILDDIR)/apps/plugins/tagcache 12 + 13 + ROCKS += $(TCPLUG_BUILDDIR)/db_commit.rock 14 + 15 + TCPLUG_FLAGS = $(PLUGINFLAGS) -fno-strict-aliasing -Wno-unused \ 16 + -I$(TCPLUG_SRCDIR) -ffunction-sections \ 17 + -fdata-sections -Wl,--gc-sections 18 + TCPLUG_SRC := $(call preprocess, $(TCPLUG_SRCDIR)/SOURCES) 19 + TCPLUG_OBJ := $(call c2obj, $(TCPLUG_SRC)) 20 + 21 + # add source files to OTHER_SRC to get automatic dependencies 22 + OTHER_SRC += $(APPSDIR)/tagcache.c $(TCPLUG_SRC) 23 + 24 + $(TCPLUG_BUILDDIR)/db_commit.rock: $(TCPLUG_OBJ) 25 + 26 + # special pattern rule for compiling with extra flags 27 + $(TCPLUG_BUILDDIR)/%.o: $(TCPLUG_SRCDIR)/%.c $(TCPLUG_SRCDIR)/tagcache.make 28 + $(SILENT)mkdir -p $(dir $@) 29 + $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) -I$(dir $<) $(TCPLUG_FLAGS) -c $< -o $@ 30 +
+53 -17
apps/tagcache.c
··· 55 55 * 56 56 */ 57 57 58 + #if !defined(PLUGIN) 58 59 59 60 /*#define LOGF_ENABLE*/ 60 61 /*#define LOGF_CLAUSES define to enable logf clause matching (LOGF_ENABLE req'd) */ ··· 91 92 #include "lang.h" 92 93 #include "eeprom_settings.h" 93 94 #endif 94 - 95 + #endif /*!defined(PLUGIN)*/ 95 96 /* 96 97 * Define this to support non-native endian tagcache files. 97 98 * Databases are always written in native endian so this is ··· 131 132 132 133 /* Idle time before committing events in the command queue. */ 133 134 #define TAGCACHE_COMMAND_QUEUE_COMMIT_DELAY HZ*2 135 + 136 + /* Dont commit database_tmp data. */ 137 + #define TAGCACHE_FILE_NOCOMMIT "database_commit.ignore" 134 138 135 139 /* Temporary database containing new tags to be committed to the main db. */ 136 140 #define TAGCACHE_FILE_TEMP "database_tmp.tcd" ··· 730 734 return true; 731 735 } 732 736 733 - 737 + #if !defined(PLUGIN) 734 738 #ifndef __PCTOOL__ 735 739 static bool do_timed_yield(void) 736 740 { ··· 2355 2359 2356 2360 #undef ADD_TAG 2357 2361 } 2362 + #endif /*!defined(PLUGIN)*/ 2363 + 2358 2364 2359 2365 static bool tempbuf_insert(char *str, int id, int idx_id, bool unique) 2360 2366 { ··· 3064 3070 } 3065 3071 str_setlen(build_idx_buf, entry.tag_length[index_type]); 3066 3072 3067 - if (TAGCACHE_IS_UNIQUE(index_type)) 3068 - error = !tempbuf_insert(build_idx_buf, i, -1, true); 3069 - else 3070 - error = !tempbuf_insert(build_idx_buf, i, 3071 - tcmh.tch.entry_count + i, false); 3073 + #if defined(PLUGIN) 3074 + if (user_check_tag(index_type, build_idx_buf)) 3075 + #endif /*defined(PLUGIN)*/ 3076 + { 3077 + if (TAGCACHE_IS_UNIQUE(index_type)) 3078 + error = !tempbuf_insert(build_idx_buf, i, -1, true); 3079 + else 3080 + error = !tempbuf_insert(build_idx_buf, i, 3081 + tcmh.tch.entry_count + i, false); 3072 3082 3073 - if (error) 3074 - { 3075 - logf("insert error"); 3076 - goto error_exit; 3083 + if (error) 3084 + { 3085 + logf("insert error"); 3086 + goto error_exit; 3087 + } 3077 3088 } 3078 - 3079 3089 /* Skip to next. */ 3080 3090 lseek(tmpfd, entry.data_length - entry.tag_offset[index_type] - 3081 3091 entry.tag_length[index_type], SEEK_CUR); ··· 3299 3309 while (write_lock) 3300 3310 sleep(1); 3301 3311 3302 - tmpfd = open_db_fd(TAGCACHE_FILE_TEMP, O_RDONLY); 3312 + #if !defined(PLUGIN) 3313 + int fd = open_db_fd(TAGCACHE_FILE_NOCOMMIT, O_RDONLY); 3314 + if (fd >= 0) 3315 + { 3316 + logf("canceling commit"); 3317 + tc_stat.commit_delayed = true; 3318 + close(fd); 3319 + tmpfd = -1; 3320 + } 3321 + else 3322 + #endif /*!defined(PLUGIN)*/ 3323 + { 3324 + tmpfd = open_db_fd(TAGCACHE_FILE_TEMP, O_RDONLY); 3325 + } 3303 3326 if (tmpfd < 0) 3304 3327 { 3305 3328 logf("nothing to commit"); ··· 3361 3384 } 3362 3385 #endif /* HAVE_TC_RAMCACHE */ 3363 3386 3387 + #if defined(PLUGIN) 3388 + if (tempbuf_size == 0) 3389 + { 3390 + tempbuf = rb->plugin_get_audio_buffer(&tempbuf_size); 3391 + tempbuf_size &= ~0x03; 3392 + } 3393 + #endif /*defined(PLUGIN)*/ 3394 + 3364 3395 /* And finally fail if there are no buffers available. */ 3365 3396 if (tempbuf_size == 0) 3366 3397 { ··· 3433 3464 close(masterfd); 3434 3465 3435 3466 logf("tagcache committed"); 3436 - tc_stat.ready = check_all_headers(); 3437 - tc_stat.readyvalid = true; 3467 + tagcache_commit_finalize(); 3438 3468 3439 3469 #if defined(HAVE_TC_RAMCACHE) 3440 3470 if (ramcache_buffer_stolen) ··· 3476 3506 return rc; 3477 3507 } 3478 3508 3509 + void tagcache_commit_finalize(void) 3510 + { 3511 + tc_stat.ready = check_all_headers(); 3512 + tc_stat.readyvalid = true; 3513 + } 3479 3514 3515 + #if !defined(PLUGIN) 3480 3516 #ifndef __PCTOOL__ 3481 3517 3482 3518 static bool modify_numeric_entry(int masterfd, int idx_id, int tag, long data) ··· 5116 5152 if (!tc_stat.ready) 5117 5153 { 5118 5154 sleep(HZ); 5119 - tc_stat.ready = check_all_headers(); 5120 - tc_stat.readyvalid = true; 5155 + tagcache_commit_finalize(); 5121 5156 } 5122 5157 5123 5158 while (1) ··· 5351 5386 { 5352 5387 return (int)(SORTED_TAGS_COUNT)+1; 5353 5388 } 5389 + #endif /*!defined(PLUGIN)*/
+1
apps/tagcache.h
··· 204 204 #endif 205 205 void tagcache_unload_ramcache(void); 206 206 #endif 207 + void tagcache_commit_finalize(void); 207 208 void tagcache_init(void) INIT_ATTR; 208 209 bool tagcache_is_initialized(void); 209 210 bool tagcache_is_fully_initialized(void);
+9
manual/rockbox_interface/tagcache.tex
··· 31 31 file named \fname{database.unignore} in it. The files in that directory and 32 32 its subdirectories will be scanned and added to the database. 33 33 34 + \subsubsection{Issues During Database Commit} 35 + 36 + You may have files on your \dap{} whose contents might not be displayed 37 + correctly or even crash the database. 38 + Placing a file named \fname{/.rockbox/database_commit.ignore} 39 + will prevent the device from committing the database automatically 40 + you can manually commit the database using the db_commit plugin in APPS 41 + with logging 42 + 34 43 \subsection{\label{ref:databasemenu}The Database Menu} 35 44 36 45 \begin{description}