static void video_query(bmdb_t *b, void *db) { sqlite3_stmt *stmt; int rc = db_prepare(db, &stmt, "SELECT i.url, p.url, i.contenttype " "FROM item AS i, item AS p " "WHERE i.url LIKE ?1 " "AND (i.contenttype == 5 OR i.contenttype == 7) " "AND i.parent = p.id" ); if(rc != SQLITE_OK) return; char q[PATH_MAX]; db_escape_path_query(q, sizeof(q), b->b_query); sqlite3_bind_text(stmt, 1, q, -1, SQLITE_STATIC); while((rc = db_step(stmt)) == SQLITE_ROW) { const char *url = (const char *)sqlite3_column_text(stmt, 0); const char *parent = (const char *)sqlite3_column_text(stmt, 1); rstr_t *ct = rstr_alloc(content2type(sqlite3_column_int(stmt, 2))); add_item(b, url, parent, ct, NULL, 0, NULL, 0); rstr_release(ct); } sqlite3_finalize(stmt); }
/** * Consume 'locate' (updatedb) output results and feed into search results. */ static void fa_locate_searcher (fa_search_t *fas) { char buf[PATH_MAX]; char iconpath[PATH_MAX]; regex_t preg; prop_t *entries[2] = {NULL, NULL}; prop_t *nodes[2] = {NULL, NULL}; int t, i; if (fa_create_paths_regex(&preg) == -1) return fa_search_destroy(fas); snprintf(iconpath, sizeof(iconpath), "%s/resources/fileaccess/fs_icon.png", showtime_dataroot()); /* Consume 'locate' results. */ while (1) { char url[PATH_MAX+strlen("file://")]; prop_t *p, *metadata; const char *type; struct fa_stat fs; int ctype; prop_courier_poll(fas->fas_pc); if (!fas->fas_run) break; if (!fgets(buf, sizeof(buf), fas->fas_fp)) break; if (!*buf || *buf == '\n') continue; buf[strlen(buf)-1] = '\0'; /* Ignore dot-files/dirs. */ if (strstr(buf, "/.")) continue; if (regexec(&preg, buf, 0, NULL, 0)) { TRACE(TRACE_DEBUG, "FA", "Searcher: %s: \"%s\" not matching regex: SKIP", fas->fas_query, buf); continue; } /* Probe media type. * * FIXME: We might want to hide matching files under a matching directory, * or the other way around. * E..g: * Metallica/ * 01-Metallica-Song1.mp3 * 02-Metallica-Song1.mp3 * * Should either hide Metallica/ or 01-Metallica-Song1..2.. * But that would require the 'locate' output to be sorted, is it? * Its also problematic where a sub set of the tracks matches * the directory name. Then what should we show?. * * There is also the problem with: * Scrubs S01E01/ * Scrubs_s01e01.avi * Sample/ * Scrubs_s01e01_sample.avi * Which will show as four separate entries, less than optimal. * * For now we provide all matches, directories and files, * matching on the entire path (not just the basename). */ snprintf(url, sizeof(url), "file://%s", buf); if (fa_stat(url, &fs, NULL, 0)) continue; metadata = prop_create_root("metadata"); if(fs.fs_type == CONTENT_DIR) { ctype = CONTENT_DIR; prop_set_string(prop_create(metadata, "title"), basename(buf)); } else { metadata_t *md = fa_probe_metadata(url, NULL, 0); if(md != NULL) { ctype = md->md_contenttype; metadata_destroy(md); } else { ctype = CONTENT_UNKNOWN; } } if (ctype == CONTENT_UNKNOWN) continue; switch(ctype) { case CONTENT_AUDIO: t = 0; break; case CONTENT_VIDEO: case CONTENT_DVD: t = 1; break; default: continue; } if(nodes[t] == NULL) if(search_class_create(fas->fas_nodes, &nodes[t], &entries[t], t ? "Local video files" : "Local audio files", iconpath)) break; prop_add_int(entries[t], 1); if ((type = content2type(ctype)) == NULL) continue; /* Unlikely.. */ p = prop_create_root(NULL); if (prop_set_parent(metadata, p)) prop_destroy(metadata); prop_set_string(prop_create(p, "url"), url); prop_set_string(prop_create(p, "type"), type); if(prop_set_parent(p, nodes[t])) { prop_destroy(p); break; } } for(i = 0; i < 2; i++) { if(nodes[i]) prop_ref_dec(nodes[i]); if(entries[i]) prop_ref_dec(entries[i]); } TRACE(TRACE_DEBUG, "FA", "Searcher: %s: Done", fas->fas_query); fa_search_destroy(fas); regfree(&preg); }