Go on 30 seconds for alarm
[gregoa/zavai.git] / src / app_alarm.vala
1 /*
2  * app_alarm - zavai alarm system
3  *
4  * Copyright (C) 2010  Enrico Zini <enrico@enricozini.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 using GLib;
22
23 namespace zavai {
24 namespace ui {
25 namespace alarm {
26
27 // Compute a-b in microseconds
28 static long timediff(Posix.timeval* a, Posix.timeval* b)
29 {
30     return (a->tv_sec - b->tv_sec) * 1000000 + (a->tv_usec - b->tv_usec);
31 }
32
33 public class AlarmNotifier : zavai.Resource, Gtk.Window
34 {
35     protected Gtk.VBox vbox;
36     protected bool shown;
37     protected Gtk.Label message;
38     protected Gtk.Button ack;
39     protected uint cancel_timeout;
40     protected weak clock.AlarmTriggerInfo current = null;
41
42     public AlarmNotifier()
43     {
44         Object(
45             type: Gtk.WindowType.TOPLEVEL,
46             title: "Alarm"
47         );
48         shown = false;
49         destroy_with_parent = true;
50         set_transient_for(zavai.app);
51         set_modal(true);
52         set_position(Gtk.WindowPosition.CENTER_ON_PARENT);
53         set_size_request(300, 500);
54
55         vbox = new Gtk.VBox(false, 0);
56         add(vbox);
57
58         cancel_timeout = 0;
59
60         //destroy += Gtk.main_quit;
61         //set_events(get_events() | Gdk.EventMask.VISIBILITY_NOTIFY_MASK);
62         //visibility_notify_event += on_visibility;
63         set_skip_pager_hint(true);
64         set_skip_taskbar_hint(true);
65         set_type_hint(Gdk.WindowTypeHint.POPUP_MENU);
66
67         message = new Gtk.Label("no message");
68         vbox.pack_start(message, false, true, 0);
69
70         ack = new Gtk.Button.with_label("Ack");
71         ack.clicked += on_iface_ack;
72         vbox.pack_start(ack, true, true, 0);
73
74         //vbox.show_all();
75         zavai.registry.register(this);
76
77         clock.alarm_trigger_queue.triggered += on_trigger;
78         clock.alarm_trigger_queue.acked += on_done;
79         clock.alarm_trigger_queue.canceled += on_done;
80     }
81
82     protected void abort_timeout()
83     {
84         if (cancel_timeout != 0)
85         {
86             Source.remove(cancel_timeout);
87             cancel_timeout = 0;
88         }
89     }
90
91     protected void on_iface_ack()
92     {
93         if (current == null) return;
94         clock.alarm_trigger_queue.ack(current);
95     }
96
97     protected bool on_iface_timeout()
98     {
99         if (current == null) return false;
100         clock.alarm_trigger_queue.cancel(current);
101         return false;
102     }
103
104     public void on_trigger(clock.AlarmTriggerInfo info)
105     {
106         current = info;
107         message.set_text(info.label);
108
109         ui.power.backlight.request("alarmnotifier");
110
111         if (!shown)
112         {
113             show_all();
114             show();
115             visible = true;
116             present();
117             shown = true;
118         } else {
119             // TODO: do more in case it is visible but has no visibility (is covered by others)
120             visible = !visible;
121             if (visible)
122                 present();
123         }
124
125         abort_timeout();
126         cancel_timeout = Timeout.add(30 * 1000, on_iface_timeout);
127     }
128
129     public void on_done(clock.AlarmTriggerInfo info)
130     {
131         if (current == null || current.id != info.id) return;
132         visible = false;
133         abort_timeout();
134         current = null;
135         ui.power.backlight.release("alarmnotifier");
136     }
137
138     public void shutdown()
139     {
140         abort_timeout();
141     }
142 }
143
144 public AlarmNotifier notifier = null;
145
146 public void init()
147 {
148     if (clock.alarm_trigger_queue != null)
149         notifier = new AlarmNotifier();
150 }
151
152 }
153 }
154 }