1 /*                                                     -*- linux-c -*-
2     Copyright (C) 2004 Tom Szilagyi
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18     $Id: gui_main.c 1310 2015-07-26 19:11:40Z tszilagyi $
19 */
20 
21 #include <config.h>
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <sys/stat.h>
28 #include <errno.h>
29 #include <time.h>
30 #include <glib.h>
31 #include <glib-object.h>
32 #include <gdk/gdk.h>
33 #include <gdk/gdkkeysyms.h>
34 #include <gdk-pixbuf/gdk-pixbuf.h>
35 #include <gtk/gtk.h>
36 
37 #ifdef HAVE_JACK
38 #include <jack/jack.h>
39 #endif /* HAVE_JACK */
40 
41 #ifdef HAVE_SRC
42 #include <samplerate.h>
43 #endif /* HAVE_SRC */
44 
45 #ifdef HAVE_LADSPA
46 #include <lrdf.h>
47 #include "plugin.h"
48 #endif /* HAVE_LADSPA */
49 
50 #ifdef HAVE_CDDA
51 #include "cdda.h"
52 #include "store_cdda.h"
53 #endif /* HAVE_CDDA */
54 
55 #ifdef HAVE_JACK_MGMT
56 #include "ports.h"
57 #endif /* HAVE_JACK_MGMT */
58 
59 #ifdef HAVE_LOOP
60 #include "loop_bar.h"
61 #endif /* HAVE_LOOP */
62 
63 #ifdef HAVE_PODCAST
64 #include "store_podcast.h"
65 #endif /* HAVE_PODCAST */
66 
67 #include "athread.h"
68 #include "ext_lua.h"
69 #include "common.h"
70 #include "utils.h"
71 #include "utils_gui.h"
72 #include "core.h"
73 #include "rb.h"
74 #include "cover.h"
75 #include "transceiver.h"
76 #include "decoder/file_decoder.h"
77 #include "about.h"
78 #include "options.h"
79 #include "skin.h"
80 #include "playlist.h"
81 #include "file_info.h"
82 #include "i18n.h"
83 #include "httpc.h"
84 #include "metadata.h"
85 #include "metadata_api.h"
86 #include "music_browser.h"
87 #include "version.h"
88 #include "gui_main.h"
89 
90 
91 /* receive at most this much remote messages in one run of timeout_callback() */
92 #define MAX_RCV_COUNT 32
93 
94 /* period of main timeout callback [ms] */
95 #define TIMEOUT_PERIOD 100
96 
97 extern options_t options;
98 
99 char pl_color_active[14];
100 char pl_color_inactive[14];
101 
102 PangoFontDescription *fd_playlist;
103 PangoFontDescription *fd_browser;
104 PangoFontDescription *fd_bigtimer;
105 PangoFontDescription *fd_smalltimer;
106 PangoFontDescription *fd_songtitle;
107 PangoFontDescription *fd_songinfo;
108 PangoFontDescription *fd_statusbar;
109 
110 /* Communication between gui thread and disk thread */
111 extern AQUALUNG_MUTEX_DECLARE(disk_thread_lock)
112 extern AQUALUNG_COND_DECLARE(disk_thread_wake)
113 extern rb_t * rb_gui2disk;
114 extern rb_t * rb_disk2gui;
115 
116 #ifdef HAVE_JACK
117 extern jack_client_t * jack_client;
118 extern char * client_name;
119 extern int jack_is_shutdown;
120 extern char * jack_shutdown_reason;
121 #endif /* HAVE_JACK */
122 
123 extern int aqualung_socket_fd;
124 extern int aqualung_session_id;
125 
126 extern GtkListStore * running_store;
127 
128 extern GtkWidget * plist_menu;
129 extern GtkWidget * playlist_notebook;
130 
131 void init_plist_menu(GtkWidget *append_menu);
132 
133 /* file decoder instance used by the disk thread - use with caution! */
134 extern file_decoder_t * fdec;
135 
136 /* the physical name of the file that is playing, or a '\0'. */
137 char current_file[MAXLEN];
138 
139 /* embedded picture in the file that is playing */
140 void * embedded_picture = NULL;
141 int embedded_picture_size = 0;
142 
143 /* default window title */
144 char win_title[MAXLEN];
145 
146 /* current application title when a file is playing */
147 char playing_app_title[MAXLEN];
148 
149 char send_cmd, recv_cmd;
150 fileinfo_t fileinfo;
151 status_t status;
152 unsigned long out_SR;
153 extern int output;
154 unsigned long rb_size;
155 unsigned long long total_samples;
156 unsigned long long sample_pos;
157 
158 /* this flag set to 1 in core.c if --play
159    for current instance is specified. */
160 int immediate_start = 0;
161 
162 /* Whether to stop playing after currently played song ends. */
163 int stop_after_current_song = 0;
164 
165 /* Whether the systray is used in this instance */
166 int systray_used = 0;
167 
168 /* the tab to load remote files */
169 char * tab_name;
170 
171 /* volume & balance sliders */
172 double vol_prev = 0.0f;
173 double vol_lin = 1.0f;
174 double bal_prev = 0.0f;
175 extern double left_gain;
176 extern double right_gain;
177 
178 /* label/display data */
179 fileinfo_t disp_info;
180 unsigned long disp_samples;
181 unsigned long disp_pos;
182 
183 GtkWidget * main_window;
184 
185 extern GtkWidget * browser_window;
186 extern GtkWidget * playlist_window;
187 extern GtkWidget * vol_window;
188 extern GtkWidget * browser_paned;
189 
190 extern int music_store_changed;
191 
192 #ifdef HAVE_LADSPA
193 extern int fxbuilder_on;
194 extern GtkWidget * fxbuilder_window;
195 GtkWidget * plugin_toggle;
196 #endif /* HAVE_LADSPA */
197 
198 GtkObject * adj_pos;
199 GtkObject * adj_vol;
200 GtkObject * adj_bal;
201 GtkWidget * scale_pos;
202 GtkWidget * scale_vol;
203 GtkWidget * scale_bal;
204 
205 GtkWidget * vbox_sep;
206 
207 #ifdef HAVE_LOOP
208 GtkWidget * loop_bar;
209 #endif /* HAVE_LOOP */
210 
211 GtkWidget * time_labels[3];
212 int refresh_time_label = 1;
213 
214 
215 gulong play_id;
216 gulong pause_id;
217 
218 GtkWidget * play_button;
219 GtkWidget * pause_button;
220 GtkWidget * prev_button;
221 GtkWidget * stop_button;
222 GtkWidget * next_button;
223 GtkWidget * repeat_button;
224 GtkWidget * repeat_all_button;
225 GtkWidget * shuffle_button;
226 
227 GtkWidget * label_title;
228 GtkWidget * label_format;
229 GtkWidget * label_samplerate;
230 GtkWidget * label_bps;
231 GtkWidget * label_mono;
232 GtkWidget * label_output;
233 GtkWidget * label_src_type;
234 
235 int x_scroll_start;
236 int x_scroll_pos;
237 int scroll_btn;
238 
239 GtkWidget * musicstore_toggle;
240 GtkWidget * playlist_toggle;
241 
242 guint timeout_tag;
243 guint vol_bal_timeout_tag = 0;
244 
245 gint timeout_callback(gpointer data);
246 
247 /* whether we are refreshing the scale on STATUS commands recv'd from disk thread */
248 int refresh_scale = 1;
249 /* suppress scale refreshing after seeking (discard this much STATUS packets).
250    Prevents position slider to momentarily jump back to original position. */
251 int refresh_scale_suppress = 0;
252 
253 /* whether we allow seeks (depending on if we are at the end of the track) */
254 int allow_seeks = 1;
255 
256 /* controls when to load the new file's data on display */
257 int fresh_new_file = 1;
258 int fresh_new_file_prev = 1;
259 
260 /* whether we have a file loaded, that is currently playing (or paused) */
261 int is_file_loaded = 0;
262 
263 /* whether playback is paused */
264 int is_paused = 0;
265 
266 /* Whether the next key binding should be for a custom key binding */
267 int custom_main_keybinding_expected = 0;
268 
269 /* popup menu for configuration */
270 GtkWidget * conf_menu;
271 GtkWidget * conf__options;
272 GtkWidget * conf__skin;
273 GtkWidget * conf__fileinfo;
274 GtkWidget * conf__about;
275 GtkWidget * conf__quit;
276 #ifdef HAVE_JACK_MGMT
277 extern GtkWidget * ports_window;
278 GtkWidget * conf__jack;
279 #endif /* HAVE_JACK_MGMT */
280 
281 GtkWidget * bigtimer_label;
282 GtkWidget * smalltimer_label_1;
283 GtkWidget * smalltimer_label_2;
284 
285 /* systray stuff */
286 #ifdef HAVE_SYSTRAY
287 
288 GtkStatusIcon * systray_icon;
289 
290 GtkWidget * systray_menu;
291 GtkWidget * systray__show;
292 GtkWidget * systray__hide;
293 GtkWidget * systray__play;
294 GtkWidget * systray__pause;
295 GtkWidget * systray__stop;
296 GtkWidget * systray__prev;
297 GtkWidget * systray__next;
298 GtkWidget * systray__quit;
299 
300 int wm_not_systray_capable = 0;
301 
302 void hide_all_windows(gpointer data);
303 
304 /* Used for not reacting too quickly to consecutive mouse wheel events */
305 guint32 last_systray_scroll_event_time = 0;
306 
307 #endif /* HAVE_SYSTRAY */
308 
309 int systray_main_window_on = 1;
310 
311 void create_main_window(char * skin_path);
312 
313 void toggle_noeffect(int id, int state);
314 
315 gint prev_event(GtkWidget * widget, GdkEvent * event, gpointer data);
316 gint play_event(GtkWidget * widget, GdkEvent * event, gpointer data);
317 gint pause_event(GtkWidget * widget, GdkEvent * event, gpointer data);
318 gint stop_event(GtkWidget * widget, GdkEvent * event, gpointer data);
319 gint next_event(GtkWidget * widget, GdkEvent * event, gpointer data);
320 
321 void load_config(void);
322 
323 void playlist_toggled(GtkWidget * widget, gpointer data);
324 
325 GtkWidget * cover_align;
326 GtkWidget * c_event_box;
327 GtkWidget * cover_image_area;
328 gint cover_show_flag;
329 
330 extern char fileinfo_name[MAXLEN];
331 extern char fileinfo_file[MAXLEN];
332 
333 extern GtkWidget * plist__fileinfo;
334 
335 extern gint playlist_state;
336 extern gint browser_state;
337 
338 
339 void
try_waking_disk_thread(void)340 try_waking_disk_thread(void) {
341 
342 	if (AQUALUNG_MUTEX_TRYLOCK(disk_thread_lock)) {
343 		AQUALUNG_COND_SIGNAL(disk_thread_wake)
344 		AQUALUNG_MUTEX_UNLOCK(disk_thread_lock)
345 	}
346 }
347 
348 
349 void
set_title_label(char * str)350 set_title_label(char * str) {
351 
352 	gchar default_title[MAXLEN];
353         char tmp[MAXLEN];
354 
355 	tmp[0] = '\0';
356 
357 	if (is_file_loaded) {
358 		/* Remember current title. */
359 		strncpy(playing_app_title, str, MAXLEN-1);
360 
361 		gtk_label_set_text(GTK_LABEL(label_title), str);
362 		if (options.show_sn_title) {
363 			if (stop_after_current_song) {
364 				strncat(tmp, "[", MAXLEN-1);
365 				strncat(tmp, _("STOPPING"), MAXLEN-1);
366 				strncat(tmp, "] ", MAXLEN-1);
367 			}
368 			strncat(tmp, str, MAXLEN-1);
369 			strncat(tmp, " - ", MAXLEN-1);
370 			strncat(tmp, win_title, MAXLEN-1);
371 			gtk_window_set_title(GTK_WINDOW(main_window), tmp);
372 #ifdef HAVE_SYSTRAY
373 			if (systray_used) {
374 				aqualung_status_icon_set_tooltip_text(systray_icon, tmp);
375 			}
376 #endif /* HAVE_SYSTRAY */
377 		} else {
378 			gtk_window_set_title(GTK_WINDOW(main_window), win_title);
379 #ifdef HAVE_SYSTRAY
380 			if (systray_used) {
381 				aqualung_status_icon_set_tooltip_text(systray_icon, win_title);
382 			}
383 #endif /* HAVE_SYSTRAY */
384 		}
385 	} else {
386 		sprintf(default_title, "Aqualung %s", AQUALUNG_VERSION);
387 		gtk_label_set_text(GTK_LABEL(label_title), default_title);
388 		gtk_window_set_title(GTK_WINDOW(main_window), win_title);
389 #ifdef HAVE_SYSTRAY
390 		if (systray_used) {
391 			aqualung_status_icon_set_tooltip_text(systray_icon, win_title);
392 		}
393 #endif /* HAVE_SYSTRAY */
394         }
395 }
396 
397 void
hide_cover_thumbnail(void)398 hide_cover_thumbnail(void) {
399         cover_show_flag = 0;
400         gtk_widget_hide(cover_image_area);
401         gtk_widget_hide(c_event_box);
402         gtk_widget_hide(cover_align);
403 }
404 
405 void
set_format_label(char * format_str)406 set_format_label(char * format_str) {
407 
408 	if (!is_file_loaded) {
409 		gtk_label_set_text(GTK_LABEL(label_format), "");
410 	} else {
411 		gtk_label_set_text(GTK_LABEL(label_format), format_str);
412 	}
413 }
414 
415 
416 void
format_bps_label(int bps,int format_flags,char * str)417 format_bps_label(int bps, int format_flags, char * str) {
418 
419 	if (bps == 0) {
420 		strcpy(str, "N/A kbit/s");
421 		return;
422 	}
423 
424 	if (format_flags & FORMAT_VBR) {
425 		sprintf(str, "%.1f kbit/s VBR", bps/1000.0);
426 	} else {
427 		if (format_flags & FORMAT_UBR) {
428 			sprintf(str, "%.1f kbit/s UBR", bps/1000.0);
429 		} else {
430 			sprintf(str, "%.1f kbit/s", bps/1000.0);
431 		}
432 	}
433 }
434 
435 void
set_bps_label(int bps,int format_flags)436 set_bps_label(int bps, int format_flags) {
437 
438 	char str[MAXLEN];
439 
440 	format_bps_label(bps, format_flags, str);
441 
442 	if (is_file_loaded) {
443 		gtk_label_set_text(GTK_LABEL(label_bps), str);
444 	} else {
445 		gtk_label_set_text(GTK_LABEL(label_bps), "");
446 	}
447 }
448 
449 
450 void
set_samplerate_label(int sr)451 set_samplerate_label(int sr) {
452 
453 	char str[MAXLEN];
454 
455 	snprintf(str, MAXLEN-1, "%d Hz", sr);
456 
457 	if (is_file_loaded) {
458 		gtk_label_set_text(GTK_LABEL(label_samplerate), str);
459 	} else {
460 		gtk_label_set_text(GTK_LABEL(label_samplerate), "");
461 	}
462 }
463 
464 
465 void
set_mono_label(int is_mono)466 set_mono_label(int is_mono) {
467 
468 	if (is_file_loaded) {
469 		if (is_mono) {
470 			gtk_label_set_text(GTK_LABEL(label_mono), _("MONO"));
471 		} else {
472 			gtk_label_set_text(GTK_LABEL(label_mono), _("STEREO"));
473 		}
474 	} else {
475 		gtk_label_set_text(GTK_LABEL(label_mono), "");
476 	}
477 }
478 
479 
480 
481 void
set_output_label(int output,int out_SR)482 set_output_label(int output, int out_SR) {
483 
484 	char str[MAXLEN];
485 
486 	switch (output) {
487 #ifdef HAVE_PULSE
488 	case PULSE_DRIVER:
489 		snprintf(str, MAXLEN-1, "%s PulseAudio @ %d Hz", _("Output:"), out_SR);
490 		break;
491 #endif /* HAVE_PULSE */
492 #ifdef HAVE_SNDIO
493 	case SNDIO_DRIVER:
494 		snprintf(str, MAXLEN-1, "%s sndio @ %d Hz", _("Output:"), out_SR);
495 		break;
496 #endif /* HAVE_SNDIO */
497 #ifdef HAVE_OSS
498 	case OSS_DRIVER:
499 		snprintf(str, MAXLEN-1, "%s OSS @ %d Hz", _("Output:"), out_SR);
500 		break;
501 #endif /* HAVE_OSS */
502 #ifdef HAVE_ALSA
503 	case ALSA_DRIVER:
504 		snprintf(str, MAXLEN-1, "%s ALSA @ %d Hz", _("Output:"), out_SR);
505 		break;
506 #endif /* HAVE_ALSA */
507 #ifdef HAVE_JACK
508 	case JACK_DRIVER:
509 		snprintf(str, MAXLEN-1, "%s JACK @ %d Hz", _("Output:"), out_SR);
510 		break;
511 #endif /* HAVE_JACK */
512 #ifdef HAVE_WINMM
513 	case WIN32_DRIVER:
514 		snprintf(str, MAXLEN-1, "%s Win32 @ %d Hz", _("Output:"), out_SR);
515 		break;
516 #endif /* HAVE_WINMM */
517 	default:
518 		strncpy(str, _("No output"), MAXLEN-1);
519 		break;
520 	}
521 
522 	gtk_label_set_text(GTK_LABEL(label_output), str);
523 }
524 
525 
526 
527 void
set_src_type_label(int src_type)528 set_src_type_label(int src_type) {
529 
530 	char str[MAXLEN];
531 
532 	strcpy(str, _("SRC Type: "));
533 #ifdef HAVE_SRC
534 	strcat(str, src_get_name(src_type));
535 #else
536 	strcat(str, _("None"));
537 #endif /* HAVE_SRC */
538 
539 	gtk_label_set_text(GTK_LABEL(label_src_type), str);
540 }
541 
542 
543 void
refresh_time_displays(void)544 refresh_time_displays(void) {
545 
546 	char str[MAXLEN];
547 
548 	if (is_file_loaded) {
549 		if (refresh_time_label || options.time_idx[0] != 0) {
550 			sample2time(disp_info.sample_rate, disp_pos, str, 0);
551 			gtk_label_set_text(GTK_LABEL(time_labels[0]), str);
552 
553 		}
554 
555 		if (refresh_time_label || options.time_idx[0] != 1) {
556 			if (disp_samples == 0) {
557 				strcpy(str, " N/A ");
558 			} else {
559 				sample2time(disp_info.sample_rate, disp_samples - disp_pos, str, 1);
560 			}
561 			gtk_label_set_text(GTK_LABEL(time_labels[1]), str);
562 
563 		}
564 
565 		if (refresh_time_label || options.time_idx[0] != 2) {
566 			if (disp_samples == 0) {
567 				strcpy(str, " N/A ");
568 			} else {
569 				sample2time(disp_info.sample_rate, disp_samples, str, 0);
570 			}
571 			gtk_label_set_text(GTK_LABEL(time_labels[2]), str);
572 
573 		}
574 	} else {
575 		int i;
576 		for (i = 0; i < 3; i++) {
577 			gtk_label_set_text(GTK_LABEL(time_labels[i]), " 00:00 ");
578 		}
579 	}
580 }
581 
582 #ifdef HAVE_LOOP
583 
584 void
loop_bar_update_tooltip(void)585 loop_bar_update_tooltip(void) {
586 
587         if (options.enable_tooltips) {
588 		char str[MAXLEN];
589 
590 		if (is_file_loaded) {
591 			char start[32];
592 			char end[32];
593 			sample2time(disp_info.sample_rate, total_samples * options.loop_range_start, start, 0);
594 			sample2time(disp_info.sample_rate, total_samples * options.loop_range_end, end, 0);
595 			snprintf(str, MAXLEN-1, _("Loop range: %d-%d%% [%s - %s]"),
596 				 (int)(100 * options.loop_range_start),
597 				 (int)(100 * options.loop_range_end),
598 				 start, end);
599 		} else {
600 			snprintf(str, MAXLEN-1, _("Loop range: %d-%d%%"),
601 				 (int)(100 * options.loop_range_start),
602 				 (int)(100 * options.loop_range_end));
603 		}
604 
605                 aqualung_widget_set_tooltip_text(loop_bar, str);
606         }
607 }
608 
609 void
loop_range_changed_cb(AqualungLoopBar * bar,float start,float end,gpointer data)610 loop_range_changed_cb(AqualungLoopBar * bar, float start, float end, gpointer data) {
611 
612 	options.loop_range_start = start;
613 	options.loop_range_end = end;
614 	loop_bar_update_tooltip();
615 }
616 
617 #endif /* HAVE_LOOP */
618 
619 void
refresh_displays(void)620 refresh_displays(void) {
621 
622 	GtkTreePath * p;
623 	GtkTreeIter iter;
624 	playlist_t * pl;
625 
626 	refresh_time_displays();
627 
628 #ifdef HAVE_LOOP
629 	loop_bar_update_tooltip();
630 #endif /* HAVE_LOOP */
631 
632 	set_format_label(disp_info.format_str);
633 	set_samplerate_label(disp_info.sample_rate);
634 	set_bps_label(disp_info.bps, disp_info.format_flags);
635 	set_mono_label(disp_info.is_mono);
636 	set_output_label(output, out_SR);
637 	set_src_type_label(options.src_type);
638 
639 	if ((pl = playlist_get_playing()) == NULL) {
640 		if ((pl = playlist_get_current()) == NULL) {
641 			set_title_label("");
642                         hide_cover_thumbnail();
643 			return;
644 		}
645 	}
646 
647 	p = playlist_get_playing_path(pl);
648 	if (p != NULL) {
649 		playlist_data_t * pldata;
650 
651 		gtk_tree_model_get_iter(GTK_TREE_MODEL(pl->store), &iter, p);
652 		gtk_tree_model_get(GTK_TREE_MODEL(pl->store), &iter, PL_COL_DATA, &pldata, -1);
653 		gtk_tree_path_free(p);
654 
655 		if (!httpc_is_url(pldata->file) && !options.use_ext_title_format) {
656 			char list_str[MAXLEN];
657 			playlist_data_get_display_name(list_str, pldata);
658 			set_title_label(list_str);
659 		} else if (!is_file_loaded) {
660 			char * name;
661 			gtk_tree_model_get(GTK_TREE_MODEL(pl->store), &iter, PL_COL_NAME, &name, -1);
662 			set_title_label(name);
663 			g_free(name);
664 		}
665 
666 		if (is_file_loaded) {
667                         if (!options.dont_show_cover) {
668 				if (embedded_picture != NULL && (find_cover_filename(pldata->file) == NULL || !options.use_external_cover_first)) {
669 					display_cover_from_binary(cover_image_area, c_event_box, cover_align, 48, 48,
670 						      embedded_picture, embedded_picture_size, TRUE, TRUE);
671 				} else {
672 					if (options.show_cover_for_ms_tracks_only) {
673 						if (IS_PL_COVER(pldata)) {
674 							display_cover(cover_image_area, c_event_box, cover_align,
675 								      48, 48, pldata->file, TRUE, TRUE);
676 						} else {
677 							hide_cover_thumbnail();
678 						}
679 					} else {
680 						display_cover(cover_image_area, c_event_box, cover_align,
681 							      48, 48, pldata->file, TRUE, TRUE);
682 					}
683 				}
684                         }
685 		}
686 	} else if (!is_file_loaded) {
687 		set_title_label("");
688                 hide_cover_thumbnail();
689 	}
690 }
691 
692 
693 void
zero_displays(void)694 zero_displays(void) {
695 
696 	disp_info.total_samples = 0;
697 	disp_info.sample_rate = 0;
698 	disp_info.channels = 2;
699 	disp_info.is_mono = 0;
700 	disp_info.bps = 0;
701 
702 	disp_samples = 0;
703 	disp_pos = 0;
704 
705 	refresh_displays();
706 }
707 
708 
709 void
save_window_position(void)710 save_window_position(void) {
711 
712 	gtk_window_get_position(GTK_WINDOW(main_window), &options.main_pos_x, &options.main_pos_y);
713 
714 	if (!options.playlist_is_embedded && options.playlist_on) {
715 		gtk_window_get_position(GTK_WINDOW(playlist_window), &options.playlist_pos_x, &options.playlist_pos_y);
716 	}
717 
718 	if (options.browser_on) {
719 		gtk_window_get_position(GTK_WINDOW(browser_window), &options.browser_pos_x, &options.browser_pos_y);
720 	}
721 
722 	gtk_window_get_size(GTK_WINDOW(main_window), &options.main_size_x, &options.main_size_y);
723 	gtk_window_get_size(GTK_WINDOW(browser_window), &options.browser_size_x, &options.browser_size_y);
724 
725 	if (!options.playlist_is_embedded) {
726 		gtk_window_get_size(GTK_WINDOW(playlist_window), &options.playlist_size_x, &options.playlist_size_y);
727 	} else {
728 		options.playlist_size_x = playlist_window->allocation.width;
729 		options.playlist_size_y = playlist_window->allocation.height;
730 	}
731 
732 	if (!options.hide_comment_pane) {
733 		options.browser_paned_pos = gtk_paned_get_position(GTK_PANED(browser_paned));
734 	}
735 }
736 
737 
738 void
restore_window_position(void)739 restore_window_position(void) {
740 
741 	gtk_window_move(GTK_WINDOW(main_window), options.main_pos_x, options.main_pos_y);
742 	gtk_window_move(GTK_WINDOW(browser_window), options.browser_pos_x, options.browser_pos_y);
743 	if (!options.playlist_is_embedded) {
744 		gtk_window_move(GTK_WINDOW(playlist_window), options.playlist_pos_x, options.playlist_pos_y);
745 	}
746 
747 	gtk_window_resize(GTK_WINDOW(main_window), options.main_size_x, options.main_size_y);
748 	gtk_window_resize(GTK_WINDOW(browser_window), options.browser_size_x, options.browser_size_y);
749 	if (!options.playlist_is_embedded) {
750 		gtk_window_resize(GTK_WINDOW(playlist_window), options.playlist_size_x, options.playlist_size_y);
751 	}
752 
753 	if (!options.hide_comment_pane) {
754 		gtk_paned_set_position(GTK_PANED(browser_paned), options.browser_paned_pos);
755 	}
756 }
757 
758 
759 gboolean
main_window_close(GtkWidget * widget,GdkEvent * event,gpointer data)760 main_window_close(GtkWidget * widget, GdkEvent * event, gpointer data) {
761 
762 	send_cmd = CMD_FINISH;
763 	rb_write(rb_gui2disk, &send_cmd, 1);
764 	try_waking_disk_thread();
765 
766 #ifdef HAVE_CDDA
767 	cdda_shutdown();
768 #endif /* HAVE_CDDA */
769 
770 	if (systray_main_window_on) {
771 		save_window_position();
772 	}
773 
774 	save_config();
775 
776 #ifdef HAVE_LADSPA
777 	save_plugin_data();
778 	lrdf_cleanup();
779 #endif /* HAVE_LADSPA */
780 
781 #ifdef HAVE_SYSTRAY
782 	if (systray_used) {
783 		gtk_status_icon_set_visible(GTK_STATUS_ICON(systray_icon), FALSE);
784 	}
785 #endif /* HAVE_SYSTRAY */
786 
787 	if (options.auto_save_playlist) {
788 		char playlist_name[MAXLEN];
789 
790 		snprintf(playlist_name, MAXLEN-1, "%s/%s", options.confdir, "playlist.xml");
791 		playlist_save_all(playlist_name);
792 	}
793 
794         pango_font_description_free(fd_playlist);
795         pango_font_description_free(fd_browser);
796 
797 	finalize_options();
798 
799 	gtk_main_quit();
800 
801 	return FALSE;
802 }
803 
804 void
main_window_closing(void)805 main_window_closing(void) {
806 
807 	if (music_store_changed) {
808 		GtkWidget * dialog;
809 		int resp;
810 
811                 dialog = gtk_message_dialog_new(GTK_WINDOW(main_window),
812                                                 GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
813                                                 GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
814                                                 _("One or more stores in Music Store have been modified.\n"
815                                                 "Do you want to save them before exiting?"));
816 
817 		gtk_dialog_add_buttons(GTK_DIALOG(dialog),
818 				       _("Save"), GTK_RESPONSE_YES,
819 				       _("Discard changes"), GTK_RESPONSE_NO,
820 				       _("Do not exit"), GTK_RESPONSE_CANCEL,
821 				       NULL);
822 
823 		gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
824 		gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_YES);
825 		gtk_container_set_border_width(GTK_CONTAINER(dialog), 5);
826                 gtk_window_set_title(GTK_WINDOW(dialog), _("Quit"));
827 
828 		resp = aqualung_dialog_run(GTK_DIALOG(dialog));
829 		gtk_widget_destroy(dialog);
830 
831 		if (resp == GTK_RESPONSE_CANCEL) {
832 			return;
833 		}
834 
835 		if (resp == GTK_RESPONSE_YES) {
836 			music_store_save_all();
837 		}
838 	}
839 
840 	main_window_close(NULL, NULL, NULL);
841 }
842 
843 gboolean
main_window_event(GtkWidget * widget,GdkEvent * event,gpointer data)844 main_window_event(GtkWidget * widget, GdkEvent * event, gpointer data) {
845 
846 	if (event->type == GDK_DELETE) {
847 #ifdef HAVE_SYSTRAY
848 		if (systray_used) {
849 			hide_all_windows(NULL);
850 		} else {
851 			main_window_closing();
852 		}
853 #else
854 		main_window_closing();
855 #endif /* HAVE_SYSTRAY */
856 		return TRUE;
857 	}
858 
859 	return FALSE;
860 }
861 
862 void
main_window_resize(void)863 main_window_resize(void) {
864 
865         if (options.playlist_is_embedded && !options.playlist_on) {
866 		gtk_window_resize(GTK_WINDOW(main_window), options.main_size_x,
867 				  options.main_size_y - 14 - 6 - 6 -
868 				  playlist_window->allocation.height);
869 	}
870 
871 	if (!options.playlist_is_embedded) {
872 		gtk_window_resize(GTK_WINDOW(main_window),
873 				  options.main_size_x, options.main_size_y - 14 - 6);
874 	}
875 }
876 
877 /***********************************************************************************/
878 
879 
880 void
conf__options_cb(gpointer data)881 conf__options_cb(gpointer data) {
882 
883 	create_options_window();
884 }
885 
886 
887 void
conf__skin_cb(gpointer data)888 conf__skin_cb(gpointer data) {
889 
890 	create_skin_window();
891 }
892 
893 
894 #ifdef HAVE_JACK_MGMT
895 void
conf__jack_cb(gpointer data)896 conf__jack_cb(gpointer data) {
897 
898 	port_setup_dialog();
899 }
900 #endif /* HAVE_JACK_MGMT */
901 
902 
903 void
conf__fileinfo_cb(gpointer data)904 conf__fileinfo_cb(gpointer data) {
905 
906 	playlist_t * pl;
907 	GtkTreePath * p;
908 	GtkTreeIter iter;
909 
910 	if (is_file_loaded) {
911 		pl = playlist_get_playing();
912 	} else {
913 		pl = playlist_get_current();
914 	}
915 	if (pl == NULL) return;
916 	p = playlist_get_playing_path(pl);
917 	if (p == NULL) return;
918 	gtk_tree_model_get_iter(GTK_TREE_MODEL(pl->store), &iter, p);
919 	gtk_tree_path_free(p);
920 	show_file_info(GTK_TREE_MODEL(pl->store), iter, playlist_model_func, 0, FALSE, TRUE);
921 }
922 
923 
924 void
conf__about_cb(gpointer data)925 conf__about_cb(gpointer data) {
926 
927 	create_about_window();
928 }
929 
930 
931 void
conf__quit_cb(gpointer data)932 conf__quit_cb(gpointer data) {
933 
934 	main_window_closing();
935 }
936 
937 
938 gint
vol_bal_timeout_callback(gpointer data)939 vol_bal_timeout_callback(gpointer data) {
940 
941 	refresh_time_label = 1;
942 	vol_bal_timeout_tag = 0;
943 	refresh_time_displays();
944 
945 	return FALSE;
946 }
947 
948 
949 void
musicstore_toggled(GtkWidget * widget,gpointer data)950 musicstore_toggled(GtkWidget * widget, gpointer data) {
951 
952 	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
953 		show_music_browser();
954 	} else {
955 		hide_music_browser();
956 	}
957 }
958 
959 
960 void
playlist_toggled(GtkWidget * widget,gpointer data)961 playlist_toggled(GtkWidget * widget, gpointer data) {
962 
963 	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
964 		show_playlist();
965 	} else {
966 		hide_playlist();
967 	}
968 }
969 
970 
971 #ifdef HAVE_LADSPA
972 void
plugin_toggled(GtkWidget * widget,gpointer data)973 plugin_toggled(GtkWidget * widget, gpointer data) {
974 
975 	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
976 		show_fxbuilder();
977 	} else {
978 		hide_fxbuilder();
979 	}
980 }
981 #endif /* HAVE_LADSPA */
982 
983 void
toggle_stop_after_current_song()984 toggle_stop_after_current_song() {
985 
986 	if (is_file_loaded) {
987 		stop_after_current_song = !stop_after_current_song;
988 		set_title_label(playing_app_title);
989 	}
990 }
991 
992 void
move_song_position_slider(GtkScrollType scroll_type)993 move_song_position_slider(GtkScrollType scroll_type) {
994 
995 	if (is_file_loaded && allow_seeks && total_samples != 0) {
996 		/* 5 seconds step */
997 		gdouble step = 5 * 100.0f * disp_info.sample_rate / total_samples;
998 		gdouble pos = gtk_adjustment_get_value(GTK_ADJUSTMENT(adj_pos));
999 
1000 		refresh_scale = 0;
1001 		if (scroll_type == GTK_SCROLL_STEP_FORWARD) {
1002 			pos += step;
1003 			if (pos > 100.0) {
1004 				pos = 100.0;
1005 			}
1006 			gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_pos), pos);
1007 		} else if (scroll_type == GTK_SCROLL_STEP_BACKWARD) {
1008 			pos -= step;
1009 			if (pos < 0) {
1010 				pos = 0.0;
1011 			}
1012 			gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_pos), pos);
1013 		}
1014 	}
1015 }
1016 
1017 void
seek_song(void)1018 seek_song(void) {
1019 
1020 	if (is_file_loaded && allow_seeks && refresh_scale == 0 && total_samples != 0) {
1021 		seek_t seek;
1022 
1023 		refresh_scale = 1;
1024 		send_cmd = CMD_SEEKTO;
1025 		seek.seek_to_pos = gtk_adjustment_get_value(GTK_ADJUSTMENT(adj_pos)) / 100.0f * total_samples;
1026 		rb_write(rb_gui2disk, &send_cmd, 1);
1027 		rb_write(rb_gui2disk, (char *)&seek, sizeof(seek_t));
1028 		try_waking_disk_thread();
1029 		refresh_scale_suppress = 2;
1030         }
1031 }
1032 
1033 void
change_volume_or_balance(GtkWidget * slider_widget,GtkScrollType scroll_type)1034 change_volume_or_balance(GtkWidget * slider_widget, GtkScrollType scroll_type) {
1035 
1036 	refresh_time_label = 0;
1037 	if (vol_bal_timeout_tag) {
1038 		g_source_remove(vol_bal_timeout_tag);
1039 	}
1040 
1041 	vol_bal_timeout_tag = aqualung_timeout_add(1000, vol_bal_timeout_callback, NULL);
1042 
1043 	g_signal_emit_by_name(G_OBJECT(slider_widget), "move-slider",
1044 			      scroll_type, NULL);
1045 }
1046 
1047 gint
main_window_key_pressed(GtkWidget * widget,GdkEventKey * event)1048 main_window_key_pressed(GtkWidget * widget, GdkEventKey * event) {
1049 
1050         int playlist_tabs = gtk_notebook_get_n_pages(GTK_NOTEBOOK(playlist_notebook));
1051 
1052 	if (custom_main_keybinding_expected) {
1053 		switch (event->keyval) {
1054 		case GDK_Shift_L:
1055 		case GDK_Shift_R:
1056 		case GDK_Control_L:
1057 		case GDK_Control_R:
1058 		case GDK_Alt_L:
1059 		case GDK_Alt_R:
1060 		case GDK_Super_L:
1061 		case GDK_Super_R:
1062 			return FALSE;
1063 		default:
1064 			run_custom_main_keybinding(gdk_keyval_name(event->keyval), event->state);
1065 			custom_main_keybinding_expected = 0;
1066 			return TRUE;
1067 		}
1068 	}
1069 
1070 	switch (event->keyval) {
1071 	case GDK_KP_Divide:
1072 	case GDK_slash:
1073                 if (event->state & GDK_MOD1_MASK) {  /* ALT + KP_Divide */
1074 			change_volume_or_balance(scale_bal, GTK_SCROLL_STEP_BACKWARD);
1075 		} else {
1076 			change_volume_or_balance(scale_vol, GTK_SCROLL_STEP_BACKWARD);
1077 		}
1078 		return TRUE;
1079 	case GDK_KP_Multiply:
1080 	case GDK_asterisk:
1081                 if (event->state & GDK_MOD1_MASK) {  /* ALT + KP_Multiply */
1082 			change_volume_or_balance(scale_bal, GTK_SCROLL_STEP_FORWARD);
1083 		} else {
1084 			change_volume_or_balance(scale_vol, GTK_SCROLL_STEP_FORWARD);
1085 		}
1086 		return TRUE;
1087 	case GDK_Right:
1088 		move_song_position_slider(GTK_SCROLL_STEP_FORWARD);
1089 		return TRUE;
1090 	case GDK_Left:
1091 		move_song_position_slider(GTK_SCROLL_STEP_BACKWARD);
1092 		return TRUE;
1093 	case GDK_b:
1094 	case GDK_B:
1095 	case GDK_period:
1096 	case GDK_AudioNext:
1097 		next_event(NULL, NULL, NULL);
1098 		return TRUE;
1099 	case GDK_z:
1100 	case GDK_Z:
1101 		if (event->state & GDK_CONTROL_MASK) {
1102 			custom_main_keybinding_expected = 1;
1103 			return TRUE;
1104 		}
1105 	case GDK_y:
1106 	case GDK_Y:
1107 	case GDK_comma:
1108 	case GDK_AudioPrev:
1109 		prev_event(NULL, NULL, NULL);
1110 		return TRUE;
1111 	case GDK_s:
1112 	case GDK_S:
1113                 if (event->state & GDK_MOD1_MASK) {  /* ALT + s */
1114 			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(musicstore_toggle),
1115 						     !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(musicstore_toggle)));
1116 		} else {
1117 			if (!(event->state & GDK_CONTROL_MASK)) {
1118 				stop_event(NULL, NULL, NULL);
1119 			} else {
1120 				toggle_stop_after_current_song();
1121 			}
1122 		}
1123 		return TRUE;
1124 	case GDK_v:
1125 	case GDK_V:
1126 		if (!(event->state & GDK_CONTROL_MASK)) {
1127 			stop_event(NULL, NULL, NULL);
1128 			return TRUE;
1129 		}
1130 		break;
1131 	case GDK_AudioStop:
1132 		stop_event(NULL, NULL, NULL);
1133 		return TRUE;
1134 	case GDK_c:
1135 	case GDK_C:
1136 	case GDK_space:
1137 		if (!(event->state & GDK_CONTROL_MASK)) {
1138 			if (!options.combine_play_pause) {
1139 				gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pause_button),
1140 		                !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pause_button)));
1141 			} else if (is_file_loaded) {
1142 				gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(play_button),
1143 		                !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(play_button)));
1144 			}
1145 			return TRUE;
1146 		}
1147 		break;
1148 	case GDK_p:
1149 	case GDK_P:
1150 	case GDK_AudioPlay:
1151 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(play_button),
1152 					     !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(play_button)));
1153 		return TRUE;
1154 	case GDK_i:
1155 	case GDK_I:
1156 		if (options.playlist_is_embedded) {
1157 			return playlist_window_key_pressed(widget, event);
1158 		} else {
1159 			conf__fileinfo_cb(NULL);
1160 		}
1161 		break;
1162 	case GDK_BackSpace:
1163 		if (allow_seeks && total_samples != 0) {
1164 			seek_t seek;
1165 
1166 			send_cmd = CMD_SEEKTO;
1167 			seek.seek_to_pos = 0.0f;
1168 			rb_write(rb_gui2disk, &send_cmd, 1);
1169 			rb_write(rb_gui2disk, (char *)&seek, sizeof(seek_t));
1170 			try_waking_disk_thread();
1171 			refresh_scale_suppress = 2;
1172 		}
1173 
1174 		if ((!options.combine_play_pause) && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pause_button))) {
1175 			gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_pos), 0.0f);
1176 		}
1177 		return TRUE;
1178 	case GDK_l:
1179 	case GDK_L:
1180                 if (event->state & GDK_MOD1_MASK) {  /* ALT + l */
1181 			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(playlist_toggle),
1182 						     !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(playlist_toggle)));
1183 		}
1184 		return TRUE;
1185 	case GDK_x:
1186 	case GDK_X:
1187 		if (event->state & GDK_CONTROL_MASK) {
1188 			break;
1189 		}
1190                 if (event->state & GDK_MOD1_MASK) {  /* ALT + x */
1191 #ifdef HAVE_LADSPA
1192 			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(plugin_toggle),
1193 						     !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(plugin_toggle)));
1194 #endif /* HAVE_LADSPA */
1195 		} else {
1196 			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(play_button),
1197 						     !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(play_button)));
1198 		}
1199 		return TRUE;
1200 	case GDK_q:
1201 	case GDK_Q:
1202                 if (event->state & GDK_CONTROL_MASK) {  /* CTRL + q */
1203 			main_window_closing();
1204 		}
1205 		return TRUE;
1206 	case GDK_k:
1207 	case GDK_K:
1208                 if (!options.disable_skin_support_settings) {
1209                 	create_skin_window();
1210                 }
1211                 return TRUE;
1212 	case GDK_o:
1213 	case GDK_O:
1214                 create_options_window();
1215                 return TRUE;
1216 	case GDK_1:
1217                 if (event->state & GDK_MOD1_MASK) {  /* ALT + 1 */
1218                         if(playlist_tabs >= 1) {
1219                                 gtk_notebook_set_current_page(GTK_NOTEBOOK(playlist_notebook), 1-1);
1220                         }
1221                 } else {
1222                         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(repeat_button))) {
1223                                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(repeat_button), FALSE);
1224                         } else {
1225                                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(repeat_button), TRUE);
1226                         }
1227                 }
1228                 return TRUE;
1229 	case GDK_2:
1230                 if (event->state & GDK_MOD1_MASK) {  /* ALT + 2 */
1231                         if(playlist_tabs >= 2) {
1232                                 gtk_notebook_set_current_page(GTK_NOTEBOOK(playlist_notebook), 2-1);
1233                         }
1234                 } else {
1235                         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(repeat_all_button))) {
1236                                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(repeat_all_button), FALSE);
1237                         } else {
1238                                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(repeat_all_button), TRUE);
1239                         }
1240                 }
1241                 return TRUE;
1242 	case GDK_3:
1243                 if (event->state & GDK_MOD1_MASK) {  /* ALT + 3 */
1244                         if(playlist_tabs >= 3) {
1245                                 gtk_notebook_set_current_page(GTK_NOTEBOOK(playlist_notebook), 3-1);
1246                         }
1247                 } else {
1248                         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(shuffle_button))) {
1249                                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(shuffle_button), FALSE);
1250                         } else {
1251                                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(shuffle_button), TRUE);
1252                         }
1253                 }
1254                 return TRUE;
1255 	case GDK_4:
1256 	case GDK_5:
1257 	case GDK_6:
1258 	case GDK_7:
1259 	case GDK_8:
1260 	case GDK_9:
1261 	case GDK_0:
1262                 if (event->state & GDK_MOD1_MASK) {  /* ALT */
1263 
1264                         int val = event->keyval - GDK_0;
1265                         val = (val == 0) ? 10 : val;
1266 
1267                         if(playlist_tabs >= val) {
1268                                 gtk_notebook_set_current_page(GTK_NOTEBOOK(playlist_notebook), val-1);
1269                         }
1270                 }
1271                 return TRUE;
1272 #ifdef HAVE_SYSTRAY
1273 	case GDK_Escape:
1274 		if (systray_used) {
1275 			hide_all_windows(NULL);
1276 		}
1277 		return TRUE;
1278 #endif /* HAVE_SYSTRAY */
1279 
1280 #ifdef HAVE_LOOP
1281 	case GDK_less:
1282 		if (options.repeat_on && is_file_loaded) {
1283 			float pos = (total_samples > 0) ? ((double)sample_pos / total_samples) : 0;
1284 			aqualung_loop_bar_adjust_start(AQUALUNG_LOOP_BAR(loop_bar), pos);
1285 		}
1286 		return TRUE;
1287 	case GDK_greater:
1288 		if (options.repeat_on && is_file_loaded) {
1289 			float pos = (total_samples > 0) ? ((double)sample_pos / total_samples) : 1;
1290 			aqualung_loop_bar_adjust_end(AQUALUNG_LOOP_BAR(loop_bar), pos);
1291 		}
1292 		return TRUE;
1293 #endif /* HAVE_LOOP */
1294 	}
1295 
1296         if (options.playlist_is_embedded) {
1297 		playlist_window_key_pressed(widget, event);
1298         }
1299 
1300 	return FALSE;
1301 }
1302 
1303 
1304 gint
main_window_key_released(GtkWidget * widget,GdkEventKey * event)1305 main_window_key_released(GtkWidget * widget, GdkEventKey * event) {
1306 
1307 	switch (event->keyval) {
1308         case GDK_Right:
1309         case GDK_Left:
1310 		seek_song();
1311                 break;
1312 	}
1313 
1314 	return FALSE;
1315 }
1316 
1317 
1318 gint
main_window_focus_out(GtkWidget * widget,GdkEventFocus * event,gpointer data)1319 main_window_focus_out(GtkWidget * widget, GdkEventFocus * event, gpointer data) {
1320 
1321         refresh_scale = 1;
1322 
1323         return FALSE;
1324 }
1325 
1326 
1327 gint
main_window_state_changed(GtkWidget * widget,GdkEventWindowState * event,gpointer data)1328 main_window_state_changed(GtkWidget * widget, GdkEventWindowState * event, gpointer data) {
1329 
1330         if (!options.united_minimization)
1331 		return FALSE;
1332 
1333 	if (event->new_window_state == GDK_WINDOW_STATE_ICONIFIED) {
1334 		if (options.browser_on) {
1335 			gtk_window_iconify(GTK_WINDOW(browser_window));
1336 		}
1337 
1338 		if (!options.playlist_is_embedded && options.playlist_on) {
1339 			gtk_window_iconify(GTK_WINDOW(playlist_window));
1340 		}
1341 
1342 		if (vol_window) {
1343 			gtk_window_iconify(GTK_WINDOW(vol_window));
1344 		}
1345 #ifdef HAVE_LADSPA
1346 		if (fxbuilder_on) {
1347 			GtkTreeIter iter;
1348 			gpointer gp_instance;
1349 			int i = 0;
1350 
1351 			gtk_window_iconify(GTK_WINDOW(fxbuilder_window));
1352 
1353 			while (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(running_store), &iter, NULL, i) &&
1354 			       i < MAX_PLUGINS) {
1355 				gtk_tree_model_get(GTK_TREE_MODEL(running_store), &iter, 1, &gp_instance, -1);
1356 				gtk_widget_hide(((plugin_instance *)gp_instance)->window);
1357 				++i;
1358 			}
1359 		}
1360 #endif /* HAVE_LADSPA */
1361 	}
1362 
1363 	if (event->new_window_state == 0) {
1364 		if (options.browser_on) {
1365 			gtk_window_deiconify(GTK_WINDOW(browser_window));
1366 		}
1367 
1368 		if (!options.playlist_is_embedded && options.playlist_on) {
1369 			gtk_window_deiconify(GTK_WINDOW(playlist_window));
1370 		}
1371 
1372 		if (vol_window) {
1373 			gtk_window_deiconify(GTK_WINDOW(vol_window));
1374 		}
1375 #ifdef HAVE_LADSPA
1376 		if (fxbuilder_on) {
1377 			gtk_window_deiconify(GTK_WINDOW(fxbuilder_window));
1378 		}
1379 #endif /* HAVE_LADSPA */
1380 	}
1381         return FALSE;
1382 }
1383 
1384 
1385 gint
main_window_button_pressed(GtkWidget * widget,GdkEventButton * event,gpointer data)1386 main_window_button_pressed(GtkWidget * widget, GdkEventButton * event, gpointer data) {
1387 
1388 	if (event->button == 3) {
1389 		if (options.playlist_is_embedded) {
1390 			/* translate and crop event coordinates over playlist widget */
1391 			event->x -= playlist_window->allocation.x;
1392 			if (event->x > playlist_window->allocation.width) {
1393 				event->x = -1;
1394 			}
1395 			event->y -= playlist_window->allocation.y;
1396 			if (event->y > playlist_window->allocation.height) {
1397 				event->y = -1;
1398 			}
1399 			return playlist_window_button_pressed(widget, event, playlist_get_current());
1400                 }
1401                 gtk_menu_popup(GTK_MENU(conf_menu), NULL, NULL, NULL, NULL,
1402 			       event->button, event->time);
1403 	}
1404 
1405 	return TRUE;
1406 }
1407 
1408 
1409 static gint
scale_button_press_event(GtkWidget * widget,GdkEventButton * event)1410 scale_button_press_event(GtkWidget * widget, GdkEventButton * event) {
1411 
1412 	if (event->button == 3)
1413 		return FALSE;
1414 
1415 	if (!is_file_loaded)
1416 		return FALSE;
1417 
1418 	if (!allow_seeks)
1419 		return FALSE;
1420 
1421 	if (total_samples == 0)
1422 		return FALSE;
1423 
1424 	refresh_scale = 0;
1425 	return FALSE;
1426 }
1427 
1428 
1429 static gint
scale_button_release_event(GtkWidget * widget,GdkEventButton * event)1430 scale_button_release_event(GtkWidget * widget, GdkEventButton * event) {
1431 
1432 	seek_t seek;
1433 
1434 	if (is_file_loaded) {
1435 
1436 		if (!allow_seeks)
1437 			return FALSE;
1438 
1439 		if (total_samples == 0)
1440 			return FALSE;
1441 
1442 		if (refresh_scale == 0) {
1443 			refresh_scale = 1;
1444 
1445 			send_cmd = CMD_SEEKTO;
1446 			seek.seek_to_pos = gtk_adjustment_get_value(GTK_ADJUSTMENT(adj_pos))
1447 				/ 100.0f * total_samples;
1448 			rb_write(rb_gui2disk, &send_cmd, 1);
1449 			rb_write(rb_gui2disk, (char *)&seek, sizeof(seek_t));
1450 			try_waking_disk_thread();
1451 			refresh_scale_suppress = 2;
1452 		}
1453 	}
1454 
1455 	return FALSE;
1456 }
1457 
1458 
1459 void
changed_pos(GtkAdjustment * adj,gpointer data)1460 changed_pos(GtkAdjustment * adj, gpointer data) {
1461 	static int pos = -1;
1462 
1463 	if (!is_file_loaded) {
1464 		gtk_adjustment_set_value(adj, 0.0f);
1465 	}
1466 
1467         if (options.enable_tooltips) {
1468 		int newpos = (int)gtk_adjustment_get_value(adj);
1469 		if (pos != newpos) {
1470 			char str[32];
1471 			snprintf(str, 31, _("Position: %d%%"), newpos);
1472 			aqualung_widget_set_tooltip_text(scale_pos, str);
1473 			pos = newpos;
1474 		}
1475         }
1476 }
1477 
1478 
1479 gint
scale_vol_button_press_event(GtkWidget * widget,GdkEventButton * event)1480 scale_vol_button_press_event(GtkWidget * widget, GdkEventButton * event) {
1481 
1482 	char str[32];
1483 	options.vol = gtk_adjustment_get_value(GTK_ADJUSTMENT(adj_vol));
1484 
1485         if (event->state & GDK_SHIFT_MASK) {  /* SHIFT */
1486 		gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_vol), 0);
1487 		return TRUE;
1488 	}
1489 
1490 	if (options.vol < -40.5f) {
1491 		snprintf(str, 31, _("Mute"));
1492 	} else {
1493 		snprintf(str, 31, _("%d dB"), (int)options.vol);
1494 	}
1495 
1496 	gtk_label_set_text(GTK_LABEL(time_labels[options.time_idx[0]]), str);
1497 
1498 	refresh_time_label = 0;
1499 
1500 	if (event->button == 3) {
1501 		return TRUE;
1502 	} else {
1503 		return FALSE;
1504 	}
1505 }
1506 
1507 
1508 void
changed_vol(GtkAdjustment * adj,gpointer date)1509 changed_vol(GtkAdjustment * adj, gpointer date) {
1510 
1511 	char str[32];
1512 	char str2[32];
1513 
1514 	options.vol = (int)gtk_adjustment_get_value(GTK_ADJUSTMENT(adj_vol));
1515 	gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_vol), options.vol);
1516 
1517         if (options.vol < -40.5f) {
1518                 snprintf(str, 31, _("Mute"));
1519         } else {
1520                 snprintf(str, 31, _("%d dB"), (int)options.vol);
1521         }
1522 
1523         if (!refresh_time_label) {
1524 		gtk_label_set_text(GTK_LABEL(time_labels[options.time_idx[0]]), str);
1525         }
1526 
1527         snprintf(str2, 31, _("Volume: %s"), str);
1528         aqualung_widget_set_tooltip_text(scale_vol, str2);
1529 }
1530 
1531 
1532 gint
scale_vol_button_release_event(GtkWidget * widget,GdkEventButton * event)1533 scale_vol_button_release_event(GtkWidget * widget, GdkEventButton * event) {
1534 
1535 	refresh_time_label = 1;
1536 	refresh_time_displays();
1537 
1538 	return FALSE;
1539 }
1540 
1541 
1542 gint
scale_bal_button_press_event(GtkWidget * widget,GdkEventButton * event)1543 scale_bal_button_press_event(GtkWidget * widget, GdkEventButton * event) {
1544 
1545 	char str[32];
1546 	options.bal = gtk_adjustment_get_value(GTK_ADJUSTMENT(adj_bal));
1547 
1548         if (event->state & GDK_SHIFT_MASK) {  /* SHIFT */
1549 		gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_bal), 0);
1550 		return TRUE;
1551 	}
1552 
1553 	if (options.bal != 0.0f) {
1554 		if (options.bal > 0.0f) {
1555 			snprintf(str, 31, _("%d%% R"), (int)options.bal);
1556 		} else {
1557 			snprintf(str, 31, _("%d%% L"), -1*(int)options.bal);
1558 		}
1559 	} else {
1560 		snprintf(str, 31, _("C"));
1561 	}
1562 
1563 	gtk_label_set_text(GTK_LABEL(time_labels[options.time_idx[0]]), str);
1564 
1565 	refresh_time_label = 0;
1566 
1567 	if (event->button == 3) {
1568 		return TRUE;
1569 	} else {
1570 		return FALSE;
1571 	}
1572 }
1573 
1574 
1575 void
changed_bal(GtkAdjustment * adj,gpointer date)1576 changed_bal(GtkAdjustment * adj, gpointer date) {
1577 
1578 	char str[32];
1579 	char str2[32];
1580 
1581 	options.bal = (int)gtk_adjustment_get_value(GTK_ADJUSTMENT(adj_bal));
1582 	gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_bal), options.bal);
1583 
1584         if (options.bal != 0.0f) {
1585                 if (options.bal > 0.0f) {
1586                         snprintf(str, 31, _("%d%% R"), (int)options.bal);
1587                 } else {
1588                         snprintf(str, 31, _("%d%% L"), -1*(int)options.bal);
1589                 }
1590         } else {
1591                 snprintf(str, 31, _("C"));
1592         }
1593 
1594         if (!refresh_time_label) {
1595 		gtk_label_set_text(GTK_LABEL(time_labels[options.time_idx[0]]), str);
1596 	}
1597 
1598         snprintf(str2, 31, _("Balance: %s"), str);
1599         aqualung_widget_set_tooltip_text(scale_bal, str2);
1600 }
1601 
1602 
1603 gint
scale_bal_button_release_event(GtkWidget * widget,GdkEventButton * event)1604 scale_bal_button_release_event(GtkWidget * widget, GdkEventButton * event) {
1605 
1606 	refresh_time_label = 1;
1607 	refresh_time_displays();
1608 
1609 	return FALSE;
1610 }
1611 
1612 
1613 void
show_scale_pos(gboolean state)1614 show_scale_pos(gboolean state) {
1615 
1616         if (state == FALSE) {
1617                 gtk_widget_hide(GTK_WIDGET(scale_pos));
1618                 gtk_widget_show(GTK_WIDGET(vbox_sep));
1619                 main_window_resize();
1620         } else {
1621                 gtk_widget_show(GTK_WIDGET(scale_pos));
1622                 gtk_widget_hide(GTK_WIDGET(vbox_sep));
1623         }
1624 }
1625 
1626 
1627 /******** Cue functions *********/
1628 
1629 void
toggle_noeffect(int id,int state)1630 toggle_noeffect(int id, int state) {
1631 	switch (id) {
1632 	case PLAY:
1633 		g_signal_handler_block(G_OBJECT(play_button), play_id);
1634 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(play_button), state);
1635 		g_signal_handler_unblock(G_OBJECT(play_button), play_id);
1636 		break;
1637 	case PAUSE:
1638 		g_signal_handler_block(G_OBJECT(pause_button), pause_id);
1639 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pause_button), state);
1640 		g_signal_handler_unblock(G_OBJECT(pause_button), pause_id);
1641 		break;
1642 	default:
1643 		printf("error in gui_main.c/toggle_noeffect(): unknown id value %d\n", id);
1644 		break;
1645 	}
1646 }
1647 
1648 
1649 void
cue_track_for_playback(GtkTreeStore * store,GtkTreeIter * piter,cue_t * cue)1650 cue_track_for_playback(GtkTreeStore * store, GtkTreeIter * piter, cue_t * cue) {
1651 
1652 	playlist_data_t * data;
1653 
1654 	gtk_tree_model_get(GTK_TREE_MODEL(store), piter, PL_COL_DATA, &data, -1);
1655 	cue->filename = strdup(data->file);
1656 	cue->voladj = options.rva_is_enabled ? data->voladj : 0.0f;
1657 	strncpy(current_file, cue->filename, MAXLEN-1);
1658 }
1659 
1660 
1661 /* retcode for choose_*_track(): 1->success, 0->empty list */
1662 int
choose_first_track(GtkTreeStore * store,GtkTreeIter * piter)1663 choose_first_track(GtkTreeStore * store, GtkTreeIter * piter) {
1664 
1665 	if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), piter)) {
1666 		if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(store), piter)) {
1667 			GtkTreeIter iter_parent = *piter;
1668 			gtk_tree_model_iter_children(GTK_TREE_MODEL(store), piter, &iter_parent);
1669 		}
1670 		return 1;
1671 	}
1672 	return 0;
1673 }
1674 
1675 
1676 /* get first or last child iter */
1677 void
get_child_iter(GtkTreeStore * store,GtkTreeIter * piter,int first)1678 get_child_iter(GtkTreeStore * store, GtkTreeIter * piter, int first) {
1679 
1680 	GtkTreeIter iter;
1681 	if (first) {
1682 		gtk_tree_model_iter_children(GTK_TREE_MODEL(store), &iter, piter);
1683 	} else {
1684 		int n = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), piter);
1685 		gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, piter, n-1);
1686 	}
1687 	*piter = iter;
1688 }
1689 
1690 
1691 int
choose_prev_track(GtkTreeStore * store,GtkTreeIter * piter)1692 choose_prev_track(GtkTreeStore * store, GtkTreeIter * piter) {
1693 
1694 	GtkTreePath * p = gtk_tree_model_get_path(GTK_TREE_MODEL(store), piter);
1695 
1696  try_again_prev:
1697 	if (gtk_tree_path_prev(p)) {
1698 		if (gtk_tree_path_get_depth(p) == 1) { /* toplevel */
1699 			GtkTreeIter iter;
1700 			gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, p);
1701 			if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(store), &iter)) {
1702 				get_child_iter(store, &iter, 0/* last */);
1703 			}
1704 			*piter = iter;
1705 		} else {
1706 			gtk_tree_model_get_iter(GTK_TREE_MODEL(store), piter, p);
1707 		}
1708 		gtk_tree_path_free(p);
1709 		return 1;
1710 	} else {
1711 		if (gtk_tree_path_get_depth(p) == 1) { /* toplevel */
1712 			GtkTreeIter iter;
1713 			int n = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
1714 			if (n) {
1715 				gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, n-1);
1716 				if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(store), &iter)) {
1717 					get_child_iter(store, &iter, 0/* last */);
1718 				}
1719 				*piter = iter;
1720 				gtk_tree_path_free(p);
1721 				return 1;
1722 			} else {
1723 				gtk_tree_path_free(p);
1724 				return 0;
1725 			}
1726 		} else {
1727 			gtk_tree_path_up(p);
1728 			goto try_again_prev;
1729 		}
1730 	}
1731 }
1732 
1733 
1734 int
choose_next_track(GtkTreeStore * store,GtkTreeIter * piter)1735 choose_next_track(GtkTreeStore * store, GtkTreeIter * piter) {
1736 	GtkTreeIter iter = *piter;
1737 
1738 	if (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter)) {
1739 		*piter = iter;
1740 		if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(store), piter)) {
1741 			get_child_iter(store, piter, 1/* first */);
1742 		}
1743 		return 1;
1744 	} else {
1745 		GtkTreePath * p = gtk_tree_model_get_path(GTK_TREE_MODEL(store), piter);
1746 
1747 		if (gtk_tree_path_get_depth(p) == 1) { /* toplevel */
1748 			int n = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
1749 			if (n) {
1750 				gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), piter);
1751 				if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(store), piter)) {
1752 					get_child_iter(store, piter, 1/* first */);
1753 				}
1754 				gtk_tree_path_free(p);
1755 				return 1;
1756 			} else {
1757 				gtk_tree_path_free(p);
1758 				return 0;
1759 			}
1760 		} else {
1761 			gtk_tree_path_up(p);
1762 			gtk_tree_model_get_iter(GTK_TREE_MODEL(store), piter, p);
1763 			gtk_tree_path_free(p);
1764 			return choose_next_track(store, piter);
1765 		}
1766 	}
1767 }
1768 
1769 
1770 /* simpler case than choose_next_track(); no support for wrap-around at end of list.
1771  * used by the timeout callback for track flow-through */
1772 int
choose_adjacent_track(GtkTreeStore * store,GtkTreeIter * piter)1773 choose_adjacent_track(GtkTreeStore * store, GtkTreeIter * piter) {
1774 	GtkTreeIter iter = *piter;
1775 
1776 	if (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter)) {
1777 		*piter = iter;
1778 		if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(store), piter)) {
1779 			get_child_iter(store, piter, 1/* first */);
1780 		}
1781 		return 1;
1782 	} else {
1783 		GtkTreePath * p = gtk_tree_model_get_path(GTK_TREE_MODEL(store), piter);
1784 		if (gtk_tree_path_get_depth(p) == 1) { /* toplevel */
1785 			gtk_tree_path_free(p);
1786 			return 0;
1787 		} else {
1788 			gtk_tree_path_up(p);
1789 			gtk_tree_model_get_iter(GTK_TREE_MODEL(store), piter, p);
1790 			gtk_tree_path_free(p);
1791 			return choose_adjacent_track(store, piter);
1792 		}
1793 	}
1794 }
1795 
1796 
1797 /* also used to pick the track numbered n_stop in the flattened tree */
1798 long
count_playlist_tracks(GtkTreeStore * store,GtkTreeIter * piter,long n_stop)1799 count_playlist_tracks(GtkTreeStore * store, GtkTreeIter * piter, long n_stop) {
1800 
1801 	GtkTreeIter iter;
1802 	long i = 0;
1803 	long n = 0;
1804 
1805 	while (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, i++)) {
1806 		long c = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), &iter);
1807 		long d = c;
1808 		if (!c) ++c;
1809 		if (n_stop > -1) {
1810 			if (n_stop > c) {
1811 				n_stop -= c;
1812 			} else {
1813 				if (d) {
1814 					gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store),
1815 								      piter, &iter, n_stop-1);
1816 				} else {
1817 					*piter = iter;
1818 				}
1819 				return 0;
1820 			}
1821 		}
1822 		n += c;
1823 	}
1824 	return n;
1825 }
1826 
1827 
1828 int
random_toplevel_item(GtkTreeStore * store,GtkTreeIter * piter)1829 random_toplevel_item(GtkTreeStore * store, GtkTreeIter * piter) {
1830 
1831 	long n_items;
1832 	long n;
1833 
1834 	n_items = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
1835 	if (!n_items) {
1836 		return 0;
1837 	}
1838 
1839 	n = (double)rand() * n_items / RAND_MAX;
1840 	if (n == n_items)
1841 		--n;
1842 
1843 	gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), piter, NULL, n);
1844 	return 1;
1845 }
1846 
1847 
1848 int
random_first_track(GtkTreeStore * store,GtkTreeIter * piter)1849 random_first_track(GtkTreeStore * store, GtkTreeIter * piter) {
1850 
1851 	if (random_toplevel_item(store, piter)) {
1852 		if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(store), piter)) {
1853 			get_child_iter(store, piter, 1/* first */);
1854 		}
1855 		return 1;
1856 	} else {
1857 		return 0;
1858 	}
1859 }
1860 
1861 
1862 int
choose_random_track(GtkTreeStore * store,GtkTreeIter * piter)1863 choose_random_track(GtkTreeStore * store, GtkTreeIter * piter) {
1864 
1865 	long n_items;
1866 	long n;
1867 
1868 	if (options.album_shuffle_mode) {
1869 		if (gtk_tree_store_iter_is_valid(store, piter)) {
1870 			int d = gtk_tree_store_iter_depth(store, piter);
1871 			if (d) {
1872 				if (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), piter)) {
1873 					return 1;
1874 				}
1875 			}
1876 		}
1877 		return random_first_track(store, piter);
1878 	} else {
1879 		n_items = count_playlist_tracks(store, NULL, -1);
1880 		if (n_items) {
1881 			n = (double)rand() * n_items / RAND_MAX;
1882 			if (n == n_items) {
1883 				--n;
1884 			}
1885 			count_playlist_tracks(store, piter, n+1);
1886 			return 1;
1887 		}
1888 		return 0;
1889 	}
1890 }
1891 
1892 
1893 void
prepare_playback(playlist_t * pl,GtkTreeIter * piter,cue_t * pcue)1894 prepare_playback(playlist_t * pl, GtkTreeIter * piter, cue_t * pcue) {
1895 
1896 	mark_track(pl, piter);
1897 	cue_track_for_playback(pl->store, piter, pcue);
1898 	is_file_loaded = 1;
1899 	toggle_noeffect(PLAY, TRUE);
1900 }
1901 
1902 
1903 void
unprepare_playback(void)1904 unprepare_playback(void) {
1905 
1906 	is_file_loaded = 0;
1907 	stop_after_current_song = 0;
1908 	current_file[0] = '\0';
1909 	zero_displays();
1910 	toggle_noeffect(PLAY, FALSE);
1911 }
1912 
1913 
1914 gint
prev_event(GtkWidget * widget,GdkEvent * event,gpointer data)1915 prev_event(GtkWidget * widget, GdkEvent * event, gpointer data) {
1916 
1917 	GtkTreeIter iter;
1918 	GtkTreePath * p;
1919 	char cmd;
1920 	cue_t cue;
1921 	playlist_t * pl;
1922 
1923 	if (!allow_seeks)
1924 		return FALSE;
1925 
1926 	if (is_file_loaded) {
1927 		pl = playlist_get_playing();
1928 	} else {
1929 		pl = playlist_get_current();
1930 	}
1931 
1932 	if (pl == NULL) {
1933 		return FALSE;
1934 	}
1935 
1936 	if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(shuffle_button))) {
1937 		/* normal or repeat mode */
1938 		p = playlist_get_playing_path(pl);
1939 		if (p != NULL) {
1940 			gtk_tree_model_get_iter(GTK_TREE_MODEL(pl->store), &iter, p);
1941 			gtk_tree_path_free(p);
1942 			unmark_track(pl, &iter);
1943 			if (choose_prev_track(pl->store, &iter)) {
1944 				mark_track(pl, &iter);
1945 			}
1946 		} else {
1947 			if (choose_first_track(pl->store, &iter)) {
1948 				mark_track(pl, &iter);
1949 			}
1950 		}
1951 	} else {
1952 		/* shuffle mode */
1953 		p = playlist_get_playing_path(pl);
1954 		if (p != NULL) {
1955 			gtk_tree_model_get_iter(GTK_TREE_MODEL(pl->store), &iter, p);
1956 			gtk_tree_path_free(p);
1957 			unmark_track(pl, &iter);
1958 		}
1959 		if (choose_random_track(pl->store, &iter)) {
1960 			mark_track(pl, &iter);
1961 		}
1962 	}
1963 
1964 	if (is_file_loaded) {
1965 		if ((p = playlist_get_playing_path(pl)) == NULL) {
1966 			if (is_paused) {
1967 				is_paused = 0;
1968 				toggle_noeffect(PAUSE, FALSE);
1969 				stop_event(NULL, NULL, NULL);
1970 			}
1971 			return FALSE;
1972 		}
1973 
1974 		gtk_tree_model_get_iter(GTK_TREE_MODEL(pl->store), &iter, p);
1975 		gtk_tree_path_free(p);
1976 		cue_track_for_playback(pl->store, &iter, &cue);
1977 
1978 		stop_after_current_song = 0;
1979 		if (is_paused) {
1980 			is_paused = 0;
1981 			toggle_noeffect(PAUSE, FALSE);
1982 			toggle_noeffect(PLAY, TRUE);
1983 		}
1984 
1985 		cmd = CMD_CUE;
1986 		flush_rb_disk2gui();
1987 		rb_write(rb_gui2disk, &cmd, sizeof(char));
1988 		rb_write(rb_gui2disk, (void *)&cue, sizeof(cue_t));
1989 		try_waking_disk_thread();
1990 	}
1991 	return FALSE;
1992 }
1993 
1994 
1995 gint
next_event(GtkWidget * widget,GdkEvent * event,gpointer data)1996 next_event(GtkWidget * widget, GdkEvent * event, gpointer data) {
1997 
1998 	GtkTreeIter iter;
1999 	GtkTreePath * p;
2000 	char cmd;
2001 	cue_t cue;
2002 	playlist_t * pl;
2003 
2004 	if (!allow_seeks)
2005 		return FALSE;
2006 
2007 	if (is_file_loaded) {
2008 		pl = playlist_get_playing();
2009 	} else {
2010 		pl = playlist_get_current();
2011 	}
2012 
2013 	if (pl == NULL) {
2014 		return FALSE;
2015 	}
2016 
2017 	if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(shuffle_button))) {
2018 		/* normal or repeat mode */
2019 		p = playlist_get_playing_path(pl);
2020 		if (p != NULL) {
2021 			gtk_tree_model_get_iter(GTK_TREE_MODEL(pl->store), &iter, p);
2022 			gtk_tree_path_free(p);
2023 			unmark_track(pl, &iter);
2024 			if (choose_next_track(pl->store, &iter)) {
2025 				mark_track(pl, &iter);
2026 			}
2027 		} else {
2028 			if (choose_first_track(pl->store, &iter)) {
2029 				mark_track(pl, &iter);
2030 			}
2031 		}
2032 	} else {
2033 		/* shuffle mode */
2034 		p = playlist_get_playing_path(pl);
2035 		if (p != NULL) {
2036 			gtk_tree_model_get_iter(GTK_TREE_MODEL(pl->store), &iter, p);
2037 			gtk_tree_path_free(p);
2038 			unmark_track(pl, &iter);
2039 		}
2040 		if (choose_random_track(pl->store, &iter)) {
2041 			mark_track(pl, &iter);
2042 		}
2043 	}
2044 
2045 	if (is_file_loaded) {
2046 		if ((p = playlist_get_playing_path(pl)) == NULL) {
2047 			if (is_paused) {
2048 				is_paused = 0;
2049 				toggle_noeffect(PAUSE, FALSE);
2050 				stop_event(NULL, NULL, NULL);
2051 			}
2052 			return FALSE;
2053 		}
2054 
2055 		gtk_tree_model_get_iter(GTK_TREE_MODEL(pl->store), &iter, p);
2056 		gtk_tree_path_free(p);
2057 		cue_track_for_playback(pl->store, &iter, &cue);
2058 
2059 		stop_after_current_song = 0;
2060 		if (is_paused) {
2061 			is_paused = 0;
2062 			toggle_noeffect(PAUSE, FALSE);
2063 			toggle_noeffect(PLAY, TRUE);
2064 		}
2065 
2066 		cmd = CMD_CUE;
2067 		flush_rb_disk2gui();
2068 		rb_write(rb_gui2disk, &cmd, sizeof(char));
2069 		rb_write(rb_gui2disk, (void *)&cue, sizeof(cue_t));
2070 		try_waking_disk_thread();
2071 	}
2072 	return FALSE;
2073 }
2074 
2075 
2076 gint
play_event(GtkWidget * widget,GdkEvent * event,gpointer data)2077 play_event(GtkWidget * widget, GdkEvent * event, gpointer data) {
2078 
2079 	GtkTreeIter iter;
2080 	GtkTreePath * p;
2081 	char cmd;
2082 	cue_t cue;
2083 	playlist_t * pl;
2084 
2085 	if (is_paused) {
2086 		is_paused = 0;
2087 		if (!options.combine_play_pause) {
2088 			toggle_noeffect(PAUSE, FALSE);
2089 		}
2090 		send_cmd = CMD_RESUME;
2091 		rb_write(rb_gui2disk, &send_cmd, 1);
2092 		try_waking_disk_thread();
2093 		return FALSE;
2094 	}
2095 	if (options.combine_play_pause && is_file_loaded) {
2096 		return pause_event(widget, event, data);
2097 	}
2098 
2099 	cmd = CMD_CUE;
2100 	cue.filename = NULL;
2101 
2102 	while ((pl = playlist_get_playing()) != NULL) {
2103 		playlist_set_playing(pl, 0);
2104 	}
2105 
2106 	if ((pl = playlist_get_current()) == NULL) {
2107 		return FALSE;
2108 	}
2109 
2110 	playlist_set_playing(pl, 1);
2111 
2112 	p = playlist_get_playing_path(pl);
2113 	if (p != NULL) {
2114 		gtk_tree_model_get_iter(GTK_TREE_MODEL(pl->store), &iter, p);
2115 		gtk_tree_path_free(p);
2116 		prepare_playback(pl, &iter, &cue);
2117 	} else {
2118 		if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(shuffle_button))) {
2119 			/* normal or repeat mode */
2120 			if (choose_first_track(pl->store, &iter)) {
2121 				prepare_playback(pl, &iter, &cue);
2122 			} else {
2123 				unprepare_playback();
2124 			}
2125 		} else { /* shuffle mode */
2126 			if (choose_random_track(pl->store, &iter)) {
2127 				prepare_playback(pl, &iter, &cue);
2128 			} else {
2129 				unprepare_playback();
2130 			}
2131 		}
2132 	}
2133 	if (cue.filename == NULL) {
2134 		stop_event(NULL, NULL, NULL);
2135 	} else {
2136 		flush_rb_disk2gui();
2137 		rb_write(rb_gui2disk, &cmd, sizeof(char));
2138 		rb_write(rb_gui2disk, (void *)&cue, sizeof(cue_t));
2139 		try_waking_disk_thread();
2140 	}
2141 	return FALSE;
2142 }
2143 
2144 
2145 gint
pause_event(GtkWidget * widget,GdkEvent * event,gpointer data)2146 pause_event(GtkWidget * widget, GdkEvent * event, gpointer data) {
2147 
2148 	if ((!allow_seeks) || (!is_file_loaded)) {
2149 		if (!options.combine_play_pause) {
2150 			toggle_noeffect(PAUSE, FALSE);
2151 		}
2152 		return FALSE;
2153 	}
2154 
2155 	if (!is_paused) {
2156 		is_paused = 1;
2157 		toggle_noeffect(PLAY, FALSE);
2158 		send_cmd = CMD_PAUSE;
2159 		rb_write(rb_gui2disk, &send_cmd, 1);
2160 
2161 	} else {
2162 		is_paused = 0;
2163 		toggle_noeffect(PLAY, TRUE);
2164 		send_cmd = CMD_RESUME;
2165 		rb_write(rb_gui2disk, &send_cmd, 1);
2166 	}
2167 
2168 	try_waking_disk_thread();
2169 	return FALSE;
2170 }
2171 
2172 
2173 gint
stop_event(GtkWidget * widget,GdkEvent * event,gpointer data)2174 stop_event(GtkWidget * widget, GdkEvent * event, gpointer data) {
2175 
2176 	char cmd;
2177 	cue_t cue;
2178 
2179 	is_file_loaded = 0;
2180 	stop_after_current_song = 0;
2181 	current_file[0] = '\0';
2182 	gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_pos), 0.0f);
2183 	zero_displays();
2184 	toggle_noeffect(PLAY, FALSE);
2185 	if (!options.combine_play_pause) {
2186 		toggle_noeffect(PAUSE, FALSE);
2187 	}
2188 
2189 	is_paused = 0;
2190 	allow_seeks = 1;
2191 
2192 	cmd = CMD_CUE;
2193 	cue.filename = NULL;
2194 	flush_rb_disk2gui();
2195         rb_write(rb_gui2disk, &cmd, sizeof(char));
2196         rb_write(rb_gui2disk, (void *)&cue, sizeof(cue_t));
2197 	try_waking_disk_thread();
2198 
2199  	show_scale_pos(TRUE);
2200 
2201         /* hide cover */
2202         hide_cover_thumbnail();
2203 
2204 	if (embedded_picture != NULL) {
2205 		free(embedded_picture);
2206 		embedded_picture = NULL;
2207 		embedded_picture_size = 0;
2208 	}
2209 
2210 	return FALSE;
2211 }
2212 
2213 
2214 /* called when a track ends without user intervention */
2215 void
decide_next_track(cue_t * pcue)2216 decide_next_track(cue_t * pcue) {
2217 
2218 	GtkTreePath * p;
2219 	GtkTreeIter iter;
2220 	playlist_t * pl;
2221 
2222 	if ((pl = playlist_get_playing()) == NULL) {
2223 		unprepare_playback();
2224 		return;
2225 	}
2226 
2227 	if (stop_after_current_song) {
2228 		unprepare_playback();
2229 		return;
2230 	}
2231 
2232 	p = playlist_get_playing_path(pl);
2233 	if (p != NULL) { /* there is a marked track in playlist */
2234 		if ((!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(shuffle_button))) &&
2235 		    (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(repeat_button)))) {
2236 			/* normal or list repeat mode */
2237 			gtk_tree_model_get_iter(GTK_TREE_MODEL(pl->store), &iter, p);
2238 			gtk_tree_path_free(p);
2239 			unmark_track(pl, &iter);
2240 			if (choose_adjacent_track(pl->store, &iter)) {
2241 				prepare_playback(pl, &iter, pcue);
2242 			} else {
2243 				if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(repeat_all_button))) {
2244 					/* normal mode */
2245 					allow_seeks = 1;
2246 					changed_pos(GTK_ADJUSTMENT(adj_pos), NULL);
2247 					unprepare_playback();
2248 				} else {
2249 					/* list repeat mode */
2250 					if (choose_first_track(pl->store, &iter)) {
2251 						prepare_playback(pl, &iter, pcue);
2252 					} else {
2253 						allow_seeks = 1;
2254 						changed_pos(GTK_ADJUSTMENT(adj_pos), NULL);
2255 						unprepare_playback();
2256 					}
2257 				}
2258 			}
2259 		} else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(repeat_button))) {
2260 			/* track repeat mode */
2261 			gtk_tree_model_get_iter(GTK_TREE_MODEL(pl->store), &iter, p);
2262 			gtk_tree_path_free(p);
2263 			prepare_playback(pl, &iter, pcue);
2264 		} else {
2265 			/* shuffle mode */
2266 			gtk_tree_model_get_iter(GTK_TREE_MODEL(pl->store), &iter, p);
2267 			gtk_tree_path_free(p);
2268 			unmark_track(pl, &iter);
2269 			if (choose_random_track(pl->store, &iter)) {
2270 				prepare_playback(pl, &iter, pcue);
2271 			} else {
2272 				unprepare_playback();
2273 			}
2274 		}
2275 	} else { /* no marked track in playlist */
2276 		if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(shuffle_button))) {
2277 			/* normal or repeat mode */
2278 			if (choose_first_track(pl->store, &iter)) {
2279 				prepare_playback(pl, &iter, pcue);
2280 			} else {
2281 				allow_seeks = 1;
2282 				changed_pos(GTK_ADJUSTMENT(adj_pos), NULL);
2283 				unprepare_playback();
2284 			}
2285 		} else { /* shuffle mode */
2286 			if (choose_random_track(pl->store, &iter)) {
2287 				prepare_playback(pl, &iter, pcue);
2288 			} else {
2289 				unprepare_playback();
2290 			}
2291 		}
2292 	}
2293 }
2294 
2295 
2296 /********************************************/
2297 
2298 void
swap_labels(int a,int b)2299 swap_labels(int a, int b) {
2300 
2301 	GtkWidget * tmp;
2302 	int t;
2303 
2304 	tmp = time_labels[options.time_idx[a]];
2305 	time_labels[options.time_idx[a]] = time_labels[options.time_idx[b]] ;
2306 	time_labels[options.time_idx[b]] = tmp;
2307 
2308 	t = options.time_idx[b];
2309 	options.time_idx[b] = options.time_idx[a];
2310 	options.time_idx[a] = t;
2311 }
2312 
2313 
2314 gint
time_label0_clicked(GtkWidget * widget,GdkEventButton * event)2315 time_label0_clicked(GtkWidget * widget, GdkEventButton * event) {
2316 
2317 	switch (event->button) {
2318 	case 1:
2319 		swap_labels(0, 1);
2320 		refresh_time_displays();
2321 		break;
2322 	case 3:
2323 		swap_labels(0, 2);
2324 		refresh_time_displays();
2325 		break;
2326 	}
2327 
2328 	return TRUE;
2329 }
2330 
2331 
2332 gint
time_label1_clicked(GtkWidget * widget,GdkEventButton * event)2333 time_label1_clicked(GtkWidget * widget, GdkEventButton * event) {
2334 
2335 	switch (event->button) {
2336 	case 1:
2337 		swap_labels(0, 1);
2338 		refresh_time_displays();
2339 		break;
2340 	case 3:
2341 		swap_labels(1, 2);
2342 		refresh_time_displays();
2343 		break;
2344 	}
2345 
2346 	return TRUE;
2347 }
2348 
2349 
2350 gint
time_label2_clicked(GtkWidget * widget,GdkEventButton * event)2351 time_label2_clicked(GtkWidget * widget, GdkEventButton * event) {
2352 
2353 	switch (event->button) {
2354 	case 1:
2355 		swap_labels(1, 2);
2356 		refresh_time_displays();
2357 		break;
2358 	case 3:
2359 		swap_labels(0, 2);
2360 		refresh_time_displays();
2361 		break;
2362 	}
2363 
2364 	return TRUE;
2365 }
2366 
2367 
2368 gint
scroll_btn_pressed(GtkWidget * widget,GdkEventButton * event)2369 scroll_btn_pressed(GtkWidget * widget, GdkEventButton * event) {
2370 
2371 	if (event->button != 1)
2372 		return FALSE;
2373 
2374 	x_scroll_start = event->x;
2375 	x_scroll_pos = event->x;
2376 	scroll_btn = event->button;
2377 
2378 	return TRUE;
2379 }
2380 
2381 gint
scroll_btn_released(GtkWidget * widget,GdkEventButton * event,gpointer * win)2382 scroll_btn_released(GtkWidget * widget, GdkEventButton * event, gpointer * win) {
2383 
2384 	scroll_btn = 0;
2385 	gdk_window_set_cursor(gtk_widget_get_parent_window(GTK_WIDGET(win)), NULL);
2386 
2387 	return TRUE;
2388 }
2389 
2390 gint
scroll_motion_notify(GtkWidget * widget,GdkEventMotion * event,gpointer * win)2391 scroll_motion_notify(GtkWidget * widget, GdkEventMotion * event, gpointer * win) {
2392 
2393 	int dx = event->x - x_scroll_start;
2394 	gboolean dummy;
2395 
2396 	if (scroll_btn != 1)
2397 		return FALSE;
2398 
2399 	if (!scroll_btn)
2400 		return TRUE;
2401 
2402 	if (dx < -10) {
2403 		GtkRange * range = GTK_RANGE(gtk_scrolled_window_get_hscrollbar(GTK_SCROLLED_WINDOW(win)));
2404 		g_signal_emit_by_name(G_OBJECT(range), "move-slider", GTK_SCROLL_STEP_RIGHT, &dummy);
2405 		x_scroll_start = event->x;
2406 		gdk_window_set_cursor(gtk_widget_get_parent_window(GTK_WIDGET(win)),
2407 				      gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW));
2408 	}
2409 
2410 	if (dx > 10) {
2411 		GtkRange * range = GTK_RANGE(gtk_scrolled_window_get_hscrollbar(GTK_SCROLLED_WINDOW(win)));
2412 		g_signal_emit_by_name(G_OBJECT(range), "move-slider", GTK_SCROLL_STEP_LEFT, &dummy);
2413 		x_scroll_start = event->x;
2414 		gdk_window_set_cursor(gtk_widget_get_parent_window(GTK_WIDGET(win)),
2415 				      gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW));
2416 	}
2417 
2418 	x_scroll_pos = event->x;
2419 
2420 	return TRUE;
2421 }
2422 
2423 #ifdef HAVE_LOOP
2424 void
hide_loop_bar()2425 hide_loop_bar() {
2426 	gtk_widget_hide(loop_bar);
2427         main_window_resize();
2428 }
2429 #endif /* HAVE_LOOP */
2430 
2431 void
repeat_toggled(GtkWidget * widget,gpointer data)2432 repeat_toggled(GtkWidget * widget, gpointer data) {
2433 
2434 	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(repeat_button))) {
2435 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(repeat_all_button), FALSE);
2436 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(shuffle_button), FALSE);
2437 		options.repeat_on = 1;
2438 	} else {
2439 		options.repeat_on = 0;
2440 	}
2441 
2442 #ifdef HAVE_LOOP
2443 	if (options.repeat_on) {
2444 		gtk_widget_show(loop_bar);
2445 	} else {
2446 		hide_loop_bar();
2447 	}
2448 #endif /* HAVE_LOOP */
2449 }
2450 
2451 
2452 void
repeat_all_toggled(GtkWidget * widget,gpointer data)2453 repeat_all_toggled(GtkWidget * widget, gpointer data) {
2454 
2455 	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(repeat_all_button))) {
2456                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(repeat_button), FALSE);
2457                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(shuffle_button), FALSE);
2458 		options.repeat_all_on = 1;
2459 	} else {
2460 		options.repeat_all_on = 0;
2461 	}
2462 }
2463 
2464 
2465 void
shuffle_toggled(GtkWidget * widget,gpointer data)2466 shuffle_toggled(GtkWidget * widget, gpointer data) {
2467 
2468 	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(shuffle_button))) {
2469                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(repeat_button), FALSE);
2470                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(repeat_all_button), FALSE);
2471 		options.shuffle_on = 1;
2472 	} else {
2473 		options.shuffle_on = 0;
2474 	}
2475 }
2476 
2477 
2478 void
button_set_content(GtkWidget * button,char * imgpath,char * alt)2479 button_set_content(GtkWidget * button, char * imgpath, char * alt) {
2480 
2481         GdkPixbuf * pixbuf;
2482 	GtkWidget * widget;
2483 
2484 	if ((widget = gtk_bin_get_child(GTK_BIN(button))) != NULL) {
2485 		gtk_widget_destroy(widget);
2486 	}
2487 
2488 	if ((pixbuf = gdk_pixbuf_new_from_file(imgpath, NULL)) != NULL) {
2489 		widget = gtk_image_new_from_pixbuf(pixbuf);
2490 	} else {
2491 		widget = gtk_label_new(alt);
2492 	}
2493 
2494 	gtk_container_add(GTK_CONTAINER(button), widget);
2495 	gtk_widget_show(widget);
2496 }
2497 
2498 void
main_buttons_set_content(char * skin_path)2499 main_buttons_set_content(char * skin_path) {
2500 
2501 	char path[MAXLEN];
2502 
2503 	sprintf(path, "%s/%s", skin_path, "prev.png");
2504 	button_set_content(prev_button, path, "prev");
2505 	sprintf(path, "%s/%s", skin_path, "stop.png");
2506 	button_set_content(stop_button, path, "stop");
2507 	sprintf(path, "%s/%s", skin_path, "next.png");
2508 	button_set_content(next_button, path, "next");
2509 	if (options.combine_play_pause) {
2510 		sprintf(path, "%s/%s", skin_path, "play_pause.png");
2511 		button_set_content(play_button, path, "play/pause");
2512 	} else {
2513 		sprintf(path, "%s/%s", skin_path, "play.png");
2514 		button_set_content(play_button, path, "play");
2515 		sprintf(path, "%s/%s", skin_path, "pause.png");
2516 		button_set_content(pause_button, path, "pause");
2517 	}
2518 	sprintf(path, "%s/%s", skin_path, "repeat.png");
2519 	button_set_content(repeat_button, path, "repeat");
2520 	sprintf(path, "%s/%s", skin_path, "repeat_all.png");
2521 	button_set_content(repeat_all_button, path, "rep_all");
2522 	sprintf(path, "%s/%s", skin_path, "shuffle.png");
2523 	button_set_content(shuffle_button, path, "shuffle");
2524 
2525 	sprintf(path, "%s/%s", skin_path, "pl.png");
2526 	button_set_content(playlist_toggle, path, "PL");
2527 	sprintf(path, "%s/%s", skin_path, "ms.png");
2528 	button_set_content(musicstore_toggle, path, "MS");
2529 #ifdef HAVE_LADSPA
2530 	sprintf(path, "%s/%s", skin_path, "fx.png");
2531 	button_set_content(plugin_toggle, path, "FX");
2532 #endif /* HAVE_LADSPA */
2533 }
2534 
2535 
2536 #ifdef HAVE_JACK
2537 void
jack_shutdown_window(void)2538 jack_shutdown_window(void) {
2539 
2540 	message_dialog(_("JACK connection lost"),
2541 		       main_window,
2542 		       GTK_MESSAGE_ERROR,
2543 		       GTK_BUTTONS_OK,
2544 		       NULL,
2545 		       _("JACK has either been shutdown or it "
2546 			 "disconnected Aqualung. Reason: %s"),
2547 		       jack_shutdown_reason);
2548 }
2549 #endif /* HAVE_JACK */
2550 
2551 
2552 void
set_win_title(void)2553 set_win_title(void) {
2554 
2555 	char str_session_id[32];
2556 
2557 	strcpy(win_title, "Aqualung");
2558 	if (aqualung_session_id > 0) {
2559 		sprintf(str_session_id, ".%d", aqualung_session_id);
2560 		strcat(win_title, str_session_id);
2561 	}
2562 #ifdef HAVE_JACK
2563 	if ((output == JACK_DRIVER) && (strcmp(client_name, "aqualung") != 0)) {
2564 		strcat(win_title, " [");
2565 		strcat(win_title, client_name);
2566 		strcat(win_title, "]");
2567 	}
2568 #endif /* HAVE_JACK */
2569 }
2570 
2571 
2572 #ifdef HAVE_SYSTRAY
2573 void
wm_systray_warn_cb(GtkWidget * widget,gpointer data)2574 wm_systray_warn_cb(GtkWidget * widget, gpointer data) {
2575 
2576 	set_option_from_toggle(widget, &options.wm_systray_warn);
2577 }
2578 
2579 void
hide_all_windows(gpointer data)2580 hide_all_windows(gpointer data) {
2581 
2582 	if (wm_not_systray_capable) {
2583 		main_window_closing();
2584 		return;
2585 	}
2586 
2587 	if (gtk_status_icon_is_embedded(systray_icon) == FALSE) {
2588 
2589 		if (!wm_not_systray_capable && options.wm_systray_warn) {
2590 
2591 			GtkWidget * check = gtk_check_button_new_with_label(_("Warn me if the Window Manager does not support system tray"));
2592 
2593 			gtk_widget_set_name(check, "check_on_window");
2594 			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
2595 			g_signal_connect(G_OBJECT(check), "toggled",
2596 					 G_CALLBACK(wm_systray_warn_cb), NULL);
2597 
2598 			message_dialog(_("Warning"),
2599 				       options.playlist_is_embedded ? main_window : playlist_window,
2600 				       GTK_MESSAGE_WARNING,
2601 				       GTK_BUTTONS_OK,
2602 				       check,
2603 				       _("Aqualung is compiled with system tray support, but "
2604 					 "the status icon could not be embedded in the notification "
2605 					 "area. Your desktop may not have support for a system tray, "
2606 					 "or it has not been configured correctly."));
2607 
2608 			wm_not_systray_capable = 1;
2609 		} else {
2610 			main_window_closing();
2611 		}
2612 
2613 		return;
2614 
2615 	} else {
2616 		options.wm_systray_warn = 1;
2617 	}
2618 
2619 	if (!systray_main_window_on) {
2620 		return;
2621 	}
2622 
2623 	systray_main_window_on = 0;
2624 
2625 	save_window_position();
2626 	toplevel_window_foreach(TOP_WIN_TRAY, gtk_widget_hide);
2627 
2628 	gtk_widget_hide(systray__hide);
2629 	gtk_widget_show(systray__show);
2630 }
2631 
2632 void
show_all_windows(gpointer data)2633 show_all_windows(gpointer data) {
2634 
2635 	systray_main_window_on = 1;
2636 
2637 	toplevel_window_foreach(TOP_WIN_TRAY, gtk_widget_show);
2638 	restore_window_position();
2639 
2640 	gtk_widget_hide(systray__show);
2641 	gtk_widget_show(systray__hide);
2642 }
2643 #endif /* HAVE_SYSTRAY */
2644 
2645 
2646 gboolean
cover_press_button_cb(GtkWidget * widget,GdkEventButton * event,gpointer user_data)2647 cover_press_button_cb (GtkWidget *widget, GdkEventButton *event, gpointer user_data) {
2648 
2649         GtkTreePath * p;
2650 	GtkTreeIter iter;
2651 	playlist_t * pl;
2652 
2653 	if ((pl = playlist_get_playing()) == NULL) {
2654 		return FALSE;
2655 	}
2656 
2657 	if (event->type == GDK_BUTTON_PRESS && event->button == 1) { /* LMB ? */
2658 		p = playlist_get_playing_path(pl);
2659 		if (p != NULL) {
2660 			gtk_tree_model_get_iter(GTK_TREE_MODEL(pl->store), &iter, p);
2661 			gtk_tree_path_free(p);
2662 			playlist_data_t * pldata;
2663 			gtk_tree_model_get(GTK_TREE_MODEL(pl->store), &iter, PL_COL_DATA, &pldata, -1);
2664 			if (is_file_loaded) {
2665 				if (embedded_picture != NULL && (find_cover_filename(pldata->file) == NULL || !options.use_external_cover_first)) {
2666 					display_zoomed_cover_from_binary(main_window, c_event_box, embedded_picture, embedded_picture_size);
2667 				} else {
2668 					display_zoomed_cover(main_window, c_event_box, pldata->file);
2669 				}
2670 			}
2671 		}
2672         }
2673         return TRUE;
2674 }
2675 
2676 void
main_window_set_font(int cond)2677 main_window_set_font(int cond) {
2678 
2679         if (cond) {
2680 		gtk_widget_modify_font(bigtimer_label, fd_bigtimer);
2681 		gtk_widget_modify_font(smalltimer_label_1, fd_smalltimer);
2682 		gtk_widget_modify_font(smalltimer_label_2, fd_smalltimer);
2683 		gtk_widget_modify_font(label_title, fd_songtitle);
2684 		gtk_widget_modify_font(label_mono, fd_songinfo);
2685 		gtk_widget_modify_font(label_samplerate, fd_songinfo);
2686 		gtk_widget_modify_font(label_bps, fd_songinfo);
2687 		gtk_widget_modify_font(label_format, fd_songinfo);
2688 		gtk_widget_modify_font(label_output, fd_songinfo);
2689 		gtk_widget_modify_font(label_src_type, fd_songinfo);
2690 	}
2691 }
2692 
2693 void
create_main_window(char * skin_path)2694 create_main_window(char * skin_path) {
2695 
2696 	GtkWidget * vbox;
2697 	GtkWidget * disp_hbox;
2698 	GtkWidget * btns_hbox;
2699 	GtkWidget * title_hbox;
2700 	GtkWidget * info_hbox;
2701 	GtkWidget * vb_table;
2702 
2703 	GtkWidget * conf__separator1;
2704 	GtkWidget * conf__separator2;
2705 
2706 	GtkWidget * time_table;
2707 	GtkWidget * time0_viewp;
2708 	GtkWidget * time1_viewp;
2709 	GtkWidget * time2_viewp;
2710 	GtkWidget * time_hbox1;
2711 	GtkWidget * time_hbox2;
2712 
2713 	GtkWidget * disp_vbox;
2714 	GtkWidget * title_viewp;
2715 	GtkWidget * title_scrolledwin;
2716 	GtkWidget * info_viewp;
2717 	GtkWidget * info_scrolledwin;
2718 	GtkWidget * info_vsep;
2719 
2720 	GtkWidget * sr_table;
2721 
2722         char path[MAXLEN];
2723 
2724 	set_win_title();
2725 	playing_app_title[0] = '\0';
2726 
2727 	main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2728 	gtk_widget_set_name(main_window, "main_window");
2729 	register_toplevel_window(main_window, TOP_WIN_SKIN | TOP_WIN_TRAY);
2730 	gtk_window_set_title(GTK_WINDOW(main_window), win_title);
2731 #ifdef HAVE_SYSTRAY
2732 	if (systray_used) {
2733 		aqualung_status_icon_set_tooltip_text(systray_icon, win_title);
2734 	}
2735 #endif /* HAVE_SYSTRAY */
2736 
2737         g_signal_connect(G_OBJECT(main_window), "event", G_CALLBACK(main_window_event), NULL);
2738 
2739         g_signal_connect(G_OBJECT(main_window), "key_press_event", G_CALLBACK(main_window_key_pressed), NULL);
2740         g_signal_connect(G_OBJECT(main_window), "key_release_event",
2741 			 G_CALLBACK(main_window_key_released), NULL);
2742         g_signal_connect(G_OBJECT(main_window), "button_press_event",
2743 			 G_CALLBACK(main_window_button_pressed), NULL);
2744         g_signal_connect(G_OBJECT(main_window), "focus_out_event",
2745                          G_CALLBACK(main_window_focus_out), NULL);
2746         g_signal_connect(G_OBJECT(main_window), "window-state-event",
2747                          G_CALLBACK(main_window_state_changed), NULL);
2748 
2749 	gtk_widget_set_events(main_window, GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
2750 	gtk_container_set_border_width(GTK_CONTAINER(main_window), 5);
2751 
2752         /* always on top ? */
2753 
2754 	if (options.main_window_always_on_top) {
2755                 gtk_window_set_keep_above (GTK_WINDOW(main_window), TRUE);
2756         }
2757 
2758         /* initialize fonts */
2759 
2760 	fd_playlist = pango_font_description_from_string(options.playlist_font);
2761  	fd_browser = pango_font_description_from_string(options.browser_font);
2762  	fd_bigtimer = pango_font_description_from_string(options.bigtimer_font);
2763  	fd_smalltimer = pango_font_description_from_string(options.smalltimer_font);
2764  	fd_songtitle = pango_font_description_from_string(options.songtitle_font);
2765  	fd_songinfo = pango_font_description_from_string(options.songinfo_font);
2766  	fd_statusbar = pango_font_description_from_string(options.statusbar_font);
2767 
2768         conf_menu = gtk_menu_new();
2769 	register_toplevel_window(conf_menu, TOP_WIN_SKIN);
2770 
2771         if (options.playlist_is_embedded) {
2772                 init_plist_menu(conf_menu);
2773                 plist_menu = conf_menu;
2774         }
2775 
2776         conf__options = gtk_menu_item_new_with_label(_("Settings"));
2777         conf__skin = gtk_menu_item_new_with_label(_("Skin chooser"));
2778         if (!options.playlist_is_embedded) {
2779                 conf__fileinfo = gtk_menu_item_new_with_label(_("File info"));
2780 	}
2781         conf__separator1 = gtk_separator_menu_item_new();
2782         conf__about = gtk_menu_item_new_with_label(_("About"));
2783         conf__separator2 = gtk_separator_menu_item_new();
2784         conf__quit = gtk_menu_item_new_with_label(_("Quit"));
2785 
2786         if (options.playlist_is_embedded) {
2787                 gtk_menu_shell_append(GTK_MENU_SHELL(conf_menu), conf__separator1);
2788 	}
2789         gtk_menu_shell_append(GTK_MENU_SHELL(conf_menu), conf__options);
2790         gtk_menu_shell_append(GTK_MENU_SHELL(conf_menu), conf__skin);
2791 
2792 #ifdef HAVE_JACK_MGMT
2793 	if (output == JACK_DRIVER) {
2794 		conf__jack = gtk_menu_item_new_with_label(_("JACK port setup"));
2795 		gtk_menu_shell_append(GTK_MENU_SHELL(conf_menu), conf__jack);
2796 		g_signal_connect_swapped(G_OBJECT(conf__jack), "activate",
2797 					 G_CALLBACK(conf__jack_cb), NULL);
2798 		gtk_widget_show(conf__jack);
2799 	}
2800 #endif /* HAVE_JACK_MGMT */
2801 
2802         if (!options.playlist_is_embedded) {
2803                 gtk_menu_shell_append(GTK_MENU_SHELL(conf_menu), conf__fileinfo);
2804                 gtk_menu_shell_append(GTK_MENU_SHELL(conf_menu), conf__separator1);
2805 	}
2806         gtk_menu_shell_append(GTK_MENU_SHELL(conf_menu), conf__about);
2807 	gtk_menu_shell_append(GTK_MENU_SHELL(conf_menu), conf__separator2);
2808         gtk_menu_shell_append(GTK_MENU_SHELL(conf_menu), conf__quit);
2809 
2810         g_signal_connect_swapped(G_OBJECT(conf__options), "activate", G_CALLBACK(conf__options_cb), NULL);
2811         g_signal_connect_swapped(G_OBJECT(conf__skin), "activate", G_CALLBACK(conf__skin_cb), NULL);
2812         g_signal_connect_swapped(G_OBJECT(conf__about), "activate", G_CALLBACK(conf__about_cb), NULL);
2813         g_signal_connect_swapped(G_OBJECT(conf__quit), "activate", G_CALLBACK(conf__quit_cb), NULL);
2814 
2815         if (!options.playlist_is_embedded) {
2816                 g_signal_connect_swapped(G_OBJECT(conf__fileinfo), "activate", G_CALLBACK(conf__fileinfo_cb), NULL);
2817                 gtk_widget_show(conf__fileinfo);
2818 	}
2819 
2820         gtk_widget_show(conf__options);
2821         if (!options.disable_skin_support_settings) {
2822                 gtk_widget_show(conf__skin);
2823         }
2824         gtk_widget_show(conf__separator1);
2825         gtk_widget_show(conf__about);
2826         gtk_widget_show(conf__separator2);
2827         gtk_widget_show(conf__quit);
2828 
2829 
2830 	vbox = gtk_vbox_new(FALSE, 0);
2831 	gtk_container_add(GTK_CONTAINER(main_window), vbox);
2832 
2833 
2834 	disp_hbox = gtk_hbox_new(FALSE, 3);
2835 	gtk_box_pack_start(GTK_BOX(vbox), disp_hbox, FALSE, FALSE, 0);
2836 
2837 
2838 	time_table = gtk_table_new(2, 2, FALSE);
2839 	disp_vbox = gtk_vbox_new(FALSE, 0);
2840 
2841 	gtk_box_pack_start(GTK_BOX(disp_hbox), time_table, FALSE, FALSE, 0);
2842 	gtk_box_pack_start(GTK_BOX(disp_hbox), disp_vbox, TRUE, TRUE, 0);
2843 
2844 	time0_viewp = gtk_viewport_new(NULL, NULL);
2845         time1_viewp = gtk_viewport_new(NULL, NULL);
2846 	time2_viewp = gtk_viewport_new(NULL, NULL);
2847 
2848 	gtk_widget_set_name(time0_viewp, "time_viewport");
2849 	gtk_widget_set_name(time1_viewp, "time_viewport");
2850 	gtk_widget_set_name(time2_viewp, "time_viewport");
2851 
2852 	g_signal_connect(G_OBJECT(time0_viewp), "button_press_event", G_CALLBACK(time_label0_clicked), NULL);
2853 	g_signal_connect(G_OBJECT(time1_viewp), "button_press_event", G_CALLBACK(time_label1_clicked), NULL);
2854 	g_signal_connect(G_OBJECT(time2_viewp), "button_press_event", G_CALLBACK(time_label2_clicked), NULL);
2855 
2856 
2857 	gtk_table_attach(GTK_TABLE(time_table), time0_viewp, 0, 2, 0, 1,
2858 			 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2859 	gtk_table_attach(GTK_TABLE(time_table), time1_viewp, 0, 1, 1, 2,
2860 			 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2861 	gtk_table_attach(GTK_TABLE(time_table), time2_viewp, 1, 2, 1, 2,
2862 			 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2863 
2864 
2865 	info_scrolledwin = gtk_scrolled_window_new(NULL, NULL);
2866         gtk_widget_set_size_request(info_scrolledwin, 1, -1);           /* MAGIC */
2867 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(info_scrolledwin),
2868 				       GTK_POLICY_NEVER, GTK_POLICY_NEVER);
2869 
2870 	info_viewp = gtk_viewport_new(NULL, NULL);
2871 	gtk_widget_set_name(info_viewp, "info_viewport");
2872 	gtk_container_add(GTK_CONTAINER(info_scrolledwin), info_viewp);
2873 	gtk_widget_set_events(info_viewp, GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);
2874 
2875         g_signal_connect(G_OBJECT(info_viewp), "button_press_event",
2876 			 G_CALLBACK(scroll_btn_pressed), NULL);
2877         g_signal_connect(G_OBJECT(info_viewp), "button_release_event",
2878 			 G_CALLBACK(scroll_btn_released), (gpointer)info_scrolledwin);
2879         g_signal_connect(G_OBJECT(info_viewp), "motion_notify_event",
2880 			 G_CALLBACK(scroll_motion_notify), (gpointer)info_scrolledwin);
2881 
2882 	info_hbox = gtk_hbox_new(FALSE, 0);
2883 	gtk_container_set_border_width(GTK_CONTAINER(info_hbox), 1);
2884 	gtk_container_add(GTK_CONTAINER(info_viewp), info_hbox);
2885 
2886 
2887 	title_scrolledwin = gtk_scrolled_window_new(NULL, NULL);
2888         gtk_widget_set_size_request(title_scrolledwin, 1, -1);          /* MAGIC */
2889 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(title_scrolledwin),
2890 				       GTK_POLICY_NEVER, GTK_POLICY_NEVER);
2891 
2892 	title_viewp = gtk_viewport_new(NULL, NULL);
2893 	gtk_widget_set_name(title_viewp, "title_viewport");
2894 	gtk_container_add(GTK_CONTAINER(title_scrolledwin), title_viewp);
2895 	gtk_widget_set_events(title_viewp, GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);
2896 	g_signal_connect(G_OBJECT(title_viewp), "button_press_event", G_CALLBACK(scroll_btn_pressed), NULL);
2897 	g_signal_connect(G_OBJECT(title_viewp), "button_release_event", G_CALLBACK(scroll_btn_released),
2898 			 (gpointer)title_scrolledwin);
2899 	g_signal_connect(G_OBJECT(title_viewp), "motion_notify_event", G_CALLBACK(scroll_motion_notify),
2900 			 (gpointer)title_scrolledwin);
2901 
2902 	title_hbox = gtk_hbox_new(FALSE, 0);
2903 	gtk_container_set_border_width(GTK_CONTAINER(title_hbox), 1);
2904 	gtk_container_add(GTK_CONTAINER(title_viewp), title_hbox);
2905 
2906 	gtk_box_pack_start(GTK_BOX(disp_vbox), title_scrolledwin, TRUE, FALSE, 0);
2907 	gtk_box_pack_start(GTK_BOX(disp_vbox), info_scrolledwin, TRUE, FALSE, 0);
2908 
2909 	/* labels */
2910 	bigtimer_label = time_labels[options.time_idx[0]] = gtk_label_new("");
2911 
2912         gtk_widget_set_name(time_labels[options.time_idx[0]], "big_timer_label");
2913 	gtk_container_add(GTK_CONTAINER(time0_viewp), time_labels[options.time_idx[0]]);
2914 
2915 	time_hbox1 = gtk_hbox_new(FALSE, 3);
2916 	gtk_container_set_border_width(GTK_CONTAINER(time_hbox1), 2);
2917 	gtk_container_add(GTK_CONTAINER(time1_viewp), time_hbox1);
2918 
2919 	smalltimer_label_1 = time_labels[options.time_idx[1]] = gtk_label_new("");
2920 
2921         gtk_widget_set_name(time_labels[options.time_idx[1]], "small_timer_label");
2922 	gtk_box_pack_start(GTK_BOX(time_hbox1), time_labels[options.time_idx[1]], TRUE, TRUE, 0);
2923 
2924 	time_hbox2 = gtk_hbox_new(FALSE, 3);
2925 	gtk_container_set_border_width(GTK_CONTAINER(time_hbox2), 2);
2926 	gtk_container_add(GTK_CONTAINER(time2_viewp), time_hbox2);
2927 
2928 	smalltimer_label_2 = time_labels[options.time_idx[2]] = gtk_label_new("");
2929 
2930         gtk_widget_set_name(time_labels[options.time_idx[2]], "small_timer_label");
2931 	gtk_box_pack_start(GTK_BOX(time_hbox2), time_labels[options.time_idx[2]], TRUE, TRUE, 0);
2932 
2933 	label_title = gtk_label_new("");
2934         gtk_widget_set_name(label_title, "label_title");
2935 	gtk_box_pack_start(GTK_BOX(title_hbox), label_title, FALSE, FALSE, 3);
2936 
2937 	label_mono = gtk_label_new("");
2938 	gtk_box_pack_start(GTK_BOX(info_hbox), label_mono, FALSE, FALSE, 3);
2939 	gtk_widget_set_name(label_mono, "label_info");
2940 
2941 	label_samplerate = gtk_label_new("0");
2942 	gtk_widget_set_name(label_samplerate, "label_info");
2943 	gtk_box_pack_start(GTK_BOX(info_hbox), label_samplerate, FALSE, FALSE, 3);
2944 
2945 	label_bps = gtk_label_new("");
2946 	gtk_widget_set_name(label_bps, "label_info");
2947 	gtk_box_pack_start(GTK_BOX(info_hbox), label_bps, FALSE, FALSE, 3);
2948 
2949 	label_format = gtk_label_new("");
2950 	gtk_widget_set_name(label_format, "label_info");
2951 	gtk_box_pack_start(GTK_BOX(info_hbox), label_format, FALSE, FALSE, 3);
2952 
2953 	info_vsep = gtk_vseparator_new();
2954 	gtk_box_pack_start(GTK_BOX(info_hbox), info_vsep, FALSE, FALSE, 3);
2955 
2956 	label_output = gtk_label_new("");
2957 	gtk_widget_set_name(label_output, "label_info");
2958 	gtk_box_pack_start(GTK_BOX(info_hbox), label_output, FALSE, FALSE, 3);
2959 
2960 	label_src_type = gtk_label_new("");
2961 	gtk_widget_set_name(label_src_type, "label_info");
2962 	gtk_box_pack_start(GTK_BOX(info_hbox), label_src_type, FALSE, FALSE, 3);
2963 
2964 	main_window_set_font(options.override_skin_settings);
2965 
2966 	/* Volume and balance slider */
2967 	vb_table = gtk_table_new(1, 3, FALSE);
2968         gtk_table_set_col_spacings(GTK_TABLE(vb_table), 3);
2969 	gtk_box_pack_start(GTK_BOX(disp_vbox), vb_table, TRUE, FALSE, 0);
2970 
2971 	adj_vol = gtk_adjustment_new(0.0f, -41.0f, 6.0f, 1.0f, 3.0f, 0.0f);
2972 	g_signal_connect(G_OBJECT(adj_vol), "value_changed", G_CALLBACK(changed_vol), NULL);
2973 	scale_vol = gtk_hscale_new(GTK_ADJUSTMENT(adj_vol));
2974 	gtk_widget_set_name(scale_vol, "scale_vol");
2975 	g_signal_connect(G_OBJECT(scale_vol), "button_press_event",
2976 			 G_CALLBACK(scale_vol_button_press_event), NULL);
2977 	g_signal_connect(G_OBJECT(scale_vol), "button_release_event",
2978 			 G_CALLBACK(scale_vol_button_release_event), NULL);
2979 	gtk_widget_set_size_request(scale_vol, -1, 8);
2980 	gtk_scale_set_digits(GTK_SCALE(scale_vol), 0);
2981 	gtk_scale_set_draw_value(GTK_SCALE(scale_vol), FALSE);
2982 	gtk_table_attach(GTK_TABLE(vb_table), scale_vol, 0, 2, 0, 1,
2983 			 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2984 
2985         adj_bal = gtk_adjustment_new(0.0f, -100.0f, 100.0f, 1.0f, 10.0f, 0.0f);
2986         g_signal_connect(G_OBJECT(adj_bal), "value_changed", G_CALLBACK(changed_bal), NULL);
2987         scale_bal = gtk_hscale_new(GTK_ADJUSTMENT(adj_bal));
2988 	gtk_scale_set_digits(GTK_SCALE(scale_bal), 0);
2989 	gtk_widget_set_size_request(scale_bal, -1, 8);
2990 	gtk_widget_set_name(scale_bal, "scale_bal");
2991 	g_signal_connect(G_OBJECT(scale_bal), "button_press_event",
2992 			 G_CALLBACK(scale_bal_button_press_event), NULL);
2993 	g_signal_connect(G_OBJECT(scale_bal), "button_release_event",
2994 			 G_CALLBACK(scale_bal_button_release_event), NULL);
2995         gtk_scale_set_draw_value(GTK_SCALE(scale_bal), FALSE);
2996 	gtk_table_attach(GTK_TABLE(vb_table), scale_bal, 2, 3, 0, 1,
2997 			 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2998 
2999 	/* Loop bar */
3000 
3001 #ifdef HAVE_LOOP
3002 	loop_bar = aqualung_loop_bar_new(options.loop_range_start, options.loop_range_end);
3003 	g_signal_connect(loop_bar, "range-changed", G_CALLBACK(loop_range_changed_cb), NULL);
3004 	gtk_widget_set_size_request(loop_bar, -1, 14);
3005 	gtk_box_pack_start(GTK_BOX(vbox), loop_bar, FALSE, FALSE, 3);
3006 #endif /* HAVE_LOOP */
3007 
3008 
3009 	/* Position slider */
3010         adj_pos = gtk_adjustment_new(0, 0, 100, 1, 5, 0);
3011         g_signal_connect(G_OBJECT(adj_pos), "value_changed", G_CALLBACK(changed_pos), NULL);
3012         scale_pos = gtk_hscale_new(GTK_ADJUSTMENT(adj_pos));
3013 	gtk_widget_set_name(scale_pos, "scale_pos");
3014 	g_signal_connect(G_OBJECT(scale_pos), "button_press_event",
3015 			 G_CALLBACK(scale_button_press_event), NULL);
3016 	g_signal_connect(G_OBJECT(scale_pos), "button_release_event",
3017 			 G_CALLBACK(scale_button_release_event), NULL);
3018 	gtk_scale_set_digits(GTK_SCALE(scale_pos), 0);
3019         gtk_scale_set_draw_value(GTK_SCALE(scale_pos), FALSE);
3020 	gtk_range_set_update_policy(GTK_RANGE(scale_pos), GTK_UPDATE_DISCONTINUOUS);
3021 	gtk_box_pack_start(GTK_BOX(vbox), scale_pos, FALSE, FALSE, 3);
3022 
3023         vbox_sep = gtk_vbox_new (FALSE, 0);
3024 	gtk_box_pack_start(GTK_BOX(vbox), vbox_sep, FALSE, FALSE, 2);
3025 
3026 	gtk_widget_set_can_focus(scale_vol, FALSE);
3027 	gtk_widget_set_can_focus(scale_bal, FALSE);
3028 	gtk_widget_set_can_focus(scale_pos, FALSE);
3029 
3030         /* cover display widget */
3031 
3032 	cover_align = gtk_alignment_new(0.5f, 0.5f, 0.0f, 0.0f);
3033 	gtk_box_pack_start(GTK_BOX(disp_hbox), cover_align, FALSE, FALSE, 0);
3034         cover_image_area = gtk_image_new();
3035         c_event_box = gtk_event_box_new();
3036 	gtk_container_add(GTK_CONTAINER(cover_align), c_event_box);
3037         gtk_container_add(GTK_CONTAINER(c_event_box), cover_image_area);
3038         g_signal_connect(G_OBJECT(c_event_box), "button_press_event",
3039                          G_CALLBACK(cover_press_button_cb), cover_image_area);
3040 
3041         /* Embedded playlist */
3042 
3043         if (options.playlist_is_embedded && options.buttons_at_the_bottom) {
3044 		playlist_window = gtk_vbox_new(FALSE, 0);
3045 		gtk_widget_set_name(playlist_window, "playlist_window");
3046 		gtk_box_pack_start(GTK_BOX(vbox), playlist_window, TRUE, TRUE, 3);
3047 	}
3048 
3049         /* Button box with prev, play, pause, stop, next buttons */
3050 
3051 	btns_hbox = gtk_hbox_new(FALSE, 0);
3052 	gtk_box_pack_start(GTK_BOX(vbox), btns_hbox, FALSE, FALSE, 0);
3053 
3054 	prev_button = gtk_button_new();
3055         aqualung_widget_set_tooltip_text(prev_button, _("Previous song"));
3056 
3057 	stop_button = gtk_button_new();
3058         aqualung_widget_set_tooltip_text(stop_button, _("Stop"));
3059 
3060 	next_button = gtk_button_new();
3061         aqualung_widget_set_tooltip_text(next_button, _("Next song"));
3062 
3063 	play_button = gtk_toggle_button_new();
3064 
3065 	if (options.combine_play_pause) {
3066 		aqualung_widget_set_tooltip_text(play_button, _("Play/Pause"));
3067 	} else {
3068 		aqualung_widget_set_tooltip_text(play_button, _("Play"));
3069 		pause_button = gtk_toggle_button_new();
3070 		aqualung_widget_set_tooltip_text(pause_button, _("Pause"));
3071 	}
3072 
3073 	gtk_widget_set_can_focus(prev_button, FALSE);
3074 	gtk_widget_set_can_focus(stop_button, FALSE);
3075 	gtk_widget_set_can_focus(next_button, FALSE);
3076 	gtk_widget_set_can_focus(play_button, FALSE);
3077 	if (!options.combine_play_pause) {
3078 		gtk_widget_set_can_focus(pause_button, FALSE);
3079 	}
3080 
3081 	gtk_box_pack_start(GTK_BOX(btns_hbox), prev_button, FALSE, FALSE, 0);
3082 	gtk_box_pack_start(GTK_BOX(btns_hbox), play_button, FALSE, FALSE, 0);
3083 	if (!options.combine_play_pause) {
3084 		gtk_box_pack_start(GTK_BOX(btns_hbox), pause_button, FALSE, FALSE, 0);
3085 	}
3086 	gtk_box_pack_start(GTK_BOX(btns_hbox), stop_button, FALSE, FALSE, 0);
3087 	gtk_box_pack_start(GTK_BOX(btns_hbox), next_button, FALSE, FALSE, 0);
3088 
3089 	g_signal_connect(prev_button, "clicked", G_CALLBACK(prev_event), NULL);
3090 	play_id = g_signal_connect(play_button, "toggled", G_CALLBACK(play_event), NULL);
3091 	if (!options.combine_play_pause) {
3092 		pause_id = g_signal_connect(pause_button, "toggled", G_CALLBACK(pause_event), NULL);
3093 	}
3094 	g_signal_connect(stop_button, "clicked", G_CALLBACK(stop_event), NULL);
3095 	g_signal_connect(next_button, "clicked", G_CALLBACK(next_event), NULL);
3096 
3097 
3098 	/* toggle buttons for shuffle and repeat */
3099 	sr_table = gtk_table_new(2, 2, FALSE);
3100 
3101 	repeat_button = gtk_toggle_button_new();
3102         aqualung_widget_set_tooltip_text(repeat_button, _("Repeat current song"));
3103 	gtk_widget_set_size_request(repeat_button, -1, 1);
3104 	gtk_table_attach(GTK_TABLE(sr_table), repeat_button, 0, 1, 0, 1,
3105 			 GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
3106 	g_signal_connect(repeat_button, "toggled", G_CALLBACK(repeat_toggled), NULL);
3107 
3108 	repeat_all_button = gtk_toggle_button_new();
3109         aqualung_widget_set_tooltip_text(repeat_all_button, _("Repeat all songs"));
3110 	gtk_widget_set_size_request(repeat_all_button, -1, 1);
3111 	gtk_table_attach(GTK_TABLE(sr_table), repeat_all_button, 0, 1, 1, 2,
3112 			 GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
3113 	g_signal_connect(repeat_all_button, "toggled", G_CALLBACK(repeat_all_toggled), NULL);
3114 
3115 	shuffle_button = gtk_toggle_button_new();
3116         aqualung_widget_set_tooltip_text(shuffle_button, _("Shuffle songs"));
3117 	gtk_widget_set_size_request(shuffle_button, -1, 1);
3118 	gtk_table_attach(GTK_TABLE(sr_table), shuffle_button, 1, 2, 0, 2,
3119 			 GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
3120 	g_signal_connect(shuffle_button, "toggled", G_CALLBACK(shuffle_toggled), NULL);
3121 
3122 	gtk_widget_set_can_focus(repeat_button, FALSE);
3123 	gtk_widget_set_can_focus(repeat_all_button, FALSE);
3124 	gtk_widget_set_can_focus(shuffle_button, FALSE);
3125 
3126         /* toggle buttons for sub-windows visibility */
3127 	playlist_toggle = gtk_toggle_button_new();
3128         aqualung_widget_set_tooltip_text(playlist_toggle, _("Toggle playlist"));
3129 	gtk_box_pack_end(GTK_BOX(btns_hbox), playlist_toggle, FALSE, FALSE, 0);
3130 
3131 	musicstore_toggle = gtk_toggle_button_new();
3132         aqualung_widget_set_tooltip_text(musicstore_toggle, _("Toggle music store"));
3133 	gtk_box_pack_end(GTK_BOX(btns_hbox), musicstore_toggle, FALSE, FALSE, 3);
3134 
3135 	g_signal_connect(playlist_toggle, "toggled", G_CALLBACK(playlist_toggled), NULL);
3136 	g_signal_connect(musicstore_toggle, "toggled", G_CALLBACK(musicstore_toggled), NULL);
3137 
3138 	gtk_widget_set_can_focus(playlist_toggle, FALSE);
3139 	gtk_widget_set_can_focus(musicstore_toggle, FALSE);
3140 
3141 #ifdef HAVE_LADSPA
3142 	plugin_toggle = gtk_toggle_button_new();
3143 	aqualung_widget_set_tooltip_text(plugin_toggle, _("Toggle LADSPA patch builder"));
3144 	gtk_box_pack_end(GTK_BOX(btns_hbox), plugin_toggle, FALSE, FALSE, 0);
3145 	g_signal_connect(plugin_toggle, "toggled", G_CALLBACK(plugin_toggled), NULL);
3146 	gtk_widget_set_can_focus(plugin_toggle, FALSE);
3147 #endif /* HAVE_LADSPA */
3148 
3149 	gtk_box_pack_end(GTK_BOX(btns_hbox), sr_table, FALSE, FALSE, 3);
3150 
3151         if (options.disable_skin_support_settings) {
3152 	        sprintf(path, "%s/no_skin", AQUALUNG_SKINDIR);
3153 	        main_buttons_set_content(path);
3154         } else {
3155 	        main_buttons_set_content(skin_path);
3156         }
3157         set_buttons_relief();
3158 
3159 	/* Embedded playlist */
3160 	if (options.playlist_is_embedded && !options.buttons_at_the_bottom) {
3161 		playlist_window = gtk_vbox_new(FALSE, 0);
3162 		gtk_widget_set_name(playlist_window, "playlist_window");
3163 		gtk_box_pack_start(GTK_BOX(vbox), playlist_window, TRUE, TRUE, 3);
3164 	}
3165 
3166 	aqualung_tooltips_set_enabled(options.enable_tooltips);
3167 }
3168 
3169 
3170 void
process_filenames(GSList * list,int enqueue,int start_playback,int has_tab,char * tab_name)3171 process_filenames(GSList * list, int enqueue, int start_playback, int has_tab, char * tab_name) {
3172 
3173 	int mode;
3174 	char * name = NULL;
3175 
3176 	if (!has_tab) {
3177 		if (enqueue) {
3178 			mode = PLAYLIST_ENQUEUE;
3179 		} else {
3180 			mode = PLAYLIST_LOAD;
3181 		}
3182 	} else {
3183 		if (strlen(tab_name) == 0) {
3184 			mode = PLAYLIST_LOAD_TAB;
3185 		} else {
3186 			if (g_utf8_validate(tab_name, -1, NULL)) {
3187 				name = g_strdup(tab_name);
3188 			} else {
3189 				name = g_locale_to_utf8(tab_name, -1, NULL, NULL, NULL);
3190 			}
3191 			if (name == NULL) {
3192 				fprintf(stderr, "process_filenames(): unable to convert tab name to UTF-8\n");
3193 			}
3194 
3195 			if (enqueue) {
3196 				mode = PLAYLIST_ENQUEUE;
3197 			} else {
3198 				mode = PLAYLIST_LOAD;
3199 			}
3200 		}
3201 	}
3202 
3203 	playlist_load(list, mode, name, start_playback);
3204 
3205 	if (name != NULL) {
3206 		g_free(name);
3207 	}
3208 }
3209 
3210 
3211 /*** Systray support ***/
3212 #ifdef HAVE_SYSTRAY
3213 void
systray_popup_menu_cb(GtkStatusIcon * systray_icon,guint button,guint time,gpointer data)3214 systray_popup_menu_cb(GtkStatusIcon * systray_icon, guint button, guint time, gpointer data) {
3215 
3216 	if (get_systray_semaphore() == 0) {
3217 		gtk_menu_popup(GTK_MENU(systray_menu), NULL, NULL,
3218 			       gtk_status_icon_position_menu, data,
3219 			       button, time);
3220 	}
3221 }
3222 
3223 void
systray__show_cb(gpointer data)3224 systray__show_cb(gpointer data) {
3225 
3226 	show_all_windows(NULL);
3227 }
3228 
3229 void
systray__hide_cb(gpointer data)3230 systray__hide_cb(gpointer data) {
3231 
3232 	hide_all_windows(NULL);
3233 }
3234 
3235 void
systray__play_cb(gpointer data)3236 systray__play_cb(gpointer data) {
3237 
3238 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(play_button),
3239 				     !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(play_button)));
3240 }
3241 
3242 void
systray__pause_cb(gpointer data)3243 systray__pause_cb(gpointer data) {
3244 
3245 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pause_button),
3246 				     !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pause_button)));
3247 }
3248 
3249 void
systray__stop_cb(gpointer data)3250 systray__stop_cb(gpointer data) {
3251 
3252 	stop_event(NULL, NULL, NULL);
3253 }
3254 
3255 void
systray__prev_cb(gpointer data)3256 systray__prev_cb(gpointer data) {
3257 
3258 	prev_event(NULL, NULL, NULL);
3259 }
3260 
3261 void
systray__next_cb(gpointer data)3262 systray__next_cb(gpointer data) {
3263 
3264 	next_event(NULL, NULL, NULL);
3265 }
3266 
3267 void
systray__quit_cb(gpointer data)3268 systray__quit_cb(gpointer data) {
3269 
3270 	main_window_closing();
3271 }
3272 
3273 void
systray_activate_cb(GtkStatusIcon * systray_icon,gpointer data)3274 systray_activate_cb(GtkStatusIcon * systray_icon, gpointer data) {
3275 
3276 	if (get_systray_semaphore() == 0) {
3277 		if (!systray_main_window_on) {
3278 			systray__show_cb(NULL);
3279 		} else {
3280 			systray__hide_cb(NULL);
3281 		}
3282 	}
3283 }
3284 
3285 GtkScrollType
reverse_direction(GtkScrollType scroll_type)3286 reverse_direction(GtkScrollType scroll_type) {
3287 	switch (scroll_type) {
3288 	case GTK_SCROLL_STEP_BACKWARD:
3289 		return GTK_SCROLL_STEP_FORWARD;
3290 	case GTK_SCROLL_STEP_FORWARD:
3291 		return GTK_SCROLL_STEP_BACKWARD;
3292 	default:
3293 		return scroll_type;
3294 	}
3295 }
3296 
3297 gboolean
systray_mouse_wheel(int mouse_wheel_option,gboolean vertical_wheel,guint32 time_since_last_event,GtkScrollType scroll_type)3298 systray_mouse_wheel(int mouse_wheel_option, gboolean vertical_wheel,
3299        	guint32 time_since_last_event, GtkScrollType scroll_type) {
3300 
3301 	switch (mouse_wheel_option) {
3302 	case SYSTRAY_MW_CMD_VOLUME:
3303 		if (time_since_last_event > 100) {
3304 			if (vertical_wheel)
3305 				scroll_type = reverse_direction(scroll_type);
3306 			change_volume_or_balance(scale_vol, scroll_type);
3307 			return TRUE;
3308 		}
3309 		break;
3310 	case SYSTRAY_MW_CMD_BALANCE:
3311 		if (time_since_last_event > 100) {
3312 			if (vertical_wheel)
3313 				scroll_type = reverse_direction(scroll_type);
3314 			change_volume_or_balance(scale_bal, scroll_type);
3315 			return TRUE;
3316 		}
3317 		break;
3318 	case SYSTRAY_MW_CMD_SONG_POSITION:
3319 		move_song_position_slider(scroll_type);
3320 		seek_song();
3321 		return TRUE;
3322 	case SYSTRAY_MW_CMD_NEXT_PREV_SONG:
3323 		// At most one per second.
3324 		if (time_since_last_event > 1000) {
3325 			if (scroll_type == GTK_SCROLL_STEP_BACKWARD) {
3326 				prev_event(NULL, NULL, NULL);
3327 				return TRUE;
3328 			} else if (scroll_type == GTK_SCROLL_STEP_FORWARD) {
3329 				next_event(NULL, NULL, NULL);
3330 				return TRUE;
3331 			}
3332 		}
3333 		break;
3334 	}
3335 
3336 	return FALSE;
3337 }
3338 
3339 gboolean
systray_scroll_event_cb(GtkStatusIcon * systray_icon,GdkEventScroll * event,gpointer user_data)3340 systray_scroll_event_cb(GtkStatusIcon * systray_icon,
3341 			GdkEventScroll * event,
3342 			gpointer user_data) {
3343 
3344 	gboolean result = FALSE;
3345 	guint32 time_since_last_event;
3346 
3347 	if (!options.use_systray)
3348 		return FALSE;
3349 
3350 	time_since_last_event = event->time - last_systray_scroll_event_time;
3351 
3352 	switch (event->direction) {
3353 	case GDK_SCROLL_LEFT:
3354 		result = systray_mouse_wheel(options.systray_mouse_wheel_horizontal,
3355 		        FALSE, time_since_last_event, GTK_SCROLL_STEP_BACKWARD);
3356 		break;
3357 	case GDK_SCROLL_RIGHT:
3358 		result = systray_mouse_wheel(options.systray_mouse_wheel_horizontal,
3359 		        FALSE, time_since_last_event, GTK_SCROLL_STEP_FORWARD);
3360 		break;
3361 	case GDK_SCROLL_UP:
3362 		result = systray_mouse_wheel(options.systray_mouse_wheel_vertical,
3363 		        TRUE, time_since_last_event, GTK_SCROLL_STEP_BACKWARD);
3364 		break;
3365 	case GDK_SCROLL_DOWN:
3366 		result = systray_mouse_wheel(options.systray_mouse_wheel_vertical,
3367 		        TRUE, time_since_last_event, GTK_SCROLL_STEP_FORWARD);
3368 		break;
3369 	}
3370 
3371 	if (result) {
3372 		last_systray_scroll_event_time = event->time;
3373 	}
3374 
3375 	return result;
3376 }
3377 
3378 gboolean
systray_mouse_button(int mouse_button_option)3379 systray_mouse_button(int mouse_button_option) {
3380 
3381 	switch (mouse_button_option) {
3382 	case SYSTRAY_MB_CMD_PLAY_STOP_SONG:
3383 		if (is_file_loaded) {
3384 			systray__stop_cb(NULL);
3385 		} else {
3386 			systray__play_cb(NULL);
3387 		}
3388 		return TRUE;
3389 	case SYSTRAY_MB_CMD_PLAY_PAUSE_SONG:
3390 		if (is_file_loaded && !options.combine_play_pause) {
3391 			systray__pause_cb(NULL);
3392 		} else {
3393 			systray__play_cb(NULL);
3394 		}
3395 		return TRUE;
3396 	case SYSTRAY_MB_CMD_PREV_SONG:
3397 		systray__prev_cb(NULL);
3398 		return TRUE;
3399 	case SYSTRAY_MB_CMD_NEXT_SONG:
3400 		systray__next_cb(NULL);
3401 		return TRUE;
3402 	}
3403 	return FALSE;
3404 }
3405 
3406 gboolean
systray_button_press_event_cb(GtkStatusIcon * systray_icon,GdkEventButton * event,gpointer user_data)3407 systray_button_press_event_cb(GtkStatusIcon * systray_icon,
3408                               GdkEventButton * event,
3409                               gpointer user_data) {
3410 
3411 	int i;
3412 
3413 	if (!options.use_systray)
3414 		return FALSE;
3415 
3416 	if (event->type == GDK_BUTTON_PRESS) {
3417 		for (i = 0; i < options.systray_mouse_buttons_count; i++) {
3418 			if (options.systray_mouse_buttons[i].button_nr == event->button) {
3419 				return systray_mouse_button(options.systray_mouse_buttons[i].command);
3420 			}
3421 		}
3422 	}
3423 
3424 	return FALSE;
3425 }
3426 
3427 /* returns a hbox with a stock image and label in it */
3428 GtkWidget *
create_systray_menu_item(const gchar * stock_id,char * text)3429 create_systray_menu_item(const gchar * stock_id, char * text) {
3430 
3431 	GtkWidget * hbox;
3432 	GtkWidget * widget;
3433 
3434 	hbox = gtk_hbox_new(FALSE, 5);
3435 	gtk_widget_show(hbox);
3436 	widget = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_MENU);
3437 	gtk_widget_show(widget);
3438 	gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, TRUE, 2);
3439 	widget = gtk_label_new(text);
3440 	gtk_widget_show(widget);
3441 	gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, TRUE, 2);
3442 
3443 	return hbox;
3444 }
3445 
3446 void
setup_systray(void)3447 setup_systray(void) {
3448 
3449 	char path[MAXLEN];
3450 
3451 	GtkWidget * systray__separator1;
3452 	GtkWidget * systray__separator2;
3453 
3454 	sprintf(path, "%s/icon_64.png", AQUALUNG_DATADIR);
3455 	systray_icon = gtk_status_icon_new_from_file(path);
3456 
3457         g_signal_connect_swapped(G_OBJECT(systray_icon), "activate",
3458 				 G_CALLBACK(systray_activate_cb), NULL);
3459         g_signal_connect_swapped(G_OBJECT(systray_icon), "popup-menu",
3460 				 G_CALLBACK(systray_popup_menu_cb), (gpointer)systray_icon);
3461 	g_signal_connect(G_OBJECT(systray_icon), "scroll-event",
3462 			 G_CALLBACK(systray_scroll_event_cb), NULL);
3463 	g_signal_connect(G_OBJECT(systray_icon), "button-press-event",
3464 			 G_CALLBACK(systray_button_press_event_cb), NULL);
3465 
3466         systray_menu = gtk_menu_new();
3467 	register_toplevel_window(systray_menu, TOP_WIN_SKIN);
3468 
3469         systray__show = gtk_menu_item_new_with_label(_("Show Aqualung"));
3470         systray__hide = gtk_menu_item_new_with_label(_("Hide Aqualung"));
3471 
3472         systray__separator1 = gtk_separator_menu_item_new();
3473 
3474         systray__play = gtk_menu_item_new();
3475 	gtk_container_add(GTK_CONTAINER(systray__play),
3476 			create_systray_menu_item(GTK_STOCK_MEDIA_PLAY,
3477 			options.combine_play_pause ? _("Play/Pause") : _("Play")));
3478 
3479 	if (!options.combine_play_pause) {
3480 		systray__pause = gtk_menu_item_new();
3481 		gtk_container_add(GTK_CONTAINER(systray__pause),
3482 				  create_systray_menu_item(GTK_STOCK_MEDIA_PAUSE, _("Pause")));
3483 	}
3484 
3485         systray__stop = gtk_menu_item_new();
3486 	gtk_container_add(GTK_CONTAINER(systray__stop),
3487 			  create_systray_menu_item(GTK_STOCK_MEDIA_STOP, _("Stop")));
3488 
3489         systray__prev = gtk_menu_item_new();
3490 	gtk_container_add(GTK_CONTAINER(systray__prev),
3491 			  create_systray_menu_item(GTK_STOCK_MEDIA_PREVIOUS, _("Previous")));
3492 
3493         systray__next = gtk_menu_item_new();
3494 	gtk_container_add(GTK_CONTAINER(systray__next),
3495 			  create_systray_menu_item(GTK_STOCK_MEDIA_NEXT, _("Next")));
3496 
3497         systray__separator2 = gtk_separator_menu_item_new();
3498 
3499         systray__quit = gtk_menu_item_new();
3500 	gtk_container_add(GTK_CONTAINER(systray__quit),
3501 			  create_systray_menu_item(GTK_STOCK_STOP, _("Quit")));
3502 
3503         gtk_menu_shell_append(GTK_MENU_SHELL(systray_menu), systray__show);
3504         gtk_menu_shell_append(GTK_MENU_SHELL(systray_menu), systray__hide);
3505         gtk_menu_shell_append(GTK_MENU_SHELL(systray_menu), systray__separator1);
3506         gtk_menu_shell_append(GTK_MENU_SHELL(systray_menu), systray__play);
3507 	if (!options.combine_play_pause) {
3508 		gtk_menu_shell_append(GTK_MENU_SHELL(systray_menu), systray__pause);
3509 	}
3510         gtk_menu_shell_append(GTK_MENU_SHELL(systray_menu), systray__stop);
3511         gtk_menu_shell_append(GTK_MENU_SHELL(systray_menu), systray__prev);
3512         gtk_menu_shell_append(GTK_MENU_SHELL(systray_menu), systray__next);
3513         gtk_menu_shell_append(GTK_MENU_SHELL(systray_menu), systray__separator2);
3514         gtk_menu_shell_append(GTK_MENU_SHELL(systray_menu), systray__quit);
3515 
3516         g_signal_connect_swapped(G_OBJECT(systray__show), "activate", G_CALLBACK(systray__show_cb), NULL);
3517         g_signal_connect_swapped(G_OBJECT(systray__hide), "activate", G_CALLBACK(systray__hide_cb), NULL);
3518         g_signal_connect_swapped(G_OBJECT(systray__play), "activate", G_CALLBACK(systray__play_cb), NULL);
3519         if (!options.combine_play_pause) {
3520 		g_signal_connect_swapped(G_OBJECT(systray__pause), "activate", G_CALLBACK(systray__pause_cb), NULL);
3521 	}
3522         g_signal_connect_swapped(G_OBJECT(systray__stop), "activate", G_CALLBACK(systray__stop_cb), NULL);
3523         g_signal_connect_swapped(G_OBJECT(systray__prev), "activate", G_CALLBACK(systray__prev_cb), NULL);
3524         g_signal_connect_swapped(G_OBJECT(systray__next), "activate", G_CALLBACK(systray__next_cb), NULL);
3525         g_signal_connect_swapped(G_OBJECT(systray__quit), "activate", G_CALLBACK(systray__quit_cb), NULL);
3526 
3527         gtk_widget_show(systray_menu);
3528         gtk_widget_show(systray__hide);
3529         gtk_widget_show(systray__separator1);
3530 	gtk_widget_show(systray__play);
3531 	if (!options.combine_play_pause) {
3532 		gtk_widget_show(systray__pause);
3533 	}
3534 	gtk_widget_show(systray__stop);
3535 	gtk_widget_show(systray__prev);
3536 	gtk_widget_show(systray__next);
3537 
3538         gtk_widget_show(systray__separator2);
3539         gtk_widget_show(systray__quit);
3540 }
3541 #endif /* HAVE_SYSTRAY */
3542 
3543 void
create_gui(int argc,char ** argv,int optind,int enqueue,unsigned long rate,unsigned long rb_audio_size)3544 create_gui(int argc, char ** argv, int optind, int enqueue,
3545 	   unsigned long rate, unsigned long rb_audio_size) {
3546 
3547 	char path[MAXLEN];
3548 	GList * glist = NULL;
3549 	GdkPixbuf * pixbuf = NULL;
3550 
3551 	srand(time(0));
3552 	sample_pos = 0;
3553 	out_SR = rate;
3554 	rb_size = rb_audio_size;
3555 
3556 	gdk_threads_enter();
3557 	gtk_init(&argc, &argv);
3558 #ifdef HAVE_LADSPA
3559 	lrdf_init();
3560 #endif /* HAVE_LADSPA */
3561 
3562 	load_config();
3563 
3564 	if (options.title_format[0] == '\0')
3565 		sprintf(options.title_format, "%%a: %%t [%%r]");
3566 	if (options.skin[0] == '\0') {
3567 		sprintf(options.skin, "%s/plain", AQUALUNG_SKINDIR);
3568 		options.main_pos_x = 280;
3569 		options.main_pos_y = 30;
3570 		options.main_size_x = 380;
3571 		options.main_size_y = 380;
3572 		options.browser_pos_x = 30;
3573 		options.browser_pos_y = 30;
3574 		options.browser_size_x = 240;
3575 		options.browser_size_y = 380;
3576 		options.browser_on = 1;
3577 		options.playlist_pos_x = 300;
3578 		options.playlist_pos_y = 180;
3579 		options.playlist_size_x = 400;
3580 		options.playlist_size_y = 500;
3581 		options.playlist_on = 1;
3582 	}
3583 
3584 	if (options.cddb_server[0] == '\0') {
3585 		sprintf(options.cddb_server, "freedb.org");
3586 	}
3587 
3588 	if (options.src_type == -1) {
3589 		options.src_type = 4;
3590 	}
3591 
3592         if (options.disable_skin_support_settings) {
3593 	        sprintf(path, "%s/no_skin/rc", AQUALUNG_SKINDIR);
3594         } else {
3595 	        sprintf(path, "%s/rc", options.skin);
3596         }
3597 	gtk_rc_parse(path);
3598 
3599 #ifdef HAVE_SYSTRAY
3600 	if (options.use_systray) {
3601 		systray_used = 1;
3602 		setup_systray();
3603 	}
3604 #endif /* HAVE_SYSTRAY */
3605 
3606 	create_main_window(options.skin);
3607 
3608 	vol_prev = -101.0f;
3609 	gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_vol), options.vol);
3610 	bal_prev = -101.0f;
3611 	gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_bal), options.bal);
3612 
3613 	create_playlist();
3614 	playlist_auto_save_reset();
3615 
3616 	create_music_browser();
3617 
3618 #ifdef HAVE_LADSPA
3619 	create_fxbuilder();
3620 	load_plugin_data();
3621 #endif /* HAVE_LADSPA */
3622 
3623 #ifdef HAVE_CDDA
3624 	create_cdda_node();
3625 	cdda_scanner_start();
3626 #endif /* HAVE_CDDA */
3627 
3628 #ifdef HAVE_PODCAST
3629 	create_podcast_node();
3630 	store_podcast_load();
3631 	store_podcast_updater_start();
3632 #endif /* HAVE_PODCAST */
3633 
3634 	music_store_load_all();
3635 
3636 	options_store_watcher_start();
3637 
3638 	sprintf(path, "%s/icon_16.png", AQUALUNG_DATADIR);
3639 	if ((pixbuf = gdk_pixbuf_new_from_file(path, NULL)) != NULL) {
3640 		glist = g_list_append(glist, gdk_pixbuf_new_from_file(path, NULL));
3641 	}
3642 
3643 	sprintf(path, "%s/icon_24.png", AQUALUNG_DATADIR);
3644 	if ((pixbuf = gdk_pixbuf_new_from_file(path, NULL)) != NULL) {
3645 		glist = g_list_append(glist, gdk_pixbuf_new_from_file(path, NULL));
3646 	}
3647 
3648 	sprintf(path, "%s/icon_32.png", AQUALUNG_DATADIR);
3649 	if ((pixbuf = gdk_pixbuf_new_from_file(path, NULL)) != NULL) {
3650 		glist = g_list_append(glist, gdk_pixbuf_new_from_file(path, NULL));
3651 	}
3652 
3653 	sprintf(path, "%s/icon_48.png", AQUALUNG_DATADIR);
3654 	if ((pixbuf = gdk_pixbuf_new_from_file(path, NULL)) != NULL) {
3655 		glist = g_list_append(glist, gdk_pixbuf_new_from_file(path, NULL));
3656 	}
3657 
3658 	sprintf(path, "%s/icon_64.png", AQUALUNG_DATADIR);
3659 	if ((pixbuf = gdk_pixbuf_new_from_file(path, NULL)) != NULL) {
3660 		glist = g_list_append(glist, gdk_pixbuf_new_from_file(path, NULL));
3661 	}
3662 
3663 	if (glist != NULL) {
3664 		gtk_window_set_default_icon_list(glist);
3665 		g_list_free(glist);
3666 	}
3667 
3668 	if (options.repeat_on) {
3669 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(repeat_button), TRUE);
3670 	}
3671 
3672 	if (options.repeat_all_on) {
3673 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(repeat_all_button), TRUE);
3674 	}
3675 
3676 	if (options.shuffle_on) {
3677 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(shuffle_button), TRUE);
3678 	}
3679 
3680         if (playlist_state != -1) {
3681                 options.playlist_on = playlist_state;
3682 	}
3683 
3684         if (browser_state != -1) {
3685                 options.browser_on = browser_state;
3686 	}
3687 
3688 	if (options.browser_on) {
3689 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(musicstore_toggle), TRUE);
3690 	}
3691 
3692 	if (options.playlist_on) {
3693 		if (options.playlist_is_embedded) {
3694 			g_signal_handlers_block_by_func(G_OBJECT(playlist_toggle), playlist_toggled, NULL);
3695 		}
3696 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(playlist_toggle), TRUE);
3697 		if (options.playlist_is_embedded) {
3698 			g_signal_handlers_unblock_by_func(G_OBJECT(playlist_toggle), playlist_toggled, NULL);
3699 		}
3700 	}
3701 
3702 	restore_window_position();
3703 
3704 	gtk_widget_show_all(main_window);
3705 
3706 #ifdef HAVE_SYSTRAY
3707 	if (options.use_systray && options.systray_start_minimized) {
3708 		toplevel_window_foreach(TOP_WIN_TRAY, gtk_widget_hide);
3709 		systray_main_window_on = 0;
3710 	}
3711 #endif /* HAVE_SYSTRAY */
3712 
3713         hide_cover_thumbnail();
3714 
3715         gtk_widget_hide(vbox_sep);
3716 
3717 	if (options.playlist_is_embedded) {
3718 		if (!options.playlist_on) {
3719                         hide_playlist();
3720 		}
3721 	}
3722 
3723 #ifdef HAVE_LOOP
3724 	if (!options.repeat_on) {
3725 		hide_loop_bar();
3726 	}
3727 #endif /* HAVE_LOOP */
3728 
3729 
3730         /* update sliders' tooltips */
3731         if (options.enable_tooltips) {
3732                 changed_vol(GTK_ADJUSTMENT(adj_vol), NULL);
3733                 changed_bal(GTK_ADJUSTMENT(adj_bal), NULL);
3734 	        changed_pos(GTK_ADJUSTMENT(adj_pos), NULL);
3735         }
3736 
3737 	zero_displays();
3738 	if (options.auto_save_playlist) {
3739 		/* start playback only if no files to be loaded on command line */
3740 		int start_playback = (argv[optind] == NULL) && immediate_start;
3741 		char file[MAXLEN];
3742 
3743 		snprintf(file, MAXLEN-1, "%s/%s", options.confdir, "playlist.xml");
3744 		if (g_file_test(file, G_FILE_TEST_EXISTS) == TRUE) {
3745 			GSList * list = g_slist_append(NULL, strdup(file));
3746 			playlist_load(list, PLAYLIST_LOAD_TAB, NULL, start_playback);
3747 		}
3748 	}
3749 
3750 	/* read command line filenames */
3751 	{
3752 		int i;
3753 		GSList * list = NULL;
3754 
3755 		for (i = optind; argv[i] != NULL; i++) {
3756 			list = g_slist_append(list, strdup(argv[i]));
3757 		}
3758 
3759 		if (list != NULL) {
3760 			process_filenames(list, enqueue, immediate_start, (tab_name != NULL), tab_name);
3761 		}
3762 	}
3763 
3764 	/* ensure that at least one playlist has been created */
3765 	playlist_ensure_tab_exists();
3766 
3767 	playlist_set_color();
3768 
3769 	/* activate jack client and connect ports */
3770 #ifdef HAVE_JACK
3771 	if (output == JACK_DRIVER) {
3772 		jack_client_start();
3773 	}
3774 #endif /* HAVE_JACK */
3775 
3776 	/* set timeout function */
3777 	timeout_tag = aqualung_timeout_add(TIMEOUT_PERIOD, timeout_callback, NULL);
3778 
3779 	/* re-apply skin to override possible WM theme */
3780 	if (!options.disable_skin_support_settings) {
3781 		apply_skin(options.skin);
3782 	}
3783 }
3784 
3785 
3786 void
adjust_remote_volume(char * str)3787 adjust_remote_volume(char * str) {
3788 
3789 	char * endptr = NULL;
3790 	int val = gtk_adjustment_get_value(GTK_ADJUSTMENT(adj_vol));
3791 
3792 	switch (str[0]) {
3793 	case 'm':
3794 	case 'M':
3795 		val = -41;
3796 		break;
3797 	case '=':
3798 		val = strtol(str + 1, &endptr, 10);
3799 		if (endptr[0] != '\0') {
3800 			fprintf(stderr, "Cannot convert to integer value: %s\n", str + 1);
3801 			return;
3802 		}
3803 		break;
3804 	default:
3805 		val += strtol(str, &endptr, 10);
3806 		if (endptr[0] != '\0') {
3807 			fprintf(stderr, "Cannot convert to integer value: %s\n", str);
3808 			return;
3809 		}
3810 		break;
3811 	}
3812 
3813 	gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_vol), val);
3814 }
3815 
3816 
3817 void
process_metablock(metadata_t * meta)3818 process_metablock(metadata_t * meta) {
3819 
3820 	char buf[MAXLEN];
3821 	char tmp[MAXLEN];
3822 	playlist_t * pl;
3823 	file_decoder_t * fdec = (file_decoder_t *)meta->fdec;
3824 	char * artist = NULL;
3825 	char * album = NULL;
3826 	char * title = NULL;
3827 	char * icy_name = NULL;
3828 	char * icy_descr = NULL;
3829 	meta_frame_t * frame;
3830 
3831 	frame = metadata_get_frame_by_type(meta, META_FIELD_APIC, NULL);
3832 	if (frame != NULL) {
3833 		if (embedded_picture != NULL) {
3834 			free(embedded_picture);
3835 		}
3836 		embedded_picture_size = frame->length;
3837 		embedded_picture = malloc(embedded_picture_size);
3838 		if (embedded_picture == NULL) {
3839 			embedded_picture_size = 0;
3840 		} else {
3841 			memcpy(embedded_picture, frame->data, embedded_picture_size);
3842 		}
3843 	} else {
3844 		if (embedded_picture != NULL) {
3845 			free(embedded_picture);
3846 			embedded_picture = NULL;
3847 		}
3848 		embedded_picture_size = 0;
3849 	}
3850 
3851 	if ((!httpc_is_url(fdec->filename)) && !options.use_ext_title_format) {
3852 		return;
3853 	}
3854 
3855 	buf[0] = '\0';
3856 	tmp[0] = '\0';
3857 
3858 	// Abuse artist variable
3859 	if ((artist = application_title_format(fdec)) != NULL) {
3860 		strncpy(buf, artist, MAXLEN-1);
3861 		free(artist);
3862 		artist = NULL;
3863 	}
3864 
3865 	if (buf[0] == '\0') {
3866 		metadata_get_artist(meta, &artist);
3867 		metadata_get_album(meta, &album);
3868 		metadata_get_title(meta, &title);
3869 		metadata_get_icy_name(meta, &icy_name);
3870 
3871 		if ((artist && !is_all_wspace(artist)) ||
3872 		    (album && !is_all_wspace(album)) ||
3873 		    (title && !is_all_wspace(title))) {
3874 			make_title_string(tmp, options.title_format, artist, album, title);
3875 			if (icy_name != NULL) {
3876 				snprintf(buf, MAXLEN-1, "%s (%s)", tmp, icy_name);
3877 			}
3878 		} else if (icy_name != NULL) {
3879 			strncpy(buf, icy_name, MAXLEN-1);
3880 		}
3881 	}
3882 
3883 	if (buf[0] != '\0') {
3884 		set_title_label(buf);
3885 	} else {
3886 		set_title_label(fdec->filename);
3887 	}
3888 
3889 	if (icy_name == NULL) {
3890 		return;
3891 	}
3892 
3893 	buf[0] = '\0';
3894 
3895 	metadata_get_icy_descr(meta, &icy_descr);
3896 
3897 	if (icy_descr != NULL) {
3898 		snprintf(buf, MAXLEN-1, "%s (%s)", icy_name, icy_descr);
3899 	} else {
3900 		strncpy(buf, icy_name, MAXLEN-1);
3901 	}
3902 
3903 	/* set playlist_str for playlist entry */
3904 	if ((pl = playlist_get_playing()) != NULL) {
3905 		GtkTreePath * p = playlist_get_playing_path(pl);
3906 		if (p != NULL) {
3907 			GtkTreeIter iter;
3908 			playlist_data_t * data;
3909 
3910 			gtk_tree_model_get_iter(GTK_TREE_MODEL(pl->store), &iter, p);
3911 			gtk_tree_model_get(GTK_TREE_MODEL(pl->store), &iter, PL_COL_DATA, &data, -1);
3912 
3913 			free_strdup(&data->title, buf);
3914 			gtk_tree_store_set(pl->store, &iter, PL_COL_NAME, buf, -1);
3915 
3916 			gtk_tree_path_free(p);
3917 		}
3918 	}
3919 }
3920 
3921 void
flush_rb_disk2gui(void)3922 flush_rb_disk2gui(void) {
3923 
3924 	char recv_cmd;
3925 
3926 	while (rb_read_space(rb_disk2gui)) {
3927 		rb_read(rb_disk2gui, &recv_cmd, 1);
3928 	}
3929 }
3930 
3931 gint
timeout_callback(gpointer data)3932 timeout_callback(gpointer data) {
3933 
3934 	char cmd;
3935 	cue_t cue;
3936 	static double left_gain_shadow;
3937 	static double right_gain_shadow;
3938 	char rcmd;
3939 	static char cmdbuf[MAXLEN];
3940 	int rcv_count;
3941 	static GSList * file_list = NULL;
3942 #ifdef HAVE_JACK
3943 	static int jack_popup_beenthere = 0;
3944 #endif /* HAVE_JACK */
3945 	metadata_t * meta;
3946 
3947 
3948 	while (rb_read_space(rb_disk2gui)) {
3949 		rb_read(rb_disk2gui, &recv_cmd, 1);
3950 		switch (recv_cmd) {
3951 
3952 		case CMD_FILEREQ:
3953 			cmd = CMD_CUE;
3954 			cue.filename = NULL;
3955 			cue.voladj = 0.0f;
3956 
3957 			if (!is_file_loaded)
3958 				break; /* ignore leftover filereq message */
3959 
3960 			decide_next_track(&cue);
3961 
3962 			if (cue.filename != NULL) {
3963 				rb_write(rb_gui2disk, &cmd, sizeof(char));
3964 				rb_write(rb_gui2disk, (void *)&cue, sizeof(cue_t));
3965 			} else {
3966 				send_cmd = CMD_STOPWOFL;
3967 				rb_write(rb_gui2disk, &send_cmd, sizeof(char));
3968 			}
3969 
3970 			try_waking_disk_thread();
3971 			break;
3972 
3973 		case CMD_FILEINFO:
3974 			while (rb_read_space(rb_disk2gui) < sizeof(fileinfo_t))
3975 				;
3976 			if (fileinfo.format_str != NULL) { /* free previous format_str, if there is one */
3977 				free(fileinfo.format_str);
3978 				fileinfo.format_str = NULL;
3979 			}
3980 			rb_read(rb_disk2gui, (char *)&fileinfo, sizeof(fileinfo_t));
3981 
3982 			sample_pos = 0;
3983 			total_samples = fileinfo.total_samples;
3984 			status.samples_left = fileinfo.total_samples;
3985 			status.sample_pos = 0;
3986 			status.sample_offset = 0;
3987 			fresh_new_file = fresh_new_file_prev = 0;
3988 			run_hooks_fdec("track_change", fdec);
3989 			break;
3990 
3991 		case CMD_STATUS:
3992 			while (rb_read_space(rb_disk2gui) < sizeof(status_t))
3993 				;
3994 			rb_read(rb_disk2gui, (char *)&status, sizeof(status_t));
3995 
3996 			sample_pos = total_samples - status.samples_left;
3997 #ifdef HAVE_LOOP
3998 			if (options.repeat_on &&
3999 			    (sample_pos < total_samples * options.loop_range_start ||
4000 			     sample_pos > total_samples * options.loop_range_end)) {
4001 
4002 				seek_t seek;
4003 
4004 				send_cmd = CMD_SEEKTO;
4005 				seek.seek_to_pos = options.loop_range_start * total_samples;
4006 				rb_write(rb_gui2disk, &send_cmd, 1);
4007 				rb_write(rb_gui2disk, (char *)&seek, sizeof(seek_t));
4008 				try_waking_disk_thread();
4009 				refresh_scale_suppress = 2;
4010 			}
4011 #endif /* HAVE_LOOP */
4012 
4013 			if ((is_file_loaded) && (status.samples_left < 2*status.sample_offset)) {
4014 				allow_seeks = 0;
4015 			} else {
4016 				allow_seeks = 1;
4017 			}
4018 
4019 			/* treat files with unknown length */
4020 			if (total_samples == 0) {
4021 				allow_seeks = 1;
4022 				sample_pos = status.sample_pos - status.sample_offset;
4023 			}
4024 
4025 			if ((!fresh_new_file) && (sample_pos > status.sample_offset)) {
4026 				fresh_new_file = 1;
4027 			}
4028 
4029 			if (fresh_new_file && !fresh_new_file_prev) {
4030 				disp_info = fileinfo;
4031 				disp_samples = total_samples;
4032 				if (sample_pos > status.sample_offset) {
4033 					disp_pos = sample_pos - status.sample_offset;
4034 				} else {
4035 					disp_pos = 0;
4036 				}
4037 				refresh_displays();
4038 			} else {
4039 				if (sample_pos > status.sample_offset) {
4040 					disp_pos = sample_pos - status.sample_offset;
4041 				} else {
4042 					disp_pos = 0;
4043 				}
4044 
4045 				if (disp_info.sample_rate != status.sample_rate) {
4046 					disp_info.sample_rate = status.sample_rate;
4047 					refresh_displays();
4048 				}
4049 
4050 				if (is_file_loaded) {
4051 					refresh_time_displays();
4052 				}
4053 			}
4054 
4055 			fresh_new_file_prev = fresh_new_file;
4056 
4057 			if (refresh_scale && !refresh_scale_suppress) {
4058 				if (total_samples == 0) {
4059 					gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_pos), 0.0f);
4060 				} else {
4061 					gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_pos),
4062 								 100.0 * sample_pos / total_samples);
4063 					run_hooks("track_position_change");
4064 				}
4065 			}
4066 
4067 			if (refresh_scale_suppress > 0) {
4068 				--refresh_scale_suppress;
4069 			}
4070 
4071                         show_scale_pos(!total_samples ? FALSE : TRUE);
4072 			break;
4073 
4074 		case CMD_METABLOCK:
4075 			while (rb_read_space(rb_disk2gui) < sizeof(metadata_t *))
4076 				;
4077 			rb_read(rb_disk2gui, (char *)&meta, sizeof(metadata_t *));
4078 
4079 			process_metablock(meta);
4080 			break;
4081 
4082 		default:
4083 			fprintf(stderr, "gui: unexpected command %d recv'd from disk\n", recv_cmd);
4084 			break;
4085 		}
4086 	}
4087         /* update volume & balance if necessary */
4088 	if ((options.vol != vol_prev) || (options.bal != bal_prev)) {
4089 		vol_prev = options.vol;
4090 		vol_lin = (options.vol < -40.5f) ? 0 : db2lin(options.vol);
4091 		bal_prev = options.bal;
4092 		if (options.bal >= 0.0f) {
4093 			left_gain_shadow = vol_lin * db2lin(-0.4f * options.bal);
4094 			right_gain_shadow = vol_lin;
4095 		} else {
4096 			left_gain_shadow = vol_lin;
4097 			right_gain_shadow = vol_lin * db2lin(0.4f * options.bal);
4098 		}
4099 			left_gain = left_gain_shadow;
4100 			right_gain = right_gain_shadow;
4101 	}
4102 
4103 	/* receive and execute remote commands, if any */
4104 	rcv_count = 0;
4105 	while (((rcmd = receive_message(aqualung_socket_fd, cmdbuf)) != 0) && (rcv_count < MAX_RCV_COUNT)) {
4106 		switch (rcmd) {
4107 		case RCMD_BACK:
4108 			prev_event(NULL, NULL, NULL);
4109 			break;
4110 		case RCMD_PAUSE:
4111 			if (!options.combine_play_pause) {
4112 				gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pause_button),
4113 				        !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pause_button)));
4114 				break;
4115 			}
4116 		case RCMD_PLAY:
4117 			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(play_button),
4118 			     !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(play_button)));
4119 			break;
4120 		case RCMD_STOP:
4121 			stop_event(NULL, NULL, NULL);
4122 			break;
4123 		case RCMD_FWD:
4124 			next_event(NULL, NULL, NULL);
4125 			break;
4126 		case RCMD_ADD_FILE:
4127 			file_list = g_slist_append(file_list, strdup(cmdbuf));
4128 			break;
4129 		case RCMD_ADD_COMMIT:
4130 			process_filenames(file_list, cmdbuf[0], cmdbuf[1], cmdbuf[2], cmdbuf+3);
4131 			file_list = NULL;
4132 			break;
4133 		case RCMD_CUSTOM:
4134 			run_custom_remote_command(cmdbuf);
4135 			break;
4136 		case RCMD_VOLADJ:
4137 			adjust_remote_volume(cmdbuf);
4138 			break;
4139 		case RCMD_QUIT:
4140 			main_window_closing();
4141 			break;
4142 		default:
4143 			fprintf(stderr, "Unrecognized remote command received: %i\n", (int)rcmd);
4144 		}
4145 		++rcv_count;
4146 	}
4147 
4148 	/* check for JACK shutdown condition */
4149 #ifdef HAVE_JACK
4150 	if (output == JACK_DRIVER) {
4151 		if (jack_is_shutdown) {
4152 			if (is_file_loaded) {
4153 				stop_event(NULL, NULL, NULL);
4154 			}
4155 			if (!jack_popup_beenthere) {
4156 				jack_shutdown_window();
4157 #ifdef HAVE_JACK_MGMT
4158 				if (ports_window) {
4159 					ports_clicked_close(NULL, NULL);
4160 				}
4161 				gtk_widget_set_sensitive(conf__jack, FALSE);
4162 #endif /* HAVE_JACK_MGMT */
4163 				jack_client_close(jack_client);
4164 				jack_popup_beenthere = 1;
4165 			}
4166 		}
4167 	}
4168 #endif /* HAVE_JACK */
4169 
4170 	return TRUE;
4171 }
4172 
4173 
4174 void
run_gui(void)4175 run_gui(void) {
4176 
4177 	gtk_main();
4178 	gdk_threads_leave();
4179 
4180 	return;
4181 }
4182 
4183 
4184 void
set_buttons_relief(void)4185 set_buttons_relief(void) {
4186 
4187 	GtkWidget *rbuttons_table[] = {
4188 		prev_button, stop_button, next_button, play_button,
4189 		pause_button, repeat_button, repeat_all_button, shuffle_button,
4190 #ifdef HAVE_LADSPA
4191 		plugin_toggle,
4192 #endif /* HAVE_LADSPA */
4193 		playlist_toggle, musicstore_toggle
4194 	};
4195 
4196 	gint i, n;
4197         i = sizeof(rbuttons_table)/sizeof(GtkWidget*);
4198 
4199         for (n = 0; n < i; n++) {
4200 		if ((rbuttons_table[n] != pause_button) || !options.combine_play_pause) {
4201 			gtk_button_set_relief(GTK_BUTTON(rbuttons_table[n]),
4202 				(options.disable_buttons_relief) ? GTK_RELIEF_NONE : GTK_RELIEF_NORMAL);
4203 		}
4204 	}
4205 }
4206 
4207 // vim: shiftwidth=8:tabstop=8:softtabstop=8 :
4208 
4209