/* * audio - audio resource for zavai * * Copyright (C) 2009--2010 Enrico Zini * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ using GLib; namespace zavai { namespace audio { public class Audio: zavai.Service { /* protected dynamic DBus.Object audiodev; protected dynamic DBus.Object vibdev; */ public Audio() { Object(name: "audio"); /* audiodev = zavai.registry.sbus.get_object( "org.freesmartphone.odeviced", "/org/freesmartphone/Device/Audio", "org.freesmartphone.Device.Audio"); vibdev = zavai.registry.sbus.get_object( "org.freesmartphone.odeviced", "/org/freesmartphone/Device/LED/neo1973_vibrator", "org.freesmartphone.Device.LED"); */ } } 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); } protected void on_message(Gst.Message message) { if (message.type == Gst.MessageType.EOS) { 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); } } } 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) { 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 MusicPlayer: zavai.Resource, Object { protected Gst.Element player; public SoundPlayer master; public signal void state_changed(Gst.State new_state); public string uri; public bool playing; public MusicPlayer() { master = null; uri = null; playing = false; player = Gst.ElementFactory.make("playbin", null); var bus = player.get_bus(); bus.add_signal_watch(); bus.message += on_message; } public void play(string uri) { this.uri = uri; playing = true; player.set_property("uri", uri); player.set_state(master != null && master.playing() ? Gst.State.PAUSED : Gst.State.PLAYING); } protected void stop_playing() { player.set_state(Gst.State.NULL); state_changed(Gst.State.NULL); } public Gst.State get_state() { return player.current_state; } public void pause() { playing = false; player.set_state(Gst.State.PAUSED); state_changed(Gst.State.PAUSED); } public void resume() { playing = true; if (master == null || !master.playing()) { player.set_state(Gst.State.PLAYING); state_changed(Gst.State.PLAYING); } } public void restart() { player.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT, 0); player.set_state(Gst.State.PLAYING); state_changed(Gst.State.PLAYING); } protected void on_message(Gst.Message message) { if (message.type == Gst.MessageType.EOS) { playing = false; stop_playing(); } } public void shutdown() { stop_playing(); } } public Audio audio = null; public SoundPlayer soundplayer = null; public MusicPlayer musicplayer = null; public void init() { audio = new Audio(); musicplayer = new MusicPlayer(); soundplayer = new SoundPlayer(); soundplayer.set_slave(musicplayer); zavai.registry.register(musicplayer); zavai.registry.register(soundplayer); } } }