Implement looping
[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         if (has_vibrator)
53         {
54             zavai.log.warning("audio: can notify alarm triggers");
55             clock.alarm_trigger_queue.triggered += on_alarm_trigger;
56             clock.alarm_trigger_queue.acked += on_alarm_done;
57             clock.alarm_trigger_queue.canceled += on_alarm_done;
58         } else {
59             zavai.log.warning("audio: no way to notify alarm triggers");
60         }
61     }
62
63     public void on_alarm_trigger(clock.AlarmTriggerInfo info)
64     {
65         zavai.log.debug("Start vibrator");
66         vibrator.brightness = 256;
67         // FIXME: is there a better way? I hope there is a better way. Please
68         // tell me there is a better way.
69         var trig = "timer";
70         for (int i = 0; ; ++i)
71         {
72             vibrator.trigger[i] = (char)trig[i];
73             if (trig[i] == 0) break;
74         }
75         vibrator.delay_on = 200;
76         vibrator.delay_off = 300;
77         vibrator.set();
78     }
79
80     public void on_alarm_done(clock.AlarmTriggerInfo info)
81     {
82         zavai.log.debug("Stop vibrator");
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
93 /*
94     public void notify_alarm(zavai.clock.Alarm a)
95     {
96         // Wiggle screen to turn on backlight
97         zavai.ui.power.backlight.wiggle();
98         try {
99             // Method does not exist in this frameworkd
100             vibdev.BlinkSeconds(5, 500, 200);
101         } catch (Error e) {
102             zavai.log.error("Cannot blink vibrator: " + e.message);
103         }
104         // TODO: play music?
105     }
106 */
107 }
108
109 public class Player: zavai.Resource, Object
110 {
111     protected Gst.Element player;
112     protected bool playing;
113     protected Player slave;
114     protected Player master;
115     protected bool loop;
116     protected string uri;
117
118     public Player()
119     {
120         slave = null;
121         master = null;
122         player = Gst.ElementFactory.make("playbin", null);
123         playing = false;
124         loop = false;
125         var bus = player.get_bus();
126         bus.add_signal_watch();
127         bus.message += on_message;
128     }
129
130     public void set_slave(Player player)
131     {
132         slave = player;
133         slave.master = this;
134     }
135
136     public void play(string uri, bool loop = false)
137     {
138         this.uri = uri;
139
140         if (slave != null && slave.playing)
141             slave.pause();
142
143         player.set_property("uri", uri);
144         player.set_state(master != null && master.playing ? Gst.State.PAUSED : Gst.State.PLAYING);
145         playing = true;
146         this.loop = loop;
147     }
148
149     public void pause()
150     {
151         player.set_state(Gst.State.PAUSED);
152     }
153
154     public void resume()
155     {
156         player.set_state(Gst.State.PLAYING);
157     }
158
159     public void restart()
160     {
161         player.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT, 0);
162         player.set_state(Gst.State.PLAYING);
163     }
164
165     public void stop()
166     {
167         playing = false;
168         player.set_state(Gst.State.NULL);
169
170         // Resume slave after we are done
171         if (slave != null && slave.playing)
172             slave.resume();
173     }
174
175     protected void on_message(Gst.Message message)
176     {
177         if (message.type == Gst.MessageType.EOS)
178         {
179             if (loop)
180                 restart();
181             else
182                 stop();
183         }
184     }
185
186     public void shutdown()
187     {
188         stop();
189     }
190 }
191
192 public Audio audio = null;
193 public Player musicplayer = null;
194 public Player soundplayer = null;
195
196 public void init()
197 {
198     audio = new Audio();
199     musicplayer = new Player();
200     soundplayer = new Player();
201     soundplayer.set_slave(musicplayer);
202     zavai.registry.register(musicplayer);
203     zavai.registry.register(soundplayer);
204 }
205
206 }
207 }