X-Git-Url: https://git.toastfreeware.priv.at/gregoa/zavai.git/blobdiff_plain/15c3d4c508afdf0de8097f8c0a3a7c129c5f585e..4ab1def9651af8f5405f2dce85374382f4a01d9b:/src/audio.vala?ds=sidebyside diff --git a/src/audio.vala b/src/audio.vala index 0a3967c..51790d0 100644 --- a/src/audio.vala +++ b/src/audio.vala @@ -44,94 +44,205 @@ public class Audio: zavai.Service "/org/freesmartphone/Device/LED/neo1973_vibrator", "org.freesmartphone.Device.LED"); */ - clock.alarm_trigger_queue.triggered += on_alarm_trigger; - clock.alarm_trigger_queue.acked += on_alarm_done; - clock.alarm_trigger_queue.canceled += on_alarm_done; + } +} + +public class PlayerState : Object +{ + protected SoundPlayer soundplayer; + protected Gst.Element player; + public string owner; + public string uri; + public bool loop; + + public PlayerState(string owner, string uri, bool loop=false) + { + soundplayer = null; + + this.owner = owner; + this.uri = uri; + this.loop = loop; + + player = Gst.ElementFactory.make("playbin", null); + var bus = player.get_bus(); + bus.add_signal_watch(); + bus.message += on_message; + + player.set_property("uri", uri); + player.set_state(Gst.State.PAUSED); + } + + public void register(SoundPlayer sp) + { + soundplayer = sp; + } + + public void stop() + { + player.set_state(Gst.State.NULL); + } + + public void pause() + { + player.set_state(Gst.State.PAUSED); + } + + public void resume() + { + player.set_state(Gst.State.PLAYING); } - public void on_alarm_trigger(clock.AlarmTriggerInfo info) + protected void on_message(Gst.Message message) { - zavai.log.debug("Make noise for alarm"); - if (zavai.led.vibrator != null) + if (message.type == Gst.MessageType.EOS) { - var state = new zavai.led.LedState("alarm"); - state.set_blink(255); - zavai.led.vibrator.push_state(state); + if (loop) + { + player.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT, 0); + player.set_state(Gst.State.PLAYING); + } + else if (soundplayer != null) + soundplayer.pop_state(owner); } - soundplayer.play(config.ringtone_alarm, true); } +} - public void on_alarm_done(clock.AlarmTriggerInfo info) +public class SoundPlayer : zavai.Resource, Object +{ + protected List states; + protected MusicPlayer slave; + protected bool slave_was_playing; + + public SoundPlayer() + { + states = new List(); + } + + public void set_slave(MusicPlayer player) { - zavai.log.debug("Stop noise for alarm"); - if (zavai.led.vibrator != null) - zavai.led.vibrator.pop_state("alarm"); - soundplayer.stop(); + slave = player; + slave.master = this; + } + + public bool playing() + { + return states != null; + } + + protected void stop_playing() + { + if (slave_was_playing) + slave.resume(); + } + + public void push_state(PlayerState state) + { + // Save current playing position + if (states == null) + { + // We start playing: see about preempting slave + slave_was_playing = (slave != null && slave.playing); + if (slave_was_playing) + slave.pause(); + } else + // We were playing: pause previous sound + states.data.pause(); + state.register(this); + states.prepend(state); + states.data.resume(); + } + + public void pop_state(string owner) + { + // Handle empty list + if (states == null) return; + + // Track if the list head changed + weak List old_top = states; + + // Remove state "name" from the stack + for (weak List i = states; i != null; i = i.next) + if (i.data.owner == owner) + { + i.data.stop(); + states.delete_link(i); + break; + } + + // If the list head changed, put into action the new top state + if (states != old_top) + { + if (states == null) + stop_playing(); + else + states.data.resume(); + } + } + + public void shutdown() + { + while (states != null) + { + states.data.stop(); + states.delete_link(states); + } + stop_playing(); } } -public class Player: zavai.Resource, Object +public class MusicPlayer: zavai.Resource, Object { protected Gst.Element player; - protected bool playing; - protected Player slave; - protected Player master; - protected bool loop; - protected string uri; + public SoundPlayer master; public signal void state_changed(Gst.State new_state); + public string uri; + public bool playing; - public Player() + public MusicPlayer() { - slave = null; master = null; - player = Gst.ElementFactory.make("playbin", null); + uri = null; playing = false; - loop = false; + player = Gst.ElementFactory.make("playbin", null); var bus = player.get_bus(); bus.add_signal_watch(); bus.message += on_message; } - public void set_slave(Player player) + public void play(string uri) { - slave = player; - slave.master = this; + this.uri = uri; + playing = true; + player.set_property("uri", uri); + player.set_state(master != null && master.playing() ? Gst.State.PAUSED : Gst.State.PLAYING); } - public void play(string uri, bool loop = false) + protected void stop_playing() { -stderr.printf("Playing %s\n", uri); - this.uri = uri; - - if (slave != null && slave.playing) - slave.pause(); - - player.set_property("uri", uri); - player.set_state(master != null && master.playing ? Gst.State.PAUSED : Gst.State.PLAYING); - playing = true; - this.loop = loop; + player.set_state(Gst.State.NULL); + state_changed(Gst.State.NULL); } public Gst.State get_state() { - Gst.State state; - Gst.State pending; - - player.get_state(out state, out pending, (Gst.ClockType)Gst.CLOCK_TIME_NONE); - - return state; + return player.current_state; } public void pause() { + playing = false; player.set_state(Gst.State.PAUSED); state_changed(Gst.State.PAUSED); } public void resume() { - player.set_state(Gst.State.PLAYING); - state_changed(Gst.State.PLAYING); + playing = true; + if (master == null || !master.playing()) + { + player.set_state(Gst.State.PLAYING); + state_changed(Gst.State.PLAYING); + } } public void restart() @@ -141,43 +252,30 @@ stderr.printf("Playing %s\n", uri); state_changed(Gst.State.PLAYING); } - public void stop() - { - playing = false; - player.set_state(Gst.State.NULL); - state_changed(Gst.State.NULL); - - // Resume slave after we are done - if (slave != null && slave.playing) - slave.resume(); - } - protected void on_message(Gst.Message message) { if (message.type == Gst.MessageType.EOS) { - if (loop) - restart(); - else - stop(); + playing = false; + stop_playing(); } } public void shutdown() { - stop(); + stop_playing(); } } public Audio audio = null; -public Player musicplayer = null; -public Player soundplayer = null; +public SoundPlayer soundplayer = null; +public MusicPlayer musicplayer = null; public void init() { audio = new Audio(); - musicplayer = new Player(); - soundplayer = new Player(); + musicplayer = new MusicPlayer(); + soundplayer = new SoundPlayer(); soundplayer.set_slave(musicplayer); zavai.registry.register(musicplayer); zavai.registry.register(soundplayer);