Facility for acking/unacking log entries
[gregoa/zavai.git] / src / audio.vala
1 /*
2  * audio - audio resource for zavai
3  *
4  * Copyright (C) 2009--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 audio {
25
26 public class Audio: zavai.Service
27 {
28     protected Omhacks.Led vibrator;
29     protected bool has_vibrator;
30
31     /*
32        protected dynamic DBus.Object audiodev;
33        protected dynamic DBus.Object vibdev;
34    */
35
36     public Audio()
37     {
38         Object(name: "audio");
39
40         has_vibrator = (vibrator.init("neo1973:vibrator") == 0);
41
42 /*
43         audiodev = zavai.registry.sbus.get_object(
44                 "org.freesmartphone.odeviced",
45                 "/org/freesmartphone/Device/Audio",
46                 "org.freesmartphone.Device.Audio");
47         vibdev = zavai.registry.sbus.get_object(
48                 "org.freesmartphone.odeviced",
49                 "/org/freesmartphone/Device/LED/neo1973_vibrator",
50                 "org.freesmartphone.Device.LED");
51 */
52         clock.alarm_trigger_queue.triggered += on_alarm_trigger;
53         clock.alarm_trigger_queue.acked += on_alarm_done;
54         clock.alarm_trigger_queue.canceled += on_alarm_done;
55     }
56
57     public void on_alarm_trigger(clock.AlarmTriggerInfo info)
58     {
59         zavai.log.debug("Make noise for alarm");
60         if (has_vibrator)
61         {
62             vibrator.brightness = 256;
63             // FIXME: is there a better way? I hope there is a better way. Please
64             // tell me there is a better way.
65             var trig = "timer";
66             for (int i = 0; ; ++i)
67             {
68                 vibrator.trigger[i] = (char)trig[i];
69                 if (trig[i] == 0) break;
70             }
71             vibrator.delay_on = 200;
72             vibrator.delay_off = 300;
73             vibrator.set();
74         }
75         soundplayer.play(config.ringtone_alarm, true);
76     }
77
78     public void on_alarm_done(clock.AlarmTriggerInfo info)
79     {
80         zavai.log.debug("Stop noise for alarm");
81         if (has_vibrator)
82         {
83             var trig = "none";
84             for (int i = 0; ; ++i)
85             {
86                 vibrator.trigger[i] = (char)trig[i];
87                 if (trig[i] == 0) break;
88             }
89             vibrator.brightness = 0;
90             vibrator.set();
91         }
92         soundplayer.stop();
93     }
94
95 /*
96     public void notify_alarm(zavai.clock.Alarm a)
97     {
98         // Wiggle screen to turn on backlight
99         zavai.ui.power.backlight.wiggle();
100         try {
101             // Method does not exist in this frameworkd
102             vibdev.BlinkSeconds(5, 500, 200);
103         } catch (Error e) {
104             zavai.log.error("Cannot blink vibrator: " + e.message);
105         }
106         // TODO: play music?
107     }
108 */
109 }
110
111 public class Player: zavai.Resource, Object
112 {
113     protected Gst.Element player;
114     protected bool playing;
115     protected Player slave;
116     protected Player master;
117     protected bool loop;
118     protected string uri;
119     public signal void state_changed(Gst.State new_state);
120
121     public Player()
122     {
123         slave = null;
124         master = null;
125         player = Gst.ElementFactory.make("playbin", null);
126         playing = false;
127         loop = false;
128         var bus = player.get_bus();
129         bus.add_signal_watch();
130         bus.message += on_message;
131     }
132
133     public void set_slave(Player player)
134     {
135         slave = player;
136         slave.master = this;
137     }
138
139     public void play(string uri, bool loop = false)
140     {
141 stderr.printf("Playing %s\n", uri);
142         this.uri = uri;
143
144         if (slave != null && slave.playing)
145             slave.pause();
146
147         player.set_property("uri", uri);
148         player.set_state(master != null && master.playing ? Gst.State.PAUSED : Gst.State.PLAYING);
149         playing = true;
150         this.loop = loop;
151     }
152
153     public Gst.State get_state()
154     {
155         Gst.State state;
156         Gst.State pending;
157
158         player.get_state(out state, out pending, (Gst.ClockType)Gst.CLOCK_TIME_NONE);
159
160         return state;
161     }
162
163     public void pause()
164     {
165         player.set_state(Gst.State.PAUSED);
166         state_changed(Gst.State.PAUSED);
167     }
168
169     public void resume()
170     {
171         player.set_state(Gst.State.PLAYING);
172         state_changed(Gst.State.PLAYING);
173     }
174
175     public void restart()
176     {
177         player.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT, 0);
178         player.set_state(Gst.State.PLAYING);
179         state_changed(Gst.State.PLAYING);
180     }
181
182     public void stop()
183     {
184         playing = false;
185         player.set_state(Gst.State.NULL);
186         state_changed(Gst.State.NULL);
187
188         // Resume slave after we are done
189         if (slave != null && slave.playing)
190             slave.resume();
191     }
192
193     protected void on_message(Gst.Message message)
194     {
195         if (message.type == Gst.MessageType.EOS)
196         {
197             if (loop)
198                 restart();
199             else
200                 stop();
201         }
202     }
203
204     public void shutdown()
205     {
206         stop();
207     }
208 }
209
210 public Audio audio = null;
211 public Player musicplayer = null;
212 public Player soundplayer = null;
213
214 public void init()
215 {
216     audio = new Audio();
217     musicplayer = new Player();
218     soundplayer = new Player();
219     soundplayer.set_slave(musicplayer);
220     zavai.registry.register(musicplayer);
221     zavai.registry.register(soundplayer);
222 }
223
224 }
225 }