Merge branch 'master' into gregoa
authorgregor herrmann <gregoa@debian.org>
Sun, 28 Mar 2010 18:34:12 +0000 (20:34 +0200)
committergregor herrmann <gregoa@debian.org>
Sun, 28 Mar 2010 18:34:12 +0000 (20:34 +0200)
12 files changed:
README
src/app_alarm.vala
src/app_aux.vala [deleted file]
src/app_music.vala
src/app_notify.vala [new file with mode: 0644]
src/audio.vala
src/clock.vala
src/config.vala
src/core.vala
src/gsm.vala
src/leds.vala [new file with mode: 0644]
src/zavai.vala

diff --git a/README b/README
index 97f1d24fc9e32609954449a1e459971a7ed57634..1c727fbc24b38de214042fee8588e2121e99d33f 100644 (file)
--- a/README
+++ b/README
@@ -193,11 +193,6 @@ using vala-dbus-binding-tool:
    system time, automatically sync it
    if GPS time is more than 1 hour different than the system time, show a
    "SYNC" button that will sync it if pressed
- - stacked notifier, with stacked modal dialogs
-   (notify sms received during phone ringing during alarm)
-    - aux acks the topmost dialog
-    - custom ringtone per every notifier (stops ringtone of modifier below,
-      saving the time offset of playing so it can be reloaded and resumed)
  - log
     - flash aux when there are unacknowledged log entries
     - write data to disk as log happens (to have at least partial logs if power
@@ -205,10 +200,6 @@ using vala-dbus-binding-tool:
     - more detailed GPX data (dop, elev..)
     - message (structured) (json?)
  - turn on/off gsm
-    - play ringtone when someone calls (not useful to pick up, but just to
-      notify a call is there)
-      (but stop ringtone if aux pressed in the meantime, to avoid annoying
-      people)
     - pick up phone call
        - phone call applet (pushed when picking up)
           - buttons for dtmf
index c3bfd7cfd4013021b707f8748ec294dc19e9c6b5..8cfff21636033d1935d66c363ed9975556401523 100644 (file)
@@ -32,114 +32,123 @@ static long timediff(Posix.timeval* a, Posix.timeval* b)
 }
 */
 
-public class AlarmNotifier : zavai.Resource, Gtk.Window
+protected class AlarmNotifierDialog : ui.notify.Notifier
 {
-    protected Gtk.VBox vbox;
-    protected bool shown;
     protected Gtk.Label message;
-    protected Gtk.Button ack;
-    protected uint cancel_timeout;
-    protected weak clock.AlarmTriggerInfo current = null;
+    protected Gtk.Button message_button;
 
-    public AlarmNotifier()
+    public AlarmNotifierDialog(string title, string text)
     {
         Object(
-            type: Gtk.WindowType.TOPLEVEL,
-            title: "Alarm"
+            notifier_name: "alarm",
+            title: title
         );
-        shown = false;
-        destroy_with_parent = true;
-        set_transient_for(zavai.app);
-        set_modal(true);
-        set_position(Gtk.WindowPosition.CENTER_ON_PARENT);
-        set_size_request(300, 500);
-
-        vbox = new Gtk.VBox(false, 0);
-        add(vbox);
 
-        cancel_timeout = 0;
-
-        //destroy += Gtk.main_quit;
-        //set_events(get_events() | Gdk.EventMask.VISIBILITY_NOTIFY_MASK);
-        //visibility_notify_event += on_visibility;
-        set_skip_pager_hint(true);
-        set_skip_taskbar_hint(true);
-        set_type_hint(Gdk.WindowTypeHint.POPUP_MENU);
+        set_size_request(300, 500);
 
-        message = new Gtk.Label("no message");
-        vbox.pack_start(message, false, true, 0);
+        add_button(Gtk.STOCK_OK, Gtk.ResponseType.OK);
+        add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL);
+        set_default_response(Gtk.ResponseType.OK);
 
-        ack = new Gtk.Button.with_label("Ack");
-        ack.clicked += on_iface_ack;
-        vbox.pack_start(ack, true, true, 0);
+        weak Gtk.VBox vbox = (Gtk.VBox)get_content_area();
 
-        //vbox.show_all();
-        zavai.registry.register(this);
+        message = new Gtk.Label(text);
+        message_button = new Gtk.Button();
+        message_button.set_image(message);
+        message_button.clicked += (b) => { response(Gtk.ResponseType.OK); };
+        vbox.pack_start(message_button, true, true, 0);
+        message_button.show();
+    }
 
-        clock.alarm_trigger_queue.triggered += on_trigger;
-        clock.alarm_trigger_queue.acked += on_done;
-        clock.alarm_trigger_queue.canceled += on_done;
+    protected override bool push_aux_state()
+    {
+        var state = new zavai.led.LedState(notifier_name);
+        state.set_blink(255);
+        zavai.led.aux.push_state(state);
+        return true;
     }
 
-    protected void abort_timeout()
+    protected override bool push_vibrator_state()
     {
-        if (cancel_timeout != 0)
-        {
-            Source.remove(cancel_timeout);
-            cancel_timeout = 0;
-        }
+        var state = new zavai.led.LedState(notifier_name);
+        state.set_blink(255);
+        zavai.led.vibrator.push_state(state);
+        return true;
     }
 
-    protected void on_iface_ack()
+    protected override bool push_ringtone_state()
     {
-        if (current == null) return;
-        clock.alarm_trigger_queue.ack(current);
+        var state = new zavai.audio.PlayerState(notifier_name, config.ringtone_alarm, true);
+        zavai.audio.soundplayer.push_state(state);
+        return true;
     }
+}
 
-    protected bool on_iface_timeout()
+public class AlarmNotifier : zavai.Resource, Object
+{
+    protected weak clock.AlarmTriggerInfo current = null;
+    protected AlarmNotifierDialog dialog = null;
+
+    public AlarmNotifier()
     {
-        if (current == null) return false;
-        clock.alarm_trigger_queue.cancel(current);
-        return false;
+        zavai.registry.register(this);
+
+        clock.alarm_trigger_queue.triggered += on_trigger;
+        clock.alarm_trigger_queue.acked += on_done;
+        clock.alarm_trigger_queue.canceled += on_done;
     }
 
     public void on_trigger(clock.AlarmTriggerInfo info)
     {
         current = info;
-        message.set_text(info.label);
+        dialog = new AlarmNotifierDialog("Alarm", info.label);
 
-        ui.power.backlight.request("alarmnotifier");
+        if (zavai.led.auxbutton != null)
+            zavai.led.auxbutton.event += on_auxbutton;
 
-        if (!shown)
+        uint cancel_timeout = 0;
+        cancel_timeout = Timeout.add(30 * 1000, () => {
+            dialog.response(Gtk.ResponseType.CANCEL);
+            cancel_timeout = 0;
+            return false;
+        });
+        int res = dialog.run();
+        if (cancel_timeout != 0) Source.remove(cancel_timeout);
+        switch (res)
         {
-            show_all();
-            show();
-            visible = true;
-            present();
-            shown = true;
-        } else {
-            // TODO: do more in case it is visible but has no visibility (is covered by others)
-            visible = !visible;
-            if (visible)
-                present();
+            case Gtk.ResponseType.OK:
+                clock.alarm_trigger_queue.ack(current);
+                break;
+            case Gtk.ResponseType.CANCEL:
+                clock.alarm_trigger_queue.cancel(current);
+                break;
         }
 
-        abort_timeout();
-        cancel_timeout = Timeout.add(30 * 1000, on_iface_timeout);
+        if (zavai.led.auxbutton != null)
+            zavai.led.auxbutton.event -= on_auxbutton;
+
+        dialog.destroy();
+        dialog = null;
+        current = null;
+    }
+
+    protected bool on_auxbutton(ulong time, bool pressed)
+    {
+        if (dialog == null) return false;
+        dialog.response(Gtk.ResponseType.OK);
+        return true;
     }
 
     public void on_done(clock.AlarmTriggerInfo info)
     {
-        if (current == null || current != info) return;
-        visible = false;
-        abort_timeout();
-        current = null;
-        ui.power.backlight.release("alarmnotifier");
+        if (current == null || dialog == null || current != info) return;
+        dialog.response(Gtk.ResponseType.NONE);
     }
 
     public void shutdown()
     {
-        abort_timeout();
+        if (dialog == null) return;
+        dialog.response(Gtk.ResponseType.CANCEL);
     }
 }
 
diff --git a/src/app_aux.vala b/src/app_aux.vala
deleted file mode 100644 (file)
index db05e99..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * app_aux - AUX button interaction
- *
- * Copyright (C) 2010  Enrico Zini <enrico@enricozini.org>
- *
- * 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 ui {
-namespace aux {
-
-public class AUX: zavai.Service
-{
-    protected Omhacks.Led auxled;
-    protected bool has_aux;
-
-    protected weak clock.AlarmTriggerInfo current_alarm = null;
-
-    public AUX()
-    {
-        Object(name: "ui.aux");
-
-        has_aux = (auxled.init("gta02-aux:red") == 0);
-
-        if (has_aux)
-        {
-            zavai.log.warning("aux: can notify alarm triggers");
-            clock.alarm_trigger_queue.triggered += on_alarm_trigger;
-            clock.alarm_trigger_queue.acked += on_alarm_done;
-            clock.alarm_trigger_queue.canceled += on_alarm_done;
-        } else {
-            zavai.log.warning("aux: no way to notify alarm triggers");
-        }
-
-        // Listen to the button via X
-        input.hotkeys.hotkey += on_auxbutton;
-        input.hotkeys.grab(zavai.config.aux_button_keycode, 0, false);
-        input.hotkeys.request("auxbutton");
-    }
-
-    protected bool on_auxbutton(uint keycode, ulong time, bool pressed)
-    {
-        if (keycode == zavai.config.aux_button_keycode)
-        {
-            if (pressed)
-            {
-                zavai.log.debug("AUX button pressed");
-                if (current_alarm != null)
-                {
-                    zavai.log.debug("HASCA");
-                    clock.alarm_trigger_queue.ack(current_alarm);
-                }
-            }
-            else
-                zavai.log.debug("AUX button released");
-            return true;
-        }
-        return false;
-    }
-
-    public void on_alarm_trigger(clock.AlarmTriggerInfo info)
-    {
-        zavai.log.debug("Start blinking");
-        auxled.brightness = 256;
-        // FIXME: is there a better way? I hope there is a better way. Please
-        // tell me there is a better way.
-        var trig = "timer";
-        for (int i = 0; ; ++i)
-        {
-            auxled.trigger[i] = (char)trig[i];
-            if (trig[i] == 0) break;
-        }
-        auxled.delay_on = 200;
-        auxled.delay_off = 300;
-        auxled.set();
-        current_alarm = info;
-    }
-
-    public void on_alarm_done(clock.AlarmTriggerInfo info)
-    {
-        zavai.log.debug("Stop blinking");
-        var trig = "none";
-        for (int i = 0; ; ++i)
-        {
-            auxled.trigger[i] = (char)trig[i];
-            if (trig[i] == 0) break;
-        }
-        auxled.brightness = 0;
-        auxled.set();
-        current_alarm = null;
-    }
-}
-
-public AUX aux = null;
-
-public void init()
-{
-    aux = new AUX();
-}
-
-}
-}
-}
index d066e3c54d4f918afe57c5e190d7caa85f0ee285..8d79e84768da3c238cfec1e22f1af8808e823b6e 100644 (file)
@@ -73,7 +73,7 @@ public class Player : Gtk.VBox
 {
     protected Gtk.Label l_status;
     protected PlayPauseButton b_playpause;
-    protected Gtk.Button b_stop;
+    //protected Gtk.Button b_stop;
     protected Gtk.Button b_prev;
     protected Gtk.Button b_next;
 
@@ -82,15 +82,15 @@ public class Player : Gtk.VBox
         l_status = new Gtk.Label("");
         //l_date.modify_font(Pango.FontDescription.from_string("Sans 40"));
         b_playpause = new PlayPauseButton();
-        b_stop = new Gtk.Button.from_stock(Gtk.STOCK_MEDIA_STOP);
-        b_stop.clicked += (b) => { audio.musicplayer.stop(); };
+        //b_stop = new Gtk.Button.from_stock(Gtk.STOCK_MEDIA_STOP);
+        //b_stop.clicked += (b) => { audio.musicplayer.stop(); };
         b_prev = new Gtk.Button.from_stock(Gtk.STOCK_MEDIA_PREVIOUS);
         b_next = new Gtk.Button.from_stock(Gtk.STOCK_MEDIA_NEXT);
         pack_start(l_status, false, false, 0);
         var buttons = new Gtk.HButtonBox();
         buttons.add(b_prev);
         buttons.add(b_playpause);
-        buttons.add(b_stop);
+        //buttons.add(b_stop);
         buttons.add(b_next);
         pack_start(buttons, false, false, 0);
 
diff --git a/src/app_notify.vala b/src/app_notify.vala
new file mode 100644 (file)
index 0000000..804277d
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * app_notify - zavai notification system
+ *
+ * Copyright (C) 2010  Enrico Zini <enrico@enricozini.org>
+ *
+ * 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 ui {
+namespace notify {
+
+public abstract class Notifier : Gtk.Dialog
+{
+    public string notifier_name { get; construct; }
+
+    construct {
+        set_transient_for(zavai.app);
+        set_modal(true);
+        set_position(Gtk.WindowPosition.CENTER_ON_PARENT);
+    }
+
+    protected virtual bool push_aux_state()
+    {
+        return false;
+    }
+
+    protected virtual bool push_vibrator_state()
+    {
+        return false;
+    }
+
+    protected virtual bool push_ringtone_state()
+    {
+        return false;
+    }
+
+    public int run()
+    {
+        ui.power.backlight.request(notifier_name);
+
+        // Setup our attention seeking strategy
+        bool has_aux = zavai.led.aux != null && push_aux_state();
+        bool has_vibrator = zavai.led.vibrator != null && push_vibrator_state();
+        bool has_ringtone = zavai.audio.soundplayer != null && push_ringtone_state();
+
+        // Run dialog
+        int res = base.run();
+
+        if (has_ringtone) zavai.audio.soundplayer.pop_state(notifier_name);
+        if (has_vibrator) zavai.led.vibrator.pop_state(notifier_name);
+        if (has_aux) zavai.led.aux.pop_state(notifier_name);
+
+        ui.power.backlight.release(notifier_name);
+        return res;
+    }
+}
+
+protected class CallNotifierDialog : ui.notify.Notifier
+{
+    protected Gtk.Label message;
+    protected Gtk.Button message_button;
+
+    public CallNotifierDialog(string title, string text)
+    {
+        Object(
+            notifier_name: "call",
+            title: title
+        );
+
+        set_size_request(300, 500);
+
+        add_button(Gtk.STOCK_OK, Gtk.ResponseType.OK);
+        add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL);
+        set_default_response(Gtk.ResponseType.OK);
+
+        weak Gtk.VBox vbox = (Gtk.VBox)get_content_area();
+
+        message = new Gtk.Label(text);
+        message_button = new Gtk.Button();
+        message_button.set_image(message);
+        message_button.clicked += (b) => { response(Gtk.ResponseType.OK); };
+        vbox.pack_start(message_button, true, true, 0);
+        message_button.show();
+    }
+
+    protected override bool push_aux_state()
+    {
+        var state = new zavai.led.LedState(notifier_name);
+        state.set_blink(255);
+        zavai.led.aux.push_state(state);
+        return true;
+    }
+
+    protected override bool push_vibrator_state()
+    {
+        var state = new zavai.led.LedState(notifier_name);
+        state.set_blink(255);
+        zavai.led.vibrator.push_state(state);
+        return true;
+    }
+
+    protected override bool push_ringtone_state()
+    {
+        var state = new zavai.audio.PlayerState(notifier_name, config.ringtone_call, true);
+        zavai.audio.soundplayer.push_state(state);
+        return true;
+    }
+}
+
+public class CallNotifier : zavai.Resource, ui.notify.Notifier
+{
+    protected int call_index = -1;
+    protected CallNotifierDialog dialog = null;
+
+    public CallNotifier()
+    {
+        zavai.registry.register(this);
+
+        zavai.gsm.gsm.new_call += trigger;
+        zavai.gsm.gsm.end_call += done;
+    }
+
+    public void trigger(int index)
+    {
+        call_index = index;
+        dialog = new CallNotifierDialog("Call", "TODO");
+
+        if (zavai.led.auxbutton != null)
+            zavai.led.auxbutton.event += on_auxbutton;
+
+        int res = dialog.run();
+        switch (res)
+        {
+            case Gtk.ResponseType.OK:
+                // TODO clock.alarm_trigger_queue.ack(current);
+                break;
+            case Gtk.ResponseType.CANCEL:
+                // TODO clock.alarm_trigger_queue.cancel(current);
+                break;
+        }
+
+        if (zavai.led.auxbutton != null)
+            zavai.led.auxbutton.event -= on_auxbutton;
+
+        dialog.destroy();
+        dialog = null;
+        call_index = -1;
+    }
+
+    protected bool on_auxbutton(ulong time, bool pressed)
+    {
+        if (dialog == null) return false;
+        dialog.response(Gtk.ResponseType.OK);
+        return true;
+    }
+
+    public void done(int index)
+    {
+        if (call_index != index || dialog == null) return;
+        dialog.response(Gtk.ResponseType.NONE);
+    }
+
+    public void shutdown()
+    {
+        if (dialog == null) return;
+        dialog.response(Gtk.ResponseType.CANCEL);
+    }
+}
+
+public CallNotifier call = null;
+
+public void sms()
+{
+    var ps = new zavai.audio.PlayerState("gsm", zavai.config.ringtone_sms, false);
+    zavai.audio.soundplayer.push_state(ps);
+}
+
+public void init()
+{
+    call = new CallNotifier();
+
+    zavai.gsm.gsm.new_sms += sms;
+}
+
+}
+}
+}
index 1c3942012a0747a8a0b71e6a31b096e869bb6fb4..51790d0aed63f4d05da2422febda74f0092175c8 100644 (file)
@@ -25,9 +25,6 @@ namespace audio {
 
 public class Audio: zavai.Service
 {
-    protected Omhacks.Led vibrator;
-    protected bool has_vibrator;
-
     /*
        protected dynamic DBus.Object audiodev;
        protected dynamic DBus.Object vibdev;
@@ -37,8 +34,6 @@ public class Audio: zavai.Service
     {
         Object(name: "audio");
 
-        has_vibrator = (vibrator.init("neo1973:vibrator") == 0);
-
 /*
         audiodev = zavai.registry.sbus.get_object(
                 "org.freesmartphone.odeviced",
@@ -49,127 +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 void on_alarm_trigger(clock.AlarmTriggerInfo info)
+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)
     {
-        zavai.log.debug("Make noise for alarm");
-        if (has_vibrator)
+        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)
         {
-            vibrator.brightness = 256;
-            // FIXME: is there a better way? I hope there is a better way. Please
-            // tell me there is a better way.
-            var trig = "timer";
-            for (int i = 0; ; ++i)
+            if (loop)
             {
-                vibrator.trigger[i] = (char)trig[i];
-                if (trig[i] == 0) break;
+                player.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT, 0);
+                player.set_state(Gst.State.PLAYING);
             }
-            vibrator.delay_on = 200;
-            vibrator.delay_off = 300;
-            vibrator.set();
+            else if (soundplayer != null)
+                soundplayer.pop_state(owner);
         }
-        soundplayer.play(config.ringtone_alarm, true);
+    }
+}
+
+public class SoundPlayer : zavai.Resource, Object
+{
+    protected List<PlayerState> states;
+    protected MusicPlayer slave;
+    protected bool slave_was_playing;
+
+    public SoundPlayer()
+    {
+        states = new List<PlayerState>();
+    }
+
+    public void set_slave(MusicPlayer player)
+    {
+        slave = player;
+        slave.master = this;
+    }
+
+    public bool playing()
+    {
+        return states != null;
     }
 
-    public void on_alarm_done(clock.AlarmTriggerInfo info)
+    protected void stop_playing()
     {
-        zavai.log.debug("Stop noise for alarm");
-        if (has_vibrator)
+        if (slave_was_playing)
+            slave.resume();
+    }
+
+    public void push_state(PlayerState state)
+    {
+        // Save current playing position
+        if (states == null)
         {
-            var trig = "none";
-            for (int i = 0; ; ++i)
+            // 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<PlayerState> old_top = states;
+
+        // Remove state "name" from the stack
+        for (weak List<PlayerState> i = states; i != null; i = i.next)
+            if (i.data.owner == owner)
             {
-                vibrator.trigger[i] = (char)trig[i];
-                if (trig[i] == 0) break;
+                i.data.stop();
+                states.delete_link(i);
+                break;
             }
-            vibrator.brightness = 0;
-            vibrator.set();
+
+        // 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();
         }
-        soundplayer.stop();
     }
 
-/*
-    public void notify_alarm(zavai.clock.Alarm a)
-    {
-        // Wiggle screen to turn on backlight
-        zavai.ui.power.backlight.wiggle();
-        try {
-            // Method does not exist in this frameworkd
-            vibdev.BlinkSeconds(5, 500, 200);
-        } catch (Error e) {
-            zavai.log.error("Cannot blink vibrator: " + e.message);
+    public void shutdown()
+    {
+        while (states != null)
+        {
+            states.data.stop();
+            states.delete_link(states);
         }
-        // TODO: play music?
+        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()
@@ -179,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);
index fd5e6f0926673c69eca3a50cc7eba828e59131be..b55d3b250c36589a60839ac5bd619d2124f21172 100644 (file)
@@ -189,6 +189,7 @@ public class AlarmTriggerQueue : zavai.Service
             info.acked = true;
             acked(info);
             info.log.add("alarm acknowledged");
+            info.log.acked = true;
             zavai.log.log.end(info.log);
         }
         done_with_first();
index c2a0e56e4a15913d7aac4b62dd6acd7162337eb8..92f8f93cb919da40afe45b291979a1ee8b15134f 100644 (file)
@@ -152,6 +152,20 @@ public class Config
         set { _ringtone_alarm = set_string("ringtone_alarm", value); }
     }
 
+    private string _ringtone_call;
+    public string ringtone_call
+    {
+        get { return _ringtone_call; }
+        set { _ringtone_call = set_string("ringtone_call", value); }
+    }
+
+    private string _ringtone_sms;
+    public string ringtone_sms
+    {
+        get { return _ringtone_sms; }
+        set { _ringtone_sms = set_string("ringtone_sms", value); }
+    }
+
     public int backlight_max
     {
         get;
@@ -194,6 +208,8 @@ public class Config
         _power_button_keycode = get_int("power_button_keycode");
         _aux_button_keycode = get_int("aux_button_keycode");
         _ringtone_alarm = get_string("ringtone_alarm");
+        _ringtone_call = get_string("ringtone_call");
+        _ringtone_sms = get_string("ringtone_sms");
     }
 
     public Config()
@@ -219,6 +235,8 @@ public class Config
         power_button_keycode = 124;
         aux_button_keycode = 177;
         ringtone_alarm = "file:///usr/share/sounds/yue-fso/lec1.ogg";
+        ringtone_call = "file:///usr/share/sounds/yue-fso/jmf1.ogg";
+        ringtone_sms = "file:///usr/share/sounds/yue-fso/nothing4.ogg";
 
         // Read config
         if (lua.do_file(homedir + "/config"))
index ade1231781311bb371d944e4c7dc75507e5df591..2e2191550fcb8d7a948b4538d7fd509a7f34f721 100644 (file)
@@ -141,7 +141,9 @@ public abstract class Service : Object, Resource {
         if (el == null)
             return false;
 
-        requests.delete_link(el);
+        ++el.data.count;
+        if (el.data.count == 0)
+            requests.delete_link(el);
 
         if (requests != null)
             return false;
index ed9c60b9c9835466b5ca34e15ed999474e59f047..de96ee389dd51c508680d0df58837fab083dcdfb 100644 (file)
@@ -138,6 +138,9 @@ public class GSM: zavai.ScriptMonitorService
 
     public signal void status_changed(string message);
     public signal void info_changed();
+    public signal void new_call(int index);
+    public signal void end_call(int index);
+    public signal void new_sms();
 
     protected void dump_table(HashTable<string, Value?> vals)
     {
@@ -342,12 +345,15 @@ stderr.printf("ACQUIRE SIG %d\n", info_signal_strength);
 
     public void on_call_status(int index, string status, HashTable<string, Value?> properties)
     {
+        bool is_new = false;
+        bool is_done = false;
         stderr.printf("CALL STATUS %d %s\n", index, status);
         dump_table(properties);
 
         CallInfo? info = lookup_call(index);
         if (info == null)
         {
+            is_new = true;
             Value? v = properties.lookup("peer");
             string title;
             if (v != null)
@@ -380,6 +386,7 @@ stderr.printf("ACQUIRE SIG %d\n", info_signal_strength);
                     calls.delete_link(i);
                     break;
                 }
+            is_done = true;
         }
 
         /*
@@ -399,6 +406,11 @@ stderr.printf("ACQUIRE SIG %d\n", info_signal_strength);
             os.system("vibrator-stop")
             os.system("ledctrl --off gta02-aux:red");
         */
+
+        if (is_new && !is_done)
+            new_call(index);
+        if (is_done)
+            end_call(index);
     }
 
     public async void sms_log_and_delete(int idx)
@@ -421,6 +433,9 @@ stderr.printf("ACQUIRE SIG %d\n", info_signal_strength);
 
         // Delete message
         yield sim.delete_message(idx);
+
+        // Notify reception of the sms
+        new_sms();
     }
 }
 
diff --git a/src/leds.vala b/src/leds.vala
new file mode 100644 (file)
index 0000000..013e1fa
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * leds - Leds support
+ *
+ * Copyright (C) 2010  Enrico Zini <enrico@enricozini.org>
+ *
+ * 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 led {
+
+public class LedState
+{
+    public string name;
+    public int brightness;
+    public string trigger;
+    public int delay_on;
+    public int delay_off;
+
+    public LedState(string name)
+    {
+        this.name = name;
+        set_constant(0);
+    }
+
+    public void set_constant(int power)
+    {
+        brightness = power;
+        trigger = "none";
+        delay_on = 0;
+        delay_off = 0;
+    }
+
+    public void set_blink(int power, int delay_on=200, int delay_off=300)
+    {
+        brightness = power;
+        trigger = "timer";
+        this.delay_on = delay_on;
+        this.delay_off = delay_off;
+    }
+
+    public void to_omhacks(ref Omhacks.Led led)
+    {
+        led.brightness = brightness;
+        Memory.copy(led.trigger, trigger, trigger.size());
+        led.delay_on = 200;
+        led.delay_off = 300;
+    }
+}
+
+public class Led : zavai.Resource, Object
+{
+    protected Omhacks.Led led;
+
+    protected List<LedState> states;
+
+    public Led(string name) throws FileError
+    {
+        if (led.init(name) != 0)
+            throw new FileError.NOENT("led " + name + " not found");
+        states = new List<LedState>();
+    }
+
+    public void turn_off()
+    {
+        led.brightness = 0;
+        Memory.copy(led.trigger, "none", 5);
+        led.set();
+    }
+
+    public void push_state(LedState state)
+    {
+        states.prepend(state);
+        state.to_omhacks(ref led);
+        led.set();
+    }
+
+    public void pop_state(string name)
+    {
+        // Handle empty list
+        if (states == null) return;
+
+        // Track if the list head changed
+        weak List<LedState> old_top = states;
+
+        // Remove state "name" from the stack
+        for (weak List<LedState> i = states; i != null; i = i.next)
+            if (i.data.name == name)
+            {
+                states.delete_link(i);
+                break;
+            }
+
+        // If the list head changed, put into action the new top state
+        if (states != old_top)
+            if (states == null)
+                turn_off();
+            else {
+                // Activate the new top
+                states.data.to_omhacks(ref led);
+                led.set();
+            }
+    }
+
+    public void shutdown()
+    {
+        while (states != null)
+            states.delete_link(states);
+        turn_off();
+    }
+}
+
+public class AUXButton: zavai.Service
+{
+    public signal bool event(ulong time, bool pressed);
+
+    public AUXButton()
+    {
+        // Listen to the button via X
+        input.hotkeys.hotkey += on_auxbutton;
+        input.hotkeys.grab(zavai.config.aux_button_keycode, 0, false);
+        input.hotkeys.request("auxbutton");
+    }
+
+    protected bool on_auxbutton(uint keycode, ulong time, bool pressed)
+    {
+        if (keycode == zavai.config.aux_button_keycode)
+            return event(time, pressed);
+        return false;
+    }
+}
+
+public Led aux = null;
+public Led vibrator = null;
+public AUXButton auxbutton = null;
+
+public void init()
+{
+    auxbutton = new AUXButton();
+
+    try {
+        aux = new Led("gta02-aux:red");
+        zavai.registry.register(aux);
+    } catch (Error e) {
+        zavai.log.info("No aux led found");
+        aux = null;
+    }
+
+    try {
+        vibrator = new Led("neo1973:vibrator");
+        zavai.registry.register(vibrator);
+    } catch (Error e) {
+        zavai.log.info("No vibrator found");
+        vibrator = null;
+    }
+}
+
+}
+}
index f9838c5af31a51de2aa3ef3b077bdb5753715889..408dfa5540659a208f6adeede6dba34ee834cf50 100644 (file)
@@ -205,6 +205,7 @@ static int main (string[] args) {
        zavai.clock.init();
        zavai.audio.init();
        zavai.log.init();
+       zavai.led.init();
        zavai.wifi.init();
        zavai.bluetooth.init();
 
@@ -218,11 +219,11 @@ static int main (string[] args) {
        // User interface
        zavai.ui.music.init();
        zavai.ui.main.init();
+       zavai.ui.notify.init();
        zavai.ui.gps.init();
        zavai.ui.gsm.init();
        zavai.config.find_and_run_script("display", "init");
        zavai.ui.power.init();
-       zavai.ui.aux.init();
        zavai.ui.kbd.init();
        zavai.ui.wm.init();
        zavai.ui.calendar.init();
@@ -297,14 +298,25 @@ static int main (string[] args) {
     {
         zavai.audio.musicplayer.play("file://" + args[2]);
 
-        // Timeout.add(3 * 1000, () => {
-        //     zavai.audio.soundplayer.play("file:///backup/ciapino/src/openmoocow/data/moo.wav", true);
-        //     Timeout.add(4 * 1000, () => {
-        //         zavai.audio.soundplayer.stop();
-        //         return false;
-        //     });
-        //     return false;
-        // });
+        Timeout.add(2 * 1000, () => {
+            var ps = new zavai.audio.PlayerState("zavai", "file:///backup/ciapino/src/openmoocow/data/moo.wav", true);
+            zavai.audio.soundplayer.push_state(ps);
+            Timeout.add(8 * 1000, () => {
+                zavai.audio.soundplayer.pop_state("zavai");
+                return false;
+            });
+            return false;
+        });
+
+        Timeout.add(3 * 1000, () => {
+            var ps = new zavai.audio.PlayerState("zavai", zavai.config.ringtone_alarm, false);
+            zavai.audio.soundplayer.push_state(ps);
+            Timeout.add(4 * 1000, () => {
+                zavai.audio.soundplayer.pop_state("zavai");
+                return false;
+            });
+            return false;
+        });
     }
 
        Gtk.main();