/* * Copyright 2013 (c) Anna Schumaker. */ #include #include #include #include #include #include #include #include /* * Internal library functions */ struct scan_info { Library *library; std :: string path; }; static void do_scan_path(struct scan_info &); static void read_tags(const std::string &path, Library *library) { Track *track = tagdb :: add_track(path, library); get_callbacks()->on_library_track_add(track->id); } static void process_path(Library *library, const std :: string &dir, const std :: string &name) { struct scan_info scan; std :: string path = dir + "/" + name; if (g_file_test(path.c_str(), G_FILE_TEST_IS_DIR) == true) { scan.library = library; scan.path = path; idle :: schedule (do_scan_path, scan); } else read_tags(path, library); } static void do_scan_path(struct scan_info &scan) { GDir *dir; const char *name; dir = g_dir_open(scan.path.c_str(), 0, NULL); if (dir == NULL) return; name = g_dir_read_name(dir); while (name != NULL) { process_path(scan.library, scan.path, name); name = g_dir_read_name(dir); } tagdb :: commit(); get_callbacks()->on_library_update(scan.library->id, scan.library); } static void do_validate_library(unsigned int &lib_id) { std :: string path; Database *db = &tagdb :: get_track_db(); Database::iterator it; for (it = db->begin(); it != db->end(); it = db->next(it)) { Track *track = *it; if (track->library->id != lib_id) continue; if (g_file_test(track->path().c_str(), G_FILE_TEST_EXISTS) == false) { dprint("Removing file: %s\n", track->path().c_str()); tagdb :: remove_track(track->id); } } get_callbacks()->on_library_update(lib_id, tagdb :: lookup_library(lib_id)); } static void do_update_library(unsigned int lib_id) { Library *library = tagdb :: lookup_library(lib_id); struct scan_info scan = { library, library->root_path }; idle :: schedule(do_validate_library, lib_id); idle :: schedule(do_scan_path, scan); } static void do_import_track(File &f, Library *library) { struct ImportData data; unsigned int year, banned, tmp; std::string filepath = f.getline(); std::string title = f.getline(); std::string artist = f.getline(); std::string album = f.getline(); std::string comment = f.getline(); std::string genre = f.getline(); std::string lenstr = f.getline(); f >> tmp /* id */ >> year >> tmp >> data.play_count; f >> data.last_day >> data.last_month >> data.last_year >> tmp; f >> tmp >> tmp >>tmp >> banned; /* bitrate, sample, channels, banned */ f.getline(); /* get rest of line */ Track *track = tagdb :: import_track(filepath, library, data); get_callbacks()->on_library_track_add(track->id); if (banned == true) get_callbacks()->on_library_import_ban(track->id); } static void do_import_library(std::string &s) { unsigned int id, next_id, size; std::string path; bool enabled; File f(s, FILE_TYPE_LEGACY); print("Importing: %s\n", f.get_filepath()); f.open(OPEN_READ); if (f.get_version() != 2) { print("Version mismatch: %u != 2\n", f.get_version()); return; } path = f.getline(); f >> id >> enabled >> next_id >> size; Library *library = tagdb :: add_library(path); if (library == NULL) { print("Library already contains path: %s, skipping\n", path.c_str()); return; } print("Adding path: %s\n", path.c_str()); get_callbacks()->on_library_add(library->id, library); f.getline(); /* Get rest of line */ for (unsigned int i = 0; i < size; i++) do_import_track(f, library); tagdb :: commit(); get_callbacks()->on_library_update(library->id, library); library :: update_path(id); } /* * API used by the GUI begins here */ void library :: init() { tagdb :: init(); Database *db = &tagdb :: get_track_db(); Database::iterator it; for (it = db->begin(); it != db->end(); it = db->next(it)) { if ((*it)->library->enabled) get_callbacks()->on_library_track_add((*it)->id); } Database *ldb = &tagdb :: get_library_db(); Database::iterator l_it; for (l_it = ldb->begin(); l_it != ldb->end(); l_it = ldb->next(l_it)) get_callbacks()->on_library_add((*l_it)->id, *l_it); } void library :: add_path(const std::string &dir) { if (g_file_test(dir.c_str(), G_FILE_TEST_IS_DIR) == false) throw -E_INVAL; Library *library = tagdb :: add_library(dir); if (!library) return; get_callbacks()->on_library_add(library->id, library); update_path(library->id); } void library :: del_path(unsigned int id) { Database *db = &tagdb :: get_track_db(); Database::iterator it; for (it = db->begin(); it != db->end(); it = db->next(it)) { if ((*it)->library->id == id) get_callbacks()->on_library_track_del((*it)->id); } tagdb :: remove_library(id); tagdb :: commit(); } void library :: update_path(unsigned int id) { Library *library = tagdb :: lookup_library(id); if (library) do_update_library(library->id); } void library :: update_all() { Database *db = &tagdb :: get_library_db(); Database::iterator it; for (it = db->begin(); it != db->end(); it = db->next(it)) update_path((*it)->id); } void library :: set_enabled(unsigned int id, bool enabled) { Library *library = tagdb :: lookup_library(id); library->enabled = enabled; tagdb :: commit_library(); Database *db = &(tagdb :: get_track_db()); Database::iterator it; for (it = db->begin(); it != db->end(); it = db->next(it)) { if ((*it)->library->id == id) { if (enabled) get_callbacks()->on_library_track_add((*it)->id); else get_callbacks()->on_library_track_del((*it)->id); } } } void library :: import() { unsigned int i = 0; std::string name; do { std::stringstream ss; ss << i; name = ss.str(); File f(name, FILE_TYPE_LEGACY); if (f.exists() == false) break; idle :: schedule(do_import_library, name); ss.clear(); i++; } while (true); } void library :: track_played(unsigned int id) { time_t the_time = time(NULL); struct tm *now = localtime(&the_time); Track *track = tagdb :: lookup(id); if (!track) return; track->play_count++; track->last_day = now->tm_mday; track->last_month = now->tm_mon + 1; track->last_year = now->tm_year + 1900; tagdb :: commit(); get_callbacks()->on_library_track_updated(track->id); } #ifdef CONFIG_TEST void library :: print_db(DB_Type type) { switch (type) { case DB_ALBUM: break; case DB_ARTIST: break; case DB_GENRE: break; case DB_LIBRARY: break; case DB_TRACK: break; } } void library :: reset() { } #endif /* CONFIG_TEST */