1 /*
2 Glurp - A GTK+ client for Music Player Daemon
3 Copyright (C) 2004, 2005 Andrej Kacian
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 http://musicpd.org/glurp.shtml
20
21 */
22
23 #include <glib.h>
24 #include <gtk/gtk.h>
25 #include <gdk/gdkkeysyms.h>
26 #include <stdlib.h>
27
28 #include <libmpd/libmpd.h>
29 #include <libmpd/libmpd-playlist.h>
30 #include <libmpd/libmpd-database.h>
31
32 #include "structs.h"
33 #include "support.h"
34 #include "comm.h"
35 #include "gui.h"
36 #include "player.h"
37 #include "conf.h"
38
39 extern GtkBuilder *builder;
40 extern GlurpState *glurp;
41
42
43
on_move_tab(GtkWidget * tab)44 void on_move_tab(GtkWidget* tab) {
45 GtkWidget *label;
46 GtkWidget *pane;
47 GtkNotebook *notebook[2] = {
48 GTK_NOTEBOOK(gtk_builder_get_object(builder, "glurp_functional_notebook1")),
49 GTK_NOTEBOOK(gtk_builder_get_object(builder, "glurp_functional_notebook2"))
50 };
51 gpointer tab_indexp;
52 gint page_num,notebook_num,tab_index, target_pos;
53 if ( ( page_num = gtk_notebook_page_num(notebook[0], tab) ) >= 0) {
54 notebook_num = 0;
55 } else {
56 if ( ( page_num = gtk_notebook_page_num(notebook[1], tab) ) >= 0) {
57 notebook_num = 1;
58 } else {
59 return;
60 }
61 }
62 /* get the position of this tab */
63 g_object_get(G_OBJECT(tab), "user_data", &tab_indexp, NULL);
64 tab_index = GPOINTER_TO_INT(tab_indexp);
65
66 label = gtk_notebook_get_tab_label(notebook[notebook_num], tab);
67 g_object_ref(tab);
68 g_object_ref(label);
69 gtk_notebook_remove_page(notebook[notebook_num], page_num);
70 for (target_pos = gtk_notebook_get_n_pages(notebook[1-notebook_num]) - 1 ; target_pos >= 0; target_pos--) {
71 g_object_get(G_OBJECT(gtk_notebook_get_nth_page(notebook[1-notebook_num], target_pos)), "user_data", &tab_indexp, NULL);
72 if (tab_index > GPOINTER_TO_INT(tab_indexp)) {
73 gtk_notebook_insert_page(notebook[1-notebook_num], tab, label, target_pos+1);
74 break;
75 }
76 }
77 if (target_pos < 0)
78 gtk_notebook_prepend_page(notebook[1-notebook_num], tab, label);
79
80 if (gtk_notebook_get_n_pages(notebook[notebook_num])==0) {
81 pane = GTK_WIDGET(gtk_builder_get_object(builder, "glurp_functional_area"));
82 gtk_paned_set_position(GTK_PANED(pane), (notebook_num==1)?0:pane->allocation.width);
83 }
84 if ( gtk_notebook_get_n_pages( notebook[1-notebook_num] ) == 1) {
85 pane = GTK_WIDGET(gtk_builder_get_object(builder, "glurp_functional_area"));
86 gtk_paned_set_position(GTK_PANED(pane), pane->allocation.width/2);
87 }
88 g_object_unref(tab);
89 g_object_unref(label);
90 }
91
on_move_playlist_tab_clicked(GtkWidget * widget,gpointer user_data)92 void on_move_playlist_tab_clicked(GtkWidget *widget, gpointer user_data) {
93 on_move_tab(GTK_WIDGET(gtk_builder_get_object(builder, "playlist_page")));
94 }
on_move_database_tab_clicked(GtkWidget * widget,gpointer user_data)95 void on_move_database_tab_clicked(GtkWidget *widget, gpointer user_data) {
96 on_move_tab(GTK_WIDGET(gtk_builder_get_object(builder, "database_page")));
97 }
on_move_streams_tab_clicked(GtkWidget * widget,gpointer user_data)98 void on_move_streams_tab_clicked(GtkWidget *widget, gpointer user_data) {
99 on_move_tab(GTK_WIDGET(gtk_builder_get_object(builder, "streams_page")));
100 }
on_move_playlists_tab_clicked(GtkWidget * widget,gpointer user_data)101 void on_move_playlists_tab_clicked(GtkWidget *widget, gpointer user_data) {
102 on_move_tab(GTK_WIDGET(gtk_builder_get_object(builder, "playlists_page")));
103 }
on_move_config_tab_clicked(GtkWidget * widget,gpointer user_data)104 void on_move_config_tab_clicked(GtkWidget *widget, gpointer user_data) {
105 on_move_tab(GTK_WIDGET(gtk_builder_get_object(builder, "config_page")));
106 }
107
108
on_ui_quit(GtkWidget * widget,gpointer user_data)109 void on_ui_quit(GtkWidget *widget, gpointer user_data) {
110
111 debug("Quitting Glurp...");
112
113 if (glurp->mpd) {
114 if( mpd_check_connected(glurp->mpd) ) glurp_disconnect();
115
116 mpd_free(glurp->mpd);
117 }
118 config_save();
119
120 gtk_main_quit();
121 }
122
on_window_moved(GtkWidget * widget,GdkEventConfigure * event,gpointer data)123 gboolean on_window_moved(GtkWidget *widget, GdkEventConfigure *event, gpointer data) {
124 debug("Storing window position and size (%dx%d+%d+%d)", event->width, event->height, event->x, event->y);
125
126 glurp->config->pos_x = event->x;
127 glurp->config->pos_y = event->y;
128
129 glurp->config->width = event->width;
130 glurp->config->height = event->height;
131
132 return FALSE;
133 }
134
set_condensed_modifier_style(GtkWidget * widget,gboolean condensed)135 static void set_condensed_modifier_style(GtkWidget* widget, gboolean condensed) {
136 GtkRcStyle* style;
137 if (condensed) {
138 style = gtk_widget_get_modifier_style(widget);
139 style->xthickness = 0;
140 style->ythickness = 0;
141 gtk_widget_modify_style(widget, style);
142 } else
143 gtk_widget_modify_style(widget, gtk_rc_style_new());
144 }
145
on_condense_clicked(GtkWidget * widget,gpointer user_data)146 gboolean on_condense_clicked(GtkWidget *widget, gpointer user_data) {
147 GtkWidget *wi, *wi2;
148 guint size;
149 gint x;
150 gint y;
151
152 wi = GTK_WIDGET(gtk_builder_get_object(builder, "glurp_window_main"));
153 gtk_window_get_position(GTK_WINDOW(wi), &x, &y);
154 gtk_widget_hide(wi);
155
156 gboolean condensed = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
157 size = condensed?gtk_icon_size_from_name ("glurp_condensed"):GTK_ICON_SIZE_BUTTON;
158 if (condensed) {
159 debug("switching to condensed style");
160 gtk_widget_hide_all(GTK_WIDGET(gtk_builder_get_object(builder, "frame_bitrate")));
161 gtk_widget_hide_all(GTK_WIDGET(gtk_builder_get_object(builder, "frame_mode")));
162 gtk_widget_hide_all(GTK_WIDGET(gtk_builder_get_object(builder, "volumebar")));
163 gtk_widget_hide_all(GTK_WIDGET(gtk_builder_get_object(builder, "statusbar_main")));
164 gtk_widget_hide_all(GTK_WIDGET(gtk_builder_get_object(builder, "progressbar")));
165 gtk_widget_hide_all(GTK_WIDGET(gtk_builder_get_object(builder, "togglebutton_outputs")));
166 if( mpd_check_connected(glurp->mpd) )
167 gtk_widget_hide_all(GTK_WIDGET(gtk_builder_get_object(builder, "button_server_connect")));
168 else
169 gtk_widget_hide_all(GTK_WIDGET(gtk_builder_get_object(builder, "button_server_disconnect")));
170
171 /* remove decoration, but add a border */
172 wi = GTK_WIDGET(gtk_builder_get_object(builder, "glurp_window_main"));
173 gtk_window_set_decorated(GTK_WINDOW(wi), FALSE);
174 wi2 = gtk_bin_get_child(GTK_BIN(wi));
175 g_object_ref(G_OBJECT(wi2));
176 gtk_container_remove(GTK_CONTAINER(wi), wi2);
177 gtk_container_add(GTK_CONTAINER(wi), gtk_frame_new(NULL));
178 wi = gtk_bin_get_child(GTK_BIN(wi));
179 gtk_frame_set_shadow_type(GTK_FRAME(wi), GTK_SHADOW_ETCHED_OUT);
180 gtk_widget_show(wi);
181 gtk_container_add(GTK_CONTAINER(wi), wi2);
182 g_object_unref(wi2);
183 gtk_container_set_border_width(GTK_CONTAINER(wi2), 3);
184 /* remove frames */
185 glurp->frame_time = GTK_WIDGET(gtk_builder_get_object(builder, "frame_time"));
186 wi = GTK_WIDGET(gtk_builder_get_object(builder, "hbox_player_info"));
187 wi2 = gtk_bin_get_child(GTK_BIN(glurp->frame_time));
188 g_object_ref(G_OBJECT(glurp->frame_time));
189 g_object_ref(G_OBJECT(wi2));
190 gtk_container_remove(GTK_CONTAINER(wi), glurp->frame_time);
191 gtk_container_remove(GTK_CONTAINER(glurp->frame_time), wi2);
192 gtk_box_pack_start(GTK_BOX(wi), wi2, FALSE, FALSE, 0);
193 g_object_unref(G_OBJECT(wi2));
194
195 glurp->frame_trackname = GTK_WIDGET(gtk_builder_get_object(builder, "frame_trackname"));
196 wi2 = gtk_bin_get_child(GTK_BIN(glurp->frame_trackname));
197 g_object_ref(G_OBJECT(glurp->frame_trackname));
198 g_object_ref(G_OBJECT(wi2));
199 gtk_container_remove(GTK_CONTAINER(wi), glurp->frame_trackname);
200 gtk_container_remove(GTK_CONTAINER(glurp->frame_trackname), wi2);
201 gtk_box_pack_start(GTK_BOX(wi), wi2, TRUE, TRUE, 0);
202 g_object_unref(G_OBJECT(wi2));
203 } else {
204 gtk_widget_show_all(GTK_WIDGET(gtk_builder_get_object(builder, "frame_bitrate")));
205 gtk_widget_show_all(GTK_WIDGET(gtk_builder_get_object(builder, "frame_mode")));
206 gtk_widget_show_all(GTK_WIDGET(gtk_builder_get_object(builder, "volumebar")));
207 gtk_widget_show_all(GTK_WIDGET(gtk_builder_get_object(builder, "statusbar_main")));
208 gtk_widget_show_all(GTK_WIDGET(gtk_builder_get_object(builder, "progressbar")));
209 gtk_widget_show_all(GTK_WIDGET(gtk_builder_get_object(builder, "togglebutton_outputs")));
210 if( mpd_check_connected(glurp->mpd) )
211 gtk_widget_show_all(GTK_WIDGET(gtk_builder_get_object(builder, "button_server_connect")));
212 else
213 gtk_widget_show_all(GTK_WIDGET(gtk_builder_get_object(builder, "button_server_disconnect")));
214 /* replace decoration and remove the border */
215 wi = GTK_WIDGET(gtk_builder_get_object(builder, "glurp_window_main"));
216 gtk_window_set_decorated(GTK_WINDOW(wi), TRUE);
217 wi = gtk_bin_get_child(GTK_BIN(wi));
218 wi2 = gtk_bin_get_child(GTK_BIN(wi));
219 g_object_ref(G_OBJECT(wi2));
220 gtk_container_remove(GTK_CONTAINER(wi), wi2);
221 gtk_widget_destroy(wi);
222 wi = GTK_WIDGET(gtk_builder_get_object(builder, "glurp_window_main"));
223 gtk_container_add(GTK_CONTAINER(wi), wi2);
224 g_object_unref(wi2);
225 gtk_container_set_border_width(GTK_CONTAINER(wi2), 0);
226 /* replace frames */
227 wi = GTK_WIDGET(gtk_builder_get_object(builder, "hbox_player_info"));
228 // wi2 = GTK_WIDGET(gtk_builder_get_object(builder, "button_time"));
229 wi2 = GTK_WIDGET(gtk_builder_get_object(builder, "label_time"));
230 g_object_ref(G_OBJECT(wi2));
231 gtk_container_remove(GTK_CONTAINER(wi), wi2);
232 gtk_box_pack_start(GTK_BOX(wi), glurp->frame_time, FALSE, FALSE, 5);
233 gtk_container_add(GTK_CONTAINER(glurp->frame_time), wi2);
234 g_object_unref(G_OBJECT(glurp->frame_time));
235 g_object_unref(G_OBJECT(wi2));
236
237 wi2 = GTK_WIDGET(gtk_builder_get_object(builder, "entry_trackname"));
238 g_object_ref(G_OBJECT(wi2));
239 gtk_container_remove(GTK_CONTAINER(wi), wi2);
240 gtk_box_pack_start(GTK_BOX(wi), glurp->frame_trackname, TRUE, TRUE, 5);
241 gtk_container_add(GTK_CONTAINER(glurp->frame_trackname), wi2);
242 g_object_unref(G_OBJECT(glurp->frame_trackname));
243 g_object_unref(G_OBJECT(wi2));
244 }
245 wi = GTK_WIDGET(gtk_builder_get_object(builder, "button_prev"));
246 set_condensed_modifier_style(wi, condensed);
247 gtk_widget_destroy(gtk_bin_get_child(GTK_BIN(wi)));
248 gtk_container_add(GTK_CONTAINER(wi), gtk_image_new_from_stock("glurp-prev", size));
249 gtk_widget_show_all(wi);
250 /* prev */
251 wi = GTK_WIDGET(gtk_builder_get_object(builder, "button_prev"));
252 set_condensed_modifier_style(wi, condensed);
253 gtk_widget_destroy(gtk_bin_get_child(GTK_BIN(wi)));
254 gtk_container_add(GTK_CONTAINER(wi), gtk_image_new_from_stock("glurp-prev", size) );
255 gtk_widget_show_all(wi);
256 /* play */
257 wi = GTK_WIDGET(gtk_builder_get_object(builder, "button_play"));
258 set_condensed_modifier_style(wi, condensed);
259 gtk_widget_destroy(gtk_bin_get_child(GTK_BIN(wi)));
260 gtk_container_add(GTK_CONTAINER(wi), gtk_image_new_from_stock("glurp-play", size) );
261 gtk_widget_show_all(wi);
262 /* pause */
263 wi = GTK_WIDGET(gtk_builder_get_object(builder, "button_pause"));
264 set_condensed_modifier_style(wi, condensed);
265 gtk_widget_destroy(gtk_bin_get_child(GTK_BIN(wi)));
266 gtk_container_add(GTK_CONTAINER(wi), gtk_image_new_from_stock("glurp-pause", size) );
267 gtk_widget_show_all(wi);
268 /* stop */
269 wi = GTK_WIDGET(gtk_builder_get_object(builder, "button_stop"));
270 set_condensed_modifier_style(wi, condensed);
271 gtk_widget_destroy(gtk_bin_get_child(GTK_BIN(wi)));
272 gtk_container_add(GTK_CONTAINER(wi), gtk_image_new_from_stock("glurp-stop", size) );
273 gtk_widget_show_all(wi);
274 /* next */
275 wi = GTK_WIDGET(gtk_builder_get_object(builder, "button_next"));
276 set_condensed_modifier_style(wi, condensed);
277 gtk_widget_destroy(gtk_bin_get_child(GTK_BIN(wi)));
278 gtk_container_add(GTK_CONTAINER(wi), gtk_image_new_from_stock("glurp-next", size) );
279 gtk_widget_show_all(wi);
280
281 /* playlist show/hide */
282 wi = GTK_WIDGET(gtk_builder_get_object(builder, "togglebutton_playlist"));
283 set_condensed_modifier_style(wi, condensed);
284 gtk_widget_destroy(gtk_bin_get_child(GTK_BIN(wi)));
285 gtk_container_add(GTK_CONTAINER(wi), gtk_image_new_from_stock("glurp-playlist", size) );
286 gtk_widget_show_all(wi);
287
288 /* repeat */
289 wi = GTK_WIDGET(gtk_builder_get_object(builder, "togglebutton_repeat"));
290 set_condensed_modifier_style(wi, condensed);
291 gtk_widget_destroy(gtk_bin_get_child(GTK_BIN(wi)));
292 gtk_container_add(GTK_CONTAINER(wi), gtk_image_new_from_stock("glurp-repeat", size) );
293 gtk_widget_show_all(wi);
294
295 /* random */
296 wi = GTK_WIDGET(gtk_builder_get_object(builder, "togglebutton_random"));
297 set_condensed_modifier_style(wi, condensed);
298 gtk_widget_destroy(gtk_bin_get_child(GTK_BIN(wi)));
299 gtk_container_add(GTK_CONTAINER(wi), gtk_image_new_from_stock("glurp-random", size) );
300 gtk_widget_show_all(wi);
301
302 /* condense */
303 wi = GTK_WIDGET(gtk_builder_get_object(builder, "togglebutton_condense"));
304 set_condensed_modifier_style(wi, condensed);
305 gtk_widget_destroy(gtk_bin_get_child(GTK_BIN(wi)));
306 gtk_container_add(GTK_CONTAINER(wi), gtk_image_new_from_stock("glurp-condense", size) );
307 gtk_widget_show_all(wi);
308
309 if (condensed)
310 gtk_window_resize(GTK_WINDOW(gtk_builder_get_object(builder, "glurp_window_main")), 1,1);
311
312 wi = GTK_WIDGET(gtk_builder_get_object(builder, "glurp_window_main"));
313 gtk_window_move(GTK_WINDOW(wi), x, y);
314 gtk_widget_show(wi);
315 return FALSE;
316 };
317
on_entry_trackname_size_allocate(GtkWidget * widget,GtkAllocation * allocation,gpointer user_data)318 void on_entry_trackname_size_allocate(GtkWidget *widget, GtkAllocation *allocation, gpointer user_data) {
319 glurp->trackname_width = allocation->width;
320 gui_check_scroll();
321 }
322
on_button_config_revert_clicked(GtkWidget * widget,gpointer user_data)323 gboolean on_button_config_revert_clicked(GtkWidget *widget, gpointer user_data) {
324
325 debug("Revert, refilling config window...");
326 populate_config();
327
328 return FALSE;
329 }
330
on_config_destroy(GtkWidget * widget,gpointer user_data)331 gboolean on_config_destroy(GtkWidget *widget, gpointer user_data) {
332 return FALSE;
333 }
334
on_button_config_apply_clicked(GtkWidget * widget,gpointer user_data)335 gboolean on_button_config_apply_clicked(GtkWidget *widget, gpointer user_data) {
336
337 debug("Apply pressed, hiding config window...");
338
339 debug("Storing variables into GlurpConfig");
340 store_config();
341
342 config_save();
343
344 statusbar_print("Config saved...");
345
346 return FALSE;
347 }
348
on_ui_press_connect(GtkWidget * widget,gpointer user_data)349 gboolean on_ui_press_connect(GtkWidget *widget, gpointer user_data) {
350 glurp_connect();
351 return FALSE;
352 }
353
on_ui_press_disconnect(GtkWidget * widget,gpointer user_data)354 gboolean on_ui_press_disconnect(GtkWidget *widget, gpointer user_data) {
355 glurp_disconnect();
356 return FALSE;
357 }
358
on_ui_volume_changed(GtkWidget * widget,gpointer user_data)359 gboolean on_ui_volume_changed(GtkWidget *widget, gpointer user_data) {
360 gdouble i = gtk_scale_button_get_value(GTK_SCALE_BUTTON(widget));
361
362 if( mpd_check_connected(glurp->mpd) ) {
363 mpd_status_set_volume(glurp->mpd, (int)(i*100));
364
365 statusbar_print("Volume: %d%%", (int)(i*100));
366 }
367
368 return FALSE;
369 }
370
on_ui_progress_change(GtkWidget * widget,gpointer user_data)371 gboolean on_ui_progress_change(GtkWidget *widget, gpointer user_data) {
372 double pos, tt;
373
374 if(!glurp->progress_dragging) return FALSE;
375
376 tt = mpd_status_get_total_song_time(glurp->mpd);
377
378 pos = gtk_range_get_value(GTK_RANGE(widget));
379
380 debug("Seeking to %d seconds", (gint)pos);
381 statusbar_print("Seek to %02d:%02d/%02d:%02d", (gint)pos/60, (gint)pos%60, (gint)tt/60, (gint)tt%60);
382 mpd_player_seek(glurp->mpd, pos);
383 debug("setting FALSE");
384 glurp->progress_dragging = FALSE;
385
386 return FALSE;
387 }
388
on_ui_progress_change_start_kb(GtkWidget * widget,GdkEventKey * event,gpointer user_data)389 gboolean on_ui_progress_change_start_kb(GtkWidget *widget, GdkEventKey *event,
390 gpointer user_data) {
391 guint k = event->keyval;
392
393 if( !glurp->progress_dragging &&
394 !(event->state & (GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_MOD1_MASK)) &&
395 ((k == GDK_KP_Left) ||
396 (k == GDK_KP_Right) ||
397 (k == GDK_Left) ||
398 (k == GDK_Right) ||
399 (k == GDK_Page_Up) ||
400 (k == GDK_Page_Down) )) {
401 debug("setting TRUE");
402 glurp->progress_dragging = TRUE;
403 } else if( glurp->progress_dragging )
404 return FALSE;
405 return TRUE;
406 }
407
on_ui_progress_change_start(GtkWidget * widget,gpointer user_data)408 gboolean on_ui_progress_change_start(GtkWidget *widget, gpointer user_data) {
409 if( !glurp->progress_dragging ) {
410 debug("setting TRUE");
411 glurp->progress_dragging = TRUE;
412 }
413 return FALSE;
414 }
415
on_ui_playlist_clicked(GtkWidget * widget,gpointer user_data)416 gboolean on_ui_playlist_clicked(GtkWidget *widget, gpointer user_data) {
417 if( !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) )
418 hide_gui_playlist();
419 else
420 show_gui_playlist();
421
422 return FALSE;
423 }
424
on_ui_player_play(GtkWidget * widget,gpointer user_data)425 gboolean on_ui_player_play(GtkWidget *widget, gpointer user_data) {
426 GtkTreeView *tv;
427 GtkTreeModel *tm;
428 GtkTreeSelection *sel;
429 GtkTreePath *path;
430 GtkTreeIter iter;
431 gint id, pos, num;
432 GList *selected_rows;
433
434 tv = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview_playlist"));
435 tm = gtk_tree_view_get_model(tv);
436
437 if(!gtk_tree_model_iter_n_children(tm, NULL)) {
438 debug("Nothing loaded in playlist, cannot play");
439 statusbar_print("Playlist empty");
440 return FALSE;
441 }
442
443 if( PAUSED )
444 /* prone to race condition... should be made better. */
445 player_pause();
446 else {
447
448 sel = gtk_tree_view_get_selection(tv);
449
450 if( !(num = gtk_tree_selection_count_selected_rows(sel)) ) {
451 debug("No song selected, letting MPD decide which song to play");
452 if( !STOPPED ) player_stop();
453 player_play_song(-1);
454 return FALSE;
455 }
456
457 if( !(selected_rows = gtk_tree_selection_get_selected_rows(sel, &tm)) ) {
458 debug("Couldn't get selected rows");
459 return FALSE;
460 }
461
462 path = (GtkTreePath *)g_list_nth_data(selected_rows, 0);
463
464 if ( !gtk_tree_model_get_iter(tm, &iter, path) ) {
465 debug("Couldn't get GtkTreeIter, what now?");
466 return FALSE;
467 }
468
469 debug("Getting trackno. of selected song");
470 gtk_tree_model_get(tm, &iter, PL_ID, &id, PL_POS, &pos, -1);
471 debug("Song number is %d, id %d", pos, id);
472
473 if( num > 1 ) gui_playlist_set_cursor(pos - 1);
474
475 if( !STOPPED ) player_stop();
476 player_play_song(id);
477 }
478
479 return FALSE;
480 }
481
on_ui_player_pause(GtkWidget * widget,gpointer user_data)482 gboolean on_ui_player_pause(GtkWidget *widget, gpointer user_data) {
483 player_pause();
484
485 return FALSE;
486 }
487
on_ui_player_stop(GtkWidget * widget,gpointer user_data)488 gboolean on_ui_player_stop(GtkWidget *widget, gpointer user_data) {
489 player_stop();
490
491 return FALSE;
492 }
493
on_ui_player_prev(GtkWidget * widget,gpointer user_data)494 gboolean on_ui_player_prev(GtkWidget *widget, gpointer user_data) {
495 player_prev();
496
497 return FALSE;
498 }
499
on_ui_player_next(GtkWidget * widget,gpointer user_data)500 gboolean on_ui_player_next(GtkWidget *widget, gpointer user_data) {
501 player_next();
502
503 return FALSE;
504 }
505 #if 0
506 gboolean on_ui_time_clicked(GtkWidget *widget, gpointer user_data) {
507 if(glurp->config->time_display_left) glurp->config->time_display_left = FALSE;
508 else glurp->config->time_display_left = TRUE;
509
510 gtk_widget_grab_focus(GTK_WIDGET(gtk_builder_get_object(builder, "glurp_functional_notebook1")));
511
512 return FALSE;
513 }
514 #endif
on_ui_playlist_row_activated(GtkTreeView * treeview,GtkTreePath * tp,GtkTreeViewColumn * col,gpointer user_data)515 gboolean on_ui_playlist_row_activated(GtkTreeView *treeview, GtkTreePath *tp, GtkTreeViewColumn *col, gpointer user_data) {
516 GtkTreeIter act;
517 GtkTreeModel *model;
518 gint id;
519
520 debug("Playlist item activated.");
521
522 if(!mpd_check_connected(glurp->mpd)) {
523 debug("We're not connected, cannot start playing anything.");
524 return FALSE;
525 }
526
527 model = gtk_tree_view_get_model(treeview);
528 gtk_tree_model_get_iter(model, &act, tp);
529 gtk_tree_model_get(model, &act, PL_ID, &id, -1);
530
531 player_stop();
532 player_play_song(id);
533
534 return FALSE;
535 }
536
on_ui_playlist_list_row_activated(GtkTreeView * treeview,GtkTreePath * tp,GtkTreeViewColumn * col,gpointer user_data)537 gboolean on_ui_playlist_list_row_activated(GtkTreeView *treeview, GtkTreePath *tp, GtkTreeViewColumn *col, gpointer user_data) {
538 GtkTreeIter act;
539 GtkTreeModel *model;
540 gchar *name;
541
542 debug("playlist activated");
543
544 if( !mpd_check_connected(glurp->mpd) ) {
545 debug("we're not connected, how can this be?");
546 return FALSE;
547 }
548
549 model = gtk_tree_view_get_model(treeview);
550 gtk_tree_model_get_iter(model, &act, tp);
551 gtk_tree_model_get(model, &act, 0, &name, -1);
552
553 load_playlist(name);
554 g_free(name);
555
556 return FALSE;
557 }
558
on_ui_playlist_load(GtkWidget * widget,gpointer user_data)559 gboolean on_ui_playlist_load(GtkWidget *widget, gpointer user_data) {
560 GtkTreeView *tv;
561
562 GtkTreeModel *tm;
563 GtkTreeSelection *sel;
564 GtkTreeIter iter;
565 gchar *name;
566
567 if( !mpd_check_connected(glurp->mpd) ) {
568 debug("We're not connected, how can this be?");
569 return FALSE;
570 }
571
572 tv = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview_playlist_list"));
573 tm = gtk_tree_view_get_model(tv);
574
575 sel = gtk_tree_view_get_selection(tv);
576 if( !gtk_tree_selection_get_selected(sel, &tm, &iter)) {
577 debug("No playlist selected");
578 return FALSE;
579 }
580
581 debug("getting name of selected playlist");
582 gtk_tree_model_get(tm, &iter, 0, &name, -1);
583
584 load_playlist(name);
585 g_free(name);
586
587 return FALSE;
588 }
589
on_ui_playlist_delete(GtkWidget * widget,gpointer user_data)590 gboolean on_ui_playlist_delete(GtkWidget *widget, gpointer user_data) {
591 GtkTreeView *tv;
592
593 GtkTreeModel *tm;
594 GtkTreeSelection *sel;
595 GtkTreeIter iter;
596 gchar *name;
597
598 if( !mpd_check_connected(glurp->mpd) ) {
599 debug("We're not connected, how can this be?");
600 return FALSE;
601 }
602
603 tv = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview_playlist_list"));
604 tm = gtk_tree_view_get_model(tv);
605
606 sel = gtk_tree_view_get_selection(tv);
607 if( !gtk_tree_selection_get_selected(sel, &tm, &iter)) {
608 debug("No playlist selected");
609 return FALSE;
610 }
611
612 gtk_tree_model_get(tm, &iter, 0, &name, -1);
613
614 mpd_database_delete_playlist(glurp->mpd, name);
615
616 debug("Playlist '%s' deleted", name);
617 g_free(name);
618 get_playlist_list();
619 populate_gui_playlist_list();
620
621 return FALSE;
622 }
623
on_ui_playlist_save(GtkWidget * widget,gpointer user_data)624 gboolean on_ui_playlist_save(GtkWidget *widget, gpointer user_data) {
625 GtkEntry *entry = GTK_ENTRY(gtk_builder_get_object(builder, "entry_playlist_name"));
626 gchar *name = (gchar *)gtk_entry_get_text(entry);
627 GlurpPl *pl;
628
629 if( !mpd_check_connected(glurp->mpd) ) {
630 debug("We're not connected, how can this be? Ignoring");
631 return FALSE;
632 }
633
634 if( !name || !g_utf8_strlen(name, -1) ) {
635 debug("Empty playlist name, ignoring");
636 return FALSE;
637 }
638
639 for( pl = glurp->playlists; pl; pl = pl->next ) {
640 if( !g_ascii_strcasecmp(pl->name, name) ) {
641 debug("Not overwriting existing playlist");
642 return FALSE;
643 }
644 }
645
646 mpd_database_save_playlist(glurp->mpd, name);
647
648 debug("Playlist '%s' saved", name);
649 get_playlist_list();
650 populate_gui_playlist_list();
651
652 return FALSE;
653 }
654
on_ui_progress_drag(GtkWidget * widget,gpointer user_data)655 gboolean on_ui_progress_drag(GtkWidget *widget, gpointer user_data) {
656 double pos = gtk_range_get_value(GTK_RANGE(widget));
657 double sec, tt;
658 gint t_min, t_sec, s_min, s_sec;
659
660 //if( !glurp->conn || !glurp->current_song ) return FALSE;
661
662 if( !glurp->progress_dragging ) return FALSE;
663
664 tt = glurp->current_song->time;
665
666 t_min = (int)tt/60;
667 t_sec = (int)tt%60;
668
669 sec = pos;
670 s_min = (int)sec/60;
671 s_sec = (int)sec%60;
672
673 statusbar_print("Seek to %02d:%02d/%02d:%02d", s_min, s_sec, t_min, t_sec);
674
675 return FALSE;
676 }
677
on_ui_playlist_list_cursor_changed(GtkWidget * widget,gpointer user_data)678 gboolean on_ui_playlist_list_cursor_changed(GtkWidget *widget, gpointer user_data) {
679 GtkTreeView *tv;
680 GtkTreeModel *tm;
681 GtkTreeSelection *sel;
682 GtkTreeIter iter;
683 gchar *name;
684
685 if( !mpd_check_connected(glurp->mpd) ) {
686 debug("We're not connected, how can this be?");
687 return FALSE;
688 }
689
690 tv = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview_playlist_list"));
691 tm = gtk_tree_view_get_model(tv);
692
693 sel = gtk_tree_view_get_selection(tv);
694 if( !gtk_tree_selection_get_selected(sel, &tm, &iter)) {
695 debug("No playlist selected");
696 return FALSE;
697 }
698
699 gtk_tree_model_get(tm, &iter, 0, &name, -1);
700
701 gtk_entry_set_text(GTK_ENTRY(gtk_builder_get_object(builder, "entry_playlist_name")), name);
702 g_free(name);
703
704 return FALSE;
705 }
706
on_ui_qsearch_activate(GtkWidget * widget,gpointer user_data)707 gboolean on_ui_qsearch_activate(GtkWidget *widget, gpointer user_data)
708 {
709 gchar *srch = (gchar *)gtk_entry_get_text(GTK_ENTRY(widget));
710 gchar *sample = NULL;
711 gint type = gtk_combo_box_get_active(GTK_COMBO_BOX(gtk_builder_get_object(builder, "combobox_qsearch_type")));
712 GtkTreePath *path;
713 GtkTreeIter iter;
714 GtkTreeView *view = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview_playlist"));
715 gint cpos, spos;
716 gboolean found = FALSE;
717
718 if( !srch || !g_utf8_strlen(srch, -1) )
719 return FALSE;
720
721 debug("QSearch string: '%s'", srch);
722
723 gtk_tree_view_get_cursor(view, &path, NULL);
724 if( path ) {
725 /* Remember starting position */
726 spos = cpos = atoi(gtk_tree_path_to_string(path));
727 gtk_tree_path_free(path);
728 } else {
729 spos = cpos = 0;
730 }
731
732 debug("Cursor position: %d", cpos + 1);
733
734 cpos++;
735
736 while( !found && cpos != spos ) {
737 if( !gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(glurp->gui_playlist), &iter, NULL, cpos) ) {
738 cpos = 0;
739 continue;
740 }
741
742 switch(type) {
743 case GLURP_QSEARCH_TITLE:
744 gtk_tree_model_get(GTK_TREE_MODEL(glurp->gui_playlist), &iter, PL_TITLE, &sample, -1);
745 if( sample && srch && g_strrstr(g_ascii_strdown(sample, -1), g_ascii_strdown(srch, -1)) ) {
746 debug("Found suitable haystack: '%s'", sample);
747 gui_playlist_scroll(cpos);
748 found = TRUE;
749 }
750
751 break;
752
753 case GLURP_QSEARCH_ARTIST:
754 gtk_tree_model_get(GTK_TREE_MODEL(glurp->gui_playlist), &iter, PL_TITLE, &sample, -1);
755 if( sample && srch && g_strrstr(g_ascii_strdown(sample, -1), g_ascii_strdown(srch, -1)) ) {
756 debug("Found suitable haystack: '%s'", sample);
757 gui_playlist_scroll(cpos);
758 found = TRUE;
759 }
760
761 break;
762
763 case GLURP_QSEARCH_ALBUM:
764 gtk_tree_model_get(GTK_TREE_MODEL(glurp->gui_playlist), &iter, PL_TITLE, &sample, -1);
765 if( sample && srch && g_strrstr(g_ascii_strdown(sample, -1), g_ascii_strdown(srch, -1)) ) {
766 debug("Found suitable haystack: '%s'", sample);
767 gui_playlist_scroll(cpos);
768 found = TRUE;
769 }
770
771 break;
772
773 case GLURP_QSEARCH_FILENAME:
774 gtk_tree_model_get(GTK_TREE_MODEL(glurp->gui_playlist), &iter, PL_TITLE, &sample, -1);
775 if( sample && srch && g_strrstr(g_ascii_strdown(sample, -1), g_ascii_strdown(srch, -1)) ) {
776 debug("Found suitable haystack: '%s'", sample);
777 gui_playlist_scroll(cpos);
778 found = TRUE;
779 }
780
781 break;
782
783 case GLURP_QSEARCH_ALL:
784 gtk_tree_model_get(GTK_TREE_MODEL(glurp->gui_playlist), &iter, PL_TITLE, &sample, -1);
785 if( sample && srch && g_strrstr(g_ascii_strdown(sample, -1), g_ascii_strdown(srch, -1)) ) {
786 debug("Found suitable haystack: '%s'", sample);
787 gui_playlist_scroll(cpos);
788 found = TRUE;
789 break;
790 }
791
792 gtk_tree_model_get(GTK_TREE_MODEL(glurp->gui_playlist), &iter, PL_TITLE, &sample, -1);
793 if( sample && srch && g_strrstr(g_ascii_strdown(sample, -1), g_ascii_strdown(srch, -1)) ) {
794 debug("Found suitable haystack: '%s'", sample);
795 gui_playlist_scroll(cpos);
796 found = TRUE;
797 break;
798 }
799
800 gtk_tree_model_get(GTK_TREE_MODEL(glurp->gui_playlist), &iter, PL_TITLE, &sample, -1);
801 if( sample && srch && g_strrstr(g_ascii_strdown(sample, -1), g_ascii_strdown(srch, -1)) ) {
802 debug("Found suitable haystack: '%s'", sample);
803 gui_playlist_scroll(cpos);
804 found = TRUE;
805 break;
806 }
807
808 gtk_tree_model_get(GTK_TREE_MODEL(glurp->gui_playlist), &iter, PL_TITLE, &sample, -1);
809 if( sample && srch && g_strrstr(g_ascii_strdown(sample, -1), g_ascii_strdown(srch, -1)) ) {
810 debug("Found suitable haystack: '%s'", sample);
811 gui_playlist_scroll(cpos);
812 found = TRUE;
813 break;
814 }
815
816 break;
817
818 }
819
820 cpos++;
821
822 }
823
824 if( !found ) debug("Nothing found...");
825
826 return FALSE;
827 }
828
on_menu_add_activate(GtkWidget * widget,gpointer data)829 gboolean on_menu_add_activate(GtkWidget *widget, gpointer data) {
830 return FALSE;
831 }
832
on_menu_pl_remove_all_activate(GtkWidget * widget,gpointer data)833 gboolean on_menu_pl_remove_all_activate(GtkWidget *widget, gpointer data) {
834 if(!mpd_check_connected(glurp->mpd)) return FALSE;
835
836 mpd_playlist_clear(glurp->mpd);
837 return FALSE;
838 }
839
on_menu_pl_remove_selected_activate(GtkWidget * widget,gpointer data)840 gboolean on_menu_pl_remove_selected_activate(GtkWidget *widget, gpointer data) {
841 GtkWidget *tv;
842 GtkTreeModel *tm;
843 GtkTreeSelection *ts;
844 gint num_sel, i, id;
845 GtkTreeIter iter;
846 GList *selected_rows;
847
848 if(!mpd_check_connected(glurp->mpd)) return FALSE;
849
850 tv = GTK_WIDGET(gtk_builder_get_object(builder, "treeview_playlist"));
851 tm = gtk_tree_view_get_model(GTK_TREE_VIEW(tv));
852 ts = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv));
853
854 num_sel = gtk_tree_selection_count_selected_rows(ts);
855 selected_rows = gtk_tree_selection_get_selected_rows(ts, NULL);
856
857 debug("Selected %d rows", num_sel);
858
859 if( num_sel ) {
860 for( i=0; i<num_sel; i++ ) {
861 gtk_tree_model_get_iter(tm, &iter, (GtkTreePath *)g_list_nth_data(selected_rows, i));
862 gtk_tree_model_get(tm, &iter, PL_ID, &id, -1);
863 mpd_playlist_queue_delete_id(glurp->mpd, id);
864 }
865 mpd_playlist_queue_commit(glurp->mpd);
866 }
867 return FALSE;
868 }
869
on_menu_pl_remove_crop_activate(GtkWidget * widget,gpointer data)870 gboolean on_menu_pl_remove_crop_activate(GtkWidget *widget, gpointer data) {
871 GtkWidget *tv;
872 GtkTreeModel *tm;
873 GtkTreeSelection *ts;
874 GtkTreeIter iter;
875 gint i = 0, id;
876
877 if(!mpd_check_connected(glurp->mpd)) return FALSE;
878
879 tv = GTK_WIDGET(gtk_builder_get_object(builder, "treeview_playlist"));
880 tm = gtk_tree_view_get_model(GTK_TREE_VIEW(tv));
881 ts = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv));
882
883 if( !gtk_tree_model_get_iter_first(tm, &iter) ) {
884 debug("Couldn't get first iter, playlist empty?");
885 return FALSE;
886 }
887
888 do {
889 if( !gtk_tree_selection_iter_is_selected(ts, &iter) ) {
890 gtk_tree_model_get(tm, &iter, PL_ID, &id, -1);
891 mpd_playlist_queue_delete_id( glurp->mpd, id);
892 }
893 else i++;
894 } while( gtk_tree_model_iter_next(tm, &iter) );
895
896 mpd_playlist_queue_commit(glurp->mpd);
897
898 return FALSE;
899 }
900
901
on_ui_add_update_clicked(GtkWidget * widget,gpointer data)902 gboolean on_ui_add_update_clicked(GtkWidget *widget, gpointer data) {
903
904 gtk_tree_store_clear(glurp->gui_addtree);
905
906 debug("Removing 'Add' treeview model");
907 //gtk_tree_view_set_model(GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview_add")), NULL);
908
909 gui_updating_disable_add_controls();
910 glurp->updating_db = TRUE;
911 statusbar_print("Updating MPD database, please wait...");
912 debug("Starting to update MPD db...");
913
914
915 mpd_database_update_dir(glurp->mpd, "/");
916 mpd_check_error(glurp->mpd);
917
918 return FALSE;
919 }
920
on_ui_add_add_clicked(GtkWidget * widget,gpointer data)921 gboolean on_ui_add_add_clicked(GtkWidget *widget, gpointer data) {
922 GtkTreeView *tv;
923 GtkTreeModel *tm;
924 GtkTreeSelection *ts;
925
926 if(!mpd_check_connected(glurp->mpd)) return FALSE;
927
928 tv = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview_add"));
929 tm = gtk_tree_view_get_model(tv);
930 if( !(ts = gtk_tree_view_get_selection(tv)) ) {
931 debug("No selection, ignoring");
932 return FALSE;
933 }
934
935 debug("Starting to add songs...");
936
937 gui_load_selected();
938
939 debug("Finished adding songs");
940
941 return FALSE;
942 }
943
on_ui_repeat_clicked(GtkWidget * widget,gpointer user_data)944 gboolean on_ui_repeat_clicked(GtkWidget *widget, gpointer user_data) {
945 if( !mpd_check_connected(glurp->mpd) ) {
946 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), FALSE);
947 return FALSE;
948 }
949
950 if( !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ) {
951 statusbar_print("Repeat Off");
952 debug("Repeat Off");
953 mpd_player_set_repeat(glurp->mpd, FALSE);
954
955 } else {
956 statusbar_print("Repeat On");
957 debug("Repeat On");
958 mpd_player_set_repeat(glurp->mpd, TRUE);
959 }
960 return FALSE;
961 }
962
on_ui_random_clicked(GtkWidget * widget,gpointer user_data)963 gboolean on_ui_random_clicked(GtkWidget *widget, gpointer user_data) {
964 if( !mpd_check_connected(glurp->mpd) ) {
965 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), FALSE);
966 return FALSE;
967 }
968
969 if( !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ) {
970 statusbar_print("Random Off");
971 debug("Random Off");
972 mpd_player_set_random(glurp->mpd, FALSE);
973 } else {
974 statusbar_print("Random On");
975 debug("Random On");
976 mpd_player_set_random(glurp->mpd, TRUE);
977 }
978 return FALSE;
979 }
980
981
on_ui_add_row_expanded(GtkTreeView * tv,GtkTreeIter * iter,GtkTreePath * path,gpointer user_data)982 gboolean on_ui_add_row_expanded(GtkTreeView *tv, GtkTreeIter *iter, GtkTreePath *path, gpointer user_data) {
983 gchar *the_path;
984 gtk_tree_model_get(GTK_TREE_MODEL(glurp->gui_addtree), iter, ADD_NAME, &the_path,-1);
985 debug("expanded path: %s", the_path);
986 gui_add_fill_dir(iter, FALSE);
987
988 return FALSE;
989 }
990
on_ui_add_row_activated(GtkTreeView * tv,GtkTreePath * path,GtkTreeViewColumn * col,gpointer user_data)991 void on_ui_add_row_activated(GtkTreeView *tv, GtkTreePath *path, GtkTreeViewColumn *col, gpointer user_data) {
992 GtkTreeModel *tm = gtk_tree_view_get_model( tv );
993 GtkTreeIter iter;
994
995 if (!tm) {
996 debug("Couldn't get the tree model for add tree");
997 return;
998 }
999
1000 if (!gtk_tree_model_get_iter(tm, &iter, path)) {
1001 debug("couldn't get a valid iter for the activated row (!)");
1002 return;
1003 }
1004
1005 if( gtk_tree_model_iter_n_children(tm, &iter) > 0 ) {
1006 /* this is a directory, so we expand it. */
1007 debug("A directory is activated in the add window");
1008 if ( gtk_tree_view_row_expanded(tv, path) ) {
1009 gtk_tree_view_collapse_row(tv, path);
1010 } else {
1011 gtk_tree_view_expand_row(tv, path, FALSE);
1012 }
1013 } else {
1014 /* this is a song, add it to the playlist
1015 * fixme: should we add the activated song, or all selected songs? */
1016 debug("A song is activated in the add window");
1017 gui_load_song(tm, iter);
1018 }
1019 }
1020
1021
on_ui_add_find_clicked(GtkWidget * widget,gpointer data)1022 gboolean on_ui_add_find_clicked( GtkWidget *widget, gpointer data) {
1023
1024 if( !mpd_check_connected(glurp->mpd)) {
1025 debug("Not connected, ignoring.");
1026 statusbar_print("Not connected, cannot add");
1027 return FALSE;
1028 }
1029 debug("Search started");
1030
1031 populate_gui_add_search_tree();
1032 gtk_widget_grab_focus(GTK_WIDGET(gtk_builder_get_object(builder, "treeview_add")));
1033 return TRUE;
1034
1035 }
1036
on_entry_add_find_what_activate(GtkWidget * widget,gpointer data)1037 void on_entry_add_find_what_activate( GtkWidget *widget, gpointer data) {
1038 debug("relaying activation of the entry to the find button");
1039 g_signal_emit_by_name( (gpointer) gtk_builder_get_object(builder, "button_add_find"), "clicked");
1040 }
1041
on_ui_stream_add_clicked(GtkWidget * widget,gpointer user_data)1042 gboolean on_ui_stream_add_clicked(GtkWidget *widget, gpointer user_data) {
1043 gchar *url = get_selected_stream();
1044
1045 if( !url || !g_utf8_strlen(url, -1) ) {
1046 debug("No stream URL to add, ignoring");
1047
1048 statusbar_print("No URL to add");
1049
1050 return FALSE;
1051 }
1052
1053 debug("Adding URL: '%s'", url);
1054 mpd_playlist_add(glurp->mpd, url);
1055 statusbar_print("URL '%s' added", url);
1056 push_stream(url);
1057 populate_stream_liststore();
1058
1059 return FALSE;
1060 }
1061
on_ui_playlist_drag_begin(GtkWidget * widget,GdkDragContext * cont,gpointer user_data)1062 gboolean on_ui_playlist_drag_begin(GtkWidget *widget, GdkDragContext *cont, gpointer user_data) {
1063 debug("DRAG BEGIN");
1064 return FALSE;
1065 }
1066
on_ui_playlist_drag_drop(GtkTreeView * tree,GdkDragContext * con,gint x,gint y,guint time,gpointer data)1067 gboolean on_ui_playlist_drag_drop(GtkTreeView *tree, GdkDragContext *con, gint x, gint y, guint time, gpointer data) {
1068 GtkTreePath *path = NULL;
1069 GtkTreeViewDropPosition pos;
1070 GtkTreeModel *tm = GTK_TREE_MODEL(glurp->gui_playlist);
1071 GtkTreeIter iter;
1072 gint did, dpos, spos;
1073 gint num_selected;
1074 gint* path_indices;
1075 GtkTreeSelection *sel;
1076 GList *selected_rows, *sel_rows_iterator;
1077
1078 debug("DRAG DROP");
1079
1080 if( !gtk_tree_view_get_dest_row_at_pos(tree, x, y, &path, &pos) ) {
1081 debug("Can't determine destination");
1082 return TRUE;
1083 }
1084
1085 if( !gtk_tree_model_get_iter(tm, &iter, path) ) {
1086 debug("Can't get iter");
1087 return TRUE;
1088 }
1089
1090 gtk_tree_model_get(tm, &iter, PL_ID, &did, -1);
1091 path_indices = gtk_tree_path_get_indices(path);
1092 dpos = path_indices[gtk_tree_path_get_depth(path) - 1];
1093
1094 if( pos == GTK_TREE_VIEW_DROP_AFTER ) debug("AFTER id:%d", did);
1095 if( pos == GTK_TREE_VIEW_DROP_BEFORE ) debug("BEFORE id:%d", did);
1096 if( pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE ) debug("INTO OR BEFORE id:%d", did);
1097 if( pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ) debug("INTO OR AFTER id:%d", did);
1098
1099 if( pos == GTK_TREE_VIEW_DROP_AFTER ) debug("AFTER pos:%d", dpos);
1100 if( pos == GTK_TREE_VIEW_DROP_BEFORE ) debug("BEFORE pos:%d", dpos);
1101 if( pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE ) debug("INTO OR BEFORE pos:%d", dpos);
1102 if( pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ) debug("INTO OR AFTER pos:%d", dpos);
1103 if( ( pos == GTK_TREE_VIEW_DROP_BEFORE ) || ( pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE ) ) dpos -= 1;
1104 // if (dpos < 0) dpos = 0;
1105
1106 sel = gtk_tree_view_get_selection(tree);
1107 sel_rows_iterator = selected_rows = gtk_tree_selection_get_selected_rows(sel, &tm);
1108 num_selected = gtk_tree_selection_count_selected_rows(sel);
1109 do {
1110 path = (GtkTreePath*)sel_rows_iterator->data;
1111 path_indices = gtk_tree_path_get_indices(path);
1112 spos = path_indices[gtk_tree_path_get_depth(path) - 1];
1113 if( spos >= dpos ) {
1114 dpos++;
1115 debug("dropping backwards");
1116 }
1117 debug("movig from pos %d to pos %d", spos, dpos);
1118 mpd_playlist_move_pos(glurp->mpd, spos, dpos);
1119 } while ( ( sel_rows_iterator = g_list_next(sel_rows_iterator) ) );
1120
1121 g_list_foreach( selected_rows, (GFunc)gtk_tree_path_free, NULL);
1122 g_list_free( selected_rows );
1123
1124 gtk_tree_selection_unselect_all(sel);
1125
1126 return FALSE;
1127 }
1128
on_ui_playlist_button_press(GtkWidget * widget,GdkEventButton * event,gpointer data)1129 gboolean on_ui_playlist_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data) {
1130 GtkTreePath *path = NULL;
1131 GtkTreeSelection *sel = NULL;
1132 GtkTreeView *tv = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview_playlist"));
1133
1134 if( event->button != 3 ) return FALSE;
1135
1136 if( gtk_tree_view_get_path_at_pos(tv, (gint)event->x, (gint)event->y, &path, NULL, NULL, NULL) ) {
1137 debug("[%d,%d]", (gint)event->x, (gint)event->y);
1138 sel = gtk_tree_view_get_selection(tv);
1139 if( !gtk_tree_selection_path_is_selected(sel, path) ) {
1140 debug("User clicked on unselected row, selecting ");
1141 gtk_tree_selection_unselect_all(sel);
1142 gtk_tree_selection_select_path(sel, path);
1143 }
1144 }
1145
1146 debug("Displaying playlist popup menu");
1147 gtk_menu_popup(GTK_MENU(gtk_builder_get_object(builder, "glurp_menu_playlist")), NULL, NULL, NULL, NULL, event->button, event->time);
1148
1149 return TRUE;
1150 }
1151
on_pmenu_playlist_play(GtkWidget * widget,gpointer data)1152 gboolean on_pmenu_playlist_play(GtkWidget *widget, gpointer data) {
1153 debug("POPUP: Playlist -> Play");
1154 on_ui_player_play(GTK_WIDGET(gtk_builder_get_object(builder, "button_play")), NULL);
1155 return FALSE;
1156 }
1157
on_pmenu_playlist_remove_selected(GtkWidget * widget,gpointer data)1158 gboolean on_pmenu_playlist_remove_selected(GtkWidget *widget, gpointer data) {
1159 debug("POPUP: Playlist -> Remove selected");
1160 on_menu_pl_remove_selected_activate(GTK_WIDGET(gtk_builder_get_object(builder, "button_play")), NULL);
1161 return FALSE;
1162 }
1163
on_pmenu_playlist_remove_crop(GtkWidget * widget,gpointer data)1164 gboolean on_pmenu_playlist_remove_crop(GtkWidget *widget, gpointer data) {
1165 debug("POPUP: Playlist -> Remove crop");
1166 on_menu_pl_remove_crop_activate(GTK_WIDGET(gtk_builder_get_object(builder, "button_play")), NULL);
1167 return FALSE;
1168 }
1169
on_pmenu_playlist_remove_all(GtkWidget * widget,gpointer data)1170 gboolean on_pmenu_playlist_remove_all(GtkWidget *widget, gpointer data) {
1171 debug("POPUP: Playlist -> Remove all");
1172 on_menu_pl_remove_all_activate(GTK_WIDGET(gtk_builder_get_object(builder, "button_play")), NULL);
1173 return FALSE;
1174 }
1175
on_ui_add_button_press(GtkWidget * widget,GdkEventButton * event,gpointer data)1176 gboolean on_ui_add_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data) {
1177 GtkTreePath *path = NULL;
1178 GtkTreeSelection *sel = NULL;
1179 GtkTreeView *tv = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview_add"));
1180
1181 if( event->button != 3 ) return FALSE;
1182
1183 if( gtk_tree_view_get_path_at_pos(tv, (gint)event->x, (gint)event->y, &path, NULL, NULL, NULL) ) {
1184 debug("[%d,%d]", (gint)event->x, (gint)event->y);
1185 sel = gtk_tree_view_get_selection(tv);
1186 if( !gtk_tree_selection_path_is_selected(sel, path) ) {
1187 debug("User clicked on unselected row, selecting ");
1188 gtk_tree_selection_unselect_all(sel);
1189 gtk_tree_selection_select_path(sel, path);
1190 }
1191 }
1192
1193 debug("Displaying add popup menu");
1194 gtk_menu_popup(GTK_MENU(gtk_builder_get_object(builder, "glurp_menu_db")), NULL, NULL, NULL, NULL, event->button, event->time);
1195 return TRUE;
1196 }
1197
on_pmenu_db_update_selected(GtkWidget * widget,gpointer data)1198 gboolean on_pmenu_db_update_selected(GtkWidget *widget, gpointer data) {
1199 GtkTreeView *tv;
1200 GtkTreeModel *tm;
1201 GtkTreeSelection *ts;
1202 GList *selected_rows;
1203 GtkTreeIter iter;
1204 gint i, num = 0;
1205 gchar *path = NULL;
1206
1207 debug("POPUP: DB -> Update selected");
1208
1209 if(!mpd_check_connected(glurp->mpd)) return FALSE;
1210 tv = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview_add"));
1211 tm = gtk_tree_view_get_model(tv);
1212 if( !((ts = gtk_tree_view_get_selection(tv)) && (num = gtk_tree_selection_count_selected_rows(ts))) ) {
1213 debug("No selection, ignoring");
1214 return FALSE;
1215 }
1216
1217 selected_rows = gtk_tree_selection_get_selected_rows(ts, NULL);
1218
1219 debug("Removing 'Add' treeview model");
1220 gtk_tree_view_set_model(tv, NULL);
1221
1222 gui_updating_disable_add_controls();
1223 glurp->updating_db = TRUE;
1224
1225 for( i = 0; i < num; i++ ) {
1226 gtk_tree_model_get_iter(tm, &iter, (GtkTreePath *)g_list_nth_data(selected_rows, i));
1227 gtk_tree_model_get(tm, &iter, 1, &path, -1);
1228 mpd_database_update_dir(glurp->mpd, path);
1229 debug("**** Updating '%s'", path);
1230 g_free(path);
1231 if (mpd_check_error(glurp->mpd)) break;
1232 }
1233
1234 return FALSE;
1235 }
1236
on_pmenu_db_add_selected(GtkWidget * widget,gpointer data)1237 gboolean on_pmenu_db_add_selected(GtkWidget *widget, gpointer data) {
1238 debug("POPUP: DB -> Add selected");
1239 on_ui_add_add_clicked(GTK_WIDGET(gtk_builder_get_object(builder, "button_add_add")), NULL);
1240 return FALSE;
1241 }
1242
on_pmenu_db_info(GtkWidget * widget,gpointer data)1243 gboolean on_pmenu_db_info(GtkWidget *widget, gpointer data) {
1244 debug("POPUP: DB -> Database information (STUB)");
1245 return FALSE;
1246 }
1247
on_pmenu_playlist_shuffle_activate(GtkWidget * widget,gpointer data)1248 gboolean on_pmenu_playlist_shuffle_activate(GtkWidget *widget, gpointer data) {
1249 if( !mpd_check_connected(glurp->mpd) ) {
1250 debug("Not connected");
1251 return FALSE;
1252 }
1253
1254 mpd_playlist_shuffle(glurp->mpd);
1255
1256 statusbar_print("Playlist shuffled.");
1257
1258 return FALSE;
1259 }
1260
on_togglebutton_pl_remove_toggled(GtkWidget * widget,gpointer data)1261 gboolean on_togglebutton_pl_remove_toggled(GtkWidget *widget, gpointer data) {
1262 if( !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ) return FALSE;
1263
1264 debug("Remove button clicked");
1265 gtk_menu_popup(GTK_MENU(gtk_builder_get_object(builder, "glurp_menu_pl_remove")), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time());
1266 return FALSE;
1267 }
1268
on_menu_pl_remove_deactivate(GtkWidget * widget,gpointer data)1269 gboolean on_menu_pl_remove_deactivate(GtkWidget *widget, gpointer data) {
1270 debug("Remove menu hidden, deactivating togglebutton");
1271 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "togglebutton_pl_remove")), FALSE);
1272 return FALSE;
1273 }
1274
on_outputs_toggled(GtkWidget * widget,gpointer data)1275 gboolean on_outputs_toggled(GtkWidget *widget, gpointer data) {
1276 GtkMenu *menu = populate_outputs_menu();
1277
1278 if( !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ) return FALSE;
1279
1280 debug("Outputs button clicked");
1281
1282 if( !menu ) return FALSE;
1283
1284 gtk_menu_popup(populate_outputs_menu(), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time());
1285 return FALSE;
1286 }
1287
on_menu_outputs_deactivate(GtkWidget * widget,gpointer data)1288 gboolean on_menu_outputs_deactivate(GtkWidget *widget, gpointer data) {
1289 debug("Outputs menu hidden, deactivating togglebutton");
1290 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "togglebutton_outputs")), FALSE);
1291 return FALSE;
1292 }
1293
on_menu_output_activate(GtkWidget * widget,gpointer data)1294 gboolean on_menu_output_activate(GtkWidget *widget, gpointer data) {
1295 gboolean enable = FALSE;
1296 gint i, d = (gint)data;
1297
1298 if( d < 0 ) enable = TRUE;
1299 i = abs(d) - 1;
1300
1301 debug("%s output %d", (enable ? "Enable" : "Disable"), i);
1302
1303 statusbar_print("%s output %d", (enable ? "Enabling" : "Disabling"), i);
1304 mpd_server_set_output_device(glurp->mpd, i, enable);
1305
1306 return FALSE;
1307 }
1308
on_ui_streams_row_activated(GtkTreeView * treeview,GtkTreePath * tp,GtkTreeViewColumn * col,gpointer user_data)1309 gboolean on_ui_streams_row_activated(GtkTreeView *treeview, GtkTreePath *tp, GtkTreeViewColumn *col, gpointer user_data) {
1310 GtkTreeIter act;
1311 GtkTreeModel *model;
1312 gchar* url;
1313 GtkWidget* entry;
1314
1315 model = gtk_tree_view_get_model(treeview);
1316 gtk_tree_model_get_iter(model, &act, tp);
1317 gtk_tree_model_get(model, &act, 0, &url, -1);
1318 entry = GTK_WIDGET(gtk_builder_get_object(builder, "streams_entry"));
1319 gtk_entry_set_text(GTK_ENTRY(entry), url);
1320 g_free(url);
1321 return FALSE;
1322 }
1323
on_ui_streams_button_press(GtkWidget * widget,GdkEventButton * event,gpointer data)1324 gboolean on_ui_streams_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data) {
1325 GtkTreePath *path = NULL;
1326 GtkTreeSelection *sel = NULL;
1327 GtkTreeView *tv = GTK_TREE_VIEW(gtk_builder_get_object(builder, "streams_treeview"));
1328
1329 if( event->button != 3 ) return FALSE;
1330
1331 if( gtk_tree_view_get_path_at_pos(tv, (gint)event->x, (gint)event->y, &path, NULL, NULL, NULL) ) {
1332 debug("[%d,%d]", (gint)event->x, (gint)event->y);
1333 sel = gtk_tree_view_get_selection(tv);
1334 if( !gtk_tree_selection_path_is_selected(sel, path) ) {
1335 debug("User clicked on unselected row, selecting ");
1336 gtk_tree_selection_unselect_all(sel);
1337 gtk_tree_selection_select_path(sel, path);
1338 }
1339 }
1340
1341 debug("Displaying stream popup menu");
1342 gtk_menu_popup(GTK_MENU(gtk_builder_get_object(builder, "glurp_menu_streams")), NULL, NULL, NULL, NULL, event->button, event->time);
1343
1344 return TRUE;
1345 }
1346
1347
on_menu_streams_remove_selected_activate(GtkWidget * widget,gpointer user_data)1348 gboolean on_menu_streams_remove_selected_activate(GtkWidget *widget, gpointer user_data) {
1349 GtkWidget *tv;
1350 GtkTreeModel *tm;
1351 GtkTreeSelection *ts;
1352 gint num_sel, i;
1353 gchar* url;
1354 GtkTreeIter iter;
1355 GList *selected_rows;
1356
1357 if(!mpd_check_connected(glurp->mpd)) return FALSE;
1358
1359 tv = GTK_WIDGET(gtk_builder_get_object(builder, "streams_treeview"));
1360 tm = gtk_tree_view_get_model(GTK_TREE_VIEW(tv));
1361 ts = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv));
1362
1363 num_sel = gtk_tree_selection_count_selected_rows(ts);
1364 selected_rows = gtk_tree_selection_get_selected_rows(ts, NULL);
1365
1366 debug("Selected %d rows", num_sel);
1367
1368 if( num_sel ) {
1369 for( i=0; i<num_sel; i++ ) {
1370 gtk_tree_model_get_iter(tm, &iter, (GtkTreePath *)g_list_nth_data(selected_rows, i));
1371 gtk_tree_model_get(tm, &iter, 0, &url, -1);
1372 pull_stream(url);
1373 }
1374 }
1375 populate_stream_liststore();
1376 return FALSE;
1377 }
1378
1379 // vim: et sw=2 smarttab
1380