Move vibrator together with aux
[gregoa/zavai.git] / src / leds.vala
1 /*
2  * leds - Leds/buttons support
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 led {
25
26 public class LedState
27 {
28     public string name;
29     public int brightness;
30     public string trigger;
31     public int delay_on;
32     public int delay_off;
33
34     public LedState(string name)
35     {
36         this.name = name;
37         set_constant(0);
38     }
39
40     public void set_constant(int power)
41     {
42         brightness = power;
43         trigger = "none";
44         delay_on = 0;
45         delay_off = 0;
46     }
47
48     public void set_blink(int power, int delay_on=200, int delay_off=300)
49     {
50         brightness = power;
51         trigger = "timer";
52         this.delay_on = delay_on;
53         this.delay_off = delay_off;
54     }
55
56     public void to_omhacks(ref Omhacks.Led led)
57     {
58         led.brightness = brightness;
59         Memory.copy(led.trigger, trigger, trigger.size());
60         led.delay_on = 200;
61         led.delay_off = 300;
62     }
63 }
64
65 public class Vibrator : zavai.Resource, Object
66 {
67     protected Omhacks.Led vibrator;
68
69     protected List<LedState> states;
70
71     public Vibrator() throws FileError
72     {
73         if (vibrator.init("neo1973:vibrator") != 0)
74             throw new FileError.NOENT("vibrator not found");
75
76         states = new List<LedState>();
77     }
78
79     public void turn_off()
80     {
81         vibrator.brightness = 0;
82         Memory.copy(vibrator.trigger, "none", 5);
83         vibrator.set();
84     }
85
86     public void push_state(LedState state)
87     {
88         states.prepend(state);
89         state.to_omhacks(ref vibrator);
90         vibrator.set();
91     }
92
93     public void pop_state(string name)
94     {
95         // Handle empty list
96         if (states == null) return;
97
98         // Track if the list head changed
99         weak List<LedState> old_top = states;
100
101         // Remove state "name" from the stack
102         for (weak List<LedState> i = states; i != null; i = i.next)
103             if (i.data.name == name)
104             {
105                 states.delete_link(i);
106                 break;
107             }
108
109         // If the list head changed, put into action the new top state
110         if (states != old_top)
111             if (states == null)
112                 turn_off();
113             else {
114                 // Activate the new top
115                 states.data.to_omhacks(ref vibrator);
116                 vibrator.set();
117             }
118     }
119
120     public void shutdown()
121     {
122         while (states != null)
123             states.delete_link(states);
124         turn_off();
125     }
126 }
127
128 public class AUX: zavai.Service
129 {
130     protected Omhacks.Led auxled;
131     protected bool has_aux;
132
133     protected weak clock.AlarmTriggerInfo current_alarm = null;
134
135     public AUX()
136     {
137         Object(name: "ui.aux");
138
139         has_aux = (auxled.init("gta02-aux:red") == 0);
140
141         if (has_aux)
142         {
143             zavai.log.warning("aux: can notify alarm triggers");
144             clock.alarm_trigger_queue.triggered += on_alarm_trigger;
145             clock.alarm_trigger_queue.acked += on_alarm_done;
146             clock.alarm_trigger_queue.canceled += on_alarm_done;
147         } else {
148             zavai.log.warning("aux: no way to notify alarm triggers");
149         }
150
151         // Listen to the button via X
152         input.hotkeys.hotkey += on_auxbutton;
153         input.hotkeys.grab(zavai.config.aux_button_keycode, 0, false);
154         input.hotkeys.request("auxbutton");
155     }
156
157     protected bool on_auxbutton(uint keycode, ulong time, bool pressed)
158     {
159         if (keycode == zavai.config.aux_button_keycode)
160         {
161             if (pressed)
162             {
163                 zavai.log.debug("AUX button pressed");
164                 if (current_alarm != null)
165                 {
166                     zavai.log.debug("HASCA");
167                     clock.alarm_trigger_queue.ack(current_alarm);
168                 }
169             }
170             else
171                 zavai.log.debug("AUX button released");
172             return true;
173         }
174         return false;
175     }
176
177     public void on_alarm_trigger(clock.AlarmTriggerInfo info)
178     {
179         zavai.log.debug("Start blinking");
180         auxled.brightness = 256;
181         // FIXME: is there a better way? I hope there is a better way. Please
182         // tell me there is a better way.
183         var trig = "timer";
184         for (int i = 0; ; ++i)
185         {
186             auxled.trigger[i] = (char)trig[i];
187             if (trig[i] == 0) break;
188         }
189         auxled.delay_on = 200;
190         auxled.delay_off = 300;
191         auxled.set();
192         current_alarm = info;
193     }
194
195     public void on_alarm_done(clock.AlarmTriggerInfo info)
196     {
197         zavai.log.debug("Stop blinking");
198         var trig = "none";
199         for (int i = 0; ; ++i)
200         {
201             auxled.trigger[i] = (char)trig[i];
202             if (trig[i] == 0) break;
203         }
204         auxled.brightness = 0;
205         auxled.set();
206         current_alarm = null;
207     }
208 }
209
210 public AUX aux = null;
211 public Vibrator vibrator = null;
212
213 public void init()
214 {
215     aux = new AUX();
216     try {
217         vibrator = new Vibrator();
218         zavai.registry.register(vibrator);
219     } catch (Error e) {
220         zavai.log.info("No vibrator found");
221         vibrator = null;
222     }
223 }
224
225 }
226 }