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