/* MiniDLNA media server * Copyright (C) 2009-2010 Justin Maggard * * This file is part of MiniDLNA. * * MiniDLNA is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * MiniDLNA is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MiniDLNA. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "tagutils/tagutils.h" #include "upnpglobalvars.h" #include "scanner.h" #include "metadata.h" #include "utils.h" #include "sql.h" #include "log.h" int insert_playlist(const char * path, char * name) { struct song_metadata plist; struct stat file; int items = 0, matches, ret; char type[4]; strncpy(type, strrchr(name, '.')+1, 4); if( start_plist(path, NULL, &file, NULL, type) != 0 ) { DPRINTF(E_WARN, L_SCANNER, "Bad playlist [%s]\n", path); return -1; } while( (ret = next_plist_track(&plist, &file, NULL, type)) == 0 ) { items++; freetags(&plist); } if( ret == 2 ) // Bad playlist -- contains binary characters { DPRINTF(E_WARN, L_SCANNER, "Bad playlist [%s]\n", path); return -1; } strip_ext(name); DPRINTF(E_DEBUG, L_SCANNER, "Playlist %s contains %d items\n", name, items); matches = sql_get_int_field(db, "SELECT count(*) from PLAYLISTS where NAME = '%q'", name); if( matches > 0 ) { sql_exec(db, "INSERT into PLAYLISTS" " (NAME, PATH, ITEMS) " "VALUES" " ('%q(%d)', '%q', %d)", name, matches, path, items); } else { sql_exec(db, "INSERT into PLAYLISTS" " (NAME, PATH, ITEMS) " "VALUES" " ('%q', '%q', %d)", name, path, items); } return 0; } static unsigned int gen_dir_hash(const char *path) { char dir[PATH_MAX], *base; int len; strncpy(dir, path, sizeof(dir)); dir[sizeof(dir)-1] = '\0'; base = strrchr(dir, '/'); if( !base ) base = strrchr(dir, '\\'); if( base ) { *base = '\0'; len = base - dir; } else return 0; return DJBHash(dir, len); } int fill_playlists() { int rows, i, found, len; char **result; char *plpath, *plname, *fname, *last_dir; unsigned int hash, last_hash = 0; char class[] = "playlistContainer"; struct song_metadata plist; struct stat file; char type[4]; sqlite_int64 plID, detailID; char sql_buf[] = "SELECT ID, NAME, PATH from PLAYLISTS where ITEMS > FOUND"; DPRINTF(E_WARN, L_SCANNER, "Parsing playlists...\n"); if( sql_get_table(db, sql_buf, &result, &rows, NULL) != SQLITE_OK ) return -1; if( !rows ) goto done; rows++; for( i=3; i 0 ) { found: DPRINTF(E_DEBUG, L_SCANNER, "+ %s found in db\n", fname); sql_exec(db, "INSERT into OBJECTS" " (OBJECT_ID, PARENT_ID, CLASS, DETAIL_ID, NAME, REF_ID) " "SELECT" " '%s$%llX$%d', '%s$%llX', CLASS, DETAIL_ID, NAME, OBJECT_ID from OBJECTS" " where DETAIL_ID = %lld and OBJECT_ID glob '" BROWSEDIR_ID "$*'", MUSIC_PLIST_ID, plID, plist.track, MUSIC_PLIST_ID, plID, detailID); if( !last_dir ) { last_dir = sql_get_text_field(db, "SELECT PATH from DETAILS where ID = %lld", detailID); fname = strrchr(last_dir, '/'); if( fname ) *fname = '\0'; last_hash = hash; } found++; } else { DPRINTF(E_DEBUG, L_SCANNER, "- %s not found in db\n", fname); if( strchr(fname, '\\') ) { fname = modifyString(fname, "\\", "/", 0); goto retry; } else if( (fname = strchr(fname, '/')) ) { fname++; goto retry; } } freetags(&plist); } if( last_dir ) { sqlite3_free(last_dir); last_dir = NULL; } sql_exec(db, "UPDATE PLAYLISTS set FOUND = %d where ID = %lld", found, plID); } done: sqlite3_free_table(result); DPRINTF(E_WARN, L_SCANNER, "Finished parsing playlists.\n"); return 0; }