/* * Copyright 2016 (c) Anna Schumaker. */ #include #include #include #include #include #include #include static void (*update_size[PL_MAX_TYPE])(struct playlist *) = { [PL_SYSTEM] = gui_pl_system_update, [PL_ARTIST] = gui_pl_artist_update, [PL_LIBRARY] = gui_pl_library_update, [PL_USER] = gui_pl_user_update, }; static void (*select_playlist[PL_MAX_TYPE])(struct playlist *) = { [PL_SYSTEM] = gui_pl_system_select, [PL_ARTIST] = gui_pl_artist_select, [PL_LIBRARY] = gui_pl_library_select, [PL_USER] = gui_pl_user_select, }; static inline void __gui_playlist_update_size(struct playlist *playlist) { update_size[playlist->pl_type](playlist); } static void __gui_playlist_alloc(struct playlist *playlist) { if (playlist->pl_type == PL_ARTIST) gui_pl_artist_add(playlist); } static void __gui_playlist_added(struct playlist *playlist, struct track *track) { gui_model_add(playlist, track); __gui_playlist_update_size(playlist); } static void __gui_playlist_removed(struct playlist *playlist, struct track *track, unsigned int n) { gui_model_remove(playlist, track, n); __gui_playlist_update_size(playlist); } struct playlist_callbacks playlist_cb = { .pl_cb_alloc = __gui_playlist_alloc, .pl_cb_added = __gui_playlist_added, .pl_cb_removed = __gui_playlist_removed, .pl_cb_updated = gui_model_update, }; static void __gui_playlist_add_selected_to(struct playlist *playlist) { GList *cur, *list = NULL; struct track *track; if (!playlist) return; list = gui_treeview_list_selected_tracks(); cur = g_list_first(list); while (cur) { track = (struct track *)cur->data; playlist_add(playlist, track); cur = g_list_next(cur); } g_list_free(list); } void __gui_playlist_add_favorites(GtkMenuItem *item, gpointer data) { __gui_playlist_add_selected_to(playlist_lookup(PL_SYSTEM, "Favorites")); } void __gui_playlist_add_hidden(GtkMenuItem *item, gpointer data) { __gui_playlist_add_selected_to(playlist_lookup(PL_SYSTEM, "Hidden")); } void __gui_playlist_add_user(GtkMenuItem *item, gpointer data) { __gui_playlist_add_selected_to(gui_pl_user_add_dialog()); } void __gui_playlist_add_other(GtkMenuItem *item, gpointer data) { __gui_playlist_add_selected_to(data); } void __gui_playlist_add_queued(GtkMenuItem *item, gpointer data) { __gui_playlist_add_selected_to(playlist_lookup(PL_SYSTEM, "Queued Tracks")); } void __gui_playlist_delete(GtkMenuItem *item, gpointer data) { struct playlist *playlist = gui_model_get_playlist(); GList *cur, *list = NULL; struct track *track; if (!playlist) return; list = gui_treeview_list_selected_tracks(); cur = g_list_first(list); while (cur) { track = (struct track *)cur->data; playlist_remove(playlist, track); cur = g_list_next(cur); } g_list_free(list); } void __gui_playlist_keypress(GtkTreeView *treeview, GdkEventKey *event, gpointer data) { switch (event->keyval) { case GDK_KEY_f: __gui_playlist_add_favorites(NULL, NULL); break; case GDK_KEY_h: __gui_playlist_add_hidden(NULL, NULL); break; case GDK_KEY_p: __gui_playlist_add_user(NULL, NULL); break; case GDK_KEY_q: __gui_playlist_add_queued(NULL, NULL); break; case GDK_KEY_Delete: __gui_playlist_delete(NULL, NULL); default: break; } } static GtkWidget *__gui_playlist_build_submenu(void) { struct playlist *playlist; GList *list = gui_pl_user_list(); GList *cur = g_list_first(list); GtkWidget *submenu, *item; if (!list) return NULL; submenu = gtk_menu_new(); while (cur) { playlist = (struct playlist *)cur->data; item = gtk_menu_item_new_with_label(playlist->pl_name); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), item); g_signal_connect(item, "activate", G_CALLBACK(__gui_playlist_add_other), playlist); cur = g_list_next(cur); } gtk_widget_show_all(submenu); g_list_free(list); return submenu; } bool __gui_playlist_button_press(GtkTreeView *treeview, GdkEventButton *event, gpointer data) { GtkWidget *submenu; if (event->button != GDK_BUTTON_SECONDARY) return false; submenu = __gui_playlist_build_submenu(); gtk_menu_item_set_submenu(gui_rc_add_to_other(), submenu); gtk_widget_set_visible(GTK_WIDGET(gui_rc_add_to_other()), submenu != NULL); gui_treeview_select_path_at_pos(event->x, event->y); gtk_menu_popup_at_pointer(gui_rc_menu(), (GdkEvent *)event); return true; } void __gui_playlist_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data) { struct playlist *prev = playlist_current(); gui_sidebar_filter_path_select(path); __gui_playlist_update_size(prev); __gui_playlist_update_size(playlist_current()); } void __gui_playlist_row_collapsed(GtkTreeView *treeview, GtkTreeIter *iter, GtkTreePath *path, gpointer data) { gui_sidebar_filter_row_expanded(iter, false); } void __gui_playlist_row_expanded(GtkTreeView *treeview, GtkTreeIter *iter, GtkTreePath *path, gpointer data) { gui_sidebar_filter_row_expanded(iter, true); } void __gui_playlist_drag_data_received(GtkTreeView *treeview, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint info, guint time, gpointer user_data) { struct playlist *playlist; GtkTreeIter iter; if (gui_sidebar_iter_from_xy(x, y, &iter)) playlist = gui_sidebar_iter_playlist(&iter); if (!playlist) playlist = gui_pl_user_add_dialog(); if (!playlist) goto out; if (playlist == playlist_lookup(PL_SYSTEM, "Collection") && gui_model_get_playlist() == playlist_lookup(PL_SYSTEM, "Hidden")) __gui_playlist_delete(NULL, NULL); else if (playlist != playlist_lookup(PL_SYSTEM, "History")) __gui_playlist_add_selected_to(playlist); out: g_signal_stop_emission_by_name(treeview, "drag_data_received"); gtk_drag_finish(context, true, true, time); } bool __gui_playlist_init_idle() { struct playlist *playlist = playlist_current(); GtkTreeModel *filter = GTK_TREE_MODEL(gui_sidebar_filter()); GtkTreeIter iter; gtk_tree_model_get_iter_first(filter, &iter); do { gui_sidebar_filter_set_expand(&iter); } while (gtk_tree_model_iter_next(filter, &iter)); select_playlist[playlist->pl_type](playlist); return true; } void gui_playlist_init() { gui_pl_system_init(); gui_pl_artist_init(); gui_pl_user_init(); gui_pl_library_init(); idle_schedule(IDLE_SYNC, __gui_playlist_init_idle, NULL); }