/* * Copyright 2016 (c) Anna Schumaker. */ #include #include #include #include #include #include #include #include static bool p_filter_enable = true; static bool p_init_done = false; static void __playlist_update_sizes(struct queue *); void __playlist_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data) { gui_sidebar_filter_path_select(path); __playlist_update_sizes(&playlist_cur()->pl_queue); } static bool __playlist_queue_set_size(struct queue *queue, GtkTreeIter *iter) { struct playlist *playlist = queue->q_private; bool match = (gui_sidebar_iter_type(iter) == playlist->pl_type); gchar *name = gui_sidebar_iter_name(iter); if (match) match = string_match(name, playlist->pl_name); if (match) gui_sidebar_iter_update(iter); g_free(name); return match; } static void __playlist_update_sizes(struct queue *queue) { GtkTreeModelFilter *filter; GtkTreeIter parent, iter; if (!gui_sidebar_iter_first(&parent)) return; do { if (__playlist_queue_set_size(queue, &parent)) goto out; if (gtk_tree_model_iter_children(gui_sidebar_model(), &iter, &parent)) { do { if (__playlist_queue_set_size(queue, &iter)) goto out; } while (gui_sidebar_iter_next(&iter)); } } while (gui_sidebar_iter_next(&parent)); out: filter = gui_sidebar_filter(); gtk_tree_model_filter_refilter(filter); } static void *__playlist_init(struct queue *queue, void *data) { struct playlist *playlist = (struct playlist *)data; if (p_init_done && playlist->pl_type == PL_ARTIST) { p_filter_enable = false; gui_playlist_add_artist(playlist); p_filter_enable = true; } if (p_init_done && playlist->pl_type == PL_USER) gui_playlist_add_user(playlist); return playlist; } static void __playlist_deinit(struct queue *queue) { gui_filter_clear_search(queue->q_private); } static void __playlist_added(struct queue *queue, unsigned int row) { gui_model_add(queue->q_private, row); __playlist_update_sizes(queue); } static void __playlist_removed(struct queue *queue, unsigned int row) { gui_model_remove(queue->q_private, row); __playlist_update_sizes(queue); } static void __playlist_cleared(struct queue *queue, unsigned int n) { gui_model_clear(queue->q_private, n); __playlist_update_sizes(queue); } static void __playlist_updated(struct queue *queue, unsigned int n) { gui_model_update(queue->q_private, n); } static bool __playlist_erase(struct queue *queue, struct track *track) { struct playlist *playlist = queue->q_private; enum playlist_type_t type = playlist->pl_type; const gchar *name = playlist->pl_name; switch (type) { case PL_SYSTEM: if (string_match(name, "Collection")) name = "Hidden"; else if (!string_match(name, "Favorites") && !string_match(name, "Hidden") && !string_match(name, "Queued Tracks")) break; case PL_USER: playlist_remove(type, name, track); default: break; }; return false; } bool __gui_playlist_init_idle() { struct db_entry *dbe, *next; GtkTreeSelection *selection; GtkTreeView *treeview; GtkTreeModel *filter; GtkTreeIter iter; filter = GTK_TREE_MODEL(gui_sidebar_filter()); treeview = gui_sidebar_treeview(); selection = gtk_tree_view_get_selection(treeview); gtk_tree_model_get_iter_first(filter, &iter); gtk_tree_selection_select_iter(selection, &iter); p_filter_enable = false; db_for_each(dbe, next, pl_user_db_get()) gui_playlist_add_user(&USER_PLAYLIST(dbe)->pl_playlist); gtk_tree_view_expand_all(treeview); db_for_each(dbe, next, artist_db_get()) gui_playlist_add_artist(ARTIST(dbe)->ar_playlist); p_filter_enable = true; p_init_done = true; return true; } void gui_playlist_init() { GtkTreeIter parent; gui_sidebar_iter_first(&parent); gui_sidebar_iter_add(&parent, playlist_get(PL_SYSTEM, "Queued Tracks"), "audio-x-generic"); gui_sidebar_iter_add(&parent, playlist_get(PL_SYSTEM, "Collection"), "media-optical"); gui_sidebar_iter_add(&parent, playlist_get(PL_SYSTEM, "History"), "document-open-recent"); /* Add "Playlists" header and playlists. */ gui_sidebar_iter_find(&parent, "Playlists", PL_MAX_TYPE); gui_sidebar_iter_append_child(&parent, playlist_get(PL_SYSTEM, "Favorites"), "emblem-favorite"); gui_sidebar_iter_append_child(&parent, playlist_get(PL_SYSTEM, "Hidden"), "window-close"); /* Add "Dynamic" header. */ gui_sidebar_iter_find(&parent, "Dynamic", PL_MAX_TYPE); gui_sidebar_iter_append_child(&parent, playlist_get(PL_SYSTEM, "Most Played"), "go-up"); gui_sidebar_iter_append_child(&parent, playlist_get(PL_SYSTEM, "Least Played"), "go-down"); gui_sidebar_iter_append_child(&parent, playlist_get(PL_SYSTEM, "Unplayed"), "audio-x-generic"); idle_schedule(IDLE_SYNC, __gui_playlist_init_idle, NULL); gui_pl_library_init(); } const gchar *gui_playlist_cur() { if (gui_model_get_playlist()) return gui_model_get_playlist()->pl_name; return NULL; } void gui_playlist_add_artist(struct playlist *playlist) { GtkTreeIter parent; gui_sidebar_iter_first(&parent); gui_sidebar_iter_find(&parent, "Collection", PL_SYSTEM); gui_sidebar_iter_sort_child(&parent, playlist, "system-users"); } void gui_playlist_add_user(struct playlist *playlist) { GtkTreeIter parent; gui_sidebar_iter_first(&parent); gui_sidebar_iter_find(&parent, "Playlists", PL_MAX_TYPE); gui_sidebar_iter_sort_child(&parent, playlist, "text-x-generic"); } struct queue_ops playlist_ops = { .qop_init = __playlist_init, .qop_deinit = __playlist_deinit, .qop_added = __playlist_added, .qop_erase = __playlist_erase, .qop_removed = __playlist_removed, .qop_cleared = __playlist_cleared, .qop_updated = __playlist_updated, };