2013-10-27 17:25:26 -04:00
|
|
|
/*
|
|
|
|
* Copyright 2013 (c) Anna Schumaker.
|
|
|
|
*/
|
2014-01-15 20:40:24 -05:00
|
|
|
#include <callback.h>
|
2014-01-01 13:34:25 -05:00
|
|
|
#include <filter.h>
|
|
|
|
#include <idle.h>
|
2013-10-27 17:25:26 -04:00
|
|
|
#include <library.h>
|
2013-12-31 20:14:52 -05:00
|
|
|
#include <print.h>
|
2013-10-27 17:25:26 -04:00
|
|
|
|
|
|
|
#include <glib.h>
|
2013-12-31 20:14:52 -05:00
|
|
|
#include <sstream>
|
2014-01-29 22:45:01 -05:00
|
|
|
#include <time.h>
|
2013-10-27 17:25:26 -04:00
|
|
|
|
2013-11-10 17:37:35 -05:00
|
|
|
|
2013-11-10 16:09:31 -05:00
|
|
|
/*
|
|
|
|
* Internal library functions
|
|
|
|
*/
|
2014-01-01 13:34:25 -05:00
|
|
|
struct scan_info {
|
2014-03-29 11:44:39 -04:00
|
|
|
Library *library;
|
2014-01-01 13:34:25 -05:00
|
|
|
std :: string path;
|
|
|
|
};
|
|
|
|
static void do_scan_path(struct scan_info &);
|
2013-11-10 16:09:31 -05:00
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
static void read_tags(const std::string &path, Library *library)
|
2013-11-10 16:09:31 -05:00
|
|
|
{
|
2014-03-29 11:44:39 -04:00
|
|
|
Track *track = tagdb :: add_track(path, library);
|
|
|
|
get_callbacks()->on_library_track_add(track->id);
|
2013-11-10 16:09:31 -05:00
|
|
|
}
|
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
static void process_path(Library *library, const std :: string &dir,
|
2013-11-10 16:09:31 -05:00
|
|
|
const std :: string &name)
|
|
|
|
{
|
2014-01-01 13:34:25 -05:00
|
|
|
struct scan_info scan;
|
2013-11-10 16:09:31 -05:00
|
|
|
std :: string path = dir + "/" + name;
|
|
|
|
|
2014-01-01 13:34:25 -05:00
|
|
|
if (g_file_test(path.c_str(), G_FILE_TEST_IS_DIR) == true) {
|
2014-03-29 11:44:39 -04:00
|
|
|
scan.library = library;
|
2014-01-01 13:34:25 -05:00
|
|
|
scan.path = path;
|
|
|
|
idle :: schedule (do_scan_path, scan);
|
2014-03-29 11:44:39 -04:00
|
|
|
} else
|
|
|
|
read_tags(path, library);
|
2013-11-10 17:37:35 -05:00
|
|
|
}
|
|
|
|
|
2014-01-01 13:34:25 -05:00
|
|
|
static void do_scan_path(struct scan_info &scan)
|
2013-11-10 16:09:31 -05:00
|
|
|
{
|
|
|
|
GDir *dir;
|
|
|
|
const char *name;
|
|
|
|
|
2014-01-01 13:34:25 -05:00
|
|
|
dir = g_dir_open(scan.path.c_str(), 0, NULL);
|
2013-11-10 16:09:31 -05:00
|
|
|
if (dir == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
name = g_dir_read_name(dir);
|
|
|
|
while (name != NULL) {
|
2014-03-29 11:44:39 -04:00
|
|
|
process_path(scan.library, scan.path, name);
|
2013-11-10 16:09:31 -05:00
|
|
|
name = g_dir_read_name(dir);
|
|
|
|
}
|
2014-01-15 20:40:24 -05:00
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
tagdb :: commit();
|
|
|
|
get_callbacks()->on_library_update(scan.library->id, scan.library);
|
2013-11-10 16:09:31 -05:00
|
|
|
}
|
|
|
|
|
2014-01-01 13:34:25 -05:00
|
|
|
static void do_validate_library(unsigned int &lib_id)
|
2013-12-22 15:38:27 -05:00
|
|
|
{
|
|
|
|
std :: string path;
|
2014-03-29 11:44:39 -04:00
|
|
|
Database<Track> *db = &tagdb :: get_track_db();
|
|
|
|
Database<Track>::iterator it;
|
2013-12-22 15:38:27 -05:00
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
for (it = db->begin(); it != db->end(); it = db->next(it)) {
|
|
|
|
Track *track = *it;
|
|
|
|
if (track->library->id != lib_id)
|
2013-12-22 15:38:27 -05:00
|
|
|
continue;
|
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
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);
|
2013-12-22 15:38:27 -05:00
|
|
|
}
|
|
|
|
}
|
2014-01-15 20:40:24 -05:00
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
get_callbacks()->on_library_update(lib_id, tagdb :: lookup_library(lib_id));
|
2013-12-22 15:38:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void do_update_library(unsigned int lib_id)
|
|
|
|
{
|
2014-03-29 11:44:39 -04:00
|
|
|
Library *library = tagdb :: lookup_library(lib_id);
|
|
|
|
struct scan_info scan = { library, library->root_path };
|
2014-01-01 13:34:25 -05:00
|
|
|
idle :: schedule(do_validate_library, lib_id);
|
|
|
|
idle :: schedule(do_scan_path, scan);
|
2013-12-22 15:38:27 -05:00
|
|
|
}
|
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
static void do_import_track(File &f, Library *library)
|
2014-01-01 20:26:18 -05:00
|
|
|
{
|
|
|
|
struct ImportData data;
|
2014-03-29 11:44:39 -04:00
|
|
|
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;
|
2014-02-02 14:20:56 -05:00
|
|
|
f >> tmp >> tmp >>tmp >> banned; /* bitrate, sample, channels, banned */
|
2014-01-01 20:26:18 -05:00
|
|
|
f.getline(); /* get rest of line */
|
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
Track *track = tagdb :: import_track(filepath, library, data);
|
|
|
|
get_callbacks()->on_library_track_add(track->id);
|
2014-02-02 14:20:56 -05:00
|
|
|
|
|
|
|
if (banned == true)
|
2014-03-29 11:44:39 -04:00
|
|
|
get_callbacks()->on_library_import_ban(track->id);
|
2014-01-01 20:26:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
Library *library = tagdb :: add_library(path);
|
|
|
|
if (library == NULL) {
|
2014-01-01 20:26:18 -05:00
|
|
|
print("Library already contains path: %s, skipping\n", path.c_str());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
print("Adding path: %s\n", path.c_str());
|
2014-03-29 11:44:39 -04:00
|
|
|
get_callbacks()->on_library_add(library->id, library);
|
2014-01-01 20:26:18 -05:00
|
|
|
|
|
|
|
f.getline(); /* Get rest of line */
|
|
|
|
for (unsigned int i = 0; i < size; i++)
|
2014-03-29 11:44:39 -04:00
|
|
|
do_import_track(f, library);
|
|
|
|
tagdb :: commit();
|
|
|
|
get_callbacks()->on_library_update(library->id, library);
|
2014-01-01 20:26:18 -05:00
|
|
|
|
|
|
|
library :: update_path(id);
|
|
|
|
}
|
|
|
|
|
2013-11-10 16:09:31 -05:00
|
|
|
|
|
|
|
|
2013-10-27 17:25:26 -04:00
|
|
|
/*
|
|
|
|
* API used by the GUI begins here
|
|
|
|
*/
|
|
|
|
|
2013-11-03 16:03:01 -05:00
|
|
|
void library :: init()
|
|
|
|
{
|
2014-03-29 11:44:39 -04:00
|
|
|
tagdb :: init();
|
2014-01-20 20:13:12 -05:00
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
Database<Track> *db = &tagdb :: get_track_db();
|
2014-03-09 14:58:06 -04:00
|
|
|
Database<Track>::iterator it;
|
2014-02-01 17:29:31 -05:00
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
for (it = db->begin(); it != db->end(); it = db->next(it)) {
|
|
|
|
if ((*it)->library->enabled)
|
2014-03-25 10:57:09 -04:00
|
|
|
get_callbacks()->on_library_track_add((*it)->id);
|
2014-01-25 13:19:40 -05:00
|
|
|
}
|
2014-03-09 14:58:06 -04:00
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
Database<Library> *ldb = &tagdb :: get_library_db();
|
2014-03-09 14:58:06 -04:00
|
|
|
Database<Library>::iterator l_it;
|
2014-03-29 11:44:39 -04:00
|
|
|
|
|
|
|
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);
|
2013-11-03 16:03:01 -05:00
|
|
|
}
|
|
|
|
|
2014-01-01 13:34:25 -05:00
|
|
|
void library :: add_path(const std::string &dir)
|
2013-10-27 17:25:26 -04:00
|
|
|
{
|
|
|
|
if (g_file_test(dir.c_str(), G_FILE_TEST_IS_DIR) == false)
|
2014-01-04 11:55:52 -05:00
|
|
|
throw -E_INVAL;
|
2013-10-27 17:25:26 -04:00
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
Library *library = tagdb :: add_library(dir);
|
|
|
|
if (!library)
|
|
|
|
return;
|
2014-01-15 20:40:24 -05:00
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
get_callbacks()->on_library_add(library->id, library);
|
|
|
|
update_path(library->id);
|
2013-10-27 17:25:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void library :: del_path(unsigned int id)
|
|
|
|
{
|
2014-03-29 11:44:39 -04:00
|
|
|
Database<Track> *db = &tagdb :: get_track_db();
|
2014-03-09 14:58:06 -04:00
|
|
|
Database<Track>::iterator it;
|
2014-01-16 22:23:36 -05:00
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
for (it = db->begin(); it != db->end(); it = db->next(it)) {
|
|
|
|
if ((*it)->library->id == id)
|
2014-03-25 10:57:09 -04:00
|
|
|
get_callbacks()->on_library_track_del((*it)->id);
|
2014-01-16 22:23:36 -05:00
|
|
|
}
|
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
tagdb :: remove_library(id);
|
|
|
|
tagdb :: commit();
|
2013-10-27 17:25:26 -04:00
|
|
|
}
|
|
|
|
|
2013-11-10 16:09:31 -05:00
|
|
|
void library :: update_path(unsigned int id)
|
|
|
|
{
|
2014-03-29 11:44:39 -04:00
|
|
|
Library *library = tagdb :: lookup_library(id);
|
|
|
|
if (library)
|
|
|
|
do_update_library(library->id);
|
2013-11-10 16:09:31 -05:00
|
|
|
}
|
|
|
|
|
2014-01-12 13:04:16 -05:00
|
|
|
void library :: update_all()
|
|
|
|
{
|
2014-03-29 11:44:39 -04:00
|
|
|
Database<Library> *db = &tagdb :: get_library_db();
|
2014-03-09 14:58:06 -04:00
|
|
|
Database<Library>::iterator it;
|
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
for (it = db->begin(); it != db->end(); it = db->next(it))
|
|
|
|
update_path((*it)->id);
|
2014-01-12 13:04:16 -05:00
|
|
|
}
|
|
|
|
|
2014-01-18 12:32:41 -05:00
|
|
|
void library :: set_enabled(unsigned int id, bool enabled)
|
|
|
|
{
|
2014-03-29 11:44:39 -04:00
|
|
|
Library *library = tagdb :: lookup_library(id);
|
2014-01-18 12:32:41 -05:00
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
library->enabled = enabled;
|
|
|
|
tagdb :: commit_library();
|
|
|
|
|
|
|
|
Database<Track> *db = &(tagdb :: get_track_db());
|
|
|
|
Database<Track>::iterator it;
|
2014-01-18 12:32:41 -05:00
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
for (it = db->begin(); it != db->end(); it = db->next(it)) {
|
|
|
|
if ((*it)->library->id == id) {
|
2014-01-18 12:32:41 -05:00
|
|
|
if (enabled)
|
2014-03-29 11:44:39 -04:00
|
|
|
get_callbacks()->on_library_track_add((*it)->id);
|
2014-01-18 12:32:41 -05:00
|
|
|
else
|
2014-03-29 11:44:39 -04:00
|
|
|
get_callbacks()->on_library_track_del((*it)->id);
|
2014-01-18 12:32:41 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-01 20:26:18 -05:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2014-01-29 22:45:01 -05:00
|
|
|
void library :: track_played(unsigned int id)
|
|
|
|
{
|
|
|
|
time_t the_time = time(NULL);
|
|
|
|
struct tm *now = localtime(&the_time);
|
2014-03-29 11:44:39 -04:00
|
|
|
Track *track = tagdb :: lookup(id);
|
|
|
|
|
|
|
|
if (!track)
|
|
|
|
return;
|
2014-01-29 22:45:01 -05:00
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
track->play_count++;
|
|
|
|
track->last_day = now->tm_mday;
|
|
|
|
track->last_month = now->tm_mon + 1;
|
|
|
|
track->last_year = now->tm_year + 1900;
|
2014-01-29 22:45:01 -05:00
|
|
|
|
2014-03-29 11:44:39 -04:00
|
|
|
tagdb :: commit();
|
|
|
|
get_callbacks()->on_library_track_updated(track->id);
|
2014-01-29 22:45:01 -05:00
|
|
|
}
|
|
|
|
|
2014-01-01 20:58:53 -05:00
|
|
|
#ifdef CONFIG_TEST
|
2013-10-27 17:25:26 -04:00
|
|
|
void library :: print_db(DB_Type type)
|
|
|
|
{
|
|
|
|
switch (type) {
|
2013-11-10 16:45:52 -05:00
|
|
|
case DB_ALBUM:
|
|
|
|
break;
|
2013-11-10 16:09:31 -05:00
|
|
|
case DB_ARTIST:
|
|
|
|
break;
|
2013-11-10 16:45:52 -05:00
|
|
|
case DB_GENRE:
|
|
|
|
break;
|
2013-10-27 17:25:26 -04:00
|
|
|
case DB_LIBRARY:
|
|
|
|
break;
|
2013-11-10 17:37:35 -05:00
|
|
|
case DB_TRACK:
|
2014-03-09 14:58:06 -04:00
|
|
|
break;
|
2013-10-27 17:25:26 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void library :: reset()
|
|
|
|
{
|
|
|
|
}
|
2014-01-01 20:58:53 -05:00
|
|
|
#endif /* CONFIG_TEST */
|