#include #include #include #include #include #include #include #include #include #include #include "mlibupdater.h" static void quit (void *data) { GMainLoop *ml = data; ERR ("xmms2d disconnected us"); g_main_loop_quit (ml); } static void handle_file_add (xmonitor_t *mon, gchar *filename) { if (g_file_test (filename, G_FILE_TEST_IS_DIR)) { monitor_add_dir (mon, filename); mon->dir_list = g_list_append (mon->dir_list, filename); DBG ("New directory: %s", filename); } else if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) { gchar tmp[MON_FILENAME_MAX]; g_snprintf (tmp, MON_FILENAME_MAX, "file://%s", filename); xmmsc_result_unref (xmmsc_medialib_add_entry (mon->conn, tmp)); DBG ("Adding %s to medialib!", tmp); } } static void handle_remove_from_mlib (xmmsc_result_t *res, void *userdata) { xmonitor_t *mon = userdata; xmmsc_result_t *res2; for (; xmmsc_result_list_valid (res); xmmsc_result_list_next (res)) { guint32 id; if (!xmmsc_result_get_uint (res, &id)) { ERR ("Failed to get entry id from hash!"); continue; } if (id == 0) { DBG ("Entry not in db!"); continue; } DBG ("Removing %d", id); res2 = xmmsc_medialib_remove_entry (mon->conn, id); xmmsc_result_unref (res2); } xmmsc_result_unref (res); } static void handle_file_del (xmonitor_t *mon, gchar *filename) { xmmsc_result_t *res; xmmsc_coll_t *univ, *coll; gchar tmp[MON_FILENAME_MAX]; g_snprintf (tmp, MON_FILENAME_MAX, "file://%s%%", filename); univ = xmmsc_coll_universe (); coll = xmmsc_coll_new (XMMS_COLLECTION_TYPE_MATCH); xmmsc_coll_add_operand (coll, univ); xmmsc_coll_attribute_set (coll, "field", "url"); xmmsc_coll_attribute_set (coll, "value", tmp); res = xmmsc_coll_query_ids (mon->conn, coll, NULL, 0, 0); DBG ("remove '%s' from mlib", tmp); xmmsc_result_notifier_set (res, handle_remove_from_mlib, mon); xmmsc_result_unref (res); xmmsc_coll_unref (coll); xmmsc_coll_unref (univ); } static void handle_mlib_update (xmmsc_result_t *res, void *userdata) { xmonitor_t *mon = userdata; xmmsc_result_t *res2; guint32 id; if (!xmmsc_result_get_uint (res, &id)) { ERR ("Failed to get id for entry!"); xmmsc_result_unref (res); return; } if (id == 0) { DBG ("Entry not in db!"); return; } res2 = xmmsc_medialib_rehash (mon->conn, id); xmmsc_result_unref (res2); xmmsc_result_unref (res); } static void handle_file_changed (xmonitor_t *mon, gchar *filename) { xmmsc_result_t *res; gchar tmp[MON_FILENAME_MAX]; g_snprintf (tmp, MON_FILENAME_MAX, "file://%s", filename); res = xmmsc_medialib_get_id (mon->conn, tmp); xmmsc_result_notifier_set (res, handle_mlib_update, mon); xmmsc_result_unref (res); DBG ("update file in medialib"); } gboolean s_callback (GIOChannel *s, GIOCondition cond, gpointer data) { xmonitor_t *mon = data; xevent_t event; while (monitor_process (mon, &event)) { switch (event.code) { case MON_DIR_CHANGED: DBG ("got changed signal for %s", event.filename); handle_file_changed (mon, event.filename); break; case MON_DIR_DELETED: handle_file_del (mon, event.filename); break; case MON_DIR_CREATED: handle_file_add (mon, event.filename); break; default: break; } } return TRUE; } static void process_dir (xmonitor_t *mon, gchar *dirpath) { GDir *dir; const gchar *tmp; gchar *path; dir = g_dir_open (dirpath, 0, NULL); if (!dir) { ERR ("Error when opening %s", dirpath); return; } while ((tmp = g_dir_read_name (dir))) { path = g_strdup_printf ("%s/%s", dirpath, tmp); if (g_file_test (path, G_FILE_TEST_IS_DIR)) { if (!monitor_add_dir (mon, path)) { ERR ("Couldn't watch directory: %s!", path); g_free (path); continue; } DBG ("Now watching dir %s", path); mon->dir_list = g_list_append (mon->dir_list, path); process_dir (mon, path); } else { g_free (path); } } g_main_context_iteration (NULL, FALSE); g_dir_close (dir); } static void handle_addpath (xmmsc_result_t *res, void *data) { xmonitor_t *mon = data; if (!monitor_add_dir (mon, mon->watch_dir)) { ERR ("Couldn't watch directory!"); return; } mon->dir_list = g_list_append (mon->dir_list, mon->watch_dir); process_dir (mon, mon->watch_dir); DBG ("Watching %d dirs", g_list_length (mon->dir_list)); xmmsc_result_unref (res); } static void do_watch_dir (xmonitor_t *mon, gchar *dirs) { xmmsc_result_t *res; GList *n; DBG ("We are going to watch '%s'", dirs); for (n = mon->dir_list; n; n = g_list_next (n)) { monitor_del_dir (mon, n->data); g_free (n->data); } if (mon->dir_list) { g_list_free (mon->dir_list); mon->dir_list = NULL; } if (strlen (dirs) < 1) { mon->watch_dir = NULL; return; } else { mon->watch_dir = g_strdup (dirs); } /* Make sure that nothing changed while we where away! */ res = xmmsc_medialib_path_import (mon->conn, mon->watch_dir); xmmsc_result_notifier_set (res, handle_addpath, mon); xmmsc_result_unref (res); } static void handle_config_changed (xmmsc_result_t *res, void *data) { xmonitor_t *mon = data; gchar *val = NULL; int s; s = xmmsc_result_get_dict_entry_string (res, "clients.mlibupdater.watch_dirs", &val); if (s) { do_watch_dir (mon, val); } } static void handle_watch_dirs (xmmsc_result_t *res, void *data) { xmonitor_t *mon = data; gchar *dirs; if (!xmmsc_result_get_string (res, &dirs)) { ERR ("Couldn't get configvalue from server!"); return; } do_watch_dir (mon, dirs); xmmsc_result_unref (res); } static void handle_configval (xmmsc_result_t *res, void *data) { xmmsc_result_t *res2; xmonitor_t *mon = data; gchar *val; if (!xmmsc_result_get_string (res, &val)) { ERR ("Couldn't register value in server!"); return; } res2 = xmmsc_configval_get (mon->conn, val); xmmsc_result_notifier_set (res2, handle_watch_dirs, mon); xmmsc_result_unref (res2); xmmsc_result_unref (res); } static void message_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { } int main (int argc, char **argv) { GIOChannel *gio; GMainLoop *ml; gchar *path; gchar *tmp; xmmsc_connection_t *conn; xmmsc_result_t *res; xmonitor_t *mon; gint fd; conn = xmmsc_init ("xmms-medialib-updater"); path = getenv ("XMMS_PATH"); if (!xmmsc_connect (conn, path)) { ERR ("Could not connect to xmms2d %s", xmmsc_get_last_error (conn)); return EXIT_FAILURE; } ml = g_main_loop_new (NULL, FALSE); xmmsc_mainloop_gmain_init (conn); xmmsc_disconnect_callback_set (conn, quit, ml); mon = g_new0 (xmonitor_t, 1); fd = monitor_init (mon); mon->conn = conn; if (fd == -1) { ERR ("Couldn't initalize monitor"); return EXIT_FAILURE; } tmp = getenv("XMMS_DEBUG"); if (!tmp) { g_log_set_handler (NULL, G_LOG_LEVEL_MESSAGE | G_LOG_FLAG_RECURSION, message_handler, NULL); } gio = g_io_channel_unix_new (fd); g_io_add_watch (gio, G_IO_IN, s_callback, mon); res = xmmsc_configval_register (conn, "mlibupdater.watch_dirs", ""); xmmsc_result_notifier_set (res, handle_configval, mon); xmmsc_result_unref (res); res = xmmsc_broadcast_configval_changed (conn); xmmsc_result_notifier_set (res, handle_config_changed, mon); xmmsc_result_unref (res); g_main_loop_run (ml); return EXIT_SUCCESS; }