1 /*
2  * alarm-settings.c -- Alarm settings dialog
3  *
4  * Copyright (C) 2007-2008 Johannes H. Jensen <joh@pseudoberries.com>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  *
20  * Authors:
21  * 		Johannes H. Jensen <joh@pseudoberries.com>
22  */
23 
24 #include "alarm-settings.h"
25 #include "alarm-applet.h"
26 #include "alarm.h"
27 #include "player.h"
28 
29 #include <glib.h>
30 #include <glib-object.h>
31 #include <gtk/gtk.h>
32 
33 
34 
35 /*
36  * GUI callbacks
37  */
38 
39 void
40 alarm_settings_changed_type (GtkToggleButton *toggle, gpointer data);
41 
42 void
43 alarm_settings_changed_label (GtkEditable *editable, gpointer data);
44 
45 void
46 alarm_settings_changed_time (GtkSpinButton *spinbutton, gpointer data);
47 
48 void
49 alarm_settings_changed_repeat (GtkToggleButton *togglebutton, gpointer data);
50 
51 void
52 alarm_settings_changed_notify_type (GtkToggleButton *togglebutton, gpointer data);
53 
54 void
55 alarm_settings_changed_sound (GtkComboBox *combo, gpointer data);
56 
57 void
58 alarm_settings_changed_sound_repeat (GtkToggleButton *togglebutton, gpointer data);
59 
60 void
61 alarm_settings_changed_app (GtkComboBox *combo, gpointer data);
62 
63 void
64 alarm_settings_changed_command (GtkEditable *editable, gpointer data);
65 
66 
67 
68 static void
69 alarm_settings_update_time (AlarmSettingsDialog *dialog);
70 
71 void
72 alarm_settings_changed_sound (GtkComboBox *combo, gpointer data);
73 
74 void
75 alarm_settings_changed_app (GtkComboBox *combo, gpointer data);
76 
77 
78 
79 #define REPEAT_LABEL	_("_Repeat: %s")
80 
81 
82 
83 /*
84  * Utility functions for updating various parts of the settings dialog.
85  */
86 
87 static void
alarm_settings_update_type(AlarmSettingsDialog * dialog)88 alarm_settings_update_type (AlarmSettingsDialog *dialog)
89 {
90 
91     AlarmType type = dialog->alarm->type;
92     gboolean clock_toggled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->clock_toggle));
93     gboolean timer_toggled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->timer_toggle));
94 
95     if ((type == ALARM_TYPE_CLOCK && clock_toggled) ||
96     	(type == ALARM_TYPE_TIMER && timer_toggled)) {
97     	// No change
98     	return;
99     }
100 
101     g_debug ("AlarmSettingsDialog: update_type()");
102 
103     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->clock_toggle),
104 		type == ALARM_TYPE_CLOCK);
105 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->timer_toggle),
106 		type == ALARM_TYPE_TIMER);
107 
108 	if (type == ALARM_TYPE_CLOCK) {
109 		gtk_widget_set_sensitive(dialog->repeat_expand, TRUE);
110 	} else {
111 		gtk_widget_set_sensitive(dialog->repeat_expand, FALSE);
112 	}
113 }
114 
115 static void
alarm_settings_update_label(AlarmSettingsDialog * dialog)116 alarm_settings_update_label (AlarmSettingsDialog *dialog)
117 {
118 	const gchar *entry_text = gtk_entry_get_text (GTK_ENTRY (dialog->label_entry));
119     if (g_strcmp0 (entry_text, dialog->alarm->message) == 0) {
120     	// No change
121     	return;
122     }
123 
124     g_debug ("AlarmSettingsDialog: update_label()");
125 
126     g_object_set (dialog->label_entry, "text", dialog->alarm->message, NULL);
127 }
128 
129 static void
alarm_settings_update_time(AlarmSettingsDialog * dialog)130 alarm_settings_update_time (AlarmSettingsDialog *dialog)
131 {
132 	struct tm *tm = alarm_get_time(dialog->alarm);
133 	gint hour = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->hour_spin));
134 	gint min = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->min_spin));
135 	gint sec = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->sec_spin));
136 
137 	if (tm->tm_hour == hour && tm->tm_min == min && tm->tm_sec == sec) {
138 		// No change
139 		return;
140 	}
141 
142     g_debug ("AlarmSettingsDialog: update_time() to %d:%d:%d", tm->tm_hour, tm->tm_min, tm->tm_sec);
143 
144 	gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->hour_spin), tm->tm_hour);
145 	gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->min_spin), tm->tm_min);
146 	gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->sec_spin), tm->tm_sec);
147 }
148 
149 static void
alarm_settings_update_repeat(AlarmSettingsDialog * dialog)150 alarm_settings_update_repeat (AlarmSettingsDialog *dialog)
151 {
152 	AlarmRepeat r;
153 	gint i;
154 	gboolean check;
155 	gchar *label, *rep;
156 
157     g_debug ("AlarmSettingsDialog: update_repeat()");
158 
159 	/*
160 	 * Update check boxes
161 	 */
162 	for (r = ALARM_REPEAT_SUN, i = 0; r <= ALARM_REPEAT_SAT; r = 1 << ++i) {
163 		check = (dialog->alarm->repeat & r) != 0;
164 
165 		// Activate the appropriate widget
166 		if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (dialog->repeat_check[i])) != check) {
167 			g_object_set (dialog->repeat_check[i], "active", check, NULL);
168 		}
169 	}
170 
171 
172     /*
173      * Update fancy expander label
174      */
175     rep = alarm_repeat_to_pretty (dialog->alarm->repeat);
176     label = g_strdup_printf (REPEAT_LABEL, rep);
177     g_object_set (dialog->repeat_label, "label", label, NULL);
178     g_free (label);
179     g_free (rep);
180 }
181 
182 static void
alarm_settings_update_notify_type(AlarmSettingsDialog * dialog)183 alarm_settings_update_notify_type (AlarmSettingsDialog *dialog)
184 {
185     AlarmNotifyType type = dialog->alarm->notify_type;
186 
187     gboolean sound_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->notify_app_radio));
188     gboolean sound_sensitive = gtk_widget_is_sensitive (dialog->notify_sound_box);
189     gboolean app_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->notify_app_radio));
190     gboolean app_sensitive = gtk_widget_is_sensitive (dialog->notify_app_box);
191 
192     if ((type == ALARM_NOTIFY_SOUND && sound_active && sound_sensitive && !app_sensitive) ||
193     	(type == ALARM_NOTIFY_COMMAND && app_active && !sound_sensitive && app_sensitive)) {
194     	// No change
195     	return;
196     }
197 
198     g_debug ("AlarmSettingsDialog: update_notify_type()");
199 
200 	// Enable selected
201 	switch (dialog->alarm->notify_type) {
202         case ALARM_NOTIFY_COMMAND:
203             g_object_set (dialog->notify_app_radio, "active", TRUE, NULL);
204             g_object_set (dialog->notify_app_box, "sensitive", TRUE, NULL);
205 
206             // Disable others
207             g_object_set (dialog->notify_sound_box, "sensitive", FALSE, NULL);
208 
209             if (dialog->player && dialog->player->state == MEDIA_PLAYER_PLAYING) {
210                 // Stop preview player
211                 media_player_stop (dialog->player);
212             }
213 
214             break;
215         default:
216             // NOTIFY_SOUND
217             g_object_set (dialog->notify_sound_radio, "active", TRUE, NULL);
218             g_object_set (dialog->notify_sound_box, "sensitive", TRUE, NULL);
219 
220             // Disable others
221             g_object_set (dialog->notify_app_box, "sensitive", FALSE, NULL);
222             break;
223     }
224 }
225 
226 static void
alarm_settings_update_sound(AlarmSettingsDialog * dialog)227 alarm_settings_update_sound (AlarmSettingsDialog *dialog)
228 {
229 	AlarmListEntry *item;
230 	GList *l;
231 	gint pos;
232 
233 	pos = gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->notify_sound_combo));
234 	item = g_list_nth_data (dialog->applet->sounds, pos);
235 
236 	if (item && g_strcmp0 (item->data, dialog->alarm->sound_file) == 0) {
237 		// No change
238 		return;
239 	}
240 
241     g_debug ("AlarmSettingsDialog: update_sound()");
242 
243 	/* Fill sounds list */
244 	fill_combo_box (GTK_COMBO_BOX (dialog->notify_sound_combo),
245 					dialog->applet->sounds, _("Select sound file..."));
246 
247 	// Look for the selected sound file
248 	for (l = dialog->applet->sounds, pos = 0; l != NULL; l = l->next, pos++) {
249 		item = (AlarmListEntry *)l->data;
250 		if (strcmp (item->data, dialog->alarm->sound_file) == 0) {
251 			// Match!
252 			gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->notify_sound_combo), pos);
253 			break;
254 		}
255 	}
256 }
257 
258 static void
alarm_settings_update_sound_repeat(AlarmSettingsDialog * dialog)259 alarm_settings_update_sound_repeat (AlarmSettingsDialog *dialog)
260 {
261 	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->notify_sound_loop_check)) == dialog->alarm->sound_loop) {
262 		// No change
263 		return;
264 	}
265 
266     g_debug ("AlarmSettingsDialog: update_sound_repeat()");
267 
268 	g_object_set (dialog->notify_sound_loop_check,
269         "active", dialog->alarm->sound_loop, NULL);
270 }
271 
272 static void
alarm_settings_update_app(AlarmSettingsDialog * dialog)273 alarm_settings_update_app (AlarmSettingsDialog *dialog)
274 {
275 	AlarmListEntry *item;
276 	GList *l;
277 	guint pos, len;
278 	gboolean custom = FALSE;
279 
280 	pos = gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->notify_app_combo));
281 	item = g_list_nth_data (dialog->applet->apps, pos);
282 
283 	if (item && g_strcmp0 (item->data, dialog->alarm->command) == 0) {
284 		// No change
285 		return;
286 	}
287 
288     g_debug ("AlarmSettingsDialog: update_app()");
289 
290 //	g_debug ("alarm_settings_update_app (%p): app_combo: %p, applet: %p, apps: %p", dialog, dialog->notify_app_combo, dialog->applet, dialog->applet->apps);
291 //	g_debug ("alarm_settings_update_app setting entry to %s", dialog->alarm->command);
292 
293 	/* Fill apps list */
294 	fill_combo_box (GTK_COMBO_BOX (dialog->notify_app_combo),
295 					dialog->applet->apps, _("Custom command..."));
296 
297 	// Look for the selected command
298 	len = g_list_length (dialog->applet->apps);
299 	for (l = dialog->applet->apps, pos = 0; l != NULL; l = l->next, pos++) {
300 		item = (AlarmListEntry *)l->data;
301 		if (strcmp (item->data, dialog->alarm->command) == 0) {
302 			// Match!
303 			break;
304 		}
305 	}
306 
307 	/* Only change sensitivity of the command entry if user
308 	 * isn't typing a custom command there already. */
309 	if (pos >= len) {
310 		// Custom command
311 		pos += 1;
312 		custom = TRUE;
313 	}
314 
315 	g_debug ("CMD ENTRY HAS FOCUS? %d", GTK_WIDGET_HAS_FOCUS (dialog->notify_app_command_entry));
316 
317 	if (!GTK_WIDGET_HAS_FOCUS (dialog->notify_app_command_entry))
318 		g_object_set (dialog->notify_app_command_entry, "sensitive", custom, NULL);
319 
320 	gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->notify_app_combo), pos);
321 }
322 
323 static void
alarm_settings_update_app_command(AlarmSettingsDialog * dialog)324 alarm_settings_update_app_command (AlarmSettingsDialog *dialog)
325 {
326     g_debug ("AlarmSettingsDialog: update_app_command()");
327 
328     if (g_strcmp0 (dialog->alarm->command, gtk_entry_get_text (GTK_ENTRY (dialog->notify_app_command_entry))) == 0) {
329     	// No change
330     	return;
331     }
332 
333     g_object_set (dialog->notify_app_command_entry, "text", dialog->alarm->command, NULL);
334 }
335 
336 static void
alarm_settings_update(AlarmSettingsDialog * dialog)337 alarm_settings_update (AlarmSettingsDialog *dialog)
338 {
339 	alarm_settings_update_type (dialog);
340     alarm_settings_update_label (dialog);
341 	alarm_settings_update_time (dialog);
342 	alarm_settings_update_repeat (dialog);
343 	alarm_settings_update_notify_type (dialog);
344 	alarm_settings_update_sound (dialog);
345     alarm_settings_update_sound_repeat (dialog);
346 	alarm_settings_update_app (dialog);
347     alarm_settings_update_app_command (dialog);
348 }
349 
350 
351 
352 
353 
354 
355 /*
356  * Alarm object callbacks
357  */
358 
359 static void
alarm_changed(GObject * object,GParamSpec * param,gpointer data)360 alarm_changed (GObject *object,
361                GParamSpec *param,
362                gpointer data)
363 {
364     AlarmSettingsDialog *dialog = (AlarmSettingsDialog *)data;
365 
366     const gchar *name = param->name;
367 
368     g_debug("AlarmSettingsDialog: alarm_changed: %s", name);
369 
370 //    alarm_settings_update (dialog);
371 //    return;
372 
373     if (g_strcmp0 (name, "type") == 0) {
374         alarm_settings_update_type (dialog);
375     }
376 
377     if (g_strcmp0 (name, "message") == 0) {
378         alarm_settings_update_label (dialog);
379     }
380 
381     if (g_strcmp0 (name, "time") == 0) {
382         alarm_settings_update_time (dialog);
383     }
384 
385     if (g_strcmp0 (name, "repeat") == 0) {
386         alarm_settings_update_repeat (dialog);
387     }
388 
389     if (g_strcmp0 (name, "notify-type") == 0) {
390         alarm_settings_update_notify_type (dialog);
391     }
392 
393     if (g_strcmp0 (name, "sound-file") == 0) {
394 	    alarm_settings_update_sound (dialog);
395     }
396 
397     if (g_strcmp0 (name, "sound-repeat") == 0) {
398        	g_object_set (dialog->notify_sound_loop_check, "active", dialog->alarm->sound_loop, NULL);
399     }
400 
401     if (g_strcmp0 (name, "command") == 0) {
402 	    alarm_settings_update_app (dialog);
403 	    alarm_settings_update_app_command (dialog);
404     }
405 /*
406     if (g_strcmp0 (name, "") == 0) {
407 
408     }
409 
410     if (g_strcmp0 (name, "") == 0) {
411 
412     }
413     */
414 }
415 
416 /*
417  * GUI utils
418  */
419 
420 static void
open_sound_file_chooser(AlarmSettingsDialog * dialog)421 open_sound_file_chooser (AlarmSettingsDialog *dialog)
422 {
423 	GtkWidget *chooser;
424 
425 	chooser = gtk_file_chooser_dialog_new (_("Select sound file..."),
426 										   GTK_WINDOW (dialog->dialog),
427 										   GTK_FILE_CHOOSER_ACTION_OPEN,
428 										   GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
429 										   GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
430 										   NULL);
431 
432 	gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (chooser), dialog->alarm->sound_file);
433 
434 	if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT) {
435 		gchar *uri;
436 
437 		uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (chooser));
438 
439 		g_debug ("RESPONSE ACCEPT: %s", uri);
440 
441 		g_object_set (dialog->alarm, "sound_file", uri, NULL);
442 
443 		g_free (uri);
444 	} else {
445 		g_debug ("RESPONSE CANCEL");
446 		alarm_settings_update_sound (dialog);
447 	}
448 
449 	gtk_widget_destroy (chooser);
450 }
451 
452 
453 
454 /*
455  * GUI callbacks
456  */
457 
458 void
alarm_settings_changed_type(GtkToggleButton * toggle,gpointer data)459 alarm_settings_changed_type (GtkToggleButton *toggle, gpointer data)
460 {
461     AlarmApplet *applet = (AlarmApplet *)data;
462     AlarmSettingsDialog *dialog = applet->settings_dialog;
463     gboolean toggled = gtk_toggle_button_get_active(toggle);
464 
465     g_assert (dialog->alarm != NULL);
466     g_debug ("alarm_settings_changed_type(%s) -> %s",
467              gtk_buildable_get_name (GTK_BUILDABLE (toggle)),
468              toggled ? "TRUE" : "FALSE");
469 
470     if (GTK_WIDGET (toggle) == dialog->clock_toggle) {
471         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->timer_toggle), !toggled);
472         if (toggled) {
473             g_debug ("alarm_settings_changed_type: clock toggled");
474             g_object_set (dialog->alarm, "type", ALARM_TYPE_CLOCK, NULL);
475             gtk_widget_set_sensitive(dialog->repeat_expand, TRUE);
476         }
477     } else {
478         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->clock_toggle), !toggled);
479         if (toggled) {
480             g_debug ("alarm_settings_changed_type: timer toggled");
481             g_object_set (dialog->alarm, "type", ALARM_TYPE_TIMER, NULL);
482             gtk_widget_set_sensitive(dialog->repeat_expand, FALSE);
483         }
484     }
485 }
486 
487 void
alarm_settings_changed_label(GtkEditable * editable,gpointer data)488 alarm_settings_changed_label (GtkEditable *editable,
489                               gpointer     data)
490 {
491     AlarmApplet *applet = (AlarmApplet *)data;
492 	AlarmSettingsDialog *dialog = applet->settings_dialog;
493     const gchar *text;
494 
495     g_assert (dialog->alarm != NULL);
496 
497     text = gtk_entry_get_text (GTK_ENTRY (editable));
498 
499     g_debug ("label_changed: %s", text);
500 
501     g_object_set (dialog->alarm, "message", text, NULL);
502 }
503 
504 void
alarm_settings_changed_time(GtkSpinButton * spinbutton,gpointer data)505 alarm_settings_changed_time (GtkSpinButton *spinbutton, gpointer data)
506 {
507     AlarmApplet *applet = (AlarmApplet *)data;
508 	AlarmSettingsDialog *dialog = applet->settings_dialog;
509 	guint hour, min, sec;
510 	struct tm *tm;
511 
512     g_assert (dialog->alarm != NULL);
513 
514     tm = alarm_get_time(dialog->alarm);
515     hour = tm->tm_hour;
516     min = tm->tm_min;
517     sec = tm->tm_sec;
518 
519     // Check which spin button emitted the signal
520     if (GTK_WIDGET (spinbutton) == dialog->hour_spin) {
521 		hour = gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->hour_spin));
522     } else if (GTK_WIDGET (spinbutton) == dialog->min_spin) {
523     	min = gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->min_spin));
524     } else if (GTK_WIDGET (spinbutton) == dialog->sec_spin) {
525     	sec = gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->sec_spin));
526     }
527 
528 	alarm_set_time (dialog->alarm, hour, min, sec);
529 }
530 
531 /**
532  * Use 2-digits in time spin buttons
533  */
534 gboolean
alarm_settings_output_time(GtkSpinButton * spin,gpointer data)535 alarm_settings_output_time (GtkSpinButton *spin, gpointer data)
536 {
537     GtkAdjustment *adj;
538     gchar *text;
539     gint value;
540     adj = gtk_spin_button_get_adjustment (spin);
541     value = (gint)gtk_adjustment_get_value (adj);
542     text = g_strdup_printf ("%02d", value);
543     gtk_entry_set_text (GTK_ENTRY (spin), text);
544     g_free (text);
545 
546     return TRUE;
547 }
548 
549 void
alarm_settings_changed_repeat(GtkToggleButton * togglebutton,gpointer data)550 alarm_settings_changed_repeat (GtkToggleButton *togglebutton, gpointer data)
551 {
552 	AlarmApplet *applet = (AlarmApplet *)data;
553 	AlarmSettingsDialog *dialog = applet->settings_dialog;
554 
555     g_assert (dialog->alarm != NULL);
556 
557 	const gchar *name;
558 	AlarmRepeat rep, new_rep;
559 	gboolean active;
560 
561 	/* The check buttons have the same name as the 3 letter
562 	 * string representation of the day.
563 	 */
564 	name   = gtk_buildable_get_name (GTK_BUILDABLE (togglebutton));
565 	rep    = alarm_repeat_from_string (name);
566 	active = gtk_toggle_button_get_active (togglebutton);
567 
568 	g_debug("Changed repeat on: %s, active: %d", name, active);
569 
570 	if (active)
571 		// Add rep
572 		new_rep = dialog->alarm->repeat | rep;
573 	else
574 		// Remove rep
575 		new_rep = dialog->alarm->repeat & ~rep;
576 
577 	g_object_set (dialog->alarm, "repeat", new_rep, NULL);
578 }
579 
580 void
alarm_settings_changed_notify_type(GtkToggleButton * togglebutton,gpointer data)581 alarm_settings_changed_notify_type (GtkToggleButton *togglebutton, gpointer data)
582 {
583     AlarmApplet *applet = (AlarmApplet *)data;
584 	AlarmSettingsDialog *dialog = applet->settings_dialog;
585 
586 	const gchar *name = gtk_buildable_get_name (GTK_BUILDABLE (togglebutton));;
587 	gboolean value    = gtk_toggle_button_get_active (togglebutton);
588 
589 	if (!value) {
590 		// Not checked, not interested
591 		return;
592 	}
593 
594     g_assert (dialog->alarm != NULL);
595 
596 	g_debug ("notify_type_changed: %s", name);
597 
598 	if (strcmp (name, "app-radio") == 0) {
599 		g_object_set (dialog->alarm, "notify_type", ALARM_NOTIFY_COMMAND, NULL);
600 	} else {
601 		g_object_set (dialog->alarm, "notify_type", ALARM_NOTIFY_SOUND, NULL);
602 	}
603 
604 	alarm_settings_update_notify_type (dialog);
605 }
606 
607 void
alarm_settings_changed_sound(GtkComboBox * combo,gpointer data)608 alarm_settings_changed_sound (GtkComboBox *combo, gpointer data)
609 {
610     AlarmApplet *applet = (AlarmApplet *)data;
611 	AlarmSettingsDialog *dialog = applet->settings_dialog;
612 
613 	g_debug ("SOUND Combo_changed");
614 
615     g_assert (dialog->alarm != NULL);
616 
617 	AlarmListEntry *item;
618 	guint current_index, len;
619 
620 	current_index = gtk_combo_box_get_active (combo);
621 	len = g_list_length (dialog->applet->sounds);
622 
623 	g_debug ("Current index: %d, n sounds: %d", current_index, len);
624 
625 	if (current_index < 0)
626 		// None selected
627 		return;
628 
629 	if (current_index >= len) {
630 		// Select sound file
631 		g_debug ("Open SOUND file chooser...");
632 		open_sound_file_chooser (dialog);
633 		return;
634 	}
635 
636 	// Valid file selected, update alarm
637 	item = (AlarmListEntry *) g_list_nth_data (dialog->applet->sounds, current_index);
638 	g_object_set (dialog->alarm, "sound_file", item->data, NULL);
639 }
640 
641 void
alarm_settings_changed_sound_repeat(GtkToggleButton * togglebutton,gpointer data)642 alarm_settings_changed_sound_repeat (GtkToggleButton *togglebutton, gpointer data)
643 {
644     AlarmApplet *applet = (AlarmApplet *)data;
645 	AlarmSettingsDialog *dialog = applet->settings_dialog;
646 
647     g_assert (dialog->alarm != NULL);
648 
649     g_debug("alarm_settings_changed_sound_repeat");
650 
651     g_object_set (dialog->alarm, "sound-repeat", gtk_toggle_button_get_active (togglebutton), NULL);
652 
653     if (dialog->player && dialog->player->state == MEDIA_PLAYER_PLAYING) {
654         // Update preview player
655         dialog->player->loop = gtk_toggle_button_get_active (togglebutton);
656     }
657 }
658 
659 void
alarm_settings_changed_app(GtkComboBox * combo,gpointer data)660 alarm_settings_changed_app (GtkComboBox *combo, gpointer data)
661 {
662     AlarmApplet *applet = (AlarmApplet *)data;
663 	AlarmSettingsDialog *dialog = applet->settings_dialog;
664 
665 	g_debug ("APP Combo_changed");
666 
667     g_assert (dialog->alarm != NULL);
668 
669 	if (GTK_WIDGET_HAS_FOCUS (dialog->notify_app_command_entry)) {
670 		g_debug (" ---- Skipping because command_entry has focus!");
671 		return;
672 	}
673 
674 	AlarmListEntry *item;
675 	guint current_index, len;
676 
677 	current_index = gtk_combo_box_get_active (combo);
678 	len = g_list_length (dialog->applet->apps);
679 
680 	if (current_index < 0)
681 		// None selected
682 		return;
683 
684 	if (current_index >= len) {
685 		// Custom command
686 		g_debug ("CUSTOM command selected...");
687 
688 		g_object_set (dialog->notify_app_command_entry, "sensitive", TRUE, NULL);
689 		gtk_widget_grab_focus (dialog->notify_app_command_entry);
690 		return;
691 	}
692 
693 	g_object_set (dialog->notify_app_command_entry, "sensitive", FALSE, NULL);
694 
695 
696 	item = (AlarmListEntry *) g_list_nth_data (dialog->applet->apps, current_index);
697 	g_object_set (dialog->alarm, "command", item->data, NULL);
698 }
699 
700 void
alarm_settings_changed_command(GtkEditable * editable,gpointer data)701 alarm_settings_changed_command (GtkEditable *editable, gpointer data)
702 {
703     AlarmApplet *applet = (AlarmApplet *)data;
704 	AlarmSettingsDialog *dialog = applet->settings_dialog;
705 
706     g_assert (dialog->alarm != NULL);
707 
708     g_object_set (dialog->alarm, "command", gtk_entry_get_text (GTK_ENTRY (editable)), NULL);
709 }
710 
711 
712 /*
713  * Preview player {{
714  */
715 
716 static void
preview_player_state_cb(MediaPlayer * player,MediaPlayerState state,gpointer data)717 preview_player_state_cb (MediaPlayer *player, MediaPlayerState state, gpointer data)
718 {
719 	AlarmSettingsDialog *dialog = (AlarmSettingsDialog *)data;
720 	const gchar *stock;
721 
722 	if (state == MEDIA_PLAYER_PLAYING) {
723 		stock = "gtk-media-stop";
724 	} else {
725 		stock = "gtk-media-play";
726 
727 		g_debug ("AlarmSettingsDialog: Freeing media player %p", player);
728 
729 		media_player_free (player);
730 		dialog->player = NULL;
731 	}
732 
733 	// Set stock
734 	gtk_button_set_label (GTK_BUTTON (dialog->notify_sound_preview), stock);
735 }
736 
737 void
alarm_settings_sound_preview(GtkButton * button,gpointer data)738 alarm_settings_sound_preview (GtkButton *button, gpointer data)
739 {
740     AlarmApplet *applet = (AlarmApplet *)data;
741 	AlarmSettingsDialog *dialog = applet->settings_dialog;
742 
743 	if (dialog->player && dialog->player->state == MEDIA_PLAYER_PLAYING) {
744 		// Stop preview player
745 		media_player_stop (dialog->player);
746 	} else {
747 		// Start preview player
748 		if (dialog->player == NULL) {
749 			dialog->player = media_player_new (dialog->alarm->sound_file,
750 											   dialog->alarm->sound_loop,
751 											   preview_player_state_cb, dialog,
752 											   media_player_error_cb, dialog->dialog);
753 			if (dialog->player == NULL) {
754 				// Unable to create player
755 				alarm_error_trigger (dialog->alarm, ALARM_ERROR_PLAY,
756 					_("Could not create player! Please check your sound settings."));
757 				return;
758 			}
759 		}
760 
761 		g_debug ("AlarmSettingsDialog: preview_start...");
762 		media_player_start (dialog->player);
763 	}
764 }
765 
766 /*
767  * }} Preview player
768  */
769 
770 
771 /*
772  * Clear settings dialog for reuse
773  *
774  * Stops any running media players
775  * Disassociates the dialog from any alarm
776  */
777 static void
alarm_settings_dialog_clear(AlarmSettingsDialog * dialog)778 alarm_settings_dialog_clear (AlarmSettingsDialog *dialog)
779 {
780     if (dialog->player) {
781 		if (dialog->player->state == MEDIA_PLAYER_STOPPED) {
782 			media_player_free (dialog->player);
783 		} else {
784 			media_player_stop (dialog->player);
785 		}
786 	}
787 
788     if (dialog->alarm) {
789 	    /* Remove alarm notify handlers! */
790         int matched = g_signal_handlers_disconnect_matched (dialog->alarm, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, alarm_changed, NULL);
791 //	    int matched = g_signal_handlers_disconnect_matched (dialog->alarm, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, dialog);
792 
793         g_debug("settings CLEAR alarm %p: %d handlers removed", dialog->alarm, matched);
794 
795         dialog->alarm = NULL;
796 
797         /* Remove signal handlers */
798         //g_signal_handlers_disconnect_by_func
799     }
800 }
801 
802 void
alarm_settings_dialog_close(AlarmSettingsDialog * dialog)803 alarm_settings_dialog_close (AlarmSettingsDialog *dialog)
804 {
805 //	g_hash_table_remove (dialog->applet->edit_alarm_dialogs, dialog->alarm->id);
806 
807 //	gtk_widget_destroy (GTK_WIDGET (dialog->dialog))
808 
809 
810     /* Enable the alarm when closing the dialog */
811     alarm_enable (dialog->alarm);
812 
813     alarm_settings_dialog_clear (dialog);
814 
815     gtk_widget_hide (dialog->dialog);
816 }
817 
818 void
alarm_settings_dialog_response(GtkDialog * dialog,gint rid,gpointer data)819 alarm_settings_dialog_response (GtkDialog *dialog,
820 								gint rid,
821 								gpointer data)
822 {
823     AlarmApplet *applet = (AlarmApplet *)data;
824 	AlarmSettingsDialog *settings_dialog = applet->settings_dialog;
825 
826     g_debug ("alarm_settings_dialog_response %d", rid);
827 
828     alarm_settings_dialog_close (settings_dialog);
829 }
830 
831 /*
832  * Associate a settings dialog with an alarm
833  *
834  * Clears any previously associated alarms
835  */
836 static void
alarm_settings_dialog_set_alarm(AlarmSettingsDialog * dialog,Alarm * alarm)837 alarm_settings_dialog_set_alarm (AlarmSettingsDialog *dialog, Alarm *alarm)
838 {
839     // Clear dialog
840     alarm_settings_dialog_clear (dialog);
841 
842     // Set alarm
843     dialog->alarm = alarm;
844 
845     // Populate widgets
846 	alarm_settings_update (dialog);
847 
848     // Notify of change to alarm
849     g_signal_connect (alarm, "notify", G_CALLBACK (alarm_changed), dialog);
850 }
851 
852 
853 /*
854  * Create a new settings dialog
855  */
856 AlarmSettingsDialog *
alarm_settings_dialog_new(AlarmApplet * applet)857 alarm_settings_dialog_new (AlarmApplet *applet)
858 {
859 	AlarmSettingsDialog *dialog;
860 	AlarmRepeat r;
861 	gint i;
862 
863     GtkBuilder *builder = applet->ui;
864 
865 	// Initialize struct
866 	dialog = g_new0 (AlarmSettingsDialog, 1);
867 
868 	dialog->applet = applet;
869 	dialog->player = NULL;
870 	dialog->dialog = GTK_WIDGET (gtk_builder_get_object (builder, "alarm-settings-dialog"));
871 
872 	// TYPE TOGGLE BUTTONS
873 	dialog->clock_toggle = GTK_WIDGET (gtk_builder_get_object (builder, "toggle-clock"));
874 	dialog->timer_toggle = GTK_WIDGET (gtk_builder_get_object (builder, "toggle-timer"));
875 
876 	// GENERAL SETTINGS
877 	dialog->label_entry = GTK_WIDGET (gtk_builder_get_object (builder, "label-entry"));
878 	gtk_widget_grab_focus (dialog->label_entry);
879 
880 	dialog->hour_spin = GTK_WIDGET (gtk_builder_get_object (builder, "hour-spin"));
881 	dialog->min_spin = GTK_WIDGET (gtk_builder_get_object (builder, "minute-spin"));
882 	dialog->sec_spin = GTK_WIDGET (gtk_builder_get_object (builder, "second-spin"));
883 
884 	// REPEAT SETTINGS
885 	dialog->repeat_expand = GTK_WIDGET (gtk_builder_get_object (builder, "repeat-expand"));
886 	dialog->repeat_label  = GTK_WIDGET (gtk_builder_get_object (builder, "repeat-label"));
887 
888 	// The check buttons have the same name as the 3 letter
889 	// string representation of the day.
890 	for (r = ALARM_REPEAT_SUN, i = 0; r <= ALARM_REPEAT_SAT; r = 1 << ++i) {
891 		dialog->repeat_check[i] = GTK_WIDGET (gtk_builder_get_object (builder, alarm_repeat_to_string (r)));
892 	}
893 
894 	// NOTIFY SETTINGS
895 	dialog->notify_sound_radio       = GTK_WIDGET (gtk_builder_get_object (builder, "sound-radio"));
896 	dialog->notify_sound_box         = GTK_WIDGET (gtk_builder_get_object (builder, "sound-box"));
897 	dialog->notify_sound_combo       = GTK_WIDGET (gtk_builder_get_object (builder, "sound-combo"));
898 	dialog->notify_sound_preview     = GTK_WIDGET (gtk_builder_get_object (builder, "sound-play"));
899 	dialog->notify_sound_loop_check  = GTK_WIDGET (gtk_builder_get_object (builder, "sound-loop-check"));
900 	dialog->notify_app_radio         = GTK_WIDGET (gtk_builder_get_object (builder, "app-radio"));
901 	dialog->notify_app_box           = GTK_WIDGET (gtk_builder_get_object (builder, "app-box"));
902 	dialog->notify_app_combo         = GTK_WIDGET (gtk_builder_get_object (builder, "app-combo"));
903 	dialog->notify_app_command_box   = GTK_WIDGET (gtk_builder_get_object (builder, "app-command-box"));
904 	dialog->notify_app_command_entry = GTK_WIDGET (gtk_builder_get_object (builder, "app-command-entry"));
905 
906 
907 	// Load apps list
908 	alarm_applet_apps_load (applet);
909 
910 	return dialog;
911 }
912 
913 void
alarm_settings_dialog_show(AlarmSettingsDialog * dialog,Alarm * alarm)914 alarm_settings_dialog_show (AlarmSettingsDialog *dialog, Alarm *alarm)
915 {
916     alarm_settings_dialog_set_alarm (dialog, alarm);
917 
918     gtk_widget_show_all (dialog->dialog);
919 	gtk_window_present (GTK_WINDOW (dialog->dialog));
920 }
921