static int file_open_file(prop_t *page, const char *url, struct fa_stat *fs) { char redir[URL_MAX]; char errbuf[200]; int c; prop_t *meta; meta = prop_create_root("metadata"); c = fa_probe(meta, url, redir, sizeof(redir), errbuf, sizeof(errbuf), fs, 1); switch(c) { case CONTENT_ARCHIVE: case CONTENT_ALBUM: prop_destroy(meta); return file_open_dir(page, redir); case CONTENT_AUDIO: if(!file_open_audio(page, url)) { prop_destroy(meta); return 0; } playqueue_play(url, meta, 0); return playqueue_open(page); case CONTENT_VIDEO: case CONTENT_DVD: prop_destroy(meta); return backend_open_video(page, url); case CONTENT_IMAGE: return file_open_image(page, meta); case CONTENT_PLUGIN: plugin_open_file(page, url); return 0; default: prop_destroy(meta); return nav_open_error(page, errbuf); } }
/** * Consume 'locate' (updatedb) output results and feed into search results. */ static void fa_locate_searcher (fa_search_t *fas) { char buf[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); /* 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 ctype = fa_probe(metadata, url, NULL, 0, NULL, 0, NULL, 1); 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", FA_LOCALFILES_ICON)) 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); }