/* Glurp - A GTK+ client for Music Player Daemon Copyright (C) 2004, 2005 Andrej Kacian This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA http://musicpd.org/glurp.shtml */ #include #include #include #include #include "structs.h" #include "support.h" #include "comm.h" #include "gui.h" #include "player.h" #include "conf.h" extern GladeXML *guixml, *configxml, *plxml, *addxml, *streamxml; extern GlurpState *glurp; void on_ui_quit(GtkWidget *widget, gpointer user_data) { debug("Quitting Glurp..."); if( glurp->conn ) glurp_disconnect(); config_save(); gtk_main_quit(); } gboolean on_window_moved(GtkWidget *widget, GdkEventConfigure *event, gpointer data) { debug("Storing window position and size (%dx%d+%d+%d)", event->width, event->height, event->x, event->y); glurp->config->pos_x = event->x; glurp->config->pos_y = event->y; glurp->config->width = event->width; glurp->config->height = event->height; return FALSE; } /* called when config button is pressed in main window */ gboolean on_ui_press_config(GtkWidget *widget, gpointer user_data) { GtkWidget *window_config; if(configxml) { debug("Config window already shown, returning"); return FALSE; } debug("Displaying config window..."); configxml = glade_xml_new(glade_path(), "glurp_window_config", NULL); glade_xml_signal_autoconnect(configxml); populate_config(); window_config = glade_xml_get_widget(configxml, "glurp_window_config"); title_print(window_config, "Config"); gtk_widget_show(window_config); return FALSE; } gboolean on_button_config_cancel_clicked(GtkWidget *widget, gpointer user_data) { GtkWidget *window_config = glade_xml_get_widget(configxml, "glurp_window_config"); debug("Cancel pressed, destroying config window..."); gtk_widget_destroy(window_config); return FALSE; } gboolean on_config_destroy(GtkWidget *widget, gpointer user_data) { debug("freeing configxml"); configxml = NULL; gui_refresh_playlist_columns(); return FALSE; } gboolean on_button_config_ok_clicked(GtkWidget *widget, gpointer user_data) { GtkWidget *window_config; debug("OK pressed, hiding config window..."); debug("Storing variables into GlurpConfig"); store_config(); config_save(); window_config = glade_xml_get_widget(configxml, "glurp_window_config"); gtk_widget_destroy(window_config); statusbar_print("Config saved..."); return FALSE; } gboolean on_ui_press_connect(GtkWidget *widget, gpointer user_data) { glurp_connect(); return FALSE; } gboolean on_ui_press_disconnect(GtkWidget *widget, gpointer user_data) { glurp_disconnect(); return FALSE; } gboolean on_ui_volume_changed(GtkWidget *widget, gpointer user_data) { gint i = gtk_range_get_value(GTK_RANGE(widget)); if( glurp->conn ) { mpd_sendSetvolCommand(glurp->conn, i); mpd_finishCommand(glurp->conn); if( check_mpd_error() ) { glurp_disconnect(); return FALSE; } statusbar_print("Volume: %d%%", i); } return FALSE; } gboolean on_ui_progress_change(GtkWidget *widget, gpointer user_data) { mpd_Status *status = NULL; double sec, pos, tt; gint t_min, t_sec, s_min, s_sec; if(!glurp->progress_dragging) return FALSE; status = get_status(TRUE); tt = status->totalTime; t_min = (int)tt/60; t_sec = (int)tt%60; pos = gtk_range_get_value(GTK_RANGE(widget)); sec = (pos / 100)*tt; s_min = (int)sec/60; s_sec = (int)sec%60; debug("Seeking to %d seconds", (gint)sec); statusbar_print("Seek to %02d:%02d/%02d:%02d", s_min, s_sec, t_min, t_sec); mpd_sendSeekCommand(glurp->conn, status->song, sec); mpd_finishCommand(glurp->conn); if( check_mpd_error() ) { glurp_disconnect(); return FALSE; } debug("setting FALSE"); glurp->progress_dragging = FALSE; return FALSE; } gboolean on_ui_progress_change_start(GtkWidget *widget, gpointer user_data) { debug("setting TRUE"); glurp->progress_dragging = TRUE; return FALSE; } gboolean on_ui_playlist_clicked(GtkWidget *widget, gpointer user_data) { if( !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ) hide_gui_playlist(); else show_gui_playlist(); return FALSE; } gboolean on_ui_player_play(GtkWidget *widget, gpointer user_data) { mpd_Status *status = get_status(TRUE); GtkTreeView *tv; GtkTreeModel *tm; GtkTreeSelection *sel; GtkTreePath *path; GtkTreeIter iter; gint id, pos, num; GList *selected_rows; if(!status) { debug("status == NULL"); return FALSE; } if(!glurp->playlist) { debug("Nothing loaded in playlist, cannot play"); statusbar_print("Playlist empty"); return FALSE; } if( status->state == MPD_STATUS_STATE_PAUSE ) player_pause(); else { tv = GTK_TREE_VIEW(glade_xml_get_widget(guixml, "treeview_playlist")); tm = gtk_tree_view_get_model(tv); sel = gtk_tree_view_get_selection(tv); if( !(num = gtk_tree_selection_count_selected_rows(sel)) ) { debug("No song selected, letting MPD decide which song to play"); if( !STOPPED ) player_stop(); player_play_song(-1); return FALSE; } if( !(selected_rows = gtk_tree_selection_get_selected_rows(sel, &tm)) ) { debug("Couldn't get selected rows"); return FALSE; } path = (GtkTreePath *)g_list_nth_data(selected_rows, 0); if ( !gtk_tree_model_get_iter(tm, &iter, path) ) { debug("Couldn't get GtkTreeIter, what now?"); return FALSE; } debug("Getting trackno. of selected song"); gtk_tree_model_get(tm, &iter, PL_ID, &id, PL_TRACK, &pos, -1); debug("Song number is %d, id %d", pos, id); if( num > 1 ) gui_playlist_set_cursor(pos - 1); if( !STOPPED ) player_stop(); player_play_song(id); } return FALSE; } gboolean on_ui_player_pause(GtkWidget *widget, gpointer user_data) { player_pause(); return FALSE; } gboolean on_ui_player_stop(GtkWidget *widget, gpointer user_data) { player_stop(); return FALSE; } gboolean on_ui_player_prev(GtkWidget *widget, gpointer user_data) { player_prev(); return FALSE; } gboolean on_ui_player_next(GtkWidget *widget, gpointer user_data) { player_next(); return FALSE; } gboolean on_ui_time_clicked(GtkWidget *widget, gpointer user_data) { if(glurp->config->time_display_left) glurp->config->time_display_left = FALSE; else glurp->config->time_display_left = TRUE; gtk_widget_grab_focus(glade_xml_get_widget(guixml, "treeview_playlist")); return FALSE; } gboolean on_ui_playlist_row_activated(GtkTreeView *treeview, GtkTreePath *tp, GtkTreeViewColumn *col, gpointer user_data) { GtkTreeIter act; GtkTreeModel *model; gint id; debug("Playlist item activated."); if(!glurp->conn) { debug("We're not connected, cannot start playing anything."); return FALSE; } model = gtk_tree_view_get_model(treeview); gtk_tree_model_get_iter(model, &act, tp); gtk_tree_model_get(model, &act, PL_ID, &id, -1); player_stop(); player_play_song(id); return FALSE; } gboolean on_ui_playlists_clicked(GtkWidget *widget, gpointer user_data) { GtkWidget *window_playlist; if(plxml) { debug("Playlists window already displayed, returning"); return FALSE; } if( !glurp->conn ) { debug("we're not connected"); return FALSE; } plxml = glade_xml_new(glade_path(), "glurp_window_playlist_list", NULL); glade_xml_signal_autoconnect(plxml); get_playlist_list(); create_playlist_list_liststore(); populate_gui_playlist_list(); window_playlist = glade_xml_get_widget(plxml, "glurp_window_playlist_list"); title_print(window_playlist, "Playlists"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plxml, "checkbutton_append_playlist")), FALSE); gtk_widget_show(window_playlist); return FALSE; } gboolean on_ui_playlist_close(GtkWidget *widget, gpointer user_data) { GtkWidget *w = glade_xml_get_widget(plxml, "glurp_window_playlist_list"); debug("Destroying playlist list window."); gtk_widget_destroy(w); return FALSE; } gboolean on_window_playlists_destroy(GtkWidget *widget, gpointer user_data) { playlists_window_destroyed(); return FALSE; } gboolean on_window_add_destroy(GtkWidget *widget, gpointer user_data) { add_window_destroyed(); return FALSE; } gboolean on_ui_playlist_list_row_activated(GtkTreeView *treeview, GtkTreePath *tp, GtkTreeViewColumn *col, gpointer user_data) { GtkTreeIter act; GtkTreeModel *model; gchar *name; debug("playlist activated"); if( !glurp->conn ) { debug("we're not connected, how can this be?"); return FALSE; } model = gtk_tree_view_get_model(treeview); gtk_tree_model_get_iter(model, &act, tp); gtk_tree_model_get(model, &act, 0, &name, -1); load_playlist(name); g_free(name); debug("Destroying playlist list window."); gtk_widget_destroy(glade_xml_get_widget(plxml, "glurp_window_playlist_list")); playlists_window_destroyed(); return FALSE; } gboolean on_ui_playlist_load(GtkWidget *widget, gpointer user_data) { GtkTreeView *tv; GtkTreeModel *tm; GtkTreeSelection *sel; GtkTreeIter iter; gchar *name; if( !glurp->conn ) { debug("We're not connected, how can this be? Just closing the window"); gtk_widget_destroy(glade_xml_get_widget(configxml, "glurp_window_playlist_list")); return FALSE; } tv = GTK_TREE_VIEW(glade_xml_get_widget(plxml, "treeview_playlist_list")); tm = gtk_tree_view_get_model(tv); sel = gtk_tree_view_get_selection(tv); if( !gtk_tree_selection_get_selected(sel, &tm, &iter)) { debug("No playlist selected"); return FALSE; } debug("getting name of selected playlist"); gtk_tree_model_get(tm, &iter, 0, &name, -1); load_playlist(name); g_free(name); debug("Destroying playlist list window."); gtk_widget_destroy(glade_xml_get_widget(plxml, "glurp_window_playlist_list")); playlists_window_destroyed(); return FALSE; } gboolean on_ui_playlist_delete(GtkWidget *widget, gpointer user_data) { GtkTreeView *tv; GtkTreeModel *tm; GtkTreeSelection *sel; GtkTreeIter iter; gchar *name; if( !glurp->conn ) { debug("We're not connected, how can this be? Just closing the window"); gtk_widget_destroy(glade_xml_get_widget(configxml, "glurp_window_playlist_list")); return FALSE; } tv = GTK_TREE_VIEW(glade_xml_get_widget(plxml, "treeview_playlist_list")); tm = gtk_tree_view_get_model(tv); sel = gtk_tree_view_get_selection(tv); if( !gtk_tree_selection_get_selected(sel, &tm, &iter)) { debug("No playlist selected"); return FALSE; } gtk_tree_model_get(tm, &iter, 0, &name, -1); mpd_sendRmCommand(glurp->conn, name); mpd_finishCommand(glurp->conn); if( check_mpd_error() ) { glurp_disconnect(); return FALSE; } debug("Playlist '%s' deleted", name); g_free(name); get_playlist_list(); populate_gui_playlist_list(); return FALSE; } gboolean on_ui_playlist_save(GtkWidget *widget, gpointer user_data) { GtkEntry *entry = GTK_ENTRY(glade_xml_get_widget(plxml, "entry_playlist_name")); gchar *name = (gchar *)gtk_entry_get_text(entry); GlurpPl *pl; if( !glurp->conn ) { debug("We're not connected, how can this be? Ignoring"); return FALSE; } if( !name || !g_utf8_strlen(name, -1) ) { debug("Empty playlist name, ignoring"); return FALSE; } for( pl = glurp->playlists; pl; pl = pl->next ) { if( !g_ascii_strcasecmp(pl->name, name) ) { debug("Not overwriting existing playlist"); return FALSE; } } mpd_sendSaveCommand(glurp->conn, name); mpd_finishCommand(glurp->conn); if( check_mpd_error() ) { glurp_disconnect(); return FALSE; } debug("Playlist '%s' saved", name); get_playlist_list(); populate_gui_playlist_list(); return FALSE; } gboolean on_ui_progress_drag(GtkWidget *widget, gpointer user_data) { double pos = gtk_range_get_value(GTK_RANGE(widget)); double sec, tt; gint t_min, t_sec, s_min, s_sec; if( !glurp->conn || !glurp->current_song ) return FALSE; if( !glurp->progress_dragging ) return FALSE; tt = glurp->current_song->time; t_min = (int)tt/60; t_sec = (int)tt%60; sec = (pos / 100)*tt; s_min = (int)sec/60; s_sec = (int)sec%60; statusbar_print("Seek to %02d:%02d/%02d:%02d", s_min, s_sec, t_min, t_sec); return FALSE; } gboolean on_ui_playlist_list_cursor_changed(GtkWidget *widget, gpointer user_data) { GtkTreeView *tv; GtkTreeModel *tm; GtkTreeSelection *sel; GtkTreeIter iter; gchar *name; if( !glurp->conn ) { debug("We're not connected, how can this be? Just closing the window"); gtk_widget_destroy(glade_xml_get_widget(configxml, "glurp_window_playlist_list")); return FALSE; } tv = GTK_TREE_VIEW(glade_xml_get_widget(plxml, "treeview_playlist_list")); tm = gtk_tree_view_get_model(tv); sel = gtk_tree_view_get_selection(tv); if( !gtk_tree_selection_get_selected(sel, &tm, &iter)) { debug("No playlist selected"); return FALSE; } gtk_tree_model_get(tm, &iter, 0, &name, -1); gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(plxml, "entry_playlist_name")), name); g_free(name); return FALSE; } gboolean on_ui_qsearch_activate(GtkWidget *widget, gpointer user_data) { gchar *srch = (gchar *)gtk_entry_get_text(GTK_ENTRY(widget)); gchar *sample = NULL; gint type = gtk_combo_box_get_active(GTK_COMBO_BOX(glade_xml_get_widget(guixml, "combobox_qsearch_type"))); gint cpos; GtkTreeIter iter, siter; GtkTreePath *path; gboolean found = FALSE; debug("QSearch string: '%s'", srch); gtk_tree_view_get_cursor(GTK_TREE_VIEW(glade_xml_get_widget(guixml, "treeview_playlist")), &path, NULL); if( path ) { cpos = atoi(gtk_tree_path_to_string(path)); gtk_tree_model_get_iter(GTK_TREE_MODEL(glurp->gui_playlist), &iter, path); gtk_tree_model_get_iter(GTK_TREE_MODEL(glurp->gui_playlist), &siter, path); gtk_tree_path_free(path); if( !gtk_tree_model_iter_next(GTK_TREE_MODEL(glurp->gui_playlist), &iter) ) return FALSE; } else { cpos = 0; if( !gtk_tree_model_get_iter_first(GTK_TREE_MODEL(glurp->gui_playlist), &iter) ) return FALSE; } debug("Cursor position: %d", cpos + 1); cpos++; do { switch(type) { case GLURP_QSEARCH_TITLE: gtk_tree_model_get(GTK_TREE_MODEL(glurp->gui_playlist), &iter, PL_TITLE, &sample, -1); if( sample && srch && g_strrstr(g_ascii_strdown(sample, -1), g_ascii_strdown(srch, -1)) ) { debug("Found suitable haystack: '%s'", sample); gui_playlist_scroll(cpos); found = TRUE; } break; case GLURP_QSEARCH_ARTIST: gtk_tree_model_get(GTK_TREE_MODEL(glurp->gui_playlist), &iter, PL_ARTIST, &sample, -1); if( sample && srch && g_strrstr(g_ascii_strdown(sample, -1), g_ascii_strdown(srch, -1)) ) { debug("Found suitable haystack: '%s'", sample); gui_playlist_scroll(cpos); found = TRUE; } break; case GLURP_QSEARCH_ALBUM: gtk_tree_model_get(GTK_TREE_MODEL(glurp->gui_playlist), &iter, PL_ALBUM, &sample, -1); if( sample && srch && g_strrstr(g_ascii_strdown(sample, -1), g_ascii_strdown(srch, -1)) ) { debug("Found suitable haystack: '%s'", sample); gui_playlist_scroll(cpos); found = TRUE; } break; case GLURP_QSEARCH_FILENAME: gtk_tree_model_get(GTK_TREE_MODEL(glurp->gui_playlist), &iter, PL_FILENAME, &sample, -1); if( sample && srch && g_strrstr(g_ascii_strdown(sample, -1), g_ascii_strdown(srch, -1)) ) { debug("Found suitable haystack: '%s'", sample); gui_playlist_scroll(cpos); found = TRUE; } break; case GLURP_QSEARCH_ALL: gtk_tree_model_get(GTK_TREE_MODEL(glurp->gui_playlist), &iter, PL_TITLE, &sample, -1); if( sample && srch && g_strrstr(g_ascii_strdown(sample, -1), g_ascii_strdown(srch, -1)) ) { debug("Found suitable haystack: '%s'", sample); gui_playlist_scroll(cpos); found = TRUE; break; } gtk_tree_model_get(GTK_TREE_MODEL(glurp->gui_playlist), &iter, PL_ARTIST, &sample, -1); if( sample && srch && g_strrstr(g_ascii_strdown(sample, -1), g_ascii_strdown(srch, -1)) ) { debug("Found suitable haystack: '%s'", sample); gui_playlist_scroll(cpos); found = TRUE; break; } gtk_tree_model_get(GTK_TREE_MODEL(glurp->gui_playlist), &iter, PL_ALBUM, &sample, -1); if( sample && srch && g_strrstr(g_ascii_strdown(sample, -1), g_ascii_strdown(srch, -1)) ) { debug("Found suitable haystack: '%s'", sample); gui_playlist_scroll(cpos); found = TRUE; break; } gtk_tree_model_get(GTK_TREE_MODEL(glurp->gui_playlist), &iter, PL_FILENAME, &sample, -1); if( sample && srch && g_strrstr(g_ascii_strdown(sample, -1), g_ascii_strdown(srch, -1)) ) { debug("Found suitable haystack: '%s'", sample); gui_playlist_scroll(cpos); found = TRUE; break; } break; } } while( !found && gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(glurp->gui_playlist), &iter, NULL, ++cpos) ); return FALSE; } gboolean on_menu_add_activate(GtkWidget *widget, gpointer data) { return FALSE; } gboolean on_menu_pl_remove_all_activate(GtkWidget *widget, gpointer data) { if(!CONNECTED) return FALSE; mpd_sendClearCommand(glurp->conn); mpd_finishCommand(glurp->conn); if( check_mpd_error() ) { glurp_disconnect(); return FALSE; } return FALSE; } gboolean on_menu_pl_remove_selected_activate(GtkWidget *widget, gpointer data) { GtkWidget *tv; GtkTreeModel *tm; GtkTreeSelection *ts; gint num_sel, i, id; GtkTreeIter iter; GList *selected_rows; if(!CONNECTED) return FALSE; tv = glade_xml_get_widget(guixml, "treeview_playlist"); tm = gtk_tree_view_get_model(GTK_TREE_VIEW(tv)); ts = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)); num_sel = gtk_tree_selection_count_selected_rows(ts); selected_rows = gtk_tree_selection_get_selected_rows(ts, NULL); debug("Selected %d rows", num_sel); if( num_sel ) { mpd_sendCommandListBegin(glurp->conn); for( i=0; iconn, id); } mpd_sendCommandListEnd(glurp->conn); mpd_finishCommand(glurp->conn); if( check_mpd_error() ) { glurp_disconnect(); return FALSE; } } return FALSE; } gboolean on_menu_pl_remove_crop_activate(GtkWidget *widget, gpointer data) { GtkWidget *tv; GtkTreeModel *tm; GtkTreeSelection *ts; GtkTreeIter iter; gint i = 0; if(!CONNECTED) return FALSE; tv = glade_xml_get_widget(guixml, "treeview_playlist"); tm = gtk_tree_view_get_model(GTK_TREE_VIEW(tv)); ts = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)); if( !gtk_tree_model_get_iter_first(tm, &iter) ) { debug("Couldn't get first iter, playlist empty?"); return FALSE; } mpd_sendCommandListBegin(glurp->conn); do { if( !gtk_tree_selection_iter_is_selected(ts, &iter) ) mpd_sendDeleteCommand(glurp->conn, i); else i++; } while( gtk_tree_model_iter_next(tm, &iter) ); mpd_sendCommandListEnd(glurp->conn); mpd_finishCommand(glurp->conn); if( check_mpd_error() ) { glurp_disconnect(); return FALSE; } return FALSE; } gboolean on_ui_add_close_clicked(GtkWidget *widget, gpointer data) { GtkWidget *window_add = glade_xml_get_widget(addxml, "glurp_window_add"); g_object_ref(G_OBJECT(glurp->gui_addtree)); debug("Close pressed, destroying 'add' window..."); gtk_widget_destroy(window_add); return FALSE; } gboolean on_ui_add_update_clicked(GtkWidget *widget, gpointer data) { gtk_tree_store_clear(glurp->gui_addtree); debug("Removing 'Add' treeview model"); gtk_tree_view_set_model(GTK_TREE_VIEW(glade_xml_get_widget(addxml, "treeview_add")), NULL); statusbar_print("Updating MPD database, please wait..."); debug("Starting to update MPD db..."); if( NONBLOCKING_UPDATE_CAPABLE_MPD ) { gui_updating_disable_add_controls(); glurp->updating_db = TRUE; } mpd_sendUpdateCommand(glurp->conn, ""); mpd_finishCommand(glurp->conn); if( check_mpd_error() ) { glurp_disconnect(); return FALSE; } if( !NONBLOCKING_UPDATE_CAPABLE_MPD ) { statusbar_print("Database updated"); debug("MPD db updated"); debug("Setting 'Add' treeview model back"); gtk_tree_view_set_model(GTK_TREE_VIEW(glade_xml_get_widget(addxml, "treeview_add")), GTK_TREE_MODEL(glurp->gui_addtree)); populate_gui_add_tree(); } return FALSE; } gboolean on_ui_add_add_clicked(GtkWidget *widget, gpointer data) { GtkTreeView *tv; GtkTreeModel *tm; GtkTreeSelection *ts; if(!CONNECTED) return FALSE; tv = GTK_TREE_VIEW(glade_xml_get_widget(addxml, "treeview_add")); tm = gtk_tree_view_get_model(tv); if( !(ts = gtk_tree_view_get_selection(tv)) ) { debug("No selection, ignoring"); return FALSE; } debug("Starting to add songs..."); gui_load_selected(); mpd_finishCommand(glurp->conn); if( check_mpd_error() ) { glurp_disconnect(); return FALSE; } debug("Finished adding songs"); return FALSE; } gboolean on_ui_repeat_clicked(GtkWidget *widget, gpointer user_data) { if( !CONNECTED ) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), FALSE); return FALSE; } if( !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ) { statusbar_print("Repeat Off"); debug("Repeat Off"); mpd_sendRepeatCommand(glurp->conn, 0); mpd_finishCommand(glurp->conn); if( check_mpd_error() ) { glurp_disconnect(); return FALSE; } } else { statusbar_print("Repeat On"); debug("Repeat On"); mpd_sendRepeatCommand(glurp->conn, 1); mpd_finishCommand(glurp->conn); if( check_mpd_error() ) { glurp_disconnect(); return FALSE; } } return FALSE; } gboolean on_ui_random_clicked(GtkWidget *widget, gpointer user_data) { if( !CONNECTED ) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), FALSE); return FALSE; } if( !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ) { statusbar_print("Random Off"); debug("Random Off"); mpd_sendRandomCommand(glurp->conn, 0); mpd_finishCommand(glurp->conn); if( check_mpd_error() ) { glurp_disconnect(); return FALSE; } } else { statusbar_print("Random On"); debug("Random On"); mpd_sendRandomCommand(glurp->conn, 1); mpd_finishCommand(glurp->conn); if( check_mpd_error() ) { glurp_disconnect(); return FALSE; } } return FALSE; } gboolean on_ui_add_row_expanded(GtkTreeView *tv, GtkTreeIter *iter, GtkTreePath *path, gpointer user_data) { gui_add_fill_dir(iter, FALSE); return FALSE; } gboolean on_ui_add_find_clicked( GtkWidget *widget, gpointer data) { if( !CONNECTED ) { debug("Not connected, ignoring."); statusbar_print("Not connected, cannot add"); return FALSE; } debug("Search started"); populate_gui_add_search_tree(); return TRUE; } gboolean on_menu_add_file_activate(GtkWidget *widget, gpointer data) { GtkWidget *window_add; GtkComboBox* combo_type; if( !CONNECTED ) { debug("Not connected, ignoring."); statusbar_print("Not connected, cannot add"); return FALSE; } if( addxml ) { debug("'Add' window already shown, returning"); return FALSE; } debug("Add menu"); addxml = glade_xml_new(glade_path(), "glurp_window_add", NULL); glade_xml_signal_autoconnect(addxml); window_add = glade_xml_get_widget(addxml, "glurp_window_add"); combo_type = GTK_COMBO_BOX(glade_xml_get_widget(addxml, "combo_add_find_type")); gtk_combo_box_set_active(combo_type, 0); create_gui_add_tree(); debug("Populating 'add' treeview..."); populate_gui_add_tree(); title_print(window_add, "Add songs to playlist"); gtk_widget_grab_focus(GTK_WIDGET(glade_xml_get_widget(addxml, "entry_add_find_what"))); gtk_widget_show(window_add); return FALSE; } gboolean on_menu_add_url_activate(GtkWidget *widget, gpointer data) { GtkWidget *window_stream; if( !CONNECTED ) return FALSE; print_stream_history(); if( !STREAM_CAPABLE_MPD ) { statusbar_print("Sorry, this MPD cannot playback streams"); debug("Sorry, this MPD cannot playback streams"); return FALSE; } if( streamxml ) { debug("Stream window already shown, returning"); return FALSE; } streamxml = glade_xml_new(glade_path(), "glurp_window_stream", NULL); glade_xml_signal_autoconnect(streamxml); create_stream_liststore(); populate_stream_liststore(); window_stream = glade_xml_get_widget(streamxml, "glurp_window_stream"); title_print(window_stream, "Add a stream to playlist"); gtk_widget_show(window_stream); return FALSE; } gboolean on_stream_destroy(GtkWidget *widget, gpointer user_data) { stream_window_destroyed(); return FALSE; } gboolean on_ui_stream_close_clicked(GtkWidget *widget, gpointer user_data) { GtkWidget *window_stream = glade_xml_get_widget(streamxml, "glurp_window_stream"); debug("Close pressed, destroying stream window..."); gtk_widget_destroy(window_stream); return FALSE; } gboolean on_ui_stream_add_clicked(GtkWidget *widget, gpointer user_data) { GtkWidget *window_stream = glade_xml_get_widget(streamxml, "glurp_window_stream"); gchar *url = get_selected_stream(); if( !url || !g_utf8_strlen(url, -1) ) { debug("No stream URL to add, ignoring"); gtk_widget_destroy(window_stream); statusbar_print("No URL to add"); return FALSE; } debug("Adding URL: '%s'", url); mpd_sendAddCommand(glurp->conn, url); mpd_finishCommand(glurp->conn); if( !check_mpd_error() ) { statusbar_print("URL '%s' added", url); push_stream(url); } else glurp_disconnect(); gtk_widget_destroy(window_stream); return FALSE; } gboolean on_ui_playlist_drag_begin(GtkWidget *widget, GdkDragContext *cont, gpointer user_data) { debug("DRAG BEGIN"); return FALSE; } gboolean on_ui_playlist_drag_drop(GtkTreeView *tree, GdkDragContext *con, gint x, gint y, guint time, gpointer data) { GtkTreePath *path = NULL; GtkTreeViewDropPosition pos; GtkTreeModel *tm = GTK_TREE_MODEL(glurp->gui_playlist); GtkTreeIter iter; gint did, sid, dpos, spos; gboolean pos_ok = FALSE, first_iter = FALSE; GtkTreeSelection *sel; GList *selected_rows; debug("DRAG DROP"); if( !gtk_tree_view_get_dest_row_at_pos(tree, x, y, &path, &pos) ) { debug("Can't determine destination"); return TRUE; } if( !gtk_tree_model_get_iter(tm, &iter, path) ) { debug("Can't get iter"); return TRUE; } gtk_tree_model_get(tm, &iter, PL_ID, &did, -1); if( pos == GTK_TREE_VIEW_DROP_AFTER ) { debug("AFTER id:%d", did); pos_ok = TRUE; } if( pos == GTK_TREE_VIEW_DROP_BEFORE ) debug("BEFORE id:%d", did); if( pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE ) debug("INTO OR BEFORE id:%d", did); if( pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ) debug("INTO OR AFTER id:%d", did); if( !pos_ok ) { if( !gtk_tree_path_prev(path) || !gtk_tree_model_get_iter(tm, &iter, path) ) { debug("Can't get prev iter, we're at the first one already"); first_iter = TRUE; } } if( first_iter ) dpos = 0; else { gtk_tree_model_get(tm, &iter, PL_ID, &did, -1); dpos = get_song_pos(get_song_by_id(did)); } sel = gtk_tree_view_get_selection(tree); selected_rows = gtk_tree_selection_get_selected_rows(sel, &tm); path = (GtkTreePath *)g_list_nth_data(selected_rows, 0); gtk_tree_model_get_iter(tm, &iter, path); gtk_tree_model_get(tm, &iter, PL_ID, &sid, -1); spos = get_song_pos(get_song_by_id(sid)); if( spos > dpos ) dpos++; mpd_sendMoveIdCommand(glurp->conn, sid, dpos); mpd_finishCommand(glurp->conn); if( !check_mpd_error() ) { debug("Move succesful"); return FALSE; } else glurp_disconnect(); debug("MPD refused song move"); return FALSE; } gboolean on_ui_playlist_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data) { GtkTreePath *path = NULL; GtkTreeSelection *sel = NULL; GtkTreeView *tv = GTK_TREE_VIEW(glade_xml_get_widget(guixml, "treeview_playlist")); if( event->button != 3 ) return FALSE; if( gtk_tree_view_get_path_at_pos(tv, (gint)event->x, (gint)event->y, &path, NULL, NULL, NULL) ) { debug("[%d,%d]", (gint)event->x, (gint)event->y); sel = gtk_tree_view_get_selection(tv); if( !gtk_tree_selection_path_is_selected(sel, path) ) { debug("User clicked on unselected row, selecting "); gtk_tree_selection_unselect_all(sel); gtk_tree_selection_select_path(sel, path); } } debug("Displaying playlist popup menu"); gtk_menu_popup(GTK_MENU(glade_xml_get_widget(guixml, "glurp_menu_playlist")), NULL, NULL, NULL, NULL, event->button, event->time); return TRUE; } gboolean on_pmenu_playlist_play(GtkWidget *widget, gpointer data) { debug("POPUP: Playlist -> Play"); on_ui_player_play(glade_xml_get_widget(guixml, "button_play"), NULL); return FALSE; } gboolean on_pmenu_playlist_remove_selected(GtkWidget *widget, gpointer data) { debug("POPUP: Playlist -> Remove selected"); on_menu_pl_remove_selected_activate(glade_xml_get_widget(guixml, "button_play"), NULL); return FALSE; } gboolean on_pmenu_playlist_remove_crop(GtkWidget *widget, gpointer data) { debug("POPUP: Playlist -> Remove crop"); on_menu_pl_remove_crop_activate(glade_xml_get_widget(guixml, "button_play"), NULL); return FALSE; } gboolean on_pmenu_playlist_remove_all(GtkWidget *widget, gpointer data) { debug("POPUP: Playlist -> Remove all"); on_menu_pl_remove_all_activate(glade_xml_get_widget(guixml, "button_play"), NULL); return FALSE; } gboolean on_ui_add_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data) { GtkTreePath *path = NULL; GtkTreeSelection *sel = NULL; GtkTreeView *tv = GTK_TREE_VIEW(glade_xml_get_widget(addxml, "treeview_add")); if( event->button != 3 ) return FALSE; if( gtk_tree_view_get_path_at_pos(tv, (gint)event->x, (gint)event->y, &path, NULL, NULL, NULL) ) { debug("[%d,%d]", (gint)event->x, (gint)event->y); sel = gtk_tree_view_get_selection(tv); if( !gtk_tree_selection_path_is_selected(sel, path) ) { debug("User clicked on unselected row, selecting "); gtk_tree_selection_unselect_all(sel); gtk_tree_selection_select_path(sel, path); } } debug("Displaying add popup menu"); gtk_menu_popup(GTK_MENU(glade_xml_get_widget(guixml, "glurp_menu_db")), NULL, NULL, NULL, NULL, event->button, event->time); return TRUE; } gboolean on_pmenu_db_update_selected(GtkWidget *widget, gpointer data) { GtkTreeView *tv; GtkTreeModel *tm; GtkTreeSelection *ts; GList *selected_rows; GtkTreeIter iter; gint i, num = 0; gchar *path = NULL; debug("POPUP: DB -> Update selected"); if(!CONNECTED) return FALSE; tv = GTK_TREE_VIEW(glade_xml_get_widget(addxml, "treeview_add")); tm = gtk_tree_view_get_model(tv); if( !((ts = gtk_tree_view_get_selection(tv)) && (num = gtk_tree_selection_count_selected_rows(ts))) ) { debug("No selection, ignoring"); return FALSE; } selected_rows = gtk_tree_selection_get_selected_rows(ts, NULL); debug("Removing 'Add' treeview model"); gtk_tree_view_set_model(tv, NULL); mpd_sendCommandListBegin(glurp->conn); if( NONBLOCKING_UPDATE_CAPABLE_MPD ) { gui_updating_disable_add_controls(); glurp->updating_db = TRUE; } for( i = 0; i < num; i++ ) { gtk_tree_model_get_iter(tm, &iter, (GtkTreePath *)g_list_nth_data(selected_rows, i)); gtk_tree_model_get(tm, &iter, 1, &path, -1); mpd_sendUpdateCommand(glurp->conn, path); debug("**** Updating '%s'", path); g_free(path); } mpd_sendCommandListEnd(glurp->conn); mpd_finishCommand(glurp->conn); if( !NONBLOCKING_UPDATE_CAPABLE_MPD ) { statusbar_print("Database updated"); debug("MPD db updated"); debug("Setting 'Add' treeview model back"); gtk_tree_view_set_model(tv, GTK_TREE_MODEL(glurp->gui_addtree)); populate_gui_add_tree(); } if( check_mpd_error() ) { glurp_disconnect(); return FALSE; } return FALSE; } gboolean on_pmenu_db_add_selected(GtkWidget *widget, gpointer data) { debug("POPUP: DB -> Add selected"); on_ui_add_add_clicked(glade_xml_get_widget(addxml, "button_add_add"), NULL); return FALSE; } gboolean on_pmenu_db_info(GtkWidget *widget, gpointer data) { debug("POPUP: DB -> Database information (STUB)"); return FALSE; } gboolean on_pmenu_playlist_shuffle_activate(GtkWidget *widget, gpointer data) { if( !CONNECTED ) { debug("Not connected"); return FALSE; } mpd_sendShuffleCommand(glurp->conn); mpd_finishCommand(glurp->conn); if( check_mpd_error() ) { glurp_disconnect(); return FALSE; } statusbar_print("Playlist shuffled."); return FALSE; } gboolean on_togglebutton_pl_add_toggled(GtkWidget *widget, gpointer data) { if( !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ) return FALSE; debug("Add button clicked"); gtk_menu_popup(GTK_MENU(glade_xml_get_widget(guixml, "glurp_menu_pl_add")), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time()); return FALSE; } gboolean on_menu_pl_add_deactivate(GtkWidget *widget, gpointer data) { debug("Add menu hidden, deactivating togglebutton"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(guixml, "togglebutton_pl_add")), FALSE); return FALSE; } gboolean on_togglebutton_pl_remove_toggled(GtkWidget *widget, gpointer data) { if( !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ) return FALSE; debug("Remove button clicked"); gtk_menu_popup(GTK_MENU(glade_xml_get_widget(guixml, "glurp_menu_pl_remove")), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time()); return FALSE; } gboolean on_menu_pl_remove_deactivate(GtkWidget *widget, gpointer data) { debug("Remove menu hidden, deactivating togglebutton"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(guixml, "togglebutton_pl_remove")), FALSE); return FALSE; } gboolean on_outputs_toggled(GtkWidget *widget, gpointer data) { GtkMenu *menu = populate_outputs_menu(); if( !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ) return FALSE; debug("Outputs button clicked"); if( !menu ) return FALSE; gtk_menu_popup(populate_outputs_menu(), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time()); return FALSE; } gboolean on_menu_outputs_deactivate(GtkWidget *widget, gpointer data) { debug("Outputs menu hidden, deactivating togglebutton"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(guixml, "togglebutton_outputs")), FALSE); return FALSE; } gboolean on_menu_output_activate(GtkWidget *widget, gpointer data) { gboolean enable = FALSE; gint i, d = (gint)data; if( d < 0 ) enable = TRUE; i = abs(d) - 1; debug("%s output %d", (enable ? "Enable" : "Disable"), i); statusbar_print("%s output %d", (enable ? "Enabling" : "Disabling"), i); if( enable ) mpd_sendEnableOutputCommand(glurp->conn, i); else mpd_sendDisableOutputCommand(glurp->conn, i); mpd_finishCommand(glurp->conn); if( check_mpd_error() ) { glurp_disconnect(); return FALSE; } return FALSE; }