/* * 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 *); static inline void __playlist_filter_get_iter(GtkTreeIter *iter, GtkTreeIter *child) { gtk_tree_model_filter_convert_iter_to_child_iter(gui_sidebar_filter(), child, iter); } void __playlist_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data) { enum playlist_type_t type; GtkTreeIter iter, child; GtkTreeModel *model; struct queue *queue; unsigned int id; gchar *name; type = settings_get("core.playlist.cur.type"); id = settings_get("core.playlist.cur.id"); model = GTK_TREE_MODEL(gui_sidebar_filter()); gtk_tree_model_get_iter(model, &iter, path); __playlist_filter_get_iter(&iter, &child); name = gui_sidebar_iter_name(&child); playlist_select(gui_sidebar_iter_type(&child), name); gui_sidebar_iter_update(&child); g_free(name); name = playlist_get_name(type, id); queue = playlist_get_queue(type, name); __playlist_update_sizes(queue); g_free(name); } static bool __playlist_queue_set_size(struct queue *queue, GtkTreeIter *iter) { struct gui_queue *gq = gui_queue(queue); bool match = (gui_sidebar_iter_type(iter) == gq->gq_playlist->pl_type); gchar *name = gui_sidebar_iter_name(iter); if (match) match = string_match(name, gq->gq_text); 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; unsigned int flags = 0; if (!string_match(playlist->pl_name, "History")) flags = GQ_CAN_RANDOM; 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 gui_queue_alloc(playlist, queue, playlist->pl_name, flags); } static void __playlist_deinit(struct queue *queue) { gui_filter_clear_search(gui_queue(queue)->gq_playlist); gui_queue_free(queue); } static void __playlist_added(struct queue *queue, unsigned int row) { gui_model_add(gui_queue(queue)->gq_playlist, row); __playlist_update_sizes(queue); } static void __playlist_removed(struct queue *queue, unsigned int row) { gui_model_remove(gui_queue(queue)->gq_playlist, row); __playlist_update_sizes(queue); } static void __playlist_cleared(struct queue *queue, unsigned int n) { gui_model_clear(gui_queue(queue)->gq_playlist, n); __playlist_update_sizes(queue); } static void __playlist_updated(struct queue *queue, unsigned int n) { gui_model_update(gui_queue(queue)->gq_playlist, n); } static bool __playlist_erase(struct queue *queue, struct track *track) { enum playlist_type_t type = gui_queue(queue)->gq_playlist->pl_type; const gchar *name = gui_queue(queue)->gq_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); } const gchar *gui_playlist_cur() { if (gui_model_get_playlist()) return gui_model_get_playlist()->pl_name; return NULL; } void gui_playlist_add_library(struct playlist *playlist) { GtkTreeIter parent; gui_sidebar_iter_first(&parent); gui_sidebar_iter_find(&parent, "Library", PL_MAX_TYPE); gui_sidebar_iter_sort_child(&parent, playlist, "folder"); } 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, };