From: gregor herrmann Date: Sun, 28 Mar 2010 18:34:12 +0000 (+0200) Subject: Merge branch 'master' into gregoa X-Git-Url: https://git.toastfreeware.priv.at/gregoa/zavai.git/commitdiff_plain/ec503392ddba6000fac8ac18dea94a0e2ba860c1?hp=d045a1d60e84f619f271b5d75509e81502ea2c77 Merge branch 'master' into gregoa --- diff --git a/README b/README index 97f1d24..1c727fb 100644 --- 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 diff --git a/src/app_alarm.vala b/src/app_alarm.vala index c3bfd7c..8cfff21 100644 --- a/src/app_alarm.vala +++ b/src/app_alarm.vala @@ -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 index db05e99..0000000 --- a/src/app_aux.vala +++ /dev/null @@ -1,118 +0,0 @@ -/* - * app_aux - AUX button interaction - * - * Copyright (C) 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 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(); -} - -} -} -} diff --git a/src/app_music.vala b/src/app_music.vala index d066e3c..8d79e84 100644 --- a/src/app_music.vala +++ b/src/app_music.vala @@ -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 index 0000000..804277d --- /dev/null +++ b/src/app_notify.vala @@ -0,0 +1,202 @@ +/* + * app_notify - zavai notification system + * + * Copyright (C) 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 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; +} + +} +} +} diff --git a/src/audio.vala b/src/audio.vala index 1c39420..51790d0 100644 --- a/src/audio.vala +++ b/src/audio.vala @@ -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 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; } - 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 old_top = states; + + // Remove state "name" from the stack + for (weak List 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); diff --git a/src/clock.vala b/src/clock.vala index fd5e6f0..b55d3b2 100644 --- a/src/clock.vala +++ b/src/clock.vala @@ -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(); diff --git a/src/config.vala b/src/config.vala index c2a0e56..92f8f93 100644 --- a/src/config.vala +++ b/src/config.vala @@ -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")) diff --git a/src/core.vala b/src/core.vala index ade1231..2e21915 100644 --- a/src/core.vala +++ b/src/core.vala @@ -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; diff --git a/src/gsm.vala b/src/gsm.vala index ed9c60b..de96ee3 100644 --- a/src/gsm.vala +++ b/src/gsm.vala @@ -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 vals) { @@ -342,12 +345,15 @@ stderr.printf("ACQUIRE SIG %d\n", info_signal_strength); public void on_call_status(int index, string status, HashTable 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 index 0000000..013e1fa --- /dev/null +++ b/src/leds.vala @@ -0,0 +1,173 @@ +/* + * leds - Leds support + * + * Copyright (C) 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 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 states; + + public Led(string name) throws FileError + { + if (led.init(name) != 0) + throw new FileError.NOENT("led " + name + " not found"); + states = new List(); + } + + 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 old_top = states; + + // Remove state "name" from the stack + for (weak List 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; + } +} + +} +} diff --git a/src/zavai.vala b/src/zavai.vala index f9838c5..408dfa5 100644 --- a/src/zavai.vala +++ b/src/zavai.vala @@ -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();