From: Enrico Zini Date: Fri, 26 Mar 2010 00:15:49 +0000 (+0000) Subject: Split non-ui functions in separate lib X-Git-Url: https://git.toastfreeware.priv.at/gregoa/zavai.git/commitdiff_plain/b58c46170a650521947aeaff5283a7a758ec75a1 Split non-ui functions in separate lib --- diff --git a/CMakeLists.txt b/CMakeLists.txt index a022b78..ae82bc4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,5 +4,6 @@ set(zavai_version "0.1") add_subdirectory(gtkfisheyelist) add_subdirectory(polygen) add_subdirectory(player) +add_subdirectory(zavai) add_subdirectory(src) #add_subdirectory(hooks) diff --git a/README b/README index 0bfa0a0..0d17b4c 100644 --- a/README +++ b/README @@ -177,22 +177,27 @@ TODO list / wish list http://git.freesmartphone.org/?p=specs.git;a=blob_plain;f=html/index.html;hb=HEAD * Features to add: + - if GPS time is more than 1 minute and less than 1 hour different than the + 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 - log - write data to disk as log happens (to have at least partial logs if power is cut) - more detailed GPX data (dop, elev..) - message (structured) (json?) + - flash aux when there are unacknowledged log entries - turn on/off gsm + start frameworkd as a subprocess, configured to only do phone + go through the dbus motions of turning on this and that, and entering PIN hardcoded in zavai config + GSM status on main screen (with messages while coming online, and operator, power and so on) - - log and refuse incoming calls and messages + - log incoming messages + - log and refuse incoming calls to "move" the GSM device to my laptop: socat FILE:/dev/ttySAC0 TCP-LISTEN:12345,bind=192.168.0.202 socat TCP:192.168.0.202:12345 PTY,link=/tmp/gps,raw,echo=0 - - alarm + play sound at alarm trigger - leave expired alarm on screen until acknowledged @@ -215,13 +220,6 @@ TODO list / wish list - audio notes - record audio notes, logging start and stop so it gets an associated GPX - shortcut icon in main screen - - check gobject introspection and dynamic loading - - there could be a basic loader core that just dynamically loads bits as - available/needed. Only the battery icon and calendar can be loaded on a - laptop, while on the moko one can also load the power menu. - Different bits can effectively work as plugins, to be there or not. - Alternative plugins can be loaded based on different technologies, too (a - gpsd satellite monitor, or a fso satellite monitor). - zavai does not look good in landscape mode - replace menus with a widget taking a list of actions, which then lays them out according to the screen size diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 657b95d..06cacbd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,7 +6,7 @@ set(zavai_version 0.1) set(packages gtk+-2.0 dbus-glib-1>=0.80 libwnck-1.0>=2.26.0 lua5.1 libomhacks x11 gdk-x11-2.0 libgps gstreamer-0.10) add_packages(ZAVAI ${packages}) -set(VALA_PACKAGES ${packages} posix linux-input dbus-extra gtkfisheyelist) +set(VALA_PACKAGES ${packages} posix linux-input dbus-extra gtkfisheyelist libzavai) set(VFLAGS --vapidir=${zavai_SOURCE_DIR} --vapidir=${gtkfisheyelist_BINARY_DIR}) add_definitions(-Wall) # -Werror @@ -22,14 +22,15 @@ else() message("-- Not using devkit-power-gobject") endif () +set(VFLAGS ${VFLAGS} --vapidir=${zavai_BINARY_DIR} --vapidir=${libzavai_SOURCE_DIR} --vapidir=${libzavai_BINARY_DIR}) + file(GLOB libvala [a-y]*.vala widgets/*.vala) -add_vala_library(libzavai ${libvala}) -add_library(libzavai STATIC ${libzavai_CSOURCES}) +add_vala_library(libzavaiui ${libvala}) +add_library(libzavaiui STATIC ${libzavaiui_CSOURCES}) -add_definitions(-DWNCK_I_KNOW_THIS_IS_UNSTABLE -DI_KNOW_THE_DEVICEKIT_POWER_API_IS_SUBJECT_TO_CHANGE -I${gtkfisheyelist_BINARY_DIR} -I${zavai_BINARY_DIR}) -set(VFLAGS ${VFLAGS} --vapidir=${zavai_BINARY_DIR}) -set(VALA_PACKAGES ${VALA_PACKAGES} libzavai) -link_libraries(gtkfisheyelist-static libzavai) +add_definitions(-DWNCK_I_KNOW_THIS_IS_UNSTABLE -DI_KNOW_THE_DEVICEKIT_POWER_API_IS_SUBJECT_TO_CHANGE -I${gtkfisheyelist_BINARY_DIR} -I${zavai_BINARY_DIR} -I${libzavai_BINARY_DIR}) +set(VALA_PACKAGES ${VALA_PACKAGES} libzavai libzavaiui) +link_libraries(gtkfisheyelist-static libzavai libzavaiui) file(GLOB zavala zavai.vala) add_vala_program(zavai ${zavala}) diff --git a/src/app.vala b/src/app.vala index 5281f56..6366b6a 100644 --- a/src/app.vala +++ b/src/app.vala @@ -158,37 +158,6 @@ public class Zavai : Gtk.Window, zavai.Resource show_all(); } } - - public void run_script(string command) - { - zavai.log.info("Run program: " + command); - string[] args = command.split(" "); - Pid pid; - try { - Process.spawn_async( - Environment.get_home_dir(), - args, - null, - SpawnFlags.SEARCH_PATH, - null, - out pid); - } catch (SpawnError e) { - zavai.log.error("Running " + command + ": " + e.message); - } - } - - public int run_script_sync(string command, out string std_out, out string std_err) - { - int status = -1; - zavai.log.info("Run program: " + command); - string[] args = command.split(" "); - try { - bool res = Process.spawn_sync(Environment.get_home_dir(), args, null, SpawnFlags.SEARCH_PATH, null, out std_out, out std_err, out status); - } catch (SpawnError e) { - zavai.log.error("Running " + command + ": " + e.message); - } - return status; - } } public abstract class Applet : Gtk.VBox, Resource diff --git a/src/app_power.vala b/src/app_power.vala index 33be3e9..8fedf3f 100644 --- a/src/app_power.vala +++ b/src/app_power.vala @@ -129,7 +129,7 @@ public class Power : zavai.Resource, Object } */ try { - zavai.app.run_script("pm-suspend"); + zavai.config.run_script("pm-suspend"); done = true; zavai.log.info("Suspend was done with zavai."); } catch (Error e) { @@ -141,7 +141,7 @@ public class Power : zavai.Resource, Object { try { //usage.Shutdown(); - zavai.app.run_script("shutdown -h now"); + zavai.config.run_script("shutdown -h now"); } catch (Error e) { zavai.log.error("Shutting down phone: " + e.message); } @@ -150,7 +150,7 @@ public class Power : zavai.Resource, Object { try { //usage.Reboot(); - zavai.app.run_script("shutdown -r now"); + zavai.config.run_script("shutdown -r now"); } catch (Error e) { zavai.log.error("Rebooting phone: " + e.message); } @@ -174,8 +174,7 @@ public class Power : zavai.Resource, Object // FIXME: X won't see events, but it's still generating interrupts, // isn't it? - int EVIOCGRAB = 0x40044590; - if (Posix.ioctl(screen_lock_fd, EVIOCGRAB, locked ? 1 : 0) != 0) + if (Posix.ioctl(screen_lock_fd, LinuxInput.Evio.CGRAB, locked ? 1 : 0) != 0) { zavai.log.error("Cannot EVIOCGRAB /dev/input/event1"); Posix.close(screen_lock_fd); @@ -486,7 +485,7 @@ public class Backlight: zavai.Service public void wiggle() { try { - zavai.app.run_script(zavai.config.homedir + "/display wiggle"); + zavai.config.run_script(zavai.config.homedir + "/display wiggle"); } catch (Error e) { zavai.log.error("Requesting/releasing resource Display: " + e.message); } @@ -497,7 +496,7 @@ public class Backlight: zavai.Service if (!started) { try { - zavai.app.run_script(zavai.config.homedir + "/display lock_off"); + zavai.config.run_script(zavai.config.homedir + "/display lock_off"); } catch (GLib.Error e) { zavai.log.error(e.message); } @@ -507,7 +506,7 @@ public class Backlight: zavai.Service public void unlock_screen() { try { - zavai.app.run_script(zavai.config.homedir + "/display defaults"); + zavai.config.run_script(zavai.config.homedir + "/display defaults"); } catch (GLib.Error e) { zavai.log.error(e.message); } @@ -517,7 +516,7 @@ public class Backlight: zavai.Service { if (started) return; try { - zavai.app.run_script(zavai.config.homedir + "/display lock_on"); + zavai.config.run_script(zavai.config.homedir + "/display lock_on"); zavai.log.info("Acquired display"); base.start(); } catch (GLib.Error e) { @@ -530,7 +529,7 @@ public class Backlight: zavai.Service { if (!started) return; try { - zavai.app.run_script(zavai.config.homedir + "/display defaults"); + zavai.config.run_script(zavai.config.homedir + "/display defaults"); zavai.log.info("Released display"); base.stop(); } catch (GLib.Error e) { diff --git a/src/at.vala b/src/at.vala deleted file mode 100644 index 33cdf27..0000000 --- a/src/at.vala +++ /dev/null @@ -1,164 +0,0 @@ -/* - * at - at interface - * - * Copyright (C) 2009 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 at { - -public struct Event -{ - int id; - time_t deadline; -} - -// Return the earliest ID in the queue, or -1 if none are found -// Queue is null for all queues, otherwise a queue name -public static Event earliestID(string? queue = null) -{ - Event res = { -1, 0 }; - - string argv[4]; - argv[0] = "/usr/bin/atq"; - if (queue == null) - argv[1] = null; - else - { - argv[1] = "-q"; - argv[2] = queue; - argv[3] = null; - } - - Pid pid; - int stdout; - - try - { - if (!Process.spawn_async_with_pipes("/", argv, null, SpawnFlags.STDERR_TO_DEV_NULL, null, out pid, null, out stdout, null)) - return res; - } catch (SpawnError e) { - stderr.printf("Cannot run 'at -q': %s\n", e.message); - return res; - } - - FileStream fs = FileStream.fdopen(stdout, "r"); - if (fs == null) - return res; - - char buf[200]; - string? line; - while ((line = fs.gets(buf)) != null) - { - if (!line[0].isdigit()) continue; - weak string rest; - ulong id = line.to_ulong(out rest, 10); - Time t = Time(); - rest = t.strptime(rest.offset(1), "%a %b %d %H:%M:%S %Y"); - if (rest == null) continue; - if (rest.size() < 2) continue; - //stderr.printf("PARSE QUEUE rest %s\n", rest); - // Skip the queue of tasks currently being executed - //if (rest[1] == '=') continue; - // Skip entries not in the wanted queue - if (queue != null && rest[1] != queue[0]) continue; - time_t tt = t.mktime(); - if (res.deadline == 0 || tt < res.deadline) { - res.id = (int)id; - res.deadline = tt; - } - } - Process.close_pid(pid); - return res; -} - -public delegate bool jobParser(int fd); - -// Get the contents of a job given its id -public static bool jobContents(int id, jobParser parser) -{ - string argv[4]; - argv[0] = "/usr/bin/at"; - argv[1] = "-c"; - argv[2] = id.to_string(); - argv[3] = null; - - Pid pid; - int stdoutfd; - - try - { - if (!Process.spawn_async_with_pipes("/", argv, null, SpawnFlags.STDERR_TO_DEV_NULL, null, out pid, null, out stdoutfd, null)) - return false; - } catch (SpawnError e) { - stderr.printf("Cannot run 'at -c': %s\n", e.message); - return false; - } - - bool res = parser(stdoutfd); - - Process.close_pid(pid); - - return res; -} - -/* -TODO: schedule alarms via at - -Uses the 'z' queue. - -atq -q z can be used to list the jobs (for example, at startup, or after a job has run) -at -c id can be used to query a job, parsing its contents (which can have - comments or variables being set) -zavai --notify ... can be used to notify the job (and start zavai if it's not running) - -Alarm needs to be able to serialize itself to an at invocation and to -deserialize itself from the output of at -c - -Alarm needs to deserialize also a job with no special markers whatsoever: a -generic at job. -*/ - - -/* -public class Alarm : Object -{ - // TODO: make a factory method to construct from an "at -c" output - - // TODO: make a method that provides an at invocation - - public signal void trigger(Alarm a); - - public time_t deadline; - public string label; - - public Alarm(time_t deadline, string label) - { - this.deadline = deadline; - this.label = label; - } -} -*/ - - // Schedule a task that notifies a string - // TODO public void schedule_label(const Alarm a); - - // Return the next item in the queue due to be run - // TODO public Alarm? next_scheduled(); - -} diff --git a/src/audio.vala b/src/audio.vala deleted file mode 100644 index 1c39420..0000000 --- a/src/audio.vala +++ /dev/null @@ -1,225 +0,0 @@ -/* - * 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 Omhacks.Led vibrator; - protected bool has_vibrator; - - /* - protected dynamic DBus.Object audiodev; - protected dynamic DBus.Object vibdev; - */ - - public Audio() - { - Object(name: "audio"); - - has_vibrator = (vibrator.init("neo1973:vibrator") == 0); - -/* - 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"); -*/ - 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) - { - zavai.log.debug("Make noise for alarm"); - if (has_vibrator) - { - 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) - { - vibrator.trigger[i] = (char)trig[i]; - if (trig[i] == 0) break; - } - vibrator.delay_on = 200; - vibrator.delay_off = 300; - vibrator.set(); - } - soundplayer.play(config.ringtone_alarm, true); - } - - public void on_alarm_done(clock.AlarmTriggerInfo info) - { - zavai.log.debug("Stop noise for alarm"); - if (has_vibrator) - { - var trig = "none"; - for (int i = 0; ; ++i) - { - vibrator.trigger[i] = (char)trig[i]; - if (trig[i] == 0) break; - } - vibrator.brightness = 0; - vibrator.set(); - } - 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); - } - // TODO: play music? - } -*/ -} - -public class Player: zavai.Resource, Object -{ - protected Gst.Element player; - protected bool playing; - protected Player slave; - protected Player master; - protected bool loop; - protected string uri; - public signal void state_changed(Gst.State new_state); - - public Player() - { - slave = null; - master = null; - player = Gst.ElementFactory.make("playbin", null); - playing = false; - loop = false; - var bus = player.get_bus(); - bus.add_signal_watch(); - bus.message += on_message; - } - - public void set_slave(Player player) - { - slave = player; - slave.master = this; - } - - public void play(string uri, bool loop = false) - { -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; - } - - 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; - } - - public void pause() - { - 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); - } - - 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); - } - - 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(); - } - } - - public void shutdown() - { - stop(); - } -} - -public Audio audio = null; -public Player musicplayer = null; -public Player soundplayer = null; - -public void init() -{ - audio = new Audio(); - musicplayer = new Player(); - soundplayer = new Player(); - soundplayer.set_slave(musicplayer); - zavai.registry.register(musicplayer); - zavai.registry.register(soundplayer); -} - -} -} diff --git a/src/bluetooth.vala b/src/bluetooth.vala deleted file mode 100644 index 0103d0f..0000000 --- a/src/bluetooth.vala +++ /dev/null @@ -1,61 +0,0 @@ -/* - * bluetooth - bluetooth resource for zavai - * - * 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 bluetooth { - -public class Bluetooth: zavai.ScriptService -{ - public Bluetooth() - { - Object(name: "bluetooth"); - started = script_status(); - } - - /// Start Bluetooth - public override void start() - { - if (started) return; - if (!script_start()) return; - zavai.log.info("bluetooth turned on"); - base.start(); - } - - // Release usage of GPS - public override void stop() - { - if (!started) return; - script_stop(); - base.stop(); - } -} - -public Bluetooth bluetooth = null; - -public void init() -{ - bluetooth = new Bluetooth(); - -} - -} -} diff --git a/src/clock.vala b/src/clock.vala deleted file mode 100644 index d08717b..0000000 --- a/src/clock.vala +++ /dev/null @@ -1,357 +0,0 @@ -/* - * clock - clock 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 clock { - -public enum SourceType -{ - SYSTEM, - GPS -} - -/* -TODO: schedule alarms via at - -Uses the 'z' queue. - -atq -q z can be used to list the jobs (for example, at startup, or after a job has run) -at -c id can be used to query a job, parsing its contents (which can have - comments or variables being set) -zavai --notify ... can be used to notify the job (and start zavai if it's not running) - -Alarm needs to be able to serialize itself to an at invocation and to -deserialize itself from the output of at -c - -Alarm needs to deserialize also a job with no special markers whatsoever: a -generic at job. - - - -refresh_alarms() -{ - oldtime = next_alarm ? next_alarm.time : 0 - next_alarm = the first alarm from atq - if (oldtime != next_alarm.time) - { - remove existing triggers - (triggers can be skipped if we don't need to support non-zavai alarms) - schedule a trigger calling refresh_alarms() at next_alarm.time + 30 seconds - (triggers can be skipped if we don't need to support non-zavai alarms) - } -} - -at clock constructor: refresh_alarms() -inotifywait -e close /usr/bin/at -> refresh_alarms() (shows when someone has just used at) - (can be skipped if we don't need to support non-zavai alarms) -at alarm triggered through zavai: refresh_alarms() - - -*/ - - -public class Alarm : Object -{ - public at.Event ev; - public string label; - - // Schedule with at - public static void schedule(string timespec, string label) throws Error - { - string argv[5]; - argv[0] = "/usr/bin/at"; - argv[1] = "-q"; - argv[2] = "z"; - argv[3] = timespec; - argv[4] = null; - - Pid pid; - int stdinfd; - - if (!Process.spawn_async_with_pipes("/", argv, null, SpawnFlags.STDERR_TO_DEV_NULL, null, out pid, out stdinfd, null, null)) - return; - - { - FileStream fs = FileStream.fdopen(stdinfd, "w"); - string display = GLib.Environment.get_variable("DISPLAY"); - if (display != null) - fs.printf("DISPLAY=\"%s\"; export DISPLAY\n", display); - fs.printf("# Zavai variables start here\n"); - fs.printf("ZAVAI_LABEL=\"%s\"\n", label.escape("")); - fs.printf("# Zavai commands starts here\n"); - fs.printf("%s notify \"$ZAVAI_LABEL\"", zavai.config.argv0); - } - - Process.close_pid(pid); - } - - // Get the label of the job with the given at ID - public static string? getLabel(int atID) - { - string label = null; - at.jobContents(atID, fd => { - FileStream fs = FileStream.fdopen(fd, "r"); - while (true) - { - string? line = fs.read_line(); - if (line == null) break; - if (line.has_prefix("ZAVAI_LABEL=\"")) - { - size_t size = line.size(); - if (size < 15) continue; - label = line.substring(13, (long)(size - 14)); - label = label.compress(); - break; - } - } - return true; - }); - return label; - } -} - -[DBus (name = "org.enricozini.zavai.Alarm")] -public class ZavaiClock : Object { - public void Notify (string label) { - clock.notify_alarm(label); - } -} - -public class AlarmTriggerInfo -{ - public uint id; - public string label; - public bool acked; - public bool canceled; - - public AlarmTriggerInfo(string label) - { - id = 0; - this.label = label; - acked = false; - canceled = false; - } -} - -public class AlarmTriggerQueue : zavai.Service -{ - protected List queue; - - public signal void triggered(AlarmTriggerInfo info); - public signal void acked(AlarmTriggerInfo info); - public signal void canceled(AlarmTriggerInfo info); - - public AlarmTriggerQueue() - { - queue = new List(); - } - - public uint enqueue_trigger(AlarmTriggerInfo info) - { - // Reuse IDs from the associated logger object - info.id = zavai.log.log.start("alarm", "Alarm " + info.label); - queue.append(info); - if (queue.data.id == info.id) - triggered(queue.data); - return info.id; - } - - protected void done_with_first() - { - var first = queue.data; - queue.remove_link(queue); - if (queue != null) - triggered(queue.data); - } - - public void ack(AlarmTriggerInfo info) - { - if (queue == null || info.id != queue.data.id) return; - if (!info.acked && !info.canceled) - { - info.acked = true; - acked(info); - zavai.log.log.add(info.id, "alarm acknowledged"); - zavai.log.log.end(info.id); - } - done_with_first(); - } - - public void cancel(AlarmTriggerInfo info) - { - if (queue == null || info.id != queue.data.id) return; - if (!info.acked && !info.canceled) - { - info.canceled = true; - canceled(info); - zavai.log.log.add(info.id, "alarm canceled"); - zavai.log.log.end(info.id); - } - done_with_first(); - } -} - -public class Clock: zavai.Service -{ - protected time_t last_gps_time; - protected time_t last_gps_time_system_time; - protected time_t last_system_time; - protected uint system_time_timeout; - protected time_t last_minute; - protected time_t chosen_time; - protected SourceType chosen_type; - protected ZavaiClock dbusClock; - - protected dynamic DBus.Object otimed_alarm; - protected dynamic DBus.Object rtc; - protected SList alarms; - - // Ticks once a minute - public signal void minute_changed(long time, SourceType source); - public signal void schedule_changed(Alarm? next); - - public Clock() - { - Object(name: "clock"); - alarms = null; - dbusClock = new ZavaiClock(); - last_minute = 0; - last_gps_time = 0; - last_gps_time_system_time = 0; - last_system_time = time_t(); - chosen_time = last_system_time; - - // FSO alarm system - otimed_alarm = zavai.registry.sbus.get_object( - "org.freesmartphone.otimed", - "/org/freesmartphone/Time/Alarm", - "org.freesmartphone.Time.Alarm"); - - rtc = zavai.registry.sbus.get_object( - "org.freesmartphone.odeviced", - "/org/freesmartphone/Device/RTC/0", - "org.freesmartphone.Device.RealtimeClock"); - - zavai.registry.sbus.register_object("/org/enricozini/Zavai/Clock", dbusClock); - } - - public void notify_alarm(string label) - { - stderr.printf("Notifying %s\n", label); - AlarmTriggerInfo info = new AlarmTriggerInfo(label); - alarm_trigger_queue.enqueue_trigger(info); - schedule_changed(next_alarm()); - } - - public Alarm? next_alarm() - { - at.Event ev; - ev = at.earliestID("z"); - if (ev.deadline == 0) - return null; - string label = Alarm.getLabel(ev.id); - Alarm res = new Alarm(); - res.ev = ev; - res.label = label; - return res; - } - - public void schedule(string timespec, string label) throws Error - { - Alarm.schedule(timespec, label); - schedule_changed(next_alarm()); - } - - private void on_gps_time(uint t) - { - if (t == 0) - { - last_gps_time_system_time = 0; - update_time(); - } else { - last_gps_time = (time_t)t; - last_gps_time_system_time = time_t(); - update_time(); - } - } - - private bool on_system_time() - { - last_system_time = time_t(); - update_time(); - return true; - } - - private void update_time() - { - if (last_gps_time_system_time + 10 > last_system_time) - { - chosen_time = last_gps_time; - chosen_type = SourceType.GPS; - } - else - { - chosen_time = last_system_time; - chosen_type = SourceType.SYSTEM; - } - if (chosen_time / 60 != last_minute) - { - last_minute = chosen_time / 60; - minute_changed(chosen_time, chosen_type); - } - } - - /// Request GPS resource - public override void start() - { - if (started) return; - - system_time_timeout = Timeout.add(5000, on_system_time); - zavai.gps.gps.time_changed += on_gps_time; - last_system_time = time_t(); - update_time(); - - base.start(); - } - - public override void stop() - { - if (!started) return; - - Source.remove(system_time_timeout); - zavai.gps.gps.time_changed -= on_gps_time; - - base.stop(); - } -} - -public Clock clock = null; -public AlarmTriggerQueue alarm_trigger_queue = null; - -public void init() -{ - clock = new Clock(); - alarm_trigger_queue = new AlarmTriggerQueue(); -} - -} -} diff --git a/src/config.vala b/src/config.vala deleted file mode 100644 index 3f9ff41..0000000 --- a/src/config.vala +++ /dev/null @@ -1,234 +0,0 @@ -/* - * config - zavai configuration - * - * 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 - */ - -namespace zavai { - -public class Config -{ - protected Lua.LuaVM lua; - protected weak string get_string(string name) - { - lua.get_global(name); - weak string res = lua.to_string(-1); - lua.pop(1); - return res; - } - protected string set_string(string name, string? val) - { - if (val == null) - lua.push_nil(); - else - lua.push_string(val); - lua.set_global(name); - return val; - } - protected weak int get_int(string name) - { - lua.get_global(name); - int res = lua.to_integer(-1); - lua.pop(1); - return res; - } - protected int set_int(string name, int val) - { - lua.push_integer(val); - lua.set_global(name); - return val; - } - - private string _version; - public string version - { - get { return _version; } - set { _version = set_string("version", value); } - } - - // "phone" or "laptop" - private string _profile; - public string profile - { - get { return _profile; } - set { _profile = set_string("profile", value); } - } - - private string _homedir; - public string homedir - { - get { return _homedir; } - set { _homedir = set_string("homedir", value); } - } - - private string _icondir; - public string icondir - { - get { return _icondir; } - set { _icondir = set_string("icondir", value); } - } - - private int _min_button_height; - public int min_button_height - { - get { return _min_button_height; } - set { _min_button_height = set_int("min_button_height", value); } - } - - private string _gpsd_host; - public string gpsd_host - { - get { return _gpsd_host; } - set { _gpsd_host = set_string("gpsd_host", value); } - } - - private string _gpsd_port; - public string gpsd_port - { - get { return _gpsd_port; } - set { _gpsd_port = set_string("gpsd_port", value); } - } - - private string _gprs_apn; - public string gprs_apn - { - get { return _gprs_apn; } - set { _gprs_apn = set_string("gprs_apn", value); } - } - - private string _gprs_user; - public string gprs_user - { - get { return _gprs_user; } - set { _gprs_user = set_string("gprs_user", value); } - } - - private string _gprs_pass; - public string gprs_pass - { - get { return _gprs_pass; } - set { _gprs_pass = set_string("gprs_pass", value); } - } - - private string _sim_pin; - public string sim_pin - { - get { return _sim_pin; } - set { _sim_pin = set_string("sim_pin", value); } - } - - private int _power_button_keycode; - public int power_button_keycode - { - get { return _power_button_keycode; } - set { _power_button_keycode = set_int("power_button_keycode", value); } - } - - private int _aux_button_keycode; - public int aux_button_keycode - { - get { return _aux_button_keycode; } - set { _aux_button_keycode = set_int("aux_button_keycode", value); } - } - - private string _ringtone_alarm; - public string ringtone_alarm - { - get { return _ringtone_alarm; } - set { _ringtone_alarm = set_string("ringtone_alarm", value); } - } - - public int backlight_max - { - get; - set; - } - - private string _argv0; - public string argv0 { - get { return _argv0; } - set { - if (value.chr(-1, '/') != null) - { - if (Path.is_absolute(value)) - { - _argv0 = value; - } else { - _argv0 = Path.build_filename(Environment.get_current_dir(), value, null); - } - } else { - _argv0 = Environment.find_program_in_path(value); - } - zavai.log.debug("ARGV0: " + _argv0); - } - } - - /// Reread config values from the Lua VM, to be run after running Lua code - protected void refresh_from_lua() - { - _version = get_string("version"); - _profile = get_string("profile"); - _homedir = get_string("homedir"); - _icondir = get_string("icondir"); - _min_button_height = get_int("min_button_height"); - _gpsd_host = get_string("gpsd_host"); - _gpsd_port = get_string("gpsd_port"); - _gprs_apn = get_string("gprs_apn"); - _gprs_user = get_string("gprs_user"); - _gprs_pass = get_string("gprs_pass"); - _sim_pin = get_string("sim_pin"); - _power_button_keycode = get_int("power_button_keycode"); - _aux_button_keycode = get_int("aux_button_keycode"); - _ringtone_alarm = get_string("ringtone_alarm"); - } - - public Config() - { - lua = new Lua.LuaVM(); - lua.open_libs(); - - // Set defaults - version = "0.1"; - profile = "phone"; - homedir = GLib.Environment.get_home_dir() + "/.zavai"; - icondir = GLib.Environment.get_variable("ZAVAI_ICONDIR"); - if (icondir == null) - icondir = "/usr/share/zavai/icons"; - min_button_height = 80; - gpsd_host = "localhost"; - gpsd_port = "gpsd"; - gprs_apn = "general.t-mobile.uk"; - gprs_user = "x"; - gprs_pass = "x"; - sim_pin = "1234"; - backlight_max = 15; - power_button_keycode = 124; - aux_button_keycode = 177; - ringtone_alarm = "file:///usr/share/sounds/yue-fso/lec1.ogg"; - - // Read config - if (lua.do_file(homedir + "/config")) - { - zavai.log.error("Failed to parse " + homedir + "/config: " + lua.to_string(-1)); - } - refresh_from_lua(); - } -} - -public Config config = null; - -} diff --git a/src/core.vala b/src/core.vala deleted file mode 100644 index 27c621b..0000000 --- a/src/core.vala +++ /dev/null @@ -1,279 +0,0 @@ -/* - * app - zavai main window - * - * Copyright (C) 2009 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 { - -public interface Resource : Object { - /** - * Shut down this resource. - * - * Normally one does nothing here, but it is important to give resources a - * chance to do cleanup when the program quits. - * - * This can be used for tasks like closing the tags on a GPX track, - * releasing a FSO resource, restoring mixer settings and so on. - */ - public abstract void shutdown(); -} - -public abstract class Service : Object, Resource { - public string name { get; construct; } - - bool _started; - public bool started { - get { return _started; } - set { _started = value; } - } - - public signal void toggled(bool new_state); - - protected class Request - { - public string requestor; - public int count; - public Request(string requestor) - { - this.requestor = requestor; - count = 1; - } - } - - protected List requests; - - construct - { - started = false; - requests = null; - zavai.registry.register(this); - } - - public void shutdown() - { - stop(); - } - - /// Activate the service - protected virtual void start() - { - if (!started) - { - zavai.log.info("Service " + name + " started\n"); - started = true; - toggled(started); - } - } - - /// Deactivate the service - protected virtual void stop() - { - if (started) - { - zavai.log.info("Service " + name + " stopped\n"); - started = false; - toggled(started); - } - } - - /** - Request a resource using the given ID. - * - * If it is the first time the resource is requested, start it and - * return true. Else, take note of the request and return false. - * - * If a resource is requested multiple times with the same ID, it will - * need to be released multiple times with that ID. - */ - public bool request(string id) - { - bool res = (requests == null); - bool got = false; - for (weak List i = requests; i != null; i = i.next) - if (i.data.requestor == id) - { - ++i.data.count; - got = true; - break; - } - if (!got) - requests.prepend(new Request(id)); - if (res) start(); - return res; - } - - /** - * Release a resource using the given ID. - * - * If after the call nothing is requesting the resource, stop it and - * return true. Else, take note of the release and return false. - * - * If a resource is requested multiple times with the same ID, it will - * need to be released multiple times with that ID. - */ - public bool release(string id) - { - weak List el = null; - for (weak List i = requests; i != null; i = i.next) - if (i.data.requestor == id) - { - el = i; - break; - } - - if (el == null) - return false; - - requests.delete_link(el); - - if (requests != null) - return false; - - stop(); - return true; - } -} - -public abstract class ScriptService : Service -{ - protected bool script_start() - { - try { - // Then run our own script - zavai.app.run_script(zavai.config.homedir + "/" + name + " start"); - return true; - } catch (Error e) { - zavai.log.error("Running " + zavai.config.homedir + "/" + name + " start: " + e.message); - return false; - } - } - - protected bool script_stop() - { - try { - // Then run our own script - zavai.app.run_script(zavai.config.homedir + "/" + name + " stop"); - return true; - } catch (Error e) { - zavai.log.error("Running " + zavai.config.homedir + "/" + name + " stop: " + e.message); - return false; - } - } - - protected bool script_status() - { - string std_out; - string std_err; - string command = zavai.config.homedir + "/" + name + " status"; - int res = zavai.app.run_script_sync(command, out std_out, out std_err); - if (res != 0) - { - zavai.log.error("Running " + command + ": " + std_err); - return false; - } - - std_out._strip(); - - return (std_out == "on"); - } -} - -public abstract class ScriptMonitorService : Service -{ - protected Pid child_pid; - protected int child_watch_id; - - ScriptMonitorService() - { - child_pid = 0; - child_watch_id = 0; - } - - protected bool script_start() - { - string command = zavai.config.homedir + "/" + name + " pre"; - try { - // Then run our own script - zavai.app.run_script(command); - } catch (Error e) { - zavai.log.error("Running " + command + ": " + e.message); - return false; - } - - command = zavai.config.homedir + "/" + name + " run"; - zavai.log.info("Run program: " + command); - string[] args = command.split(" "); - try { - Process.spawn_async( - Environment.get_home_dir(), - args, - null, - SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD, - null, - out child_pid); - } catch (SpawnError e) { - zavai.log.error("Running " + command + ": " + e.message); - return false; - } - - // Add a child watch source to know when it ends - ChildWatch.add(child_pid, on_child); - - return true; - } - - protected bool script_stop() - { - Posix.kill((Posix.pid_t)child_pid, Posix.SIGTERM); - return true; - } - - protected void on_child(Pid pid, int status) - { - zavai.log.info("Exited"); -stderr.printf("STATUS %d\n", status); - Process.close_pid(pid); - - string command = zavai.config.homedir + "/" + name + " post"; - try { - // Then run our own script - zavai.app.run_script(command); - } catch (Error e) { - zavai.log.error("Running " + command + ": " + e.message); - return; - } - - cleanup_after_script_stop(); - - base.stop(); - } - - protected virtual void cleanup_after_script_stop() - { - } - - /* - protected bool script_status() - { - } - */ -} - -} diff --git a/src/dbus-extra.vapi b/src/dbus-extra.vapi deleted file mode 100644 index 5213899..0000000 --- a/src/dbus-extra.vapi +++ /dev/null @@ -1,5 +0,0 @@ -namespace DBus { - [CCode (cname = "dbus_bus_get_unique_name")] - public unowned string bus_get_unique_name (DBus.RawConnection conn); -} - diff --git a/src/devkit-power-gobject.vapi b/src/devkit-power-gobject.vapi deleted file mode 100644 index 139abc2..0000000 --- a/src/devkit-power-gobject.vapi +++ /dev/null @@ -1,232 +0,0 @@ -/* devkit-power-gobject.vapi generated by vapigen, do not modify. */ - -[CCode (cprefix = "Dkp", lower_case_cprefix = "dkp_")] -namespace Dkp { - [CCode (cheader_filename = "devkit-power-gobject/devicekit-power.h")] - public class Client : GLib.Object { - [CCode (has_construct_function = false)] - public Client (); - public unowned GLib.PtrArray enumerate_devices () throws GLib.Error; - [CCode (cname = "dkp_client_can_hibernate")] - public bool get_can_hibernate (); - [CCode (cname = "dkp_client_can_suspend")] - public bool get_can_suspend (); - public unowned string get_daemon_version (); - [CCode (cname = "dkp_client_lid_is_closed")] - public bool get_lid_is_closed (); - [CCode (cname = "dkp_client_on_battery")] - public bool get_on_battery (); - [CCode (cname = "dkp_client_on_low_battery")] - public bool get_on_low_battery (); - public bool hibernate () throws GLib.Error; - public bool suspend () throws GLib.Error; - [NoAccessorMethod] - public bool can_hibernate { get; } - [NoAccessorMethod] - public bool can_suspend { get; } - public string daemon_version { get; } - [NoAccessorMethod] - public bool lid_is_closed { get; } - [NoAccessorMethod] - public bool lid_is_present { get; } - [NoAccessorMethod] - public bool on_battery { get; } - [NoAccessorMethod] - public bool on_low_battery { get; } - public virtual signal void changed (); - public virtual signal void device_added (void* device); - public virtual signal void device_changed (void* device); - public virtual signal void device_removed (void* device); - } - [CCode (cheader_filename = "devkit-power-gobject/devicekit-power.h")] - public class Device : GLib.Object { - [CCode (has_construct_function = false)] - public Device (); - public unowned GLib.PtrArray get_history (string type, uint timespec, uint resolution) throws GLib.Error; - public unowned string get_object_path (); - public unowned GLib.PtrArray get_statistics (string type) throws GLib.Error; - public bool print (); - public bool refresh () throws GLib.Error; - public bool set_object_path (string object_path) throws GLib.Error; - public static Dkp.DeviceState state_from_text (string state); - public static unowned string state_to_text (Dkp.DeviceState state_enum); - public static Dkp.DeviceTechnology technology_from_text (string technology); - public static unowned string technology_to_text (Dkp.DeviceTechnology technology_enum); - public static Dkp.DeviceType type_from_text (string type); - public static unowned string type_to_text (Dkp.DeviceType type_enum); - [NoAccessorMethod] - public double capacity { get; set; } - [NoAccessorMethod] - public double energy { get; set; } - [NoAccessorMethod] - public double energy_empty { get; set; } - [NoAccessorMethod] - public double energy_full { get; set; } - [NoAccessorMethod] - public double energy_full_design { get; set; } - [NoAccessorMethod] - public double energy_rate { get; set; } - [NoAccessorMethod] - public bool has_history { get; set; } - [NoAccessorMethod] - public bool has_statistics { get; set; } - [NoAccessorMethod] - public bool is_present { get; set; } - [NoAccessorMethod] - public bool is_rechargeable { get; set; } - [NoAccessorMethod] - public string model { owned get; set; } - [NoAccessorMethod] - public string native_path { owned get; set; } - [NoAccessorMethod] - public bool online { get; set; } - [NoAccessorMethod] - public double percentage { get; set; } - [NoAccessorMethod] - public bool power_supply { get; set; } - [NoAccessorMethod] - public bool recall_notice { get; set; } - [NoAccessorMethod] - public string recall_url { owned get; set; } - [NoAccessorMethod] - public string recall_vendor { owned get; set; } - [NoAccessorMethod] - public string serial { owned get; set; } - [NoAccessorMethod] - public uint state { get; set; } - [NoAccessorMethod] - public uint technology { get; set; } - [NoAccessorMethod] - public int64 time_to_empty { get; set; } - [NoAccessorMethod] - public int64 time_to_full { get; set; } - [NoAccessorMethod] - public uint type { get; set; } - [NoAccessorMethod] - public uint64 update_time { get; set; } - [NoAccessorMethod] - public string vendor { owned get; set; } - [NoAccessorMethod] - public double voltage { get; set; } - public virtual signal void changed (void* obj); - } - [Compact] - [CCode (copy_function = "dkp_history_obj_copy", cheader_filename = "devkit-power-gobject/devicekit-power.h")] - public class HistoryObj { - public Dkp.DeviceState state; - public uint time; - public double value; - [CCode (has_construct_function = false)] - public HistoryObj (); - public bool clear (); - public unowned Dkp.HistoryObj copy (); - public static unowned Dkp.HistoryObj create (double value, Dkp.DeviceState state); - public bool equal (Dkp.HistoryObj obj2); - public static unowned Dkp.HistoryObj from_string (string text); - public bool print (); - public unowned string to_string (); - } - [Compact] - [CCode (copy_function = "dkp_qos_obj_copy", cheader_filename = "devkit-power-gobject/devicekit-power.h")] - public class QosObj { - public weak string cmdline; - public uint cookie; - public bool persistent; - public uint pid; - public weak string sender; - public uint64 timespec; - public Dkp.QosType type; - public uint uid; - public int value; - [CCode (has_construct_function = false)] - public QosObj (); - public unowned Dkp.QosObj copy (); - public bool equal (Dkp.QosObj obj2); - public bool print (); - } - [Compact] - [CCode (copy_function = "dkp_stats_obj_copy", cheader_filename = "devkit-power-gobject/devicekit-power.h")] - public class StatsObj { - public double accuracy; - public double value; - [CCode (has_construct_function = false)] - public StatsObj (); - public unowned Dkp.StatsObj copy (); - public static unowned Dkp.StatsObj create (double value, double accuracy); - public static unowned Dkp.StatsObj from_string (string text); - public unowned string to_string (); - } - [CCode (cheader_filename = "devkit-power-gobject/devicekit-power.h")] - public class Wakeups : GLib.Object { - [CCode (has_construct_function = false)] - public Wakeups (); - public unowned GLib.PtrArray get_data () throws GLib.Error; - public uint get_total () throws GLib.Error; - public bool has_capability (); - public virtual signal void data_changed (); - public virtual signal void total_changed (uint value); - } - [Compact] - [CCode (copy_function = "dkp_wakeups_obj_copy", cheader_filename = "devkit-power-gobject/devicekit-power.h")] - public class WakeupsObj { - public weak string cmdline; - public weak string details; - public uint id; - public bool is_userspace; - public uint old; - public float value; - [CCode (has_construct_function = false)] - public WakeupsObj (); - public unowned Dkp.WakeupsObj copy (); - public bool equal (Dkp.WakeupsObj obj2); - public bool print (); - } - [CCode (cprefix = "DKP_DEVICE_STATE_", has_type_id = "0", cheader_filename = "devkit-power-gobject/devicekit-power.h")] - public enum DeviceState { - UNKNOWN, - CHARGING, - DISCHARGING, - EMPTY, - FULLY_CHARGED, - PENDING_CHARGE, - PENDING_DISCHARGE, - LAST - } - [CCode (cprefix = "DKP_DEVICE_TECHNOLOGY_", has_type_id = "0", cheader_filename = "devkit-power-gobject/devicekit-power.h")] - public enum DeviceTechnology { - UNKNOWN, - LITHIUM_ION, - LITHIUM_POLYMER, - LITHIUM_IRON_PHOSPHATE, - LEAD_ACID, - NICKEL_CADMIUM, - NICKEL_METAL_HYDRIDE, - LAST - } - [CCode (cprefix = "DKP_DEVICE_TYPE_", has_type_id = "0", cheader_filename = "devkit-power-gobject/devicekit-power.h")] - public enum DeviceType { - UNKNOWN, - LINE_POWER, - BATTERY, - UPS, - MONITOR, - MOUSE, - KEYBOARD, - PDA, - PHONE, - LAST - } - [CCode (cprefix = "DKP_QOS_TYPE_", has_type_id = "0", cheader_filename = "devkit-power-gobject/devicekit-power.h")] - public enum QosType { - UNKNOWN, - NETWORK, - CPU_DMA, - LAST - } - [CCode (cheader_filename = "devkit-power-gobject/devicekit-power.h")] - public const int COMPILE_VERSION; - [CCode (cheader_filename = "devkit-power-gobject/devicekit-power.h")] - public static Dkp.QosType qos_type_from_text (string type); - [CCode (cheader_filename = "devkit-power-gobject/devicekit-power.h")] - public static unowned string qos_type_to_text (Dkp.QosType type); -} diff --git a/src/gps.py b/src/gps.py new file mode 100755 index 0000000..2b73da7 --- /dev/null +++ b/src/gps.py @@ -0,0 +1,345 @@ +# gps - gps resource for zavai +# +# Copyright (C) 2009 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 + +#import sys +import os +import os.path +import time +import dbus +import zavai + +class GPSMonitor(zavai.Service): + def __init__(self, gps): + super(GPSMonitor, self).__init__(["satellites"]) + + self.gps = gps + self.gps_ubx = gps.gps_ubx + + # This piece of machinery is taken from Zhone + self.debug_busy = None + self.debug_want = set( ["NAV-STATUS", "NAV-SVINFO"] ) + self.debug_have = set() + self.debug_error = set() + + def debug_update(self): + if self.debug_busy is None: + pending = self.debug_want - self.debug_have - self.debug_error + if pending: + self.debug_busy = pending.pop() + self.gps_ubx.SetDebugFilter( + self.debug_busy, + True, + reply_handler=self.on_debug_reply, + error_handler=self.on_debug_error, + ) + + def debug_request(self): + self.debug_have = set() + self.debug_update() + + def on_debug_reply(self): + self.debug_have.add(self.debug_busy) + self.debug_busy = None + self.debug_update() + + def on_debug_error(self, e): + zavai.info(e, "error while requesting debug packet %s" % self.debug_busy) + self.debug_error.add(self.debug_busy) + self.debug_busy = None + self.debug_update() + + def on_satellites_changed(self, satellites): + zavai.info("gps monitor: satellites changed") + self.debug_request() + + def on_ubxdebug_packet(self, clid, length, data): + zavai.info("gps monitor: UBX debug packet") + self.notify("satellites", clid, length, data) + + def start(self): + self.gps.connect("gps", self) + # TODO: find out how come sometimes these events are not sent + self.gps.bus.add_signal_receiver( + self.on_satellites_changed, 'SatellitesChanged', 'org.freedesktop.Gypsy.Satellite', + 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') + self.gps.bus.add_signal_receiver( + self.on_ubxdebug_packet, 'DebugPacket', 'org.freesmartphone.GPS.UBX', + 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') + self.debug_request() + + def stop(self): + self.gps.bus.remove_signal_receiver( + self.on_satellites_changed, 'SatellitesChanged', 'org.freedesktop.Gypsy.Satellite', + 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') + self.gps.bus.remove_signal_receiver( + self.on_ubxdebug_packet, 'DebugPacket', 'org.freesmartphone.GPS.UBX', + 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') + self.gps.disconnect("gps", self) + + +class GPSPosition(zavai.Service): + def __init__(self, gps): + super(GPSPosition, self).__init__(["position"]) + self.gps = gps + + def on_position_changed(self, fields, tstamp, lat, lon, alt): + zavai.info("gps position: position changed") + self.notify("position", fields, tstamp, lat, lon, alt) + + def start(self): + self.gps.connect("gps", self) + self.gps.bus.add_signal_receiver( + self.on_position_changed, 'PositionChanged', 'org.freedesktop.Gypsy.Position', + 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') + + def stop(self): + self.gps.bus.remove_signal_receiver( + self.on_position_changed, 'PositionChanged', 'org.freedesktop.Gypsy.Position', + 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') + self.gps.disconnect("gps", self) + +# For a list of dbus services, look in /etc/dbus-1/system.d/ +class GPS(zavai.Service): + def __init__(self, registry, name): + super(GPS, self).__init__(["gps"]) + + self.bus = registry.resource("dbus.system_bus") + + # see mdbus -s org.freesmartphone.ousaged /org/freesmartphone/Usage + self.usage = self.bus.get_object('org.freesmartphone.ousaged', '/org/freesmartphone/Usage') + self.usage = dbus.Interface(self.usage, "org.freesmartphone.Usage") + + # see mdbus -s org.freesmartphone.ogpsd /org/freedesktop/Gypsy + gps = self.bus.get_object('org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') + self.gps = dbus.Interface(gps, "org.freedesktop.Gypsy.Device") + self.gps_time = dbus.Interface(gps, "org.freedesktop.Gypsy.Time") + self.gps_position = dbus.Interface(gps, 'org.freedesktop.Gypsy.Position') + self.gps_ubx = dbus.Interface(gps, 'org.freesmartphone.GPS.UBX') + + self.monitor = GPSMonitor(self) + self.position = GPSPosition(self) + + def start(self): + """Request GPS resource""" + self.usage.RequestResource('GPS') + zavai.info("Acquired GPS") + + def stop(self): + """Release usage of GPS""" + self.usage.ReleaseResource('GPS') + zavai.info("Released GPS") + +# def wait_for_fix(self, callback): +# status = self.gps.GetFixStatus() +# if status in [2, 3]: +# zavai.info("We already have a fix, good.") +# callback() +# return True +# else: +# zavai.info("Waiting for a fix...") +# self.waiting_for_fix = callback +# self.bus.add_signal_receiver( +# self.on_fix_status_changed, 'FixStatusChanged', 'org.freedesktop.Gypsy.Device', +# 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') +# return False +# +# def on_fix_status_changed(self, status): +# if status not in [2, 3]: return +# +# zavai.info("Got GPS fix") +# self.bus.remove_signal_receiver( +# self.on_fix_status_changed, 'FixStatusChanged', 'org.freedesktop.Gypsy.Device', +# 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') +# +# if self.waiting_for_fix: +# self.waiting_for_fix() +# self.waiting_for_fix = None +# + +# def start_recording(self): +# if self.gps_monitor: +# self.gps_monitor.stop() +# self.gps_monitor = None +# +# if not self.audio: +# return +# +# # Sync system time +# gpstime = self.gps.gps_time.GetTime() +# subprocess.call(["date", "-s", "@%d" % gpstime]) +# subprocess.call(["hwclock", "--systohc"]) +# +# # Compute basename for output files +# self.basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(gpstime)) +# self.basename = os.path.join(AUDIODIR, self.basename) +# +# # Start recording the GPX track +# self.gpx = GPX(self.basename) +# self.gps.track_position(self.on_position_changed) +# +# # Start recording in background forking arecord +# self.audio.set_basename(self.basename) +# self.audio.start_recording() +# + +class GPX(zavai.Service): + "Write GPX track and waypoint files" + def __init__(self, registry, name): + super(GPX, self).__init__(["gpx"]) + self.registry = registry + self.trk = None + self.wpt = None + self.last_pos = None + conf = registry.resource("conf") + self.trackdir = conf.homedir + self.activity_monitors = set() + + def add_activity_monitor(self, cb): + self.activity_monitors.add(cb) + cb(self, self.last_pos is not None) + + def del_activity_monitor(self, cb): + self.activity_monitors.discard(cb) + + def notify_activity_monitors(self): + for mon in self.activity_monitors: + mon(self, self.last_pos is not None) + + def start(self): + zavai.info("Starting GPX trace subsystem") + gps = self.registry.resource("gps") + gps.position.connect("position", self.on_position_changed) + + def stop(self): + zavai.info("Stopping GPX trace subsystem") + gps = self.registry.resource("gps") + gps.position.disconnect("position", self.on_position_changed) + self.stop_track() + + def on_position_changed(self, fields, tstamp, lat, lon, alt): + self.last_pos = (fields, tstamp, lat, lon, alt) + self.trackpoint() + + def start_track(self, tstamp = None, basename = None): + if basename is not None: + self.basename = basename + elif tstamp is not None: + # Compute basename for output files + self.basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(tstamp)) + self.basename = os.path.join(self.trackdir, self.basename) + + self.trk = open(self.basename + "-trk.gpx", "wt") + print >>self.trk, """ + + + """ % zavai.VERSION + + self.wpt = open(self.basename + "-wpt.gpx", "wt") + print >>self.wpt, """ +""" % zavai.VERSION + + self.wpt_seq = 1; + self.notify_activity_monitors() + + def stop_track(self): + if self.trk is not None: + print >>self.trk, "" + self.trk.close() + self.trk = None + if self.wpt is not None: + print >>self.wpt, "" + self.wpt.close() + self.wpt = None + self.last_pos = None + self.notify_activity_monitors() + + def trackpoint(self): + "Mark a track point" + if self.last_pos is None: + return + + fields, tstamp, lat, lon, ele = self.last_pos + + if not self.trk: + self.start_track(tstamp) + + print >>self.trk, """ + + %f""" % (lat, lon, time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(tstamp)), ele) + #if course is not None: print >>self.trk, " %f" % course + #if speed is not None: print >>self.trk, " %f" % speed + #if fix is not None: print >>self.trk, " %f" % fix + #if hdop is not None: print >>self.trk, " %f" % hdop + print >>self.trk, "" + + def waypoint(self, name = None): + "Mark a waypoint" + if self.last_pos is None: + return + + fields, tstamp, lat, lon, ele = self.last_pos + + if not self.wpt: + self.start_track(tstamp) + + if name is None: + name = "wpt_%d" % self.wpt_seq + self.wpt_seq += 1 + + print >>self.wpt, """ + %s + + %f +""" % ( + lat, lon, name, time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(tstamp)), ele) + + +# def record(self): +# self.audio = Audio(self.make_waypoint) +# self.gps = GPS() +# # Get a fix and start recording +# if not self.gps.wait_for_fix(self.start_recording): +# self.gps_monitor = GPSMonitor(self.gps) +# self.gps_monitor.start() +# +# def monitor(self): +# self.audio = None +# self.gps = GPS() +# self.gps_monitor = GPSMonitor(self.gps) +# self.gps_monitor.start() +# +# +# def make_waypoint(self): +# if self.gpx is None: +# return +# if self.last_pos is None: +# self.last_pos = self.gps.gps_position.GetPosition() +# (fields, tstamp, lat, lon, alt) = self.last_pos +# self.gpx.waypoint(tstamp, lat, lon, alt) +# zavai.info("Making waypoint at %s: %f, %f, %f" % ( +# time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(tstamp)), lat, lon, alt)) diff --git a/src/gps.vala b/src/gps.vala deleted file mode 100644 index 950d76b..0000000 --- a/src/gps.vala +++ /dev/null @@ -1,247 +0,0 @@ -/* - * gps - gps 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 gps { - -// For a list of dbus services, look in /etc/dbus-1/system.d/ -public class GPS: zavai.ScriptService -{ - protected libgps.data_t data; - protected IOChannel gpsfd = null; - protected uint gpsfd_watch = 0; - - protected int old_fix_status = libgps.STATUS_NO_FIX; - protected uint old_time = 0; - protected double old_lat = 1000; - protected double old_lon = 1000; - - public signal void fix_status_changed(int status); - public signal void time_changed(uint time); - public signal void pos_changed(); - - public GPS() - { - Object(name: "gps"); - data = libgps.data_t(); - started = script_status(); - } - - public int fix_status() { return old_fix_status; } - public double time() { return old_time; } - public weak libgps.data_t info() { return data; } - - protected bool on_input_data(IOChannel source, IOCondition condition) - { - while (libgps.waiting(ref data)) - { - int res = libgps.poll(ref data); - if (res != 0) - zavai.log.error(libgps.errstr(res)); - - if (data.status != old_fix_status) - { - fix_status_changed(data.status); - old_fix_status = data.status; - } - - uint cur_time = (uint)data.fix.time; - if (data.status != libgps.STATUS_NO_FIX && old_time != cur_time) - { - time_changed(cur_time); - old_time = cur_time; - } - - double lat = (data.status == libgps.STATUS_NO_FIX ? 1000 : data.fix.latitude); - double lon = (data.status == libgps.STATUS_NO_FIX ? 1000 : data.fix.longitude); - if (lat != old_lat || lon != old_lon) - pos_changed(); - - /* - stderr.printf("GPSMSG %d %d\n", (int)data.set, data.status); - stderr.printf("SATUSED %d\n", data.satellites_used); - stderr.printf("SWT %f\n", data.skyview_time); - stderr.printf("SATVIS %d\n", data.satellites_visible); - for (int i = 0; i < data.satellites_visible; ++i) - { - stderr.printf("PRN %d ELE %d AZI %d SS %f\n", - data.PRN[i], data.elevation[i], data.azimuth[i], data.ss[i]); - } - */ - } - return true; - } - - /// Request GPS resource - public override void start() - { - if (started) return; - - if (!script_start()) return; - - zavai.log.info("Connecting to gpsd at " + config.gpsd_host + ":" + config.gpsd_port); - int res = libgps.open_r(config.gpsd_host, config.gpsd_port, ref data); - if (res != 0) - { - zavai.log.error(libgps.errstr(res)); - return; - } - - res = libgps.stream(ref data, libgps.WATCH_ENABLE, null); - if (res != 0) - { - zavai.log.error(libgps.errstr(res)); - return; - } - - //res = libgps.send(ref data, "?SKY;"); - //res = libgps.send(ref data, "?WATCH;"); - //if (res != 0) zavai.log.error(libgps.errstr(res)); - - gpsfd = new IOChannel.unix_new(data.gps_fd); - try { - gpsfd.set_encoding(null); - } catch (Error e) { - zavai.log.error("Setting encoding to null on gpsd io channel: " + e.message); - } - //gpsfd.set_buffered(false); - gpsfd_watch = gpsfd.add_watch(IOCondition.IN, on_input_data); - - zavai.log.info("GPS turned on"); - base.start(); - } - - // Release usage of GPS - public override void stop() - { - if (!started) return; - - Source.remove(gpsfd_watch); - - int res = libgps.close(ref data); - if (res != 0) - zavai.log.error(libgps.errstr(res)); - - script_stop(); - - if (old_fix_status != libgps.STATUS_NO_FIX) - { - old_fix_status = libgps.STATUS_NO_FIX; - fix_status_changed(old_fix_status); - } - - if (old_time != 0) - { - old_time = 0; - time_changed(old_time); - } - - base.stop(); - } -} - -// # def start_recording(self): -// # if self.gps_monitor: -// # self.gps_monitor.stop() -// # self.gps_monitor = None -// # -// # if not self.audio: -// # return -// # -// # # Sync system time -// # gpstime = self.gps.gps_time.GetTime() -// # subprocess.call(["date", "-s", "@%d" % gpstime]) -// # subprocess.call(["hwclock", "--systohc"]) -// # -// # # Compute basename for output files -// # self.basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(gpstime)) -// # self.basename = os.path.join(AUDIODIR, self.basename) -// # -// # # Start recording the GPX track -// # self.gpx = GPX(self.basename) -// # self.gps.track_position(self.on_position_changed) -// # -// # # Start recording in background forking arecord -// # self.audio.set_basename(self.basename) -// # self.audio.start_recording() -// # - -// Write GPX track and waypoint files -public class GPX : Service -{ - protected uint wpt_seq = 0; - protected uint log_id = 0; - - public GPX() - { - Object(name: "gps.gpx"); - } - - public override void start() - { - if (!started) - { - log_id = log.log.start("track", "GPS track"); - base.start(); - } - } - - public override void stop() - { - if (started) - { - log.log.end(log_id); - log_id = 0; - base.stop(); - } - } - - // Mark a waypoint - public void waypoint(string? name = null) - { - if (log_id == 0) return; - - string wptname; - if (name == null) - { - wptname = "wpt_%u".printf(wpt_seq); - wpt_seq += 1; - } else { - wptname = name; - } - - log.log.add(log_id, wptname); - } -} - -public zavai.gps.GPS gps = null; -public zavai.gps.GPX gpx = null; - -public void init() -{ - gps = new GPS(); - gpx = new GPX(); - -} - -} -} diff --git a/src/gsm.vala b/src/gsm.vala deleted file mode 100644 index b11065d..0000000 --- a/src/gsm.vala +++ /dev/null @@ -1,256 +0,0 @@ -/* - * gsm - gsm resource for zavai - * - * Copyright (C) 2009 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 gsm { - -// Isolate here the insane loops we need to go through to turn on the bloody -// gsm -protected class GSMActivator : Object -{ - public dynamic DBus.Object device; - public dynamic DBus.Object network; - public dynamic DBus.Object sim; - - public signal void status_changed(string message); - - public GSMActivator() - { - device = null; - network = null; - sim = null; - } - - public void begin() - { - if (device == null) - { - device = zavai.registry.sbus.get_object( - "org.freesmartphone.ogsmd", - "/org/freesmartphone/GSM/Device", - "org.freesmartphone.GSM.Device"); - network = zavai.registry.sbus.get_object( - "org.freesmartphone.ogsmd", - "/org/freesmartphone/GSM/Device", - "org.freesmartphone.GSM.Network"); - sim = zavai.registry.sbus.get_object( - "org.freesmartphone.ogsmd", - "/org/freesmartphone/GSM/Device", - "org.freesmartphone.GSM.SIM"); - } - - status_changed("Turning on antenna"); - device.SetAntennaPower(true, on_antenna_power); - } - - protected void on_antenna_power(Error e) - { - if (e != null) - { - zavai.log.warning("on_antenna_power: " + e.message); - if (e.message.str("current status is 'enabling'") != null - || e.message.str("current status is 'unknown'") != null) - { - status_changed("Waiting for ogsmd to settle"); - zavai.log.info("trying again after 2 seconds"); - Timeout.add(2 * 1000, () => { - device.SetAntennaPower(true, on_antenna_power); - return false; - }); - } else { - status_changed("Checking if PIN is required"); - sim.GetAuthStatus(on_auth_status); - } - return; - } - zavai.log.warning("on_antenna_power ok"); - status_changed("Registering with network"); - network.Register(on_network_register); - } - - protected void on_network_register(Error e) - { - if (e != null) - { - zavai.log.warning("on_network_register: " + e.message); - return; - } - status_changed("Registered with network"); - } - - protected void on_auth_status(string status, Error e) - { - if (e != null) - { - zavai.log.warning("on_auth_status: " + e.message); - return; - } - zavai.log.info("on_auth_status: " + status); - if (status == "READY") - { - status_changed("PIN ok"); - device.SetAntennaPower(true, on_antenna_power); - } - else if (status == "SIM PIN") - { - status_changed("Sending PIN"); - sim.SendAuthCode(zavai.config.sim_pin, on_auth_code); - } - else - zavai.log.debug("Unknown status: " + status); - } - - protected void on_auth_code(Error e) - { - if (e != null) - { - zavai.log.warning("on_auth_code: " + e.message); - return; - } - status_changed("PIN OK"); - } -} - -public class GSM: zavai.ScriptMonitorService -{ - protected dynamic DBus.Object dbus; - public dynamic DBus.Object call; - protected GSMActivator activator; - - public signal void status_changed(string message); - - public GSM() - { - Object(name: "gsm"); - - activator = new GSMActivator(); - activator.status_changed += (msg) => { status_changed(msg); }; - - call = null; - - dbus = zavai.registry.sbus.get_object( - "org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus"); - dbus.NameOwnerChanged += on_name_owner_changed; - } - - /// Request GPS resource - public override void start() - { - if (started) return; - - status_changed("Starting"); - - script_start(); - - call = zavai.registry.sbus.get_object( - "org.freesmartphone.ogsmd", - "/org/freesmartphone/GSM/Device", - "org.freesmartphone.GSM.Call"); - - base.start(); - } - - protected void on_name_owner_changed(DBus.Object sender, string name, string oldOwner, string newOwner) - { - zavai.log.debug("NOC " + name + " from " + oldOwner + " to " + newOwner); - if (name == "org.freesmartphone.ogsmd" && newOwner != "") - { - status_changed("ogpsd came online"); - activator.begin(); - } - } - - // Release usage of GPS - public override void stop() - { - if (!started) return; - - script_stop(); - } - - protected override void cleanup_after_script_stop() - { - call = null; - } -} - -public class GPRS: zavai.Service -{ - public dynamic DBus.Object device; - - public GPRS() - { - Object(name: "gsm.gprs"); - - device = zavai.registry.sbus.get_object( - "org.freesmartphone.ogsmd", - "/org/freesmartphone/GSM/Device", - "org.freesmartphone.GSM.PDP"); - } - - /// Request GPS resource - public override void start() - { - if (started) return; - try { - //gsm.request(name); - device.ActivateContext( - zavai.config.gprs_apn, - zavai.config.gprs_user, - zavai.config.gprs_pass); - zavai.log.info("Started GPRS"); - base.start(); - } catch (GLib.Error e) { - zavai.log.error(e.message); - } - base.start(); - } - - // Release usage of GPS - public override void stop() - { - if (!started) return; - try { - //gsm.release(name); - device.DeactivateContext(); - zavai.log.info("Stopped GPRS"); - base.stop(); - } catch (GLib.Error e) { - zavai.log.error(e.message); - } - base.stop(); - } -} - -public zavai.gsm.GSM gsm = null; -public zavai.gsm.GPRS gprs = null; - -public void init() -{ - gsm = new GSM(); - gprs = new GPRS(); -} - -} -} diff --git a/src/input.vala b/src/input.vala deleted file mode 100644 index ffa0add..0000000 --- a/src/input.vala +++ /dev/null @@ -1,425 +0,0 @@ -/* - * devinput - zavai /dev/input device handling - * - * Copyright (C) 2009 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 - */ - -namespace zavai { -namespace input { - -public class DevInput : zavai.Service -{ - public string device { get; construct; } - - public signal bool event(LinuxInput.Event* ev); - - protected IOChannel fd = null; - protected uint fd_watch = 0; - - public DevInput(string name, string device) - { - Object(name: "input.power_button", device: "/dev/input/event0"); - } - - protected void close_fd() - { - if (fd != null) - { - try { - fd.shutdown(false); - } catch (IOChannelError e) { - zavai.log.error("When closing " + device + ": " + e.message); - } - - fd = null; - } - } - - protected bool on_input_data(IOChannel source, IOCondition condition) - { - if (condition != IOCondition.IN) return true; - - //stderr.printf("GOT INPUT ON %s %d\n", device, source.unix_get_fd()); - char[] buf = new char[sizeof(LinuxInput.Event)]; - size_t count_read; - try { - source.read_chars(buf, out count_read); - } catch (Error e) { - zavai.log.error("Reading from " + device + ": " + e.message); - return true; - } - //stderr.printf("READ %zu chars\n", count_read); - - LinuxInput.Event* ie = (LinuxInput.Event*)buf; - //stderr.printf("INPUT EVENT time %lu.%lu type %hu code %hu val %d\n", (ulong)ie->time.tv_sec, ie->time.tv_usec, ie->type, ie->code, ie->val); - - /* - ts1, ts2, type, code, value = struct.unpack("LLHHI", buf) - #print ts1, ts2, type, code, value - if type == 1 and code == 119: - if value: - #print "BUTTON RELEASE" - pass - else: - if self.last_button_press + 1 < ts1: - self.last_button_press = ts1 - if self.button_press_handler is not None: - self.button_press_handler() - #print "BUTTON PRESS" - elif type == 5 and code == 2: - if value: - info("Headset plugged in") - self.mixer_for_headset(self) - else: - info("Headset plugged out") - self.mixer_for_handset(self) - */ - return event(ie); - } - - /// Start reading from the device - public override void start() - { - if (started) return; - - if (fd != null) - close_fd(); - - // Open the device and listed to it using the GObject main loop - zavai.log.info("Opening device " + device); - fd = new IOChannel.file(device, "r"); - try { - fd.set_encoding(null); - } catch (Error e) { - zavai.log.error("Setting encoding to null on " + device + ": " + e.message); - } - fd.set_buffered(false); - fd_watch = fd.add_watch(IOCondition.IN, on_input_data); - - base.start(); - } - - // Stop reading from the device - public override void stop() - { - if (!started) return; - - if (fd != null) - { - Source.remove(fd_watch); - close_fd(); - } - - base.stop(); - } -} - -public class HotKeys : zavai.Service -{ - protected List grabbed; - public signal bool hotkey(uint keycode, ulong time, bool pressed); - - public HotKeys() - { - Object(name: "input.hotkeys"); - - grabbed = new List(); - } - - // Hotkey handlink takes inspiration from - // http://old.nabble.com/-PATCH--Initial-non-working-implementation-of-wxWindow::%28Un%29RegisterHotKey-on-wxGTK-td14557263.html - private static Gdk.FilterReturn on_hotkey(Gdk.XEvent* xevent, Gdk.Event? event, void* data) - { - // Global events don't get their data translated to gdk, as there is no - // GdkWindow to work with, therefore we need to use the xevent, because - // GdkEvent* is always GDK_NOTHING - X.Event* xev = (X.Event*)xevent; - - switch (xev->type) - { - case X.EventType.KeyPress: - return zavai.input.hotkeys.my_on_hotkey(xev, true); - case X.EventType.KeyRelease: - return zavai.input.hotkeys.my_on_hotkey(xev, false); - default: - return Gdk.FilterReturn.CONTINUE; - } - } - - //public Gdk.FilterReturn on_hotkey(Gdk.XEvent xevent, Gdk.Event? event) - private Gdk.FilterReturn my_on_hotkey(X.Event* xev, bool pressed) - { - // From http://tronche.com/gui/x/xlib/input/pointer-grabbing.html: - // - // A timestamp is a time value, expressed in milliseconds. It typically is the - // time since the last server reset. Timestamp values wrap around (after about - // 49.7 days). The server, given its current time is represented by timestamp - // T, always interprets timestamps from clients by treating half of the - // timestamp space as being later in time than T. One timestamp value, named - // CurrentTime, is never generated by the server. This value is reserved for - // use in requests to represent the current server time. - - if (grabbed.index((int)xev->xkey.keycode) == -1) - return Gdk.FilterReturn.CONTINUE; - - if (hotkey(xev->xkey.keycode, xev->xkey.time, pressed)) - return Gdk.FilterReturn.REMOVE; - return Gdk.FilterReturn.CONTINUE; - } - - public void grab(int keycode, int modifiers, bool owner_events) - { - // We need to grab the keys we want to listen to - int res = Gdk.x11_get_default_xdisplay().grab_key(keycode, modifiers, Gdk.x11_get_default_root_xwindow(), owner_events, X.GrabMode.Async, X.GrabMode.Async); - if (res != 0) - stderr.printf("Grab result: %d\n", res); // We get BadRequest and don't know why - grabbed.append(keycode); - } - - /// Start reading from the device - public override void start() - { - if (started) return; - - //gdk_window_add_filter (NULL, _wxgtk_global_hotkey_callback, this); - ((Gdk.Window*)null)->add_filter((Gdk.FilterFunc)on_hotkey); - - grab(160, 0, false); - - base.start(); - } - - // Stop reading from the device - public override void stop() - { - if (!started) return; - - //gdk_window_remove_filter(NULL, _wxgtk_global_hotkey_callback, this); - ((Gdk.Window*)null)->remove_filter((Gdk.FilterFunc)on_hotkey); - - base.stop(); - } -} - -public class PowerButton : zavai.Service -{ - protected DevInput devinput; - - public signal void power_button(Posix.timeval* time, bool pressed); - - public PowerButton() - { - // FIXME: change to event0 for the power button - // FIXME: change to event4 for the aux button and headset button - string inputdev = "/dev/input/event0"; - if (Posix.access(inputdev, Posix.R_OK) == 0) - { - zavai.log.info("Handle power button via " + inputdev); - // Listen via input device - devinput = new DevInput("input.power_button", "/dev/input/event0"); - devinput.event += on_event; - devinput.request("powerbutton"); - } else { - zavai.log.info("Handle power button via XGrabKey on keycode " + zavai.config.power_button_keycode.to_string()); - // Listen via X - hotkeys.hotkey += on_hotkey; - hotkeys.grab(zavai.config.power_button_keycode, 0, false); - hotkeys.request("powerbutton"); - } - } - - protected bool on_event(LinuxInput.Event* ev) - { - if (ev->type == LinuxInput.Type.KEY && - ev->code == LinuxInput.Key.POWER) - { - power_button(&(ev->time), ev->val == 0 ? false : true); - } - return true; - } - - protected bool on_hotkey(uint keycode, ulong time, bool pressed) - { - if (keycode == zavai.config.power_button_keycode) - { - // Convert X time to a fake timeval - // TODO: handle wraparound - Posix.timeval tv = { - (time_t)(time / 1000), - (long)((time % 1000) * 1000) - }; - power_button(&tv, pressed); - return true; - } - return false; - } -} - - -/* -# TODO: -# - hook into the headset plugged/unplugged event -# - if unplugged, turn on handset microphone -# - if plugged, redo headest mixer settings -class Audio: - "Handle mixer settings, audio recording and headset button presses" - def __init__(self, button_press_handler = None): - self.saved_scenario = os.path.expanduser("~/.audiomap.state") - - # Setup the mixer - # Set mixer to record from headset and handle headset button - self.save_scenario(self.saved_scenario) - self.load_scenario("/usr/share/openmoko/scenarios/voip-handset.state") - - # This is a work-around because I have not found a way to query for the - # current headset state, I can only know when it changes. So in my - # system I configured oeventsd with a rule to touch this file when the - # headset is plugged in, and remove the file when it's plugged out. - if os.path.exists("/tmp/has_headset"): - self.mixer_for_headset(True) - else: - self.mixer_for_handset(True) - - #self.mixer_set("DAPM Handset Mic", "mute") - #self.mixer_set("DAPM Headset Mic", "unmute") - #self.mixer_set("Left Mixer Sidetone Playback Sw", "unmute") - #self.mixer_set("ALC Mixer Mic1", "cap") - #self.mixer_set("Amp Spk", "mute") # We don't need the phone playing what we say - - # Watch the headset button - self.button_press_handler = button_press_handler - self.input_fd = open("/dev/input/event4", "rb") - self.input_watch = gobject.io_add_watch(self.input_fd.fileno(), gobject.IO_IN, self.on_input_data) - - self.last_button_press = 0 - self.recorder = None - self.basename = None - - def mixer_for_headset(self, force=False): - if not force and self.has_headset: return - info("Setting mixer for headset") - # TODO: find out how to disable the handset microphone: this does not - # seem to be sufficient - self.mixer_set_many( - ("DAPM Handset Mic", "mute"), - ("DAPM Headset Mic", "unmute"), - ("Left Mixer Sidetone Playback Sw", "unmute"), - ("ALC Mixer Mic1", "cap"), - ("Amp Spk", "mute") # We don't need the phone playing what we say - ) - self.has_headset = True - - def mixer_for_handset(self, force=False): - if not force and not self.has_headset: return - info("Setting mixer for handset") - self.mixer_set_many( - ("DAPM Handset Mic", "unmute"), - ("DAPM Headset Mic", "mute"), - ("Left Mixer Sidetone Playback Sw", "mute"), - ("ALC Mixer Mic1", "cap"), - ("Amp Spk", "mute") # We don't need the phone playing what we say - ) - self.has_headset = False - - def set_basename(self, basename): - self.basename = basename - - def start_recording(self): - if self.basename is None: - raise RuntimeError("Recording requested but basename not set") - self.recorder = subprocess.Popen( - ["arecord", "-D", "hw", "-f", "cd", "-r", "8000", "-t", "wav", self.basename + ".wav"]) - - def start_levels(self): - self.recorder = subprocess.Popen( - ["arecord", "-D", "hw", "-f", "cd", "-r", "8000", "-t", "wav", "-V", "stereo", "/dev/null"]) - - def close(self): - if self.recorder is not None: - os.kill(self.recorder.pid, signal.SIGINT) - self.recorder.wait() - - # Restore mixer settings - self.load_scenario(self.saved_scenario) - - gobject.source_remove(self.input_watch) - self.input_fd.close() - - def on_input_data(self, source, condition): - buf = self.input_fd.read(16) - ts1, ts2, type, code, value = struct.unpack("LLHHI", buf) - #print ts1, ts2, type, code, value - if type == 1 and code == 119: - if value: - #print "BUTTON RELEASE" - pass - else: - if self.last_button_press + 1 < ts1: - self.last_button_press = ts1 - if self.button_press_handler is not None: - self.button_press_handler() - #print "BUTTON PRESS" - elif type == 5 and code == 2: - if value: - info("Headset plugged in") - self.mixer_for_headset(self) - else: - info("Headset plugged out") - self.mixer_for_handset(self) - return True - - def save_scenario(self, name): - res = subprocess.call(["alsactl", "store", "-f", name]) - if res != 0: - raise RuntimeError("Saving audio scenario to '%s' failed" % name) - - def load_scenario(self, name): - res = subprocess.call(["alsactl", "restore", "-f", name]) - if res != 0: - raise RuntimeError("Loading audio scenario '%s' failed" % name) - - def mixer_set(self, name, *args): - args = map(str, args) - res = subprocess.call(["amixer", "-q", "set", name] + args) - if res != 0: - raise RuntimeError("Setting mixer '%s' to %s failed" % (name, " ".join(args))) - - # Will do this when we find out the syntax for giving amixer commands on stdin - def mixer_set_many(self, *args): - """Perform many mixer set operations via amixer --stdin""" - proc = subprocess.Popen(["amixer", "-q", "--stdin"], stdin=subprocess.PIPE) - cmd_input = [] - for k, v in args: - cmd_input.append("sset " + repr(k) + " " + repr(v)) - (out, err) = proc.communicate(input="\n".join(cmd_input)) - res = proc.wait() - if res != 0: - raise RuntimeError("Setting mixer failed") -*/ - - -public HotKeys hotkeys = null; -public PowerButton power_button = null; - -public void init() -{ - hotkeys = new HotKeys(); - power_button = new PowerButton(); -} - -} -} diff --git a/src/libgps.vapi b/src/libgps.vapi deleted file mode 100644 index da29fcd..0000000 --- a/src/libgps.vapi +++ /dev/null @@ -1,238 +0,0 @@ -[CCode (lower_case_cprefix="", cprefix="", cheader_filename="gps.h")] -namespace libgps -{ - public const int MAXCHANNELS; - - [SimpleType] - [IntegerType (rank = 9)] - public struct mask_t {} - - [CCode (cname = "struct gps_fix_t")] - public struct fix_t - { - double time; /* Time of update, seconds since Unix epoch */ - int mode; /* Mode of fix */ - double ept; /* Expected time uncertainty */ - double latitude; /* Latitude in degrees (valid if mode >= 2) */ - double epy; /* Latitude position uncertainty, meters */ - double longitude; /* Longitude in degrees (valid if mode >= 2) */ - double epx; /* Longitude position uncertainty, meters */ - double altitude; /* Altitude in meters (valid if mode == 3) */ - double epv; /* Vertical position uncertainty, meters */ - double track; /* Course made good (relative to true north) */ - double epd; /* Track uncertainty, degrees */ - double speed; /* Speed over ground, meters/sec */ - double eps; /* Speed uncertainty, meters/sec */ - double climb; /* Vertical speed, meters/sec */ - double epc; /* Vertical speed uncertainty */ - } - public const int MODE_NOT_SEEN; /* mode update not seen yet */ - public const int MODE_NO_FIX; /* none */ - public const int MODE_2D; /* good for latitude/longitude */ - public const int MODE_3D; /* good for altitude/climb too */ - - [CCode (cname = "struct dop_t")] - public struct dop_t - { - /* Dilution of precision factors */ - double xdop; - double ydop; - double pdop; - double hdop; - double vdop; - double tdop; - double gdop; - } - - [CCode (cname = "struct gps_data_t", destroy_function = "")] - public struct data_t - { - mask_t set; - double online; - int gps_fd; - fix_t fix; - double separation; - int status; - int satellites_used; /* Number of satellites used in solution */ - int[] used; /* PRNs of satellites used in solution */ - dop_t dop; - /* redundant with the estimate elements in the fix structure */ - double epe; /* spherical position error, 95% confidence (meters) */ - - /* satellite status -- valid when satellites_visible > 0 */ - double skyview_time; /* skyview timestamp */ - int satellites_visible; /* # of satellites in view */ - int[] PRN; /* PRNs of satellite */ - int[] elevation; /* elevation of satellite */ - int[] azimuth; /* azimuth */ - double[] ss; /* signal-to-noise ratio (dB) */ - - //struct devconfig_t dev; /* device that shipped last update */ - - //struct policy_t policy; /* our listening policy */ - - //char tag[MAXTAGLEN+1]; /* tag of last sentence processed */ - } - public const int ONLINE_SET; - public const int TIME_SET; - public const int TIMERR_SET; - public const int LATLON_SET; - public const int ALTITUDE_SET; - public const int SPEED_SET; - public const int TRACK_SET; - public const int CLIMB_SET; - public const int STATUS_SET; - public const int MODE_SET; - public const int DOP_SET; - public const int VERSION_SET; /* only used in client library */ - public const int HERR_SET; - public const int VERR_SET; - public const int PERR_SET; - public const int POLICY_SET; /* only used in client library */ - public const int ERR_SET; - public const int SATELLITE_SET; - public const int RAW_SET; - public const int USED_SET; - public const int SPEEDERR_SET; - public const int TRACKERR_SET; - public const int CLIMBERR_SET; - public const int DEVICE_SET; - public const int DEVICELIST_SET; - public const int DEVICEID_SET; - public const int ERROR_SET; - public const int RTCM2_SET; - public const int RTCM3_SET; - public const int AIS_SET; - public const int PACKET_SET; - public const int CLEAR_SET; /* sentence starts a reporting cycle */ - public const int REPORT_SET; /* sentence ends a reporting cycle */ - public const int DATA_SET; - - public const int STATUS_NO_FIX; /* no */ - public const int STATUS_FIX; /* yes, without DGPS */ - public const int STATUS_DGPS_FIX; /* yes, with DGPS */ - - [CCode (cname = "gps_open_r")] - public int open_r(string server, string port, ref data_t gpsdata); - - [CCode (cname = "gps_close")] - public int close(ref data_t gpsdata); - - [CCode (cname = "gps_errstr")] - public weak string errstr(int err); - - [CCode (cname = "gps_poll")] - public int poll(ref data_t gpsdata); - - [CCode (cname = "gps_waiting")] - public bool waiting(ref data_t gpsdata); - - [CCode (cname = "gps_send")] - public int send(ref data_t gpsdata, string fmt, ...); - - [CCode (cname = "gps_stream")] - public int stream(ref data_t gpsdata, uint flags, void* data); - - /* mode flags for gps_stream() */ - public int WATCH_DISABLE; /* disable watching */ - public int WATCH_ENABLE; /* enable streaming */ - public int WATCH_JSON; /* enable JSON output */ - public int WATCH_NMEA; /* enable output in NMEA */ - public int WATCH_RARE; /* enable output of packets in hex */ - public int WATCH_RAW; /* enable output of raw packets */ - public int WATCH_SCALED; /* scale output to floats, when applicable */ - public int WATCH_NEWSTYLE; /* force JSON streaming */ - public int WATCH_OLDSTYLE; /* force old-style streaming */ - public int WATCH_DEVICE; /* watch specific device */ - public int POLL_NONBLOCK; /* set non-blocking poll */ - - /* - [CCode (cname = "struct input_event")] - public struct Event - { - public Posix.timeval time; - public uint16 type; - public uint16 code; - [CCode (cname="value")] - public int32 val; - } - - [CCode (cprefix="KEY_")] - public enum Key - { - POWER - } - - [CCode (cprefix="EV_")] - public enum Type - { - SYN, - KEY, - REL, - ABS, - MSC, - SW, - LED, - SND, - REP, - FF, - PWR, - FF_STATUS - } -} -[CCode (cprefix="", cheader_filename="omhacks/all.h")] -namespace Omhacks -{ - [CCode (cname = "struct om_led", cheader_filename = "omhacks/led.h", destroy_function = "")] - public struct Led - { - public char name[255]; - public string dir; - public int dir_len; - public int brightness; - public char trigger[255]; - public int delay_on; - public int delay_off; - - [CCode (cname = "om_led_init")] - public int init(string name); - [CCode (cname = "om_led_get")] - public int get(); - [CCode (cname = "om_led_set")] - public int set(); - } - - namespace Screen - { - namespace Brightness - { - [CCode (cname = "om_screen_brightness_get")] - public int get(); - [CCode (cname = "om_screen_brightness_get_max")] - public int get_max(); - [CCode (cname = "om_screen_brightness_set")] - public int set(int val); - } - } - - namespace UEvent - { - [CCode (cname = "struct om_uevent", cheader_filename = "omhacks/uevent.h", destroy_function = "")] - public struct Event - { - public string buffer; - size_t buflen; - weak string action; - weak string devpath; - weak string[] envp; - } - - [CCode (cname = "om_uevent_open")] - public int open(); - [CCode (cname = "om_uevent_read")] - public int read(int sock, ref Event ou); - [CCode (cname = "om_uevent_parse")] - public int parse(ref Event ou); - } - */ -} diff --git a/src/libomhacks.vapi b/src/libomhacks.vapi deleted file mode 100644 index 83434f3..0000000 --- a/src/libomhacks.vapi +++ /dev/null @@ -1,55 +0,0 @@ -[CCode (cprefix="", cheader_filename="omhacks/all.h")] -namespace Omhacks -{ - [CCode (cname = "struct om_led", cheader_filename = "omhacks/led.h", destroy_function = "")] - public struct Led - { - public char name[255]; - public string dir; - public int dir_len; - public int brightness; - public char trigger[255]; - public int delay_on; - public int delay_off; - - [CCode (cname = "om_led_init")] - public int init(string name); - [CCode (cname = "om_led_get")] - public int get(); - [CCode (cname = "om_led_set")] - public int set(); - } - - namespace Screen - { - namespace Brightness - { - [CCode (cname = "om_screen_brightness_get")] - public int get(); - [CCode (cname = "om_screen_brightness_get_max")] - public int get_max(); - [CCode (cname = "om_screen_brightness_set")] - public int set(int val); - } - } - - namespace UEvent - { - [CCode (cname = "struct om_uevent", cheader_filename = "omhacks/uevent.h", destroy_function = "")] - public struct Event - { - public string buffer; - size_t buflen; - weak string action; - weak string devpath; - weak string[] envp; - } - - [CCode (cname = "om_uevent_open")] - public int open(); - [CCode (cname = "om_uevent_read")] - public int read(int sock, ref Event ou); - [CCode (cname = "om_uevent_parse")] - public int parse(ref Event ou); - } -} diff --git a/src/linux-input.vapi b/src/linux-input.vapi deleted file mode 100644 index 835f849..0000000 --- a/src/linux-input.vapi +++ /dev/null @@ -1,36 +0,0 @@ -[CCode (lower_case_cprefix="", cprefix="", cheader_filename="linux/input.h")] -namespace LinuxInput -{ - [CCode (cname = "struct input_event")] - public struct Event - { - public Posix.timeval time; - public uint16 type; - public uint16 code; - [CCode (cname="value")] - public int32 val; - } - - [CCode (cprefix="KEY_")] - public enum Key - { - POWER - } - - [CCode (cprefix="EV_")] - public enum Type - { - SYN, - KEY, - REL, - ABS, - MSC, - SW, - LED, - SND, - REP, - FF, - PWR, - FF_STATUS - } -} diff --git a/src/log.vala b/src/log.vala deleted file mode 100644 index eb78363..0000000 --- a/src/log.vala +++ /dev/null @@ -1,317 +0,0 @@ -/* - * log - logging functions - * - * 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 log { - -public class Waypoint : Object -{ - public time_t ts; - public double lat; - public double lon; - - public Waypoint() - { - if (gps.gps.fix_status() != libgps.STATUS_NO_FIX) - { - lat = gps.gps.info().fix.latitude; - lon = gps.gps.info().fix.longitude; - ts = (time_t)gps.gps.info().fix.time; - } else { - // Use 1000 as missing values - lat = 1000; - lon = 1000; - ts = time_t(); - } - } - - public void writeInside(FileStream outfd) - { - var t = Time.gm(ts); - outfd.printf(" \n", t.format("%Y-%m-%dT%H:%M:%SZ")); - } -} - - -public class LogEntry : Waypoint -{ - public string msg; - - public LogEntry() - { - base(); - } - - public void write(FileStream outfd) - { - outfd.printf(" \n", lat, lon); - writeInside(outfd); - outfd.printf(" %s\n", Markup.escape_text(msg)); - outfd.puts(" \n"); - } -} - -public class TrackEntry : Waypoint -{ - public TrackEntry() - { - base(); - } - - public void write(FileStream outfd) - { - outfd.printf(" \n", lat, lon); - writeInside(outfd); - outfd.puts(" \n"); - } -} - - -public class Log : Object -{ - public uint id; - public string tag; - public string title; - public List entries; - public List track; - - public Log(uint id, string tag, string title) - { - this.id = id; - this.tag = tag; - this.title = title; - entries = null; - track = null; - } - - public void add(string msg) - { - var entry = new LogEntry(); - entry.msg = msg; - entries.append(entry); - } - - public void add_trackpoint() - { - track.append(new TrackEntry()); - } - - public void save() - { - if (entries == null) return; - - // Directory where we save the log - string dir = config.homedir + "/log-" + tag; - DirUtils.create(dir, 0777); - - // First try with a plain name - var t = Time.local(entries.data.ts); - string basename = dir + "/" + t.format("%Y%m%d-%H%M%S"); - - string pathname = basename + ".gpx"; - - // Find a pathname that does not exist already - for (int i = 1; FileUtils.test(pathname, FileTest.EXISTS); ++i) - pathname = "%s-%d.gpx".printf(basename, i); - - // Write out - var outfd = FileStream.open(pathname, "w"); - if (outfd == null) - { - zavai.log.error("opening " + pathname + ": " + strerror(errno)); - return; - } - - write(outfd); - outfd.flush(); - } - - protected void writeTrack(FileStream outfd) - { - outfd.puts(" \n"); - outfd.puts(" \n"); - for (weak List i = track; i != null; i = i.next) - i.data.write(outfd); - outfd.puts(" \n"); - outfd.puts(" \n"); - } - - protected void writeEntries(FileStream outfd) - { - outfd.puts(" \n"); - for (weak List i = entries; i != null; i = i.next) - i.data.write(outfd); - outfd.puts(" \n"); - } - - protected void write(FileStream outfd) - { - outfd.puts("\n"); - outfd.puts("\n"); - outfd.puts(" \n"); - outfd.printf(" %s\n", Markup.escape_text(title)); - outfd.puts(" \n"); - if (track != null) writeTrack(outfd); - if (entries != null) writeEntries(outfd); - outfd.puts(" \n"); - } -} - -public class Logger : Resource, Object -{ - protected List logs; - protected uint seq; - - public Logger() - { - logs = null; - seq = 0; - - zavai.registry.register(this); - } - - protected void start_trace() - { - gps.gps.pos_changed += on_pos_changed; - } - - protected void end_trace() - { - gps.gps.pos_changed -= on_pos_changed; - } - - protected void on_pos_changed() - { - for (weak List i = logs; i != null; i = i.next) - i.data.add_trackpoint(); - } - - protected uint gen_seq() - { - // Increase avoiding 0 on rollover - while (true) - { - if (++seq == 0) ++seq; - bool found = false; - for (weak List i = logs; i != null; i = i.next) - { - if (i.data.id == seq) - { - found = true; - break; - } - } - if (!found) break; - } - return seq; - } - - protected weak Log? find(uint id) - { - for (weak List i = logs; i != null; i = i.next) - if (i.data.id == id) - return i.data; - return null; - } - - protected Log? pop(uint id) - { - for (weak List i = logs; i != null; i = i.next) - if (i.data.id == id) - { - Log res = i.data; - logs.delete_link(i); - return res; - } - return null; - } - - public uint start(string tag, string title) - { - bool was_empty = (logs == null); - uint id = gen_seq(); - logs.append(new Log(id, tag, title)); - if (was_empty) start_trace(); - return id; - } - - public void add(uint id, string msg) - { - Log log = find(id); - if (log == null) return; - log.add(msg); - } - - public void end(uint id) - { - Log log = pop(id); - log.save(); - if (log == null) end_trace(); - } - - public void instant(string tag, string msg) - { - var log = new Log(0, tag, msg); - log.add(msg); - log.save(); - } - - public void shutdown() - { - while (logs != null) - { - var log = pop(logs.data.id); - log.save(); - } - } -} - -public void error(string s) -{ - stderr.printf("%s\n", s); -} -public void warning(string s) -{ - stderr.printf("%s\n", s); -} -public void info(string s) -{ - stderr.printf("%s\n", s); -} -public void debug(string s) -{ - stderr.printf("%s\n", s); -} - -Logger log = null; - -public void init() -{ - log = new Logger(); -} - -} -} diff --git a/src/lua5.1.vapi b/src/lua5.1.vapi deleted file mode 120000 index e730dfc..0000000 --- a/src/lua5.1.vapi +++ /dev/null @@ -1 +0,0 @@ -/usr/share/vala/vapi/lua.vapi \ No newline at end of file diff --git a/src/power.vala b/src/power.vala deleted file mode 100644 index 5583708..0000000 --- a/src/power.vala +++ /dev/null @@ -1,192 +0,0 @@ -/* - * power - zavai power event handling - * - * Copyright (C) 2009 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 power { - -class Power : Service -{ - public enum State - { - UNKNOWN, - CHARGING, - DISCHARGING, - FULLY_CHARGED, - } - - protected string battery_device; - protected uint timeout; - public signal void changed(); - public State state; - public int percentage; - - public Power() - { - battery_device = "/sys/class/power_supply/battery/"; - if (Posix.access(battery_device, Posix.R_OK) != 0) - battery_device = null; - timeout = 0; - state = State.UNKNOWN; - percentage = 0; - } - - /// Activate the service - protected override void start() - { - if (started) return; - - uint poll_time; - if (uevent.uevent != null) - { - zavai.log.info("We have uevent: poll rarely"); - uevent.uevent.event += on_uevent; - uevent.uevent.request("zavai.power"); - // If we can get plug/unplug notifications, it's ok to just poll - // every 5 minutes - poll_time = 300 * 1000; - } else { - if (battery_device == null) - { - zavai.log.warning("No battery device found that I know how to read: try building with devkit-power"); - poll_time = 0; - } else { - zavai.log.info("Polling battery device only"); - // Else poll every 30 seconds to be somehow reactive to plug/unplug - // events - poll_time = 30 * 1000; - } - } - - poll(); - - // Poll battery every minute - if (poll_time != 0) - timeout = Timeout.add(poll_time, on_timeout); - - base.start(); - } - - /// Deactivate the service - protected override void stop() - { - if (!started) return; - - // Stop polling - if (timeout != 0) - Source.remove(timeout); - - if (uevent.uevent != null) - { - uevent.uevent.release("zavai.power"); - uevent.uevent.event -= on_uevent; - } - - base.stop(); - } - - protected void poll() - { - if (battery_device == null) - return; - - char buf[200]; - State new_state = State.UNKNOWN; - int new_percentage = 0; - - FileStream state_fd = FileStream.open(battery_device + "/status", "r"); - string val = state_fd.gets(buf); - if (val == "Charging") - new_state = State.CHARGING; - else if (val == "Discharging") - new_state = State.DISCHARGING; - else if (val == "Not charging") - new_state = State.FULLY_CHARGED; - - FileStream cap_fd = FileStream.open(battery_device + "/capacity", "r"); - val = cap_fd.gets(buf); - new_percentage = val.to_int(); - - if (new_state != state || new_percentage != percentage) - { - state = new_state; - percentage = new_percentage; - changed(); - } - } - - protected bool on_timeout() - { - poll(); - return true; - } - - protected void on_uevent() - { - /* if (uevent.uevent.event_data.buffer.has_prefix("change@/class/power_supply/ac")) - { - changed(); - } - else */ - if (uevent.uevent.event_data.buffer.has_prefix("change@/class/power_supply/battery")) - { - State new_state = State.UNKNOWN; - int new_percentage = 0; - - Omhacks.UEvent.parse(ref uevent.uevent.event_data); - for (int i = 0; uevent.uevent.event_data.envp[i] != null; ++i) - { - if (uevent.uevent.event_data.envp[i].has_prefix("POWER_SUPPLY_STATUS=")) - { - var val = uevent.uevent.event_data.envp[i].offset(20); - if (val == "Charging") - new_state = State.CHARGING; - else if (val == "Discharging") - new_state = State.DISCHARGING; - else if (val == "Not charging") - new_state = State.FULLY_CHARGED; - else - zavai.log.warning("Unknown state: " + uevent.uevent.event_data.envp[i]); - } - else if (uevent.uevent.event_data.envp[i].has_prefix("POWER_SUPPLY_CAPACITY=")) - { - new_percentage = uevent.uevent.event_data.envp[i].offset(22).to_int(); - } - } - if (new_state != state || new_percentage != percentage) - { - state = new_state; - percentage = new_percentage; - changed(); - } - } - } -} - -Power power; - -public void init() -{ - power = new Power(); -} - -} -} diff --git a/src/registry.vala b/src/registry.vala deleted file mode 100644 index 3d549da..0000000 --- a/src/registry.vala +++ /dev/null @@ -1,83 +0,0 @@ -/* - * registry - zavai resource registry - * - * Copyright (C) 2009 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 { - -public class Registry : Object, Resource -{ - List resources; - public DBus.Connection sbus; - public string bus_name; - - public Registry() - { - resources = new List(); - try { - sbus = DBus.Bus.get(DBus.BusType.SYSTEM); - } catch (DBus.Error e) { - stderr.printf("Cannot access system DBus bus: %s\n", e.message); - sbus = null; - } - - bus_name = DBus.bus_get_unique_name(sbus.get_connection()); - zavai.log.info("My bus name: " + bus_name); - - dynamic DBus.Object tmp_dbus = sbus.get_object( - "org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus"); - bus_name = "org.enricozini.zavai"; - uint res = tmp_dbus.RequestName(bus_name, (uint)DBus.NameFlag.DO_NOT_QUEUE); - switch (res) - { - case DBus.RequestNameReply.PRIMARY_OWNER: - zavai.log.info("Registered to dbus as " + bus_name); - break; - case DBus.RequestNameReply.IN_QUEUE: - zavai.log.info("In queue, but I asked not to"); - break; - case DBus.RequestNameReply.EXISTS: - zavai.log.info(bus_name + " already exists"); - break; - case DBus.RequestNameReply.ALREADY_OWNER: - zavai.log.info("I already own the name " + bus_name + " but I do not remember asking for it"); - break; - } - } - - public void shutdown() - { - // Shutdown in reverse registration order - for (weak List i = resources; i != null; i = i.next) - i.data.shutdown(); - } - - public void register(Resource obj) - { - resources.prepend(obj); - } -} - -public zavai.Registry registry; - -} - diff --git a/src/uevent.vala b/src/uevent.vala deleted file mode 100644 index b9475ae..0000000 --- a/src/uevent.vala +++ /dev/null @@ -1,92 +0,0 @@ -/* - * uevent - zavai uevent handling - * - * Copyright (C) 2009 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 uevent { - -class UEvent : Service -{ - protected IOChannel sock; - protected uint sock_watch = 0; - public Omhacks.UEvent.Event event_data; - public signal void event(); - - public UEvent() - { - event_data = Omhacks.UEvent.Event(); - } - - protected bool on_input_data(IOChannel source, IOCondition condition) - { - if (condition != IOCondition.IN) return true; - - Omhacks.UEvent.read(sock.unix_get_fd(), ref event_data); - event(); - - return true; - } - - /// Activate the service - protected override void start() - { - if (started) return; - - int sock_fd = Omhacks.UEvent.open(); - if (sock_fd < 0) - { - zavai.log.error("UEvent: error getting socket"); - return; - } - - sock = new IOChannel.unix_new(sock_fd); - sock_watch = sock.add_watch(IOCondition.IN, on_input_data); - - base.start(); - } - - /// Deactivate the service - protected override void stop() - { - if (!started) return; - Source.remove(sock_watch); - try { - sock.shutdown(false); - } catch (IOChannelError e) { - zavai.log.error("When closing UEvent socket: " + e.message); - } - sock = null; - base.stop(); - } -} - -UEvent uevent; - -public void init() -{ - if (Posix.getuid() == 0) - uevent = new UEvent(); - else - uevent = null; -} - -} -} diff --git a/src/wifi.vala b/src/wifi.vala deleted file mode 100644 index 55cf1cc..0000000 --- a/src/wifi.vala +++ /dev/null @@ -1,61 +0,0 @@ -/* - * wifi - wifi resource for zavai - * - * 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 wifi { - -public class Wifi: zavai.ScriptService -{ - public Wifi() - { - Object(name: "wifi"); - started = script_status(); - } - - /// Start wifi - public override void start() - { - if (started) return; - if (!script_start()) return; - zavai.log.info("wifi turned on"); - base.start(); - } - - // Release usage of wifi - public override void stop() - { - if (!started) return; - script_stop(); - base.stop(); - } -} - -public Wifi wifi = null; - -public void init() -{ - wifi = new Wifi(); - -} - -} -} diff --git a/src/x11.vapi b/src/x11.vapi deleted file mode 100644 index ec8b074..0000000 --- a/src/x11.vapi +++ /dev/null @@ -1,883 +0,0 @@ -/* x11.vapi - * - * Copyright (C) 2009 Jürg Billeter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: - * Jürg Billeter - */ - -[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "X11/Xlib.h,X11/Xatom.h,X11/Xutil.h")] -namespace X { - // Note: must be called before opening a display or calling any other Xlib function, - // see http://tronche.com/gui/x/xlib/display/XInitThreads.html - [CCode (cname = "XInitThreads")] - public Status init_threads (); - - [Compact] - [CCode (cname = "Display", ref_function = "", unref_function = "")] - public class Display { - [CCode (cname = "XOpenDisplay")] - public Display (string? name = null); - - [CCode (cname = "XGetAtomName")] - public string get_atom_name(Atom a); - - [CCode (cname = "XAllPlanes")] - public static ulong get_all_planes (); - - [CCode (cname = "XAddToSaveSet")] - public int add_to_save_set (Window w); - - [CCode (cname = "XAllowEvents")] - public int allow_events (int event_mode, int time); - - [CCode (cname = "XBitmapBitOrder")] - public int bitmap_bit_order (); - - [CCode (cname = "XBitmapUnit")] - public int bitmap_scanline_unit (); - - [CCode (cname = "XBitmapPad")] - public int bitmap_scanline_padding (); - - [CCode (cname = "XChangeProperty")] - public int change_property (Window w, Atom property, Atom type, int format, int mode, [CCode (array_length = false)] uchar[] data, int nelements); - - [CCode (cname = "XChangeWindowAttributes")] - public int change_window_attributes (Window w, ulong valuemask, SetWindowAttributes attributes); - - [CCode (cname = "XConfigureWindow")] - public int configure_window (Window w, uint value_mask, WindowChanges values); - - [CCode (cname = "ConnectionNumber")] - public int connection_number (); - - [CCode (cname = "DefaultRootWindow")] - public Window default_root_window (); - - [CCode (cname = "XDefaultScreenOfDisplay")] - public unowned Screen default_screen (); - - [CCode (cname = "XScreenOfDisplay")] - public unowned Screen screen_by_id (int screen_number); - - [CCode (cname = "DisplayString")] - public string display_string (); - - [CCode (cname = "XQLength")] - public int event_queue_length (); - - [CCode (cname = "XFlush")] - public int flush (); - - [CCode (cname = "XGetKeyboardMapping", array_length = false)] - public weak uint[] get_keyboard_mapping (uint first_keycode, int keycode_count, ref int keysyms_per_keycode_return); - - [CCode (cname = "XGetModifierMapping")] - public ModifierKeymap get_modifier_mapping (); - - [CCode (cname = "XGetSelectionOwner")] - public Window get_selection_owner (Atom selection); - - [CCode (cname = "XGetWindowAttributes")] - public void get_window_attributes (Window w, out WindowAttributes window_attributes_return); - - [CCode (cname = "XGetWindowProperty")] - public int get_window_property (Window w, Atom property, long long_offset, long long_length, bool delete, Atom req_type, out Atom actual_type_return, out int actual_format_return, out ulong nitems_return, out ulong bytes_after_return, out void* prop_return); - - [CCode (cname = "XGrabButton")] - public int grab_button (uint button, uint modifiers, Window grab_window, bool owner_events, uint event_mask, int pointer_mode, int keyboard_mode, Window confine_to, uint cursor); - - [CCode (cname = "XGrabKey")] - public int grab_key (int keycode, uint modifiers, Window grab_window, bool owner_events, int pointer_mode, int keyboard_mode); - - [CCode (cname = "XGrabPointer")] - public int grab_pointer (Window grab_window, bool owner_events, uint event_mask, int pointer_mode, int keyboard_mode, Window confine_to, uint cursor, int time); - - [CCode (cname = "XGrabServer")] - public int grab_server (); - - [CCode (cname = "XImageByteOrder")] - public int image_byte_order (); - - [CCode (cname = "XInternAtom")] - public Atom intern_atom (string atom_name, bool only_if_exists); - - [CCode (cname = "XInternAtoms")] - public void intern_atoms (string[] names, bool only_if_exists, [CCode (array_length = false)] Atom[] atoms_return); - - [CCode (cname = "XInternalConnectionNumbers")] - public Status internal_connection_numbers (ref int[] fd_return); - - [CCode (cname = "XDisplayKeycodes")] - public int keycodes (ref int min_keycodes_return, ref int max_keycodes_return); - - [CCode (cname = "XKeysymToKeycode")] - public int keysym_to_keycode (uint keysym); - - [CCode (cname = "XLastKnownRequestProcessed")] - public ulong last_known_request_processed (); - - [CCode (cname = "XLockDisplay")] - public void lock_display (); - - [CCode (cname = "XMapWindow")] - public int map_window (Window w); - - [CCode (cname = "XMaxRequestSize")] - public long max_request_size (); - - [CCode (cname = "XExtendedMaxRequestSize")] - public long max_extended_request_size (); - - [CCode (cname = "XNextEvent")] - public int next_event (ref Event event_return); - - [CCode (cname = "XNextRequest")] - public ulong next_request (); - - [CCode (cname = "XNoOp")] - public void no_operation (); - - [CCode (cname = "XScreenCount")] - public int number_of_screens (); - - [CCode (cname = "XPending")] - public int pending (); - - [CCode (cname = "XProcessInternalConnection")] - public void process_internal_connection (int fd); - - [CCode (cname = "XProtocolVersion")] - public int protocol_version (); - - [CCode (cname = "XProtocolRevision")] - public int protocol_revision (); - - [CCode (cname = "XRaiseWindow")] - public int raise_window (Window w); - - [CCode (cname = "XReparentWindow")] - public int reparent_window (Window w, Window parent, int x, int y); - - [CCode (cname = "XResizeWindow")] - public int resize_window (Window w, uint width, uint height); - - [CCode (cname = "XRootWindow")] - public Window root_window (int screen_number); - - [CCode (cname = "ScreenCount")] - public int screen_count (); - - [CCode (cname = "XScreenOfDisplay")] - public weak Screen screen_of_display (int screen_number); - - [CCode (cname = "XSelectInput")] - public int select_input (Window w, long event_mask); - - [CCode (cname = "XSendEvent")] - public void send_event (Window w, bool prpagate, long event_mask, ref Event event_send); - - [CCode (cname = "XSetCloseDownMode")] - public void set_close_down_mode (int close_mode); - - [CCode (cname = "XSetSelectionOwner")] - public Window set_selection_owner (Atom selection, Window owner, int time); - - [CCode (cname = "XSetInputFocus")] - public int set_input_focus (Window focus, int revert_to, int time); - - [CCode (cname = "XUngrabButton")] - public int ungrab_button (uint button, uint modifiers, Window grab_window); - - [CCode (cname = "XUngrabPointer")] - public int ungrab_pointer (int time); - - [CCode (cname = "XUngrabServer")] - public int ungrab_server (); - - [CCode (cname = "XUnlockDisplay")] - public void unlock_display (); - - [CCode (cname = "XUnmapWindow")] - public int unmap_window (Window w); - - [CCode (cname = "XQueryTree")] - public void query_tree (Window w, out Window root_return, out Window parent_return, out Window[] children_return); - - [CCode (cname = "XWindowEvent")] - public int window_event (Window w, EventMask event_mask, out Event event_return); - - [CCode (cname = "XServerVendor")] - public string xserver_vendor_name (); - - [CCode (cname = "XVendorRelease")] - public string xserver_vendor_release (); - - [CCode (cname = "XMoveWindow")] - public void move_window (Window window, int x, int y); - } - - [Compact] - [CCode (cname = "XModifierKeymap", free_function = "XFreeModifiermap")] - public class ModifierKeymap { - // The server's max # of keys per modifier - public int max_keypermod; - // An 8 by max_keypermod array of modifiers - public uchar[] modifiermap; - } - - [SimpleType] - [IntegerType (rank = 9)] - [CCode (cname = "Atom")] - public struct Atom { - } - - [SimpleType] - [IntegerType (rank = 9)] - [CCode (cname = "Colormap")] - public struct Colormap { - } - - [SimpleType] - [CCode (cname = "GC")] - public struct GC { - } - - [SimpleType] - [IntegerType (rank = 9)] - [CCode (cname = "Status")] - public struct Status { - } - - [SimpleType] - [IntegerType (rank = 9)] - [CCode (cname = "Window", type_id = "G_TYPE_INT", - marshaller_type_name = "INT", - get_value_function = "g_value_get_int", - set_value_function = "g_value_set_int", default_value = "0", - type_signature = "i")] - public struct Window { - } - - public struct Visual { - } - - public struct WindowChanges { - public int x; - public int y; - public int width; - public int height; - public int border_width; - public Window sibling; - public int stack_mode; - } - public struct SizeHints { - public long @flags; - public int x; - public int y; - public int width; - public int height; - } - - [CCode (cname = "XCreateWindow")] - public Window create_window (Display display, Window parent, int x, int y, uint width, uint height, uint border_width, int depth, uint @class, Visual? visual, X.CW valuemask, ref SetWindowAttributes attributes); - - [CCode (cname = "XSetWindowAttributes")] - public struct SetWindowAttributes { - // public Pixmap background_pixmap; /* background or None or ParentRelative */ - public ulong background_pixel; /* background pixel */ - // public Pixmap border_pixmap; /* border of the window */ - public ulong border_pixel; /* border pixel value */ - public int bit_gravity; /* one of bit gravity values */ - public int win_gravity; /* one of the window gravity values */ - public int backing_store; /* NotUseful, WhenMapped, Always */ - public ulong backing_planes;/* planes to be preseved if possible */ - public ulong backing_pixel;/* value to use in restoring planes */ - public bool save_under; /* should bits under be saved? (popups) */ - public long event_mask; /* set of events that should be saved */ - public long do_not_propagate_mask; /* set of events that should not propagate */ - public bool override_redirect; /* boolean value for override-redirect */ - // public Colormap colormap; /* color map to be associated with window */ - // public Cursor cursor; /* cursor to be displayed (or None) */ - } - - [CCode(cname = "XWindowAttributes", - cheader_filename = "X11/Xlib.h,X11/Xatom.h,X11/Xutil.h")] - public struct WindowAttributes { - public int x; - public int y; /* location of window */ - public int width; - public int height; /* width and height of window */ - public int border_width; /* border width of window */ - public int depth; /* depth of window */ - public Visual visual; /* the associated visual structure */ - public Window root; /* root of screen containing window */ - public int @class; /* InputOutput, InputOnly*/ - public int bit_gravity; /* one of bit gravity values */ - public int win_gravity; /* one of the window gravity values */ - public int backing_store; /* NotUseful, WhenMapped, Always */ - public ulong backing_planes;/* planes to be preserved if possible */ - public ulong backing_pixel;/* value to be used when restoring planes */ - public bool save_under; /* boolean, should bits under be saved? */ - // public Colormap colormap; /* color map to be associated with window */ - public bool map_installed; /* boolean, is color map currently installed*/ - public int map_state; /* IsUnmapped, IsUnviewable, IsViewable */ - public long all_event_masks; /* set of events all people have interest in*/ - public long your_event_mask; /* my event mask */ - public long do_not_propagate_mask; /* set of events that should not propagate */ - public bool override_redirect; /* boolean value for override-redirect */ - // public Screen screen; /* back pointer to correct screen */ - } - - [CCode (cname = "CopyFromParent")] - public const int COPY_FROM_PARENT; - - [CCode (cname = "CurrentTime")] - public const ulong CURRENT_TIME; - - [CCode (cname = "Success")] - public int Success; - - [CCode (cname = "XFree")] - public int free (void* data); - - [CCode (cprefix = "CW", cname = "int")] - public enum CW { - BackPixmap, - BackPixel, - BackingStore, - BackingPlanes, - BackingPixel, - BitGravity, - BorderPixmap, - BorderPixel, - BorderWidth, - Colormap, - Cursor, - DontPropagate, - EventMask, - Height, - OverrideRedirect, - SaveUnder, - Sibling, - StackMode, - X, - Y, - Width, - WinGravity - } - - [CCode (cprefix = "GrabMode")] - public enum GrabMode { - Sync, - Async - } - - [CCode (cprefix = "")] - public enum EventMask { - NoEventMask, - KeyPressMask, - KeyReleaseMask, - ButtonPressMask, - ButtonReleaseMask, - EnterWindowMask, - LeaveWindowMask, - PointerMotionMask, - PointerMotionHintMask, - Button1MotionMask, - Button2MotionMask, - Button3MotionMask, - Button4MotionMask, - Button5MotionMask, - ButtonMotionMask, - KeymapStateMask, - ExposureMask, - VisibilityChangeMask, - StructureNotifyMask, - ResizeRedirectMask, - SubstructureNotifyMask, - SubstructureRedirectMask, - FocusChangeMask, - PropertyChangeMask, - ColormapChangeMask, - OwnerGrabButtonMask - } - - [CCode (cprefix = "")] - public enum KeyMask { - ShiftMask, - LockMask, - ControlMask, - Mod1Mask, - Mod2Mask, - Mod3Mask, - Mod4Mask, - Mod5Mask - } - - [CCode (cprefix = "")] - public enum EventType { - KeyPress, - KeyRelease, - ButtonPress, - ButtonRelease, - MotionNotify, - EnterNotify, - LeaveNotify, - FocusIn, - FocusOut, - KeymapNotify, - Expose, - GraphicsExpose, - NoExpose, - VisibilityNotify, - CreateNotify, - DestroyNotify, - UnmapNotify, - MapNotify, - MapRequest, - ReparentNotify, - ConfigureNotify, - ConfigureRequest, - GravityNotify, - ResizeRequest, - CirculateNotify, - CirculateRequest, - PropertyNotify, - SelectionClear, - SelectionRequest, - SelectionNotify, - ColormapNotify, - ClientMessage, - MappingNotify - } - - // union - [CCode (cname = "XEvent")] - public struct Event { - public int type; - public AnyEvent xany; - public KeyEvent xkey; - public ButtonEvent xbutton; - public MotionEvent xmotion; - public CrossingEvent xcrossing; - public CreateWindowEvent xcreatewindow; - public DestroyWindowEvent xdestroywindow; - public UnmapEvent xunmap; - public MapEvent xmap; - public MapRequestEvent xmaprequest; - public ReparentEvent xreparent; - public ConfigureEvent xconfigure; - public GravityEvent xgravity; - public ConfigureRequestEvent xconfigurerequest; - public CirculateEvent xcirculate; - public CirculateRequestEvent xcirculaterequest; - public PropertyEvent xproperty; - public SelectionEvent xselection; - public ClientMessageEvent xclient; - } - - [CCode (cname = "XAnyEvent")] - public struct AnyEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window window; - } - - [CCode (cname = "XKeyEvent")] - public struct KeyEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window window; - public Window root; - public Window subwindow; - public ulong time; - public int x; - public int y; - public int x_root; - public int y_root; - public uint state; - public uint keycode; - public bool same_screen; - } - - [CCode (cname = "XButtonEvent")] - public struct ButtonEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window window; - public Window subwindow; - public ulong time; - public int x; - public int y; - public int x_root; - public int y_root; - public uint state; - public uint button; - public bool same_screen; - } - - [CCode (cname = "XMotionEvent")] - public struct MotionEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window window; - public Window subwindow; - public ulong time; - public int x; - public int y; - public int x_root; - public int y_root; - public uint state; - public char is_hint; - public bool same_screen; - } - - [CCode (cname = "XCrossingEvent")] - public struct CrossingEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window window; - public Window root; - public Window subwindow; - public ulong time; - public int x; - public int y; - public int x_root; - public int y_root; - public int mode; - public int detail; - public bool same_screen; - public bool focus; - public uint state; - } - - [CCode (cname = "XCreateWindowEvent")] - public struct CreateWindowEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window parent; - public Window window; - public int x; - public int y; - public int width; - public int height; - public int border_width; - public bool override_redirect; - } - - [CCode (cname = "XDestroyWindowEvent")] - public struct DestroyWindowEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window event; - public Window window; - } - - [CCode (cname = "XUnmapEvent")] - public struct UnmapEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window event; - public Window window; - public bool from_configure; - } - - [CCode (cname = "XMapEvent")] - public struct MapEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window event; - public Window window; - public bool override_redirect; - } - - [CCode (cname = "XMapRequestEvent")] - public struct MapRequestEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window parent; - public Window window; - } - - [CCode (cname = "XReparentEvent")] - public struct ReparentEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window event; - public Window window; - public Window parent; - public int x; - public int y; - public bool override_redirect; - } - - [CCode (cname = "XConfigureEvent")] - public struct ConfigureEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window event; - public Window window; - public int x; - public int y; - public int width; - public int height; - public int border_width; - public Window above; - public bool override_redirect; - } - - [CCode (cname = "XGravityEvent")] - public struct GravityEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window event; - public Window window; - public int x; - public int y; - } - - [CCode (cname = "XConfigureRequestEvent")] - public struct ConfigureRequestEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window parent; - public Window window; - public int x; - public int y; - public int width; - public int height; - public int border_width; - public Window above; - public int detail; - public ulong value_mask; - } - - [CCode (cname = "XCirculateEvent")] - public struct CirculateEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window event; - public Window window; - public int place; - } - - [CCode (cname = "XCirculateRequestEvent")] - public struct CirculateRequestEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window parent; - public Window window; - public int place; - } - - [CCode (cname = "XPropertyEvent")] - public struct PropertyEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window window; - public Atom atom; - public ulong time; - public int state; - } - - [CCode (cname = "XSelectionEvent")] - public struct SelectionEvent { - public int type; - public ulong serial; - public bool send_event; - public unowned Display display; - public Window requestor; - public Atom selection; - public Atom target; - public Atom property; - public ulong time; - } - - [CCode (cname = "XClientMessageEvent")] - public struct ClientMessageEvent { - public int type; - public ulong serial; /* # of last request processed by server */ - public bool send_event; /* true if this came from a SendEvent request */ - public unowned Display display; /* Display the event was read from */ - public Window window; - public Atom message_type; - public int format; - public ClientMessageEventData data; - } - - // union - public struct ClientMessageEventData { - public unowned char[] b; - public unowned short[] s; - public unowned long[] l; - } - - [CCode (cprefix = "PropMode")] - public enum PropMode { - Replace, - Prepend, - Append - } - - [CCode (cprefix = "")] - public enum AllowEventsMode { - AsyncPointer, - SyncPointer, - ReplayPointer, - AsyncKeyboard, - SyncKeyboard, - ReplayKeyboard, - AsyncBoth, - SyncBoth - } - - [CCode (cprefix = "")] - public enum MapState { - IsUnmapped, - IsUnviewable, - IsViewable - } - - [CCode (cprefix = "RevertTo")] - public enum RevertTo { - None, - PointerRoot, - Parent - } - - [Compact] - [CCode (cname = "Screen")] - public class Screen { - public Display display; - public Window root; - public int width; - public int height; - - [CCode (cname = "XScreenOfDisplay")] - public static unowned Screen get_screen (Display disp, int screen_number); - - [CCode (cname = "XBlackPixelOfScreen")] - public ulong black_pixel_of_screen (); - - [CCode (cname = "XCellsOfScreen")] - public int cells_of_screen (); - - [CCode (cname = "XDefaultColormapOfScreen")] - public Colormap default_colormap_of_screen (); - - [CCode (cname = "XDefaultDepthOfScreen")] - public int default_depth_of_screen (); - - [CCode (cname = "XDefaultGCOfScreen")] - public GC default_gc_of_screen (); - - [CCode (cname = "XDefaultVisualOfScreen")] - public Visual default_visual_of_screen (); - - [CCode (cname = "XDisplayOfScreen")] - public unowned Display display_of_screen (); - - [CCode (cname = "XDoesBackingStore")] - public int does_backing_store (); - - [CCode (cname = "XDoesSaveUnders")] - public bool does_save_unders (); - - [CCode (cname = "XEventMaskOfScreen")] - public long event_mask_of_Screen (); - - [CCode (cname = "XHeightMMOfScreen")] - public int height_in_mm_of_screen (); - - [CCode (cname = "XHeightOfScreen")] - public int height_of_screen (); - - [CCode (cname = "XMaxCmapsOfScreen")] - public int max_colormaps_of_screen (); - - [CCode (cname = "XMinCmapsOfScreen")] - public int min_colormaps_of_screen (); - - [CCode (cname = "XPlanesOfScreen")] - public int planes_of_screen (); - - [CCode (cname = "XRootWindowOfScreen")] - public Window root_window_of_screen (); - - [CCode (cname = "XScreenNumberOfScreen")] - public int screen_number_of_screen (); - - [CCode (cname = "XWhitePixelOfScreen")] - public ulong white_pixel_of_screen (); - - [CCode (cname = "XWidthMMOfScreen")] - public int width_in_mm_of_screen (); - - [CCode (cname = "XWidthOfScreen")] - public int width_of_screen (); - } - - public const X.Atom XA_ATOM; - public const X.Atom XA_CARDINAL; - public const X.Atom XA_WINDOW; - public const X.Atom XA_WM_CLASS; - public const X.Atom XA_WM_HINTS; - public const X.Atom XA_WM_ICON_NAME; - public const X.Atom XA_WM_NAME; - public const X.Atom XA_WM_NORMAL_HINTS; - public const X.Atom XA_WM_TRANSIENT_FOR; - - public const uint XK_Num_Lock; - public const uint XK_Scroll_Lock; -} - diff --git a/src/zavai.vala b/src/zavai.vala index 50a2c39..d1dede5 100644 --- a/src/zavai.vala +++ b/src/zavai.vala @@ -117,7 +117,7 @@ static int main (string[] args) { zavai.ui.main.init(); zavai.ui.gps.init(); zavai.ui.gsm.init(); - zavai.app.run_script(zavai.config.homedir + "/display init"); + zavai.config.run_script(zavai.config.homedir + "/display init"); zavai.ui.power.init(); zavai.ui.aux.init(); zavai.ui.kbd.init(); diff --git a/zavai/__init__.py b/zavai/__init__.py deleted file mode 100644 index 4d48db9..0000000 --- a/zavai/__init__.py +++ /dev/null @@ -1,40 +0,0 @@ -# zavai shared code -# -# Copyright (C) 2009 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 - -from conf import read_config -from config import Config -from plugins import load_plugins -from registry import Registry, Resource, Service, get_parent, default_label -from menu import Menu, MenuButton, LinkButton, ToggleButton -from app import Zavai, Applet -from gps import GPS, GPX -from audio import Audio, Recorder - -VERSION="0.1" - -def warn(*args): - import sys - sys.stderr.write(" ".join(map(str, args)) + "\n") -def info(*args): - import sys - sys.stderr.write(" ".join(map(str, args)) + "\n") - -def set_quiet(): - def info(*args): - pass - diff --git a/zavai/app.py b/zavai/app.py deleted file mode 100644 index 4ce7852..0000000 --- a/zavai/app.py +++ /dev/null @@ -1,91 +0,0 @@ -# app - zavai main window -# -# Copyright (C) 2009 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 - -import sys -from gettext import gettext as _ -import gtk, gobject -import zavai - -class Zavai(gtk.Window, zavai.Resource): - def __init__(self, registry, name): - super(Zavai, self).__init__() - self.registry = registry - self.current = None - self.activate_resource("menu.main") - - def activate_resource(self, name): - widget = self.registry.resource(name) - if widget is None: - widget = self.registry.resource("menu.main") - if isinstance(widget, gtk.Action): - widget.activate() - else: - self.show_widget(name, widget) - - def show_widget(self, name, widget): - # Remove the current widget. - # If it is an Applet, stop it - if self.current is not None: - cur = self.registry.resource(self.current) - if isinstance(cur, zavai.Applet): - cur.stop() - self.remove(self.get_child()) - self.current = None - - # Add the new widget. If it is an applet, start it - self.add(widget) - self.current = name - if isinstance(widget, zavai.Applet): - widget.start() - widget.show_all() - - def run(self): - self.set_size_request(100, 200) - #self.fullscreen() - self.show_all() - gtk.main() - -class Applet(gtk.VBox): - name = gobject.property(type=str) - label = gobject.property(type=str) - - def __init__(self, registry, name, label = None): - super(Applet, self).__init__() - - self.zavai_registry = registry - - self.props.name = name - if label is None: - self.props.label = zavai.default_label(name) - else: - self.props.label = label - - self.back_link = zavai.LinkButton(registry, zavai.get_parent(name), _("Back")) - self.pack_end(self.back_link, False, False) - - def add(self, widget): - self.pack_start(widget, True, True) - - def shutdown(self): - self.stop() - - def start(self, *args): - pass - - def stop(self, *args): - pass diff --git a/zavai/at.vala b/zavai/at.vala new file mode 100644 index 0000000..33cdf27 --- /dev/null +++ b/zavai/at.vala @@ -0,0 +1,164 @@ +/* + * at - at interface + * + * Copyright (C) 2009 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 at { + +public struct Event +{ + int id; + time_t deadline; +} + +// Return the earliest ID in the queue, or -1 if none are found +// Queue is null for all queues, otherwise a queue name +public static Event earliestID(string? queue = null) +{ + Event res = { -1, 0 }; + + string argv[4]; + argv[0] = "/usr/bin/atq"; + if (queue == null) + argv[1] = null; + else + { + argv[1] = "-q"; + argv[2] = queue; + argv[3] = null; + } + + Pid pid; + int stdout; + + try + { + if (!Process.spawn_async_with_pipes("/", argv, null, SpawnFlags.STDERR_TO_DEV_NULL, null, out pid, null, out stdout, null)) + return res; + } catch (SpawnError e) { + stderr.printf("Cannot run 'at -q': %s\n", e.message); + return res; + } + + FileStream fs = FileStream.fdopen(stdout, "r"); + if (fs == null) + return res; + + char buf[200]; + string? line; + while ((line = fs.gets(buf)) != null) + { + if (!line[0].isdigit()) continue; + weak string rest; + ulong id = line.to_ulong(out rest, 10); + Time t = Time(); + rest = t.strptime(rest.offset(1), "%a %b %d %H:%M:%S %Y"); + if (rest == null) continue; + if (rest.size() < 2) continue; + //stderr.printf("PARSE QUEUE rest %s\n", rest); + // Skip the queue of tasks currently being executed + //if (rest[1] == '=') continue; + // Skip entries not in the wanted queue + if (queue != null && rest[1] != queue[0]) continue; + time_t tt = t.mktime(); + if (res.deadline == 0 || tt < res.deadline) { + res.id = (int)id; + res.deadline = tt; + } + } + Process.close_pid(pid); + return res; +} + +public delegate bool jobParser(int fd); + +// Get the contents of a job given its id +public static bool jobContents(int id, jobParser parser) +{ + string argv[4]; + argv[0] = "/usr/bin/at"; + argv[1] = "-c"; + argv[2] = id.to_string(); + argv[3] = null; + + Pid pid; + int stdoutfd; + + try + { + if (!Process.spawn_async_with_pipes("/", argv, null, SpawnFlags.STDERR_TO_DEV_NULL, null, out pid, null, out stdoutfd, null)) + return false; + } catch (SpawnError e) { + stderr.printf("Cannot run 'at -c': %s\n", e.message); + return false; + } + + bool res = parser(stdoutfd); + + Process.close_pid(pid); + + return res; +} + +/* +TODO: schedule alarms via at + +Uses the 'z' queue. + +atq -q z can be used to list the jobs (for example, at startup, or after a job has run) +at -c id can be used to query a job, parsing its contents (which can have + comments or variables being set) +zavai --notify ... can be used to notify the job (and start zavai if it's not running) + +Alarm needs to be able to serialize itself to an at invocation and to +deserialize itself from the output of at -c + +Alarm needs to deserialize also a job with no special markers whatsoever: a +generic at job. +*/ + + +/* +public class Alarm : Object +{ + // TODO: make a factory method to construct from an "at -c" output + + // TODO: make a method that provides an at invocation + + public signal void trigger(Alarm a); + + public time_t deadline; + public string label; + + public Alarm(time_t deadline, string label) + { + this.deadline = deadline; + this.label = label; + } +} +*/ + + // Schedule a task that notifies a string + // TODO public void schedule_label(const Alarm a); + + // Return the next item in the queue due to be run + // TODO public Alarm? next_scheduled(); + +} diff --git a/zavai/audio.py b/zavai/audio.py deleted file mode 100755 index 9d7835e..0000000 --- a/zavai/audio.py +++ /dev/null @@ -1,295 +0,0 @@ -# audio - zavai audio resource -# -# Copyright (C) 2009 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 - -import zavai -import struct -import gobject -import os -import os.path -import subprocess -import signal -#import sys -#import time -#import dbus - -class Recorder(zavai.Resource): - def __init__(self, registry): - super(Recorder, self).__init__() - self.registry = registry - self.recorder = None - - def shutdown(self): - self.stop() - - def start(self, filename): - if self.recorder is not None: return - - self.registry.resource("audio").connect("audio", self) - - self.recorder = subprocess.Popen( - ["arecord", "-D", "hw", "-f", "cd", "-r", "8000", "-t", "wav", filename]) - - def stop(self): - if self.recorder is None: return - - os.kill(self.recorder.pid, signal.SIGINT) - self.recorder.wait() - self.recorder = None - - self.registry.resource("audio").disconnect("audio", self) - - -# TODO: -# - hook into the headset plugged/unplugged event -# - if unplugged, turn on handset microphone -# - if plugged, redo headest mixer settings -class Audio(zavai.Service): - "Handle mixer settings, audio recording and headset button presses" - def __init__(self, registry, name): - super(Audio, self).__init__(["audio", "button", "jack"]) - - conf = registry.resource("conf") - self.saved_scenario = os.path.join(conf.homedir, "audiomap.state") - - self.input_fd = None - self.input_watch = None - - - def start(self): - # Setup the mixer - # Set mixer to record from headset and handle headset button - self.save_scenario(self.saved_scenario) - self.load_scenario("/usr/share/openmoko/scenarios/voip-handset.state") - - # This is a work-around because I have not found a way to query for the - # current headset state, I can only know when it changes. So in my - # system I configured oeventsd with a rule to touch this file when the - # headset is plugged in, and remove the file when it's plugged out. - if os.path.exists("/tmp/has_headset"): - self.mixer_for_headset(force = True) - else: - self.mixer_for_handset(force = True) - - # Watch the event device - self.input_fd = open("/dev/input/event4", "rb") - self.input_watch = gobject.io_add_watch(self.input_fd.fileno(), gobject.IO_IN, self.on_input_data) - self.last_button_press = 0 - -# #self.mixer_set("DAPM Handset Mic", "mute") -# #self.mixer_set("DAPM Headset Mic", "unmute") -# #self.mixer_set("Left Mixer Sidetone Playback Sw", "unmute") -# #self.mixer_set("ALC Mixer Mic1", "cap") -# #self.mixer_set("Amp Spk", "mute") # We don't need the phone playing what we say -# -# self.recorder = None -# self.basename = None - - def stop(self): - # Stop watching the event device - if self.input_fd is None: - return - gobject.source_remove(self.input_watch) - self.input_watch = None - self.input_fd.close() - self.input_fd = None - - # Restore mixer settings - self.load_scenario(self.saved_scenario) - - def on_input_data(self, source, condition): - buf = self.input_fd.read(16) - ts1, ts2, type, code, value = struct.unpack("LLHHI", buf) - if type == 1 and code == 119: - if self.last_button_press + 1 < ts1: - self.last_button_press = ts1 - else: - return True - if value: - zavai.info("Headset button release") - self.notify("button", False) - else: - zavai.info("Headset button press") - self.notify("button", True) - elif type == 5 and code == 2: - if value: - zavai.info("Headset plugged in") - self.mixer_for_headset() - self.notify("jack", True) - else: - zavai.info("Headset plugged out") - self.mixer_for_handset() - self.notify("jack", False) - return True - - def mixer_for_headset(self, force=False): - if not force and self.has_headset: return - zavai.info("Setting mixer for headset") - # TODO: find out how to disable the handset microphone: this does not - # seem to be sufficient - self.mixer_set_many( - ("DAPM Handset Mic", "mute"), - ("DAPM Headset Mic", "unmute"), - ("Left Mixer Sidetone Playback Sw", "unmute"), - ("ALC Mixer Mic1", "cap"), - ("Amp Spk", "mute") # We don't need the phone playing what we say - ) - self.has_headset = True - - def mixer_for_handset(self, force=False): - if not force and not self.has_headset: return - zavai.info("Setting mixer for handset") - self.mixer_set_many( - ("DAPM Handset Mic", "unmute"), - ("DAPM Headset Mic", "mute"), - ("Left Mixer Sidetone Playback Sw", "mute"), - ("ALC Mixer Mic1", "cap"), - ("Amp Spk", "mute") # We don't need the phone playing what we say - ) - self.has_headset = False - -# def set_basename(self, basename): -# self.basename = basename -# -# def start_levels(self): -# self.recorder = subprocess.Popen( -# ["arecord", "-D", "hw", "-f", "cd", "-r", "8000", "-t", "wav", "-V", "stereo", "/dev/null"]) - - def save_scenario(self, name): - while True: - res = subprocess.call(["alsactl", "store", "-f", name]) - if res == 0: return - if res > 0: - raise RuntimeError("Saving audio scenario to '%s' failed" % name) - - def load_scenario(self, name): - while True: - res = subprocess.call(["alsactl", "restore", "-f", name]) - if res == 0: return - if res > 0: - raise RuntimeError("Loading audio scenario '%s' failed with error %d" % (name, res)) - - def mixer_set(self, name, *args): - args = map(str, args) - while True: - res = subprocess.call(["amixer", "-q", "set", name] + args) - if res == 0: return - if res > 0: - raise RuntimeError("Setting mixer '%s' to %s failed with error %d" % (name, " ".join(args), res)) - - def mixer_set_many(self, *args): - """Perform many mixer set operations via amixer --stdin""" - cmd_input = [] - for k, v in args: - cmd_input.append("sset " + repr(k) + " " + repr(v)) - while True: - proc = subprocess.Popen(["amixer", "-q", "--stdin"], stdin=subprocess.PIPE) - (out, err) = proc.communicate(input="\n".join(cmd_input)) - res = proc.wait() - if res == 0: return - if res > 0: - raise RuntimeError("Setting mixer failed with error %d" % res) - - -#class Hub: -# """Hub that manages all the various resources that we use, and initiates -# operations.""" -# def __init__(self, bus = None): -# self.bus = bus -# self.waiting_for_fix = False -# self.basename = None -# self.recorder = None -# self.gpx = None -# self.gps = None -# self.gps_monitor = None -# self.audio = None -# self.last_pos = None -# -# def shutdown(self): -# # Stop recording -# if self.audio is not None: -# self.audio.close() -# -# # Close waypoints file -# if self.gpx is not None: -# self.gpx.close() -# -# # Stop the GPS monitor -# if self.gps_monitor: -# self.gps_monitor.stop() -# -# # Release the GPS -# if self.gps is not None: -# self.gps.close() -# -# def levels(self): -# self.audio = Audio() -# self.audio.start_levels() -# -# def record(self): -# self.audio = Audio(self.make_waypoint) -# self.gps = GPS() -# # Get a fix and start recording -# if not self.gps.wait_for_fix(self.start_recording): -# self.gps_monitor = GPSMonitor(self.gps) -# self.gps_monitor.start() -# -# def monitor(self): -# self.audio = None -# self.gps = GPS() -# self.gps_monitor = GPSMonitor(self.gps) -# self.gps_monitor.start() -# -# def start_recording(self): -# if self.gps_monitor: -# self.gps_monitor.stop() -# self.gps_monitor = None -# -# if not self.audio: -# return -# -# # Sync system time -# gpstime = self.gps.gps_time.GetTime() -# subprocess.call(["date", "-s", "@%d" % gpstime]) -# subprocess.call(["hwclock", "--systohc"]) -# -# # Compute basename for output files -# self.basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(gpstime)) -# self.basename = os.path.join(AUDIODIR, self.basename) -# -# # Start recording the GPX track -# self.gpx = GPX(self.basename) -# self.gps.track_position(self.on_position_changed) -# -# # Start recording in background forking arecord -# self.audio.set_basename(self.basename) -# self.audio.start_recording() -# -# def on_position_changed(self, fields, tstamp, lat, lon, alt): -# self.last_pos = (fields, tstamp, lat, lon, alt) -# if self.gpx: -# self.gpx.trackpoint(tstamp, lat, lon, alt) -# -# def make_waypoint(self): -# if self.gpx is None: -# return -# if self.last_pos is None: -# self.last_pos = self.gps.gps_position.GetPosition() -# (fields, tstamp, lat, lon, alt) = self.last_pos -# self.gpx.waypoint(tstamp, lat, lon, alt) -# info("Making waypoint at %s: %f, %f, %f" % ( -# time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(tstamp)), lat, lon, alt)) diff --git a/zavai/audio.vala b/zavai/audio.vala new file mode 100644 index 0000000..1c39420 --- /dev/null +++ b/zavai/audio.vala @@ -0,0 +1,225 @@ +/* + * 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 Omhacks.Led vibrator; + protected bool has_vibrator; + + /* + protected dynamic DBus.Object audiodev; + protected dynamic DBus.Object vibdev; + */ + + public Audio() + { + Object(name: "audio"); + + has_vibrator = (vibrator.init("neo1973:vibrator") == 0); + +/* + 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"); +*/ + 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) + { + zavai.log.debug("Make noise for alarm"); + if (has_vibrator) + { + 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) + { + vibrator.trigger[i] = (char)trig[i]; + if (trig[i] == 0) break; + } + vibrator.delay_on = 200; + vibrator.delay_off = 300; + vibrator.set(); + } + soundplayer.play(config.ringtone_alarm, true); + } + + public void on_alarm_done(clock.AlarmTriggerInfo info) + { + zavai.log.debug("Stop noise for alarm"); + if (has_vibrator) + { + var trig = "none"; + for (int i = 0; ; ++i) + { + vibrator.trigger[i] = (char)trig[i]; + if (trig[i] == 0) break; + } + vibrator.brightness = 0; + vibrator.set(); + } + 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); + } + // TODO: play music? + } +*/ +} + +public class Player: zavai.Resource, Object +{ + protected Gst.Element player; + protected bool playing; + protected Player slave; + protected Player master; + protected bool loop; + protected string uri; + public signal void state_changed(Gst.State new_state); + + public Player() + { + slave = null; + master = null; + player = Gst.ElementFactory.make("playbin", null); + playing = false; + loop = false; + var bus = player.get_bus(); + bus.add_signal_watch(); + bus.message += on_message; + } + + public void set_slave(Player player) + { + slave = player; + slave.master = this; + } + + public void play(string uri, bool loop = false) + { +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; + } + + 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; + } + + public void pause() + { + 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); + } + + 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); + } + + 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(); + } + } + + public void shutdown() + { + stop(); + } +} + +public Audio audio = null; +public Player musicplayer = null; +public Player soundplayer = null; + +public void init() +{ + audio = new Audio(); + musicplayer = new Player(); + soundplayer = new Player(); + soundplayer.set_slave(musicplayer); + zavai.registry.register(musicplayer); + zavai.registry.register(soundplayer); +} + +} +} diff --git a/zavai/bluetooth.vala b/zavai/bluetooth.vala new file mode 100644 index 0000000..0103d0f --- /dev/null +++ b/zavai/bluetooth.vala @@ -0,0 +1,61 @@ +/* + * bluetooth - bluetooth resource for zavai + * + * 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 bluetooth { + +public class Bluetooth: zavai.ScriptService +{ + public Bluetooth() + { + Object(name: "bluetooth"); + started = script_status(); + } + + /// Start Bluetooth + public override void start() + { + if (started) return; + if (!script_start()) return; + zavai.log.info("bluetooth turned on"); + base.start(); + } + + // Release usage of GPS + public override void stop() + { + if (!started) return; + script_stop(); + base.stop(); + } +} + +public Bluetooth bluetooth = null; + +public void init() +{ + bluetooth = new Bluetooth(); + +} + +} +} diff --git a/zavai/clock.vala b/zavai/clock.vala new file mode 100644 index 0000000..d08717b --- /dev/null +++ b/zavai/clock.vala @@ -0,0 +1,357 @@ +/* + * clock - clock 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 clock { + +public enum SourceType +{ + SYSTEM, + GPS +} + +/* +TODO: schedule alarms via at + +Uses the 'z' queue. + +atq -q z can be used to list the jobs (for example, at startup, or after a job has run) +at -c id can be used to query a job, parsing its contents (which can have + comments or variables being set) +zavai --notify ... can be used to notify the job (and start zavai if it's not running) + +Alarm needs to be able to serialize itself to an at invocation and to +deserialize itself from the output of at -c + +Alarm needs to deserialize also a job with no special markers whatsoever: a +generic at job. + + + +refresh_alarms() +{ + oldtime = next_alarm ? next_alarm.time : 0 + next_alarm = the first alarm from atq + if (oldtime != next_alarm.time) + { + remove existing triggers + (triggers can be skipped if we don't need to support non-zavai alarms) + schedule a trigger calling refresh_alarms() at next_alarm.time + 30 seconds + (triggers can be skipped if we don't need to support non-zavai alarms) + } +} + +at clock constructor: refresh_alarms() +inotifywait -e close /usr/bin/at -> refresh_alarms() (shows when someone has just used at) + (can be skipped if we don't need to support non-zavai alarms) +at alarm triggered through zavai: refresh_alarms() + + +*/ + + +public class Alarm : Object +{ + public at.Event ev; + public string label; + + // Schedule with at + public static void schedule(string timespec, string label) throws Error + { + string argv[5]; + argv[0] = "/usr/bin/at"; + argv[1] = "-q"; + argv[2] = "z"; + argv[3] = timespec; + argv[4] = null; + + Pid pid; + int stdinfd; + + if (!Process.spawn_async_with_pipes("/", argv, null, SpawnFlags.STDERR_TO_DEV_NULL, null, out pid, out stdinfd, null, null)) + return; + + { + FileStream fs = FileStream.fdopen(stdinfd, "w"); + string display = GLib.Environment.get_variable("DISPLAY"); + if (display != null) + fs.printf("DISPLAY=\"%s\"; export DISPLAY\n", display); + fs.printf("# Zavai variables start here\n"); + fs.printf("ZAVAI_LABEL=\"%s\"\n", label.escape("")); + fs.printf("# Zavai commands starts here\n"); + fs.printf("%s notify \"$ZAVAI_LABEL\"", zavai.config.argv0); + } + + Process.close_pid(pid); + } + + // Get the label of the job with the given at ID + public static string? getLabel(int atID) + { + string label = null; + at.jobContents(atID, fd => { + FileStream fs = FileStream.fdopen(fd, "r"); + while (true) + { + string? line = fs.read_line(); + if (line == null) break; + if (line.has_prefix("ZAVAI_LABEL=\"")) + { + size_t size = line.size(); + if (size < 15) continue; + label = line.substring(13, (long)(size - 14)); + label = label.compress(); + break; + } + } + return true; + }); + return label; + } +} + +[DBus (name = "org.enricozini.zavai.Alarm")] +public class ZavaiClock : Object { + public void Notify (string label) { + clock.notify_alarm(label); + } +} + +public class AlarmTriggerInfo +{ + public uint id; + public string label; + public bool acked; + public bool canceled; + + public AlarmTriggerInfo(string label) + { + id = 0; + this.label = label; + acked = false; + canceled = false; + } +} + +public class AlarmTriggerQueue : zavai.Service +{ + protected List queue; + + public signal void triggered(AlarmTriggerInfo info); + public signal void acked(AlarmTriggerInfo info); + public signal void canceled(AlarmTriggerInfo info); + + public AlarmTriggerQueue() + { + queue = new List(); + } + + public uint enqueue_trigger(AlarmTriggerInfo info) + { + // Reuse IDs from the associated logger object + info.id = zavai.log.log.start("alarm", "Alarm " + info.label); + queue.append(info); + if (queue.data.id == info.id) + triggered(queue.data); + return info.id; + } + + protected void done_with_first() + { + var first = queue.data; + queue.remove_link(queue); + if (queue != null) + triggered(queue.data); + } + + public void ack(AlarmTriggerInfo info) + { + if (queue == null || info.id != queue.data.id) return; + if (!info.acked && !info.canceled) + { + info.acked = true; + acked(info); + zavai.log.log.add(info.id, "alarm acknowledged"); + zavai.log.log.end(info.id); + } + done_with_first(); + } + + public void cancel(AlarmTriggerInfo info) + { + if (queue == null || info.id != queue.data.id) return; + if (!info.acked && !info.canceled) + { + info.canceled = true; + canceled(info); + zavai.log.log.add(info.id, "alarm canceled"); + zavai.log.log.end(info.id); + } + done_with_first(); + } +} + +public class Clock: zavai.Service +{ + protected time_t last_gps_time; + protected time_t last_gps_time_system_time; + protected time_t last_system_time; + protected uint system_time_timeout; + protected time_t last_minute; + protected time_t chosen_time; + protected SourceType chosen_type; + protected ZavaiClock dbusClock; + + protected dynamic DBus.Object otimed_alarm; + protected dynamic DBus.Object rtc; + protected SList alarms; + + // Ticks once a minute + public signal void minute_changed(long time, SourceType source); + public signal void schedule_changed(Alarm? next); + + public Clock() + { + Object(name: "clock"); + alarms = null; + dbusClock = new ZavaiClock(); + last_minute = 0; + last_gps_time = 0; + last_gps_time_system_time = 0; + last_system_time = time_t(); + chosen_time = last_system_time; + + // FSO alarm system + otimed_alarm = zavai.registry.sbus.get_object( + "org.freesmartphone.otimed", + "/org/freesmartphone/Time/Alarm", + "org.freesmartphone.Time.Alarm"); + + rtc = zavai.registry.sbus.get_object( + "org.freesmartphone.odeviced", + "/org/freesmartphone/Device/RTC/0", + "org.freesmartphone.Device.RealtimeClock"); + + zavai.registry.sbus.register_object("/org/enricozini/Zavai/Clock", dbusClock); + } + + public void notify_alarm(string label) + { + stderr.printf("Notifying %s\n", label); + AlarmTriggerInfo info = new AlarmTriggerInfo(label); + alarm_trigger_queue.enqueue_trigger(info); + schedule_changed(next_alarm()); + } + + public Alarm? next_alarm() + { + at.Event ev; + ev = at.earliestID("z"); + if (ev.deadline == 0) + return null; + string label = Alarm.getLabel(ev.id); + Alarm res = new Alarm(); + res.ev = ev; + res.label = label; + return res; + } + + public void schedule(string timespec, string label) throws Error + { + Alarm.schedule(timespec, label); + schedule_changed(next_alarm()); + } + + private void on_gps_time(uint t) + { + if (t == 0) + { + last_gps_time_system_time = 0; + update_time(); + } else { + last_gps_time = (time_t)t; + last_gps_time_system_time = time_t(); + update_time(); + } + } + + private bool on_system_time() + { + last_system_time = time_t(); + update_time(); + return true; + } + + private void update_time() + { + if (last_gps_time_system_time + 10 > last_system_time) + { + chosen_time = last_gps_time; + chosen_type = SourceType.GPS; + } + else + { + chosen_time = last_system_time; + chosen_type = SourceType.SYSTEM; + } + if (chosen_time / 60 != last_minute) + { + last_minute = chosen_time / 60; + minute_changed(chosen_time, chosen_type); + } + } + + /// Request GPS resource + public override void start() + { + if (started) return; + + system_time_timeout = Timeout.add(5000, on_system_time); + zavai.gps.gps.time_changed += on_gps_time; + last_system_time = time_t(); + update_time(); + + base.start(); + } + + public override void stop() + { + if (!started) return; + + Source.remove(system_time_timeout); + zavai.gps.gps.time_changed -= on_gps_time; + + base.stop(); + } +} + +public Clock clock = null; +public AlarmTriggerQueue alarm_trigger_queue = null; + +public void init() +{ + clock = new Clock(); + alarm_trigger_queue = new AlarmTriggerQueue(); +} + +} +} diff --git a/zavai/conf.py b/zavai/conf.py deleted file mode 100644 index ba253a4..0000000 --- a/zavai/conf.py +++ /dev/null @@ -1,33 +0,0 @@ -import os -import ConfigParser, StringIO - -def read_config(rootDir = None, defaults = None, nick="octofuss"): - """ - Read octofuss configuration, returning a ConfigParser object - """ - if rootDir == None: - rootDir = os.environ.get(nick.upper() + "_CONFDIR", "/etc/" + nick) - files = [] - def trytouse(path): - if os.path.exists(path): - files.append(path) - - # Start with the main config file - trytouse(os.path.join(rootDir, nick + ".conf")) - - # Add snippets found in rc.d style directory - subdir = os.path.join(rootDir, nick + ".conf.d") - if os.path.isdir(subdir): - for file in sorted(os.listdir(subdir)): - if file.startswith('#'): continue - if file.startswith('.'): continue - if file.endswith('~'): continue - if file.endswith('.bak'): continue - trytouse(os.path.join(subdir, file)) - - config = ConfigParser.ConfigParser() - if defaults != None: - infile = StringIO.StringIO(defaults) - config.readfp(infile, "defaults") - config.read(files) - return config diff --git a/zavai/config.py b/zavai/config.py deleted file mode 100644 index e328cb8..0000000 --- a/zavai/config.py +++ /dev/null @@ -1,23 +0,0 @@ -import os.path -import zavai - -class Config: - def __init__(self): - self.conf = zavai.read_config(nick="zavai") - - def get(self, section, name, default=None): - if self.conf.has_section(section): - if self.conf.has_option(section, name): - return self.conf.get(section, name) - return None - - def _get_homedir(self): - res = self.get("global", "home") - if res is None: - res = os.path.expanduser("~/.zavai") - if not os.path.isdir(res): - zavai.info("Creating directory", res) - os.makedirs(res) - return res - - homedir = property(_get_homedir) diff --git a/zavai/config.vala b/zavai/config.vala new file mode 100644 index 0000000..444bbc2 --- /dev/null +++ b/zavai/config.vala @@ -0,0 +1,265 @@ +/* + * config - zavai configuration + * + * 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 + */ + +namespace zavai { + +public class Config +{ + protected Lua.LuaVM lua; + protected weak string get_string(string name) + { + lua.get_global(name); + weak string res = lua.to_string(-1); + lua.pop(1); + return res; + } + protected string set_string(string name, string? val) + { + if (val == null) + lua.push_nil(); + else + lua.push_string(val); + lua.set_global(name); + return val; + } + protected weak int get_int(string name) + { + lua.get_global(name); + int res = lua.to_integer(-1); + lua.pop(1); + return res; + } + protected int set_int(string name, int val) + { + lua.push_integer(val); + lua.set_global(name); + return val; + } + + private string _version; + public string version + { + get { return _version; } + set { _version = set_string("version", value); } + } + + // "phone" or "laptop" + private string _profile; + public string profile + { + get { return _profile; } + set { _profile = set_string("profile", value); } + } + + private string _homedir; + public string homedir + { + get { return _homedir; } + set { _homedir = set_string("homedir", value); } + } + + private string _icondir; + public string icondir + { + get { return _icondir; } + set { _icondir = set_string("icondir", value); } + } + + private int _min_button_height; + public int min_button_height + { + get { return _min_button_height; } + set { _min_button_height = set_int("min_button_height", value); } + } + + private string _gpsd_host; + public string gpsd_host + { + get { return _gpsd_host; } + set { _gpsd_host = set_string("gpsd_host", value); } + } + + private string _gpsd_port; + public string gpsd_port + { + get { return _gpsd_port; } + set { _gpsd_port = set_string("gpsd_port", value); } + } + + private string _gprs_apn; + public string gprs_apn + { + get { return _gprs_apn; } + set { _gprs_apn = set_string("gprs_apn", value); } + } + + private string _gprs_user; + public string gprs_user + { + get { return _gprs_user; } + set { _gprs_user = set_string("gprs_user", value); } + } + + private string _gprs_pass; + public string gprs_pass + { + get { return _gprs_pass; } + set { _gprs_pass = set_string("gprs_pass", value); } + } + + private string _sim_pin; + public string sim_pin + { + get { return _sim_pin; } + set { _sim_pin = set_string("sim_pin", value); } + } + + private int _power_button_keycode; + public int power_button_keycode + { + get { return _power_button_keycode; } + set { _power_button_keycode = set_int("power_button_keycode", value); } + } + + private int _aux_button_keycode; + public int aux_button_keycode + { + get { return _aux_button_keycode; } + set { _aux_button_keycode = set_int("aux_button_keycode", value); } + } + + private string _ringtone_alarm; + public string ringtone_alarm + { + get { return _ringtone_alarm; } + set { _ringtone_alarm = set_string("ringtone_alarm", value); } + } + + public int backlight_max + { + get; + set; + } + + private string _argv0; + public string argv0 { + get { return _argv0; } + set { + if (value.chr(-1, '/') != null) + { + if (Path.is_absolute(value)) + { + _argv0 = value; + } else { + _argv0 = Path.build_filename(Environment.get_current_dir(), value, null); + } + } else { + _argv0 = Environment.find_program_in_path(value); + } + zavai.log.debug("ARGV0: " + _argv0); + } + } + + /// Reread config values from the Lua VM, to be run after running Lua code + protected void refresh_from_lua() + { + _version = get_string("version"); + _profile = get_string("profile"); + _homedir = get_string("homedir"); + _icondir = get_string("icondir"); + _min_button_height = get_int("min_button_height"); + _gpsd_host = get_string("gpsd_host"); + _gpsd_port = get_string("gpsd_port"); + _gprs_apn = get_string("gprs_apn"); + _gprs_user = get_string("gprs_user"); + _gprs_pass = get_string("gprs_pass"); + _sim_pin = get_string("sim_pin"); + _power_button_keycode = get_int("power_button_keycode"); + _aux_button_keycode = get_int("aux_button_keycode"); + _ringtone_alarm = get_string("ringtone_alarm"); + } + + public Config() + { + lua = new Lua.LuaVM(); + lua.open_libs(); + + // Set defaults + version = "0.1"; + profile = "phone"; + homedir = GLib.Environment.get_home_dir() + "/.zavai"; + icondir = GLib.Environment.get_variable("ZAVAI_ICONDIR"); + if (icondir == null) + icondir = "/usr/share/zavai/icons"; + min_button_height = 80; + gpsd_host = "localhost"; + gpsd_port = "gpsd"; + gprs_apn = "general.t-mobile.uk"; + gprs_user = "x"; + gprs_pass = "x"; + sim_pin = "1234"; + backlight_max = 15; + power_button_keycode = 124; + aux_button_keycode = 177; + ringtone_alarm = "file:///usr/share/sounds/yue-fso/lec1.ogg"; + + // Read config + if (lua.do_file(homedir + "/config")) + { + zavai.log.error("Failed to parse " + homedir + "/config: " + lua.to_string(-1)); + } + refresh_from_lua(); + } + + public void run_script(string command) + { + zavai.log.info("Run program: " + command); + string[] args = command.split(" "); + Pid pid; + try { + Process.spawn_async( + Environment.get_home_dir(), + args, + null, + SpawnFlags.SEARCH_PATH, + null, + out pid); + } catch (SpawnError e) { + zavai.log.error("Running " + command + ": " + e.message); + } + } + + public int run_script_sync(string command, out string std_out, out string std_err) + { + int status = -1; + zavai.log.info("Run program: " + command); + string[] args = command.split(" "); + try { + bool res = Process.spawn_sync(Environment.get_home_dir(), args, null, SpawnFlags.SEARCH_PATH, null, out std_out, out std_err, out status); + } catch (SpawnError e) { + zavai.log.error("Running " + command + ": " + e.message); + } + return status; + } +} + +public Config config = null; + +} diff --git a/zavai/core.vala b/zavai/core.vala new file mode 100644 index 0000000..3c31ccd --- /dev/null +++ b/zavai/core.vala @@ -0,0 +1,279 @@ +/* + * app - zavai main window + * + * Copyright (C) 2009 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 { + +public interface Resource : Object { + /** + * Shut down this resource. + * + * Normally one does nothing here, but it is important to give resources a + * chance to do cleanup when the program quits. + * + * This can be used for tasks like closing the tags on a GPX track, + * releasing a FSO resource, restoring mixer settings and so on. + */ + public abstract void shutdown(); +} + +public abstract class Service : Object, Resource { + public string name { get; construct; } + + bool _started; + public bool started { + get { return _started; } + set { _started = value; } + } + + public signal void toggled(bool new_state); + + protected class Request + { + public string requestor; + public int count; + public Request(string requestor) + { + this.requestor = requestor; + count = 1; + } + } + + protected List requests; + + construct + { + started = false; + requests = null; + zavai.registry.register(this); + } + + public void shutdown() + { + stop(); + } + + /// Activate the service + protected virtual void start() + { + if (!started) + { + zavai.log.info("Service " + name + " started\n"); + started = true; + toggled(started); + } + } + + /// Deactivate the service + protected virtual void stop() + { + if (started) + { + zavai.log.info("Service " + name + " stopped\n"); + started = false; + toggled(started); + } + } + + /** + Request a resource using the given ID. + * + * If it is the first time the resource is requested, start it and + * return true. Else, take note of the request and return false. + * + * If a resource is requested multiple times with the same ID, it will + * need to be released multiple times with that ID. + */ + public bool request(string id) + { + bool res = (requests == null); + bool got = false; + for (weak List i = requests; i != null; i = i.next) + if (i.data.requestor == id) + { + ++i.data.count; + got = true; + break; + } + if (!got) + requests.prepend(new Request(id)); + if (res) start(); + return res; + } + + /** + * Release a resource using the given ID. + * + * If after the call nothing is requesting the resource, stop it and + * return true. Else, take note of the release and return false. + * + * If a resource is requested multiple times with the same ID, it will + * need to be released multiple times with that ID. + */ + public bool release(string id) + { + weak List el = null; + for (weak List i = requests; i != null; i = i.next) + if (i.data.requestor == id) + { + el = i; + break; + } + + if (el == null) + return false; + + requests.delete_link(el); + + if (requests != null) + return false; + + stop(); + return true; + } +} + +public abstract class ScriptService : Service +{ + protected bool script_start() + { + try { + // Then run our own script + zavai.config.run_script(zavai.config.homedir + "/" + name + " start"); + return true; + } catch (Error e) { + zavai.log.error("Running " + zavai.config.homedir + "/" + name + " start: " + e.message); + return false; + } + } + + protected bool script_stop() + { + try { + // Then run our own script + zavai.config.run_script(zavai.config.homedir + "/" + name + " stop"); + return true; + } catch (Error e) { + zavai.log.error("Running " + zavai.config.homedir + "/" + name + " stop: " + e.message); + return false; + } + } + + protected bool script_status() + { + string std_out; + string std_err; + string command = zavai.config.homedir + "/" + name + " status"; + int res = zavai.config.run_script_sync(command, out std_out, out std_err); + if (res != 0) + { + zavai.log.error("Running " + command + ": " + std_err); + return false; + } + + std_out._strip(); + + return (std_out == "on"); + } +} + +public abstract class ScriptMonitorService : Service +{ + protected Pid child_pid; + protected int child_watch_id; + + ScriptMonitorService() + { + child_pid = 0; + child_watch_id = 0; + } + + protected bool script_start() + { + string command = zavai.config.homedir + "/" + name + " pre"; + try { + // Then run our own script + zavai.config.run_script(command); + } catch (Error e) { + zavai.log.error("Running " + command + ": " + e.message); + return false; + } + + command = zavai.config.homedir + "/" + name + " run"; + zavai.log.info("Run program: " + command); + string[] args = command.split(" "); + try { + Process.spawn_async( + Environment.get_home_dir(), + args, + null, + SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD, + null, + out child_pid); + } catch (SpawnError e) { + zavai.log.error("Running " + command + ": " + e.message); + return false; + } + + // Add a child watch source to know when it ends + ChildWatch.add(child_pid, on_child); + + return true; + } + + protected bool script_stop() + { + Posix.kill((Posix.pid_t)child_pid, Posix.SIGTERM); + return true; + } + + protected void on_child(Pid pid, int status) + { + zavai.log.info("Exited"); +stderr.printf("STATUS %d\n", status); + Process.close_pid(pid); + + string command = zavai.config.homedir + "/" + name + " post"; + try { + // Then run our own script + zavai.config.run_script(command); + } catch (Error e) { + zavai.log.error("Running " + command + ": " + e.message); + return; + } + + cleanup_after_script_stop(); + + base.stop(); + } + + protected virtual void cleanup_after_script_stop() + { + } + + /* + protected bool script_status() + { + } + */ +} + +} diff --git a/zavai/dbus-extra.vapi b/zavai/dbus-extra.vapi new file mode 100644 index 0000000..5213899 --- /dev/null +++ b/zavai/dbus-extra.vapi @@ -0,0 +1,5 @@ +namespace DBus { + [CCode (cname = "dbus_bus_get_unique_name")] + public unowned string bus_get_unique_name (DBus.RawConnection conn); +} + diff --git a/zavai/devkit-power-gobject.vapi b/zavai/devkit-power-gobject.vapi new file mode 100644 index 0000000..139abc2 --- /dev/null +++ b/zavai/devkit-power-gobject.vapi @@ -0,0 +1,232 @@ +/* devkit-power-gobject.vapi generated by vapigen, do not modify. */ + +[CCode (cprefix = "Dkp", lower_case_cprefix = "dkp_")] +namespace Dkp { + [CCode (cheader_filename = "devkit-power-gobject/devicekit-power.h")] + public class Client : GLib.Object { + [CCode (has_construct_function = false)] + public Client (); + public unowned GLib.PtrArray enumerate_devices () throws GLib.Error; + [CCode (cname = "dkp_client_can_hibernate")] + public bool get_can_hibernate (); + [CCode (cname = "dkp_client_can_suspend")] + public bool get_can_suspend (); + public unowned string get_daemon_version (); + [CCode (cname = "dkp_client_lid_is_closed")] + public bool get_lid_is_closed (); + [CCode (cname = "dkp_client_on_battery")] + public bool get_on_battery (); + [CCode (cname = "dkp_client_on_low_battery")] + public bool get_on_low_battery (); + public bool hibernate () throws GLib.Error; + public bool suspend () throws GLib.Error; + [NoAccessorMethod] + public bool can_hibernate { get; } + [NoAccessorMethod] + public bool can_suspend { get; } + public string daemon_version { get; } + [NoAccessorMethod] + public bool lid_is_closed { get; } + [NoAccessorMethod] + public bool lid_is_present { get; } + [NoAccessorMethod] + public bool on_battery { get; } + [NoAccessorMethod] + public bool on_low_battery { get; } + public virtual signal void changed (); + public virtual signal void device_added (void* device); + public virtual signal void device_changed (void* device); + public virtual signal void device_removed (void* device); + } + [CCode (cheader_filename = "devkit-power-gobject/devicekit-power.h")] + public class Device : GLib.Object { + [CCode (has_construct_function = false)] + public Device (); + public unowned GLib.PtrArray get_history (string type, uint timespec, uint resolution) throws GLib.Error; + public unowned string get_object_path (); + public unowned GLib.PtrArray get_statistics (string type) throws GLib.Error; + public bool print (); + public bool refresh () throws GLib.Error; + public bool set_object_path (string object_path) throws GLib.Error; + public static Dkp.DeviceState state_from_text (string state); + public static unowned string state_to_text (Dkp.DeviceState state_enum); + public static Dkp.DeviceTechnology technology_from_text (string technology); + public static unowned string technology_to_text (Dkp.DeviceTechnology technology_enum); + public static Dkp.DeviceType type_from_text (string type); + public static unowned string type_to_text (Dkp.DeviceType type_enum); + [NoAccessorMethod] + public double capacity { get; set; } + [NoAccessorMethod] + public double energy { get; set; } + [NoAccessorMethod] + public double energy_empty { get; set; } + [NoAccessorMethod] + public double energy_full { get; set; } + [NoAccessorMethod] + public double energy_full_design { get; set; } + [NoAccessorMethod] + public double energy_rate { get; set; } + [NoAccessorMethod] + public bool has_history { get; set; } + [NoAccessorMethod] + public bool has_statistics { get; set; } + [NoAccessorMethod] + public bool is_present { get; set; } + [NoAccessorMethod] + public bool is_rechargeable { get; set; } + [NoAccessorMethod] + public string model { owned get; set; } + [NoAccessorMethod] + public string native_path { owned get; set; } + [NoAccessorMethod] + public bool online { get; set; } + [NoAccessorMethod] + public double percentage { get; set; } + [NoAccessorMethod] + public bool power_supply { get; set; } + [NoAccessorMethod] + public bool recall_notice { get; set; } + [NoAccessorMethod] + public string recall_url { owned get; set; } + [NoAccessorMethod] + public string recall_vendor { owned get; set; } + [NoAccessorMethod] + public string serial { owned get; set; } + [NoAccessorMethod] + public uint state { get; set; } + [NoAccessorMethod] + public uint technology { get; set; } + [NoAccessorMethod] + public int64 time_to_empty { get; set; } + [NoAccessorMethod] + public int64 time_to_full { get; set; } + [NoAccessorMethod] + public uint type { get; set; } + [NoAccessorMethod] + public uint64 update_time { get; set; } + [NoAccessorMethod] + public string vendor { owned get; set; } + [NoAccessorMethod] + public double voltage { get; set; } + public virtual signal void changed (void* obj); + } + [Compact] + [CCode (copy_function = "dkp_history_obj_copy", cheader_filename = "devkit-power-gobject/devicekit-power.h")] + public class HistoryObj { + public Dkp.DeviceState state; + public uint time; + public double value; + [CCode (has_construct_function = false)] + public HistoryObj (); + public bool clear (); + public unowned Dkp.HistoryObj copy (); + public static unowned Dkp.HistoryObj create (double value, Dkp.DeviceState state); + public bool equal (Dkp.HistoryObj obj2); + public static unowned Dkp.HistoryObj from_string (string text); + public bool print (); + public unowned string to_string (); + } + [Compact] + [CCode (copy_function = "dkp_qos_obj_copy", cheader_filename = "devkit-power-gobject/devicekit-power.h")] + public class QosObj { + public weak string cmdline; + public uint cookie; + public bool persistent; + public uint pid; + public weak string sender; + public uint64 timespec; + public Dkp.QosType type; + public uint uid; + public int value; + [CCode (has_construct_function = false)] + public QosObj (); + public unowned Dkp.QosObj copy (); + public bool equal (Dkp.QosObj obj2); + public bool print (); + } + [Compact] + [CCode (copy_function = "dkp_stats_obj_copy", cheader_filename = "devkit-power-gobject/devicekit-power.h")] + public class StatsObj { + public double accuracy; + public double value; + [CCode (has_construct_function = false)] + public StatsObj (); + public unowned Dkp.StatsObj copy (); + public static unowned Dkp.StatsObj create (double value, double accuracy); + public static unowned Dkp.StatsObj from_string (string text); + public unowned string to_string (); + } + [CCode (cheader_filename = "devkit-power-gobject/devicekit-power.h")] + public class Wakeups : GLib.Object { + [CCode (has_construct_function = false)] + public Wakeups (); + public unowned GLib.PtrArray get_data () throws GLib.Error; + public uint get_total () throws GLib.Error; + public bool has_capability (); + public virtual signal void data_changed (); + public virtual signal void total_changed (uint value); + } + [Compact] + [CCode (copy_function = "dkp_wakeups_obj_copy", cheader_filename = "devkit-power-gobject/devicekit-power.h")] + public class WakeupsObj { + public weak string cmdline; + public weak string details; + public uint id; + public bool is_userspace; + public uint old; + public float value; + [CCode (has_construct_function = false)] + public WakeupsObj (); + public unowned Dkp.WakeupsObj copy (); + public bool equal (Dkp.WakeupsObj obj2); + public bool print (); + } + [CCode (cprefix = "DKP_DEVICE_STATE_", has_type_id = "0", cheader_filename = "devkit-power-gobject/devicekit-power.h")] + public enum DeviceState { + UNKNOWN, + CHARGING, + DISCHARGING, + EMPTY, + FULLY_CHARGED, + PENDING_CHARGE, + PENDING_DISCHARGE, + LAST + } + [CCode (cprefix = "DKP_DEVICE_TECHNOLOGY_", has_type_id = "0", cheader_filename = "devkit-power-gobject/devicekit-power.h")] + public enum DeviceTechnology { + UNKNOWN, + LITHIUM_ION, + LITHIUM_POLYMER, + LITHIUM_IRON_PHOSPHATE, + LEAD_ACID, + NICKEL_CADMIUM, + NICKEL_METAL_HYDRIDE, + LAST + } + [CCode (cprefix = "DKP_DEVICE_TYPE_", has_type_id = "0", cheader_filename = "devkit-power-gobject/devicekit-power.h")] + public enum DeviceType { + UNKNOWN, + LINE_POWER, + BATTERY, + UPS, + MONITOR, + MOUSE, + KEYBOARD, + PDA, + PHONE, + LAST + } + [CCode (cprefix = "DKP_QOS_TYPE_", has_type_id = "0", cheader_filename = "devkit-power-gobject/devicekit-power.h")] + public enum QosType { + UNKNOWN, + NETWORK, + CPU_DMA, + LAST + } + [CCode (cheader_filename = "devkit-power-gobject/devicekit-power.h")] + public const int COMPILE_VERSION; + [CCode (cheader_filename = "devkit-power-gobject/devicekit-power.h")] + public static Dkp.QosType qos_type_from_text (string type); + [CCode (cheader_filename = "devkit-power-gobject/devicekit-power.h")] + public static unowned string qos_type_to_text (Dkp.QosType type); +} diff --git a/zavai/gps.py b/zavai/gps.py deleted file mode 100755 index 2b73da7..0000000 --- a/zavai/gps.py +++ /dev/null @@ -1,345 +0,0 @@ -# gps - gps resource for zavai -# -# Copyright (C) 2009 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 - -#import sys -import os -import os.path -import time -import dbus -import zavai - -class GPSMonitor(zavai.Service): - def __init__(self, gps): - super(GPSMonitor, self).__init__(["satellites"]) - - self.gps = gps - self.gps_ubx = gps.gps_ubx - - # This piece of machinery is taken from Zhone - self.debug_busy = None - self.debug_want = set( ["NAV-STATUS", "NAV-SVINFO"] ) - self.debug_have = set() - self.debug_error = set() - - def debug_update(self): - if self.debug_busy is None: - pending = self.debug_want - self.debug_have - self.debug_error - if pending: - self.debug_busy = pending.pop() - self.gps_ubx.SetDebugFilter( - self.debug_busy, - True, - reply_handler=self.on_debug_reply, - error_handler=self.on_debug_error, - ) - - def debug_request(self): - self.debug_have = set() - self.debug_update() - - def on_debug_reply(self): - self.debug_have.add(self.debug_busy) - self.debug_busy = None - self.debug_update() - - def on_debug_error(self, e): - zavai.info(e, "error while requesting debug packet %s" % self.debug_busy) - self.debug_error.add(self.debug_busy) - self.debug_busy = None - self.debug_update() - - def on_satellites_changed(self, satellites): - zavai.info("gps monitor: satellites changed") - self.debug_request() - - def on_ubxdebug_packet(self, clid, length, data): - zavai.info("gps monitor: UBX debug packet") - self.notify("satellites", clid, length, data) - - def start(self): - self.gps.connect("gps", self) - # TODO: find out how come sometimes these events are not sent - self.gps.bus.add_signal_receiver( - self.on_satellites_changed, 'SatellitesChanged', 'org.freedesktop.Gypsy.Satellite', - 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') - self.gps.bus.add_signal_receiver( - self.on_ubxdebug_packet, 'DebugPacket', 'org.freesmartphone.GPS.UBX', - 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') - self.debug_request() - - def stop(self): - self.gps.bus.remove_signal_receiver( - self.on_satellites_changed, 'SatellitesChanged', 'org.freedesktop.Gypsy.Satellite', - 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') - self.gps.bus.remove_signal_receiver( - self.on_ubxdebug_packet, 'DebugPacket', 'org.freesmartphone.GPS.UBX', - 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') - self.gps.disconnect("gps", self) - - -class GPSPosition(zavai.Service): - def __init__(self, gps): - super(GPSPosition, self).__init__(["position"]) - self.gps = gps - - def on_position_changed(self, fields, tstamp, lat, lon, alt): - zavai.info("gps position: position changed") - self.notify("position", fields, tstamp, lat, lon, alt) - - def start(self): - self.gps.connect("gps", self) - self.gps.bus.add_signal_receiver( - self.on_position_changed, 'PositionChanged', 'org.freedesktop.Gypsy.Position', - 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') - - def stop(self): - self.gps.bus.remove_signal_receiver( - self.on_position_changed, 'PositionChanged', 'org.freedesktop.Gypsy.Position', - 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') - self.gps.disconnect("gps", self) - -# For a list of dbus services, look in /etc/dbus-1/system.d/ -class GPS(zavai.Service): - def __init__(self, registry, name): - super(GPS, self).__init__(["gps"]) - - self.bus = registry.resource("dbus.system_bus") - - # see mdbus -s org.freesmartphone.ousaged /org/freesmartphone/Usage - self.usage = self.bus.get_object('org.freesmartphone.ousaged', '/org/freesmartphone/Usage') - self.usage = dbus.Interface(self.usage, "org.freesmartphone.Usage") - - # see mdbus -s org.freesmartphone.ogpsd /org/freedesktop/Gypsy - gps = self.bus.get_object('org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') - self.gps = dbus.Interface(gps, "org.freedesktop.Gypsy.Device") - self.gps_time = dbus.Interface(gps, "org.freedesktop.Gypsy.Time") - self.gps_position = dbus.Interface(gps, 'org.freedesktop.Gypsy.Position') - self.gps_ubx = dbus.Interface(gps, 'org.freesmartphone.GPS.UBX') - - self.monitor = GPSMonitor(self) - self.position = GPSPosition(self) - - def start(self): - """Request GPS resource""" - self.usage.RequestResource('GPS') - zavai.info("Acquired GPS") - - def stop(self): - """Release usage of GPS""" - self.usage.ReleaseResource('GPS') - zavai.info("Released GPS") - -# def wait_for_fix(self, callback): -# status = self.gps.GetFixStatus() -# if status in [2, 3]: -# zavai.info("We already have a fix, good.") -# callback() -# return True -# else: -# zavai.info("Waiting for a fix...") -# self.waiting_for_fix = callback -# self.bus.add_signal_receiver( -# self.on_fix_status_changed, 'FixStatusChanged', 'org.freedesktop.Gypsy.Device', -# 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') -# return False -# -# def on_fix_status_changed(self, status): -# if status not in [2, 3]: return -# -# zavai.info("Got GPS fix") -# self.bus.remove_signal_receiver( -# self.on_fix_status_changed, 'FixStatusChanged', 'org.freedesktop.Gypsy.Device', -# 'org.freesmartphone.ogpsd', '/org/freedesktop/Gypsy') -# -# if self.waiting_for_fix: -# self.waiting_for_fix() -# self.waiting_for_fix = None -# - -# def start_recording(self): -# if self.gps_monitor: -# self.gps_monitor.stop() -# self.gps_monitor = None -# -# if not self.audio: -# return -# -# # Sync system time -# gpstime = self.gps.gps_time.GetTime() -# subprocess.call(["date", "-s", "@%d" % gpstime]) -# subprocess.call(["hwclock", "--systohc"]) -# -# # Compute basename for output files -# self.basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(gpstime)) -# self.basename = os.path.join(AUDIODIR, self.basename) -# -# # Start recording the GPX track -# self.gpx = GPX(self.basename) -# self.gps.track_position(self.on_position_changed) -# -# # Start recording in background forking arecord -# self.audio.set_basename(self.basename) -# self.audio.start_recording() -# - -class GPX(zavai.Service): - "Write GPX track and waypoint files" - def __init__(self, registry, name): - super(GPX, self).__init__(["gpx"]) - self.registry = registry - self.trk = None - self.wpt = None - self.last_pos = None - conf = registry.resource("conf") - self.trackdir = conf.homedir - self.activity_monitors = set() - - def add_activity_monitor(self, cb): - self.activity_monitors.add(cb) - cb(self, self.last_pos is not None) - - def del_activity_monitor(self, cb): - self.activity_monitors.discard(cb) - - def notify_activity_monitors(self): - for mon in self.activity_monitors: - mon(self, self.last_pos is not None) - - def start(self): - zavai.info("Starting GPX trace subsystem") - gps = self.registry.resource("gps") - gps.position.connect("position", self.on_position_changed) - - def stop(self): - zavai.info("Stopping GPX trace subsystem") - gps = self.registry.resource("gps") - gps.position.disconnect("position", self.on_position_changed) - self.stop_track() - - def on_position_changed(self, fields, tstamp, lat, lon, alt): - self.last_pos = (fields, tstamp, lat, lon, alt) - self.trackpoint() - - def start_track(self, tstamp = None, basename = None): - if basename is not None: - self.basename = basename - elif tstamp is not None: - # Compute basename for output files - self.basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(tstamp)) - self.basename = os.path.join(self.trackdir, self.basename) - - self.trk = open(self.basename + "-trk.gpx", "wt") - print >>self.trk, """ - - - """ % zavai.VERSION - - self.wpt = open(self.basename + "-wpt.gpx", "wt") - print >>self.wpt, """ -""" % zavai.VERSION - - self.wpt_seq = 1; - self.notify_activity_monitors() - - def stop_track(self): - if self.trk is not None: - print >>self.trk, "" - self.trk.close() - self.trk = None - if self.wpt is not None: - print >>self.wpt, "" - self.wpt.close() - self.wpt = None - self.last_pos = None - self.notify_activity_monitors() - - def trackpoint(self): - "Mark a track point" - if self.last_pos is None: - return - - fields, tstamp, lat, lon, ele = self.last_pos - - if not self.trk: - self.start_track(tstamp) - - print >>self.trk, """ - - %f""" % (lat, lon, time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(tstamp)), ele) - #if course is not None: print >>self.trk, " %f" % course - #if speed is not None: print >>self.trk, " %f" % speed - #if fix is not None: print >>self.trk, " %f" % fix - #if hdop is not None: print >>self.trk, " %f" % hdop - print >>self.trk, "" - - def waypoint(self, name = None): - "Mark a waypoint" - if self.last_pos is None: - return - - fields, tstamp, lat, lon, ele = self.last_pos - - if not self.wpt: - self.start_track(tstamp) - - if name is None: - name = "wpt_%d" % self.wpt_seq - self.wpt_seq += 1 - - print >>self.wpt, """ - %s - - %f -""" % ( - lat, lon, name, time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(tstamp)), ele) - - -# def record(self): -# self.audio = Audio(self.make_waypoint) -# self.gps = GPS() -# # Get a fix and start recording -# if not self.gps.wait_for_fix(self.start_recording): -# self.gps_monitor = GPSMonitor(self.gps) -# self.gps_monitor.start() -# -# def monitor(self): -# self.audio = None -# self.gps = GPS() -# self.gps_monitor = GPSMonitor(self.gps) -# self.gps_monitor.start() -# -# -# def make_waypoint(self): -# if self.gpx is None: -# return -# if self.last_pos is None: -# self.last_pos = self.gps.gps_position.GetPosition() -# (fields, tstamp, lat, lon, alt) = self.last_pos -# self.gpx.waypoint(tstamp, lat, lon, alt) -# zavai.info("Making waypoint at %s: %f, %f, %f" % ( -# time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(tstamp)), lat, lon, alt)) diff --git a/zavai/gps.vala b/zavai/gps.vala new file mode 100644 index 0000000..950d76b --- /dev/null +++ b/zavai/gps.vala @@ -0,0 +1,247 @@ +/* + * gps - gps 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 gps { + +// For a list of dbus services, look in /etc/dbus-1/system.d/ +public class GPS: zavai.ScriptService +{ + protected libgps.data_t data; + protected IOChannel gpsfd = null; + protected uint gpsfd_watch = 0; + + protected int old_fix_status = libgps.STATUS_NO_FIX; + protected uint old_time = 0; + protected double old_lat = 1000; + protected double old_lon = 1000; + + public signal void fix_status_changed(int status); + public signal void time_changed(uint time); + public signal void pos_changed(); + + public GPS() + { + Object(name: "gps"); + data = libgps.data_t(); + started = script_status(); + } + + public int fix_status() { return old_fix_status; } + public double time() { return old_time; } + public weak libgps.data_t info() { return data; } + + protected bool on_input_data(IOChannel source, IOCondition condition) + { + while (libgps.waiting(ref data)) + { + int res = libgps.poll(ref data); + if (res != 0) + zavai.log.error(libgps.errstr(res)); + + if (data.status != old_fix_status) + { + fix_status_changed(data.status); + old_fix_status = data.status; + } + + uint cur_time = (uint)data.fix.time; + if (data.status != libgps.STATUS_NO_FIX && old_time != cur_time) + { + time_changed(cur_time); + old_time = cur_time; + } + + double lat = (data.status == libgps.STATUS_NO_FIX ? 1000 : data.fix.latitude); + double lon = (data.status == libgps.STATUS_NO_FIX ? 1000 : data.fix.longitude); + if (lat != old_lat || lon != old_lon) + pos_changed(); + + /* + stderr.printf("GPSMSG %d %d\n", (int)data.set, data.status); + stderr.printf("SATUSED %d\n", data.satellites_used); + stderr.printf("SWT %f\n", data.skyview_time); + stderr.printf("SATVIS %d\n", data.satellites_visible); + for (int i = 0; i < data.satellites_visible; ++i) + { + stderr.printf("PRN %d ELE %d AZI %d SS %f\n", + data.PRN[i], data.elevation[i], data.azimuth[i], data.ss[i]); + } + */ + } + return true; + } + + /// Request GPS resource + public override void start() + { + if (started) return; + + if (!script_start()) return; + + zavai.log.info("Connecting to gpsd at " + config.gpsd_host + ":" + config.gpsd_port); + int res = libgps.open_r(config.gpsd_host, config.gpsd_port, ref data); + if (res != 0) + { + zavai.log.error(libgps.errstr(res)); + return; + } + + res = libgps.stream(ref data, libgps.WATCH_ENABLE, null); + if (res != 0) + { + zavai.log.error(libgps.errstr(res)); + return; + } + + //res = libgps.send(ref data, "?SKY;"); + //res = libgps.send(ref data, "?WATCH;"); + //if (res != 0) zavai.log.error(libgps.errstr(res)); + + gpsfd = new IOChannel.unix_new(data.gps_fd); + try { + gpsfd.set_encoding(null); + } catch (Error e) { + zavai.log.error("Setting encoding to null on gpsd io channel: " + e.message); + } + //gpsfd.set_buffered(false); + gpsfd_watch = gpsfd.add_watch(IOCondition.IN, on_input_data); + + zavai.log.info("GPS turned on"); + base.start(); + } + + // Release usage of GPS + public override void stop() + { + if (!started) return; + + Source.remove(gpsfd_watch); + + int res = libgps.close(ref data); + if (res != 0) + zavai.log.error(libgps.errstr(res)); + + script_stop(); + + if (old_fix_status != libgps.STATUS_NO_FIX) + { + old_fix_status = libgps.STATUS_NO_FIX; + fix_status_changed(old_fix_status); + } + + if (old_time != 0) + { + old_time = 0; + time_changed(old_time); + } + + base.stop(); + } +} + +// # def start_recording(self): +// # if self.gps_monitor: +// # self.gps_monitor.stop() +// # self.gps_monitor = None +// # +// # if not self.audio: +// # return +// # +// # # Sync system time +// # gpstime = self.gps.gps_time.GetTime() +// # subprocess.call(["date", "-s", "@%d" % gpstime]) +// # subprocess.call(["hwclock", "--systohc"]) +// # +// # # Compute basename for output files +// # self.basename = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(gpstime)) +// # self.basename = os.path.join(AUDIODIR, self.basename) +// # +// # # Start recording the GPX track +// # self.gpx = GPX(self.basename) +// # self.gps.track_position(self.on_position_changed) +// # +// # # Start recording in background forking arecord +// # self.audio.set_basename(self.basename) +// # self.audio.start_recording() +// # + +// Write GPX track and waypoint files +public class GPX : Service +{ + protected uint wpt_seq = 0; + protected uint log_id = 0; + + public GPX() + { + Object(name: "gps.gpx"); + } + + public override void start() + { + if (!started) + { + log_id = log.log.start("track", "GPS track"); + base.start(); + } + } + + public override void stop() + { + if (started) + { + log.log.end(log_id); + log_id = 0; + base.stop(); + } + } + + // Mark a waypoint + public void waypoint(string? name = null) + { + if (log_id == 0) return; + + string wptname; + if (name == null) + { + wptname = "wpt_%u".printf(wpt_seq); + wpt_seq += 1; + } else { + wptname = name; + } + + log.log.add(log_id, wptname); + } +} + +public zavai.gps.GPS gps = null; +public zavai.gps.GPX gpx = null; + +public void init() +{ + gps = new GPS(); + gpx = new GPX(); + +} + +} +} diff --git a/zavai/gsm.vala b/zavai/gsm.vala new file mode 100644 index 0000000..b11065d --- /dev/null +++ b/zavai/gsm.vala @@ -0,0 +1,256 @@ +/* + * gsm - gsm resource for zavai + * + * Copyright (C) 2009 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 gsm { + +// Isolate here the insane loops we need to go through to turn on the bloody +// gsm +protected class GSMActivator : Object +{ + public dynamic DBus.Object device; + public dynamic DBus.Object network; + public dynamic DBus.Object sim; + + public signal void status_changed(string message); + + public GSMActivator() + { + device = null; + network = null; + sim = null; + } + + public void begin() + { + if (device == null) + { + device = zavai.registry.sbus.get_object( + "org.freesmartphone.ogsmd", + "/org/freesmartphone/GSM/Device", + "org.freesmartphone.GSM.Device"); + network = zavai.registry.sbus.get_object( + "org.freesmartphone.ogsmd", + "/org/freesmartphone/GSM/Device", + "org.freesmartphone.GSM.Network"); + sim = zavai.registry.sbus.get_object( + "org.freesmartphone.ogsmd", + "/org/freesmartphone/GSM/Device", + "org.freesmartphone.GSM.SIM"); + } + + status_changed("Turning on antenna"); + device.SetAntennaPower(true, on_antenna_power); + } + + protected void on_antenna_power(Error e) + { + if (e != null) + { + zavai.log.warning("on_antenna_power: " + e.message); + if (e.message.str("current status is 'enabling'") != null + || e.message.str("current status is 'unknown'") != null) + { + status_changed("Waiting for ogsmd to settle"); + zavai.log.info("trying again after 2 seconds"); + Timeout.add(2 * 1000, () => { + device.SetAntennaPower(true, on_antenna_power); + return false; + }); + } else { + status_changed("Checking if PIN is required"); + sim.GetAuthStatus(on_auth_status); + } + return; + } + zavai.log.warning("on_antenna_power ok"); + status_changed("Registering with network"); + network.Register(on_network_register); + } + + protected void on_network_register(Error e) + { + if (e != null) + { + zavai.log.warning("on_network_register: " + e.message); + return; + } + status_changed("Registered with network"); + } + + protected void on_auth_status(string status, Error e) + { + if (e != null) + { + zavai.log.warning("on_auth_status: " + e.message); + return; + } + zavai.log.info("on_auth_status: " + status); + if (status == "READY") + { + status_changed("PIN ok"); + device.SetAntennaPower(true, on_antenna_power); + } + else if (status == "SIM PIN") + { + status_changed("Sending PIN"); + sim.SendAuthCode(zavai.config.sim_pin, on_auth_code); + } + else + zavai.log.debug("Unknown status: " + status); + } + + protected void on_auth_code(Error e) + { + if (e != null) + { + zavai.log.warning("on_auth_code: " + e.message); + return; + } + status_changed("PIN OK"); + } +} + +public class GSM: zavai.ScriptMonitorService +{ + protected dynamic DBus.Object dbus; + public dynamic DBus.Object call; + protected GSMActivator activator; + + public signal void status_changed(string message); + + public GSM() + { + Object(name: "gsm"); + + activator = new GSMActivator(); + activator.status_changed += (msg) => { status_changed(msg); }; + + call = null; + + dbus = zavai.registry.sbus.get_object( + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus"); + dbus.NameOwnerChanged += on_name_owner_changed; + } + + /// Request GPS resource + public override void start() + { + if (started) return; + + status_changed("Starting"); + + script_start(); + + call = zavai.registry.sbus.get_object( + "org.freesmartphone.ogsmd", + "/org/freesmartphone/GSM/Device", + "org.freesmartphone.GSM.Call"); + + base.start(); + } + + protected void on_name_owner_changed(DBus.Object sender, string name, string oldOwner, string newOwner) + { + zavai.log.debug("NOC " + name + " from " + oldOwner + " to " + newOwner); + if (name == "org.freesmartphone.ogsmd" && newOwner != "") + { + status_changed("ogpsd came online"); + activator.begin(); + } + } + + // Release usage of GPS + public override void stop() + { + if (!started) return; + + script_stop(); + } + + protected override void cleanup_after_script_stop() + { + call = null; + } +} + +public class GPRS: zavai.Service +{ + public dynamic DBus.Object device; + + public GPRS() + { + Object(name: "gsm.gprs"); + + device = zavai.registry.sbus.get_object( + "org.freesmartphone.ogsmd", + "/org/freesmartphone/GSM/Device", + "org.freesmartphone.GSM.PDP"); + } + + /// Request GPS resource + public override void start() + { + if (started) return; + try { + //gsm.request(name); + device.ActivateContext( + zavai.config.gprs_apn, + zavai.config.gprs_user, + zavai.config.gprs_pass); + zavai.log.info("Started GPRS"); + base.start(); + } catch (GLib.Error e) { + zavai.log.error(e.message); + } + base.start(); + } + + // Release usage of GPS + public override void stop() + { + if (!started) return; + try { + //gsm.release(name); + device.DeactivateContext(); + zavai.log.info("Stopped GPRS"); + base.stop(); + } catch (GLib.Error e) { + zavai.log.error(e.message); + } + base.stop(); + } +} + +public zavai.gsm.GSM gsm = null; +public zavai.gsm.GPRS gprs = null; + +public void init() +{ + gsm = new GSM(); + gprs = new GPRS(); +} + +} +} diff --git a/zavai/input.vala b/zavai/input.vala new file mode 100644 index 0000000..ffa0add --- /dev/null +++ b/zavai/input.vala @@ -0,0 +1,425 @@ +/* + * devinput - zavai /dev/input device handling + * + * Copyright (C) 2009 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 + */ + +namespace zavai { +namespace input { + +public class DevInput : zavai.Service +{ + public string device { get; construct; } + + public signal bool event(LinuxInput.Event* ev); + + protected IOChannel fd = null; + protected uint fd_watch = 0; + + public DevInput(string name, string device) + { + Object(name: "input.power_button", device: "/dev/input/event0"); + } + + protected void close_fd() + { + if (fd != null) + { + try { + fd.shutdown(false); + } catch (IOChannelError e) { + zavai.log.error("When closing " + device + ": " + e.message); + } + + fd = null; + } + } + + protected bool on_input_data(IOChannel source, IOCondition condition) + { + if (condition != IOCondition.IN) return true; + + //stderr.printf("GOT INPUT ON %s %d\n", device, source.unix_get_fd()); + char[] buf = new char[sizeof(LinuxInput.Event)]; + size_t count_read; + try { + source.read_chars(buf, out count_read); + } catch (Error e) { + zavai.log.error("Reading from " + device + ": " + e.message); + return true; + } + //stderr.printf("READ %zu chars\n", count_read); + + LinuxInput.Event* ie = (LinuxInput.Event*)buf; + //stderr.printf("INPUT EVENT time %lu.%lu type %hu code %hu val %d\n", (ulong)ie->time.tv_sec, ie->time.tv_usec, ie->type, ie->code, ie->val); + + /* + ts1, ts2, type, code, value = struct.unpack("LLHHI", buf) + #print ts1, ts2, type, code, value + if type == 1 and code == 119: + if value: + #print "BUTTON RELEASE" + pass + else: + if self.last_button_press + 1 < ts1: + self.last_button_press = ts1 + if self.button_press_handler is not None: + self.button_press_handler() + #print "BUTTON PRESS" + elif type == 5 and code == 2: + if value: + info("Headset plugged in") + self.mixer_for_headset(self) + else: + info("Headset plugged out") + self.mixer_for_handset(self) + */ + return event(ie); + } + + /// Start reading from the device + public override void start() + { + if (started) return; + + if (fd != null) + close_fd(); + + // Open the device and listed to it using the GObject main loop + zavai.log.info("Opening device " + device); + fd = new IOChannel.file(device, "r"); + try { + fd.set_encoding(null); + } catch (Error e) { + zavai.log.error("Setting encoding to null on " + device + ": " + e.message); + } + fd.set_buffered(false); + fd_watch = fd.add_watch(IOCondition.IN, on_input_data); + + base.start(); + } + + // Stop reading from the device + public override void stop() + { + if (!started) return; + + if (fd != null) + { + Source.remove(fd_watch); + close_fd(); + } + + base.stop(); + } +} + +public class HotKeys : zavai.Service +{ + protected List grabbed; + public signal bool hotkey(uint keycode, ulong time, bool pressed); + + public HotKeys() + { + Object(name: "input.hotkeys"); + + grabbed = new List(); + } + + // Hotkey handlink takes inspiration from + // http://old.nabble.com/-PATCH--Initial-non-working-implementation-of-wxWindow::%28Un%29RegisterHotKey-on-wxGTK-td14557263.html + private static Gdk.FilterReturn on_hotkey(Gdk.XEvent* xevent, Gdk.Event? event, void* data) + { + // Global events don't get their data translated to gdk, as there is no + // GdkWindow to work with, therefore we need to use the xevent, because + // GdkEvent* is always GDK_NOTHING + X.Event* xev = (X.Event*)xevent; + + switch (xev->type) + { + case X.EventType.KeyPress: + return zavai.input.hotkeys.my_on_hotkey(xev, true); + case X.EventType.KeyRelease: + return zavai.input.hotkeys.my_on_hotkey(xev, false); + default: + return Gdk.FilterReturn.CONTINUE; + } + } + + //public Gdk.FilterReturn on_hotkey(Gdk.XEvent xevent, Gdk.Event? event) + private Gdk.FilterReturn my_on_hotkey(X.Event* xev, bool pressed) + { + // From http://tronche.com/gui/x/xlib/input/pointer-grabbing.html: + // + // A timestamp is a time value, expressed in milliseconds. It typically is the + // time since the last server reset. Timestamp values wrap around (after about + // 49.7 days). The server, given its current time is represented by timestamp + // T, always interprets timestamps from clients by treating half of the + // timestamp space as being later in time than T. One timestamp value, named + // CurrentTime, is never generated by the server. This value is reserved for + // use in requests to represent the current server time. + + if (grabbed.index((int)xev->xkey.keycode) == -1) + return Gdk.FilterReturn.CONTINUE; + + if (hotkey(xev->xkey.keycode, xev->xkey.time, pressed)) + return Gdk.FilterReturn.REMOVE; + return Gdk.FilterReturn.CONTINUE; + } + + public void grab(int keycode, int modifiers, bool owner_events) + { + // We need to grab the keys we want to listen to + int res = Gdk.x11_get_default_xdisplay().grab_key(keycode, modifiers, Gdk.x11_get_default_root_xwindow(), owner_events, X.GrabMode.Async, X.GrabMode.Async); + if (res != 0) + stderr.printf("Grab result: %d\n", res); // We get BadRequest and don't know why + grabbed.append(keycode); + } + + /// Start reading from the device + public override void start() + { + if (started) return; + + //gdk_window_add_filter (NULL, _wxgtk_global_hotkey_callback, this); + ((Gdk.Window*)null)->add_filter((Gdk.FilterFunc)on_hotkey); + + grab(160, 0, false); + + base.start(); + } + + // Stop reading from the device + public override void stop() + { + if (!started) return; + + //gdk_window_remove_filter(NULL, _wxgtk_global_hotkey_callback, this); + ((Gdk.Window*)null)->remove_filter((Gdk.FilterFunc)on_hotkey); + + base.stop(); + } +} + +public class PowerButton : zavai.Service +{ + protected DevInput devinput; + + public signal void power_button(Posix.timeval* time, bool pressed); + + public PowerButton() + { + // FIXME: change to event0 for the power button + // FIXME: change to event4 for the aux button and headset button + string inputdev = "/dev/input/event0"; + if (Posix.access(inputdev, Posix.R_OK) == 0) + { + zavai.log.info("Handle power button via " + inputdev); + // Listen via input device + devinput = new DevInput("input.power_button", "/dev/input/event0"); + devinput.event += on_event; + devinput.request("powerbutton"); + } else { + zavai.log.info("Handle power button via XGrabKey on keycode " + zavai.config.power_button_keycode.to_string()); + // Listen via X + hotkeys.hotkey += on_hotkey; + hotkeys.grab(zavai.config.power_button_keycode, 0, false); + hotkeys.request("powerbutton"); + } + } + + protected bool on_event(LinuxInput.Event* ev) + { + if (ev->type == LinuxInput.Type.KEY && + ev->code == LinuxInput.Key.POWER) + { + power_button(&(ev->time), ev->val == 0 ? false : true); + } + return true; + } + + protected bool on_hotkey(uint keycode, ulong time, bool pressed) + { + if (keycode == zavai.config.power_button_keycode) + { + // Convert X time to a fake timeval + // TODO: handle wraparound + Posix.timeval tv = { + (time_t)(time / 1000), + (long)((time % 1000) * 1000) + }; + power_button(&tv, pressed); + return true; + } + return false; + } +} + + +/* +# TODO: +# - hook into the headset plugged/unplugged event +# - if unplugged, turn on handset microphone +# - if plugged, redo headest mixer settings +class Audio: + "Handle mixer settings, audio recording and headset button presses" + def __init__(self, button_press_handler = None): + self.saved_scenario = os.path.expanduser("~/.audiomap.state") + + # Setup the mixer + # Set mixer to record from headset and handle headset button + self.save_scenario(self.saved_scenario) + self.load_scenario("/usr/share/openmoko/scenarios/voip-handset.state") + + # This is a work-around because I have not found a way to query for the + # current headset state, I can only know when it changes. So in my + # system I configured oeventsd with a rule to touch this file when the + # headset is plugged in, and remove the file when it's plugged out. + if os.path.exists("/tmp/has_headset"): + self.mixer_for_headset(True) + else: + self.mixer_for_handset(True) + + #self.mixer_set("DAPM Handset Mic", "mute") + #self.mixer_set("DAPM Headset Mic", "unmute") + #self.mixer_set("Left Mixer Sidetone Playback Sw", "unmute") + #self.mixer_set("ALC Mixer Mic1", "cap") + #self.mixer_set("Amp Spk", "mute") # We don't need the phone playing what we say + + # Watch the headset button + self.button_press_handler = button_press_handler + self.input_fd = open("/dev/input/event4", "rb") + self.input_watch = gobject.io_add_watch(self.input_fd.fileno(), gobject.IO_IN, self.on_input_data) + + self.last_button_press = 0 + self.recorder = None + self.basename = None + + def mixer_for_headset(self, force=False): + if not force and self.has_headset: return + info("Setting mixer for headset") + # TODO: find out how to disable the handset microphone: this does not + # seem to be sufficient + self.mixer_set_many( + ("DAPM Handset Mic", "mute"), + ("DAPM Headset Mic", "unmute"), + ("Left Mixer Sidetone Playback Sw", "unmute"), + ("ALC Mixer Mic1", "cap"), + ("Amp Spk", "mute") # We don't need the phone playing what we say + ) + self.has_headset = True + + def mixer_for_handset(self, force=False): + if not force and not self.has_headset: return + info("Setting mixer for handset") + self.mixer_set_many( + ("DAPM Handset Mic", "unmute"), + ("DAPM Headset Mic", "mute"), + ("Left Mixer Sidetone Playback Sw", "mute"), + ("ALC Mixer Mic1", "cap"), + ("Amp Spk", "mute") # We don't need the phone playing what we say + ) + self.has_headset = False + + def set_basename(self, basename): + self.basename = basename + + def start_recording(self): + if self.basename is None: + raise RuntimeError("Recording requested but basename not set") + self.recorder = subprocess.Popen( + ["arecord", "-D", "hw", "-f", "cd", "-r", "8000", "-t", "wav", self.basename + ".wav"]) + + def start_levels(self): + self.recorder = subprocess.Popen( + ["arecord", "-D", "hw", "-f", "cd", "-r", "8000", "-t", "wav", "-V", "stereo", "/dev/null"]) + + def close(self): + if self.recorder is not None: + os.kill(self.recorder.pid, signal.SIGINT) + self.recorder.wait() + + # Restore mixer settings + self.load_scenario(self.saved_scenario) + + gobject.source_remove(self.input_watch) + self.input_fd.close() + + def on_input_data(self, source, condition): + buf = self.input_fd.read(16) + ts1, ts2, type, code, value = struct.unpack("LLHHI", buf) + #print ts1, ts2, type, code, value + if type == 1 and code == 119: + if value: + #print "BUTTON RELEASE" + pass + else: + if self.last_button_press + 1 < ts1: + self.last_button_press = ts1 + if self.button_press_handler is not None: + self.button_press_handler() + #print "BUTTON PRESS" + elif type == 5 and code == 2: + if value: + info("Headset plugged in") + self.mixer_for_headset(self) + else: + info("Headset plugged out") + self.mixer_for_handset(self) + return True + + def save_scenario(self, name): + res = subprocess.call(["alsactl", "store", "-f", name]) + if res != 0: + raise RuntimeError("Saving audio scenario to '%s' failed" % name) + + def load_scenario(self, name): + res = subprocess.call(["alsactl", "restore", "-f", name]) + if res != 0: + raise RuntimeError("Loading audio scenario '%s' failed" % name) + + def mixer_set(self, name, *args): + args = map(str, args) + res = subprocess.call(["amixer", "-q", "set", name] + args) + if res != 0: + raise RuntimeError("Setting mixer '%s' to %s failed" % (name, " ".join(args))) + + # Will do this when we find out the syntax for giving amixer commands on stdin + def mixer_set_many(self, *args): + """Perform many mixer set operations via amixer --stdin""" + proc = subprocess.Popen(["amixer", "-q", "--stdin"], stdin=subprocess.PIPE) + cmd_input = [] + for k, v in args: + cmd_input.append("sset " + repr(k) + " " + repr(v)) + (out, err) = proc.communicate(input="\n".join(cmd_input)) + res = proc.wait() + if res != 0: + raise RuntimeError("Setting mixer failed") +*/ + + +public HotKeys hotkeys = null; +public PowerButton power_button = null; + +public void init() +{ + hotkeys = new HotKeys(); + power_button = new PowerButton(); +} + +} +} diff --git a/zavai/libgps.vapi b/zavai/libgps.vapi new file mode 100644 index 0000000..da29fcd --- /dev/null +++ b/zavai/libgps.vapi @@ -0,0 +1,238 @@ +[CCode (lower_case_cprefix="", cprefix="", cheader_filename="gps.h")] +namespace libgps +{ + public const int MAXCHANNELS; + + [SimpleType] + [IntegerType (rank = 9)] + public struct mask_t {} + + [CCode (cname = "struct gps_fix_t")] + public struct fix_t + { + double time; /* Time of update, seconds since Unix epoch */ + int mode; /* Mode of fix */ + double ept; /* Expected time uncertainty */ + double latitude; /* Latitude in degrees (valid if mode >= 2) */ + double epy; /* Latitude position uncertainty, meters */ + double longitude; /* Longitude in degrees (valid if mode >= 2) */ + double epx; /* Longitude position uncertainty, meters */ + double altitude; /* Altitude in meters (valid if mode == 3) */ + double epv; /* Vertical position uncertainty, meters */ + double track; /* Course made good (relative to true north) */ + double epd; /* Track uncertainty, degrees */ + double speed; /* Speed over ground, meters/sec */ + double eps; /* Speed uncertainty, meters/sec */ + double climb; /* Vertical speed, meters/sec */ + double epc; /* Vertical speed uncertainty */ + } + public const int MODE_NOT_SEEN; /* mode update not seen yet */ + public const int MODE_NO_FIX; /* none */ + public const int MODE_2D; /* good for latitude/longitude */ + public const int MODE_3D; /* good for altitude/climb too */ + + [CCode (cname = "struct dop_t")] + public struct dop_t + { + /* Dilution of precision factors */ + double xdop; + double ydop; + double pdop; + double hdop; + double vdop; + double tdop; + double gdop; + } + + [CCode (cname = "struct gps_data_t", destroy_function = "")] + public struct data_t + { + mask_t set; + double online; + int gps_fd; + fix_t fix; + double separation; + int status; + int satellites_used; /* Number of satellites used in solution */ + int[] used; /* PRNs of satellites used in solution */ + dop_t dop; + /* redundant with the estimate elements in the fix structure */ + double epe; /* spherical position error, 95% confidence (meters) */ + + /* satellite status -- valid when satellites_visible > 0 */ + double skyview_time; /* skyview timestamp */ + int satellites_visible; /* # of satellites in view */ + int[] PRN; /* PRNs of satellite */ + int[] elevation; /* elevation of satellite */ + int[] azimuth; /* azimuth */ + double[] ss; /* signal-to-noise ratio (dB) */ + + //struct devconfig_t dev; /* device that shipped last update */ + + //struct policy_t policy; /* our listening policy */ + + //char tag[MAXTAGLEN+1]; /* tag of last sentence processed */ + } + public const int ONLINE_SET; + public const int TIME_SET; + public const int TIMERR_SET; + public const int LATLON_SET; + public const int ALTITUDE_SET; + public const int SPEED_SET; + public const int TRACK_SET; + public const int CLIMB_SET; + public const int STATUS_SET; + public const int MODE_SET; + public const int DOP_SET; + public const int VERSION_SET; /* only used in client library */ + public const int HERR_SET; + public const int VERR_SET; + public const int PERR_SET; + public const int POLICY_SET; /* only used in client library */ + public const int ERR_SET; + public const int SATELLITE_SET; + public const int RAW_SET; + public const int USED_SET; + public const int SPEEDERR_SET; + public const int TRACKERR_SET; + public const int CLIMBERR_SET; + public const int DEVICE_SET; + public const int DEVICELIST_SET; + public const int DEVICEID_SET; + public const int ERROR_SET; + public const int RTCM2_SET; + public const int RTCM3_SET; + public const int AIS_SET; + public const int PACKET_SET; + public const int CLEAR_SET; /* sentence starts a reporting cycle */ + public const int REPORT_SET; /* sentence ends a reporting cycle */ + public const int DATA_SET; + + public const int STATUS_NO_FIX; /* no */ + public const int STATUS_FIX; /* yes, without DGPS */ + public const int STATUS_DGPS_FIX; /* yes, with DGPS */ + + [CCode (cname = "gps_open_r")] + public int open_r(string server, string port, ref data_t gpsdata); + + [CCode (cname = "gps_close")] + public int close(ref data_t gpsdata); + + [CCode (cname = "gps_errstr")] + public weak string errstr(int err); + + [CCode (cname = "gps_poll")] + public int poll(ref data_t gpsdata); + + [CCode (cname = "gps_waiting")] + public bool waiting(ref data_t gpsdata); + + [CCode (cname = "gps_send")] + public int send(ref data_t gpsdata, string fmt, ...); + + [CCode (cname = "gps_stream")] + public int stream(ref data_t gpsdata, uint flags, void* data); + + /* mode flags for gps_stream() */ + public int WATCH_DISABLE; /* disable watching */ + public int WATCH_ENABLE; /* enable streaming */ + public int WATCH_JSON; /* enable JSON output */ + public int WATCH_NMEA; /* enable output in NMEA */ + public int WATCH_RARE; /* enable output of packets in hex */ + public int WATCH_RAW; /* enable output of raw packets */ + public int WATCH_SCALED; /* scale output to floats, when applicable */ + public int WATCH_NEWSTYLE; /* force JSON streaming */ + public int WATCH_OLDSTYLE; /* force old-style streaming */ + public int WATCH_DEVICE; /* watch specific device */ + public int POLL_NONBLOCK; /* set non-blocking poll */ + + /* + [CCode (cname = "struct input_event")] + public struct Event + { + public Posix.timeval time; + public uint16 type; + public uint16 code; + [CCode (cname="value")] + public int32 val; + } + + [CCode (cprefix="KEY_")] + public enum Key + { + POWER + } + + [CCode (cprefix="EV_")] + public enum Type + { + SYN, + KEY, + REL, + ABS, + MSC, + SW, + LED, + SND, + REP, + FF, + PWR, + FF_STATUS + } +} +[CCode (cprefix="", cheader_filename="omhacks/all.h")] +namespace Omhacks +{ + [CCode (cname = "struct om_led", cheader_filename = "omhacks/led.h", destroy_function = "")] + public struct Led + { + public char name[255]; + public string dir; + public int dir_len; + public int brightness; + public char trigger[255]; + public int delay_on; + public int delay_off; + + [CCode (cname = "om_led_init")] + public int init(string name); + [CCode (cname = "om_led_get")] + public int get(); + [CCode (cname = "om_led_set")] + public int set(); + } + + namespace Screen + { + namespace Brightness + { + [CCode (cname = "om_screen_brightness_get")] + public int get(); + [CCode (cname = "om_screen_brightness_get_max")] + public int get_max(); + [CCode (cname = "om_screen_brightness_set")] + public int set(int val); + } + } + + namespace UEvent + { + [CCode (cname = "struct om_uevent", cheader_filename = "omhacks/uevent.h", destroy_function = "")] + public struct Event + { + public string buffer; + size_t buflen; + weak string action; + weak string devpath; + weak string[] envp; + } + + [CCode (cname = "om_uevent_open")] + public int open(); + [CCode (cname = "om_uevent_read")] + public int read(int sock, ref Event ou); + [CCode (cname = "om_uevent_parse")] + public int parse(ref Event ou); + } + */ +} diff --git a/zavai/libomhacks.vapi b/zavai/libomhacks.vapi new file mode 100644 index 0000000..83434f3 --- /dev/null +++ b/zavai/libomhacks.vapi @@ -0,0 +1,55 @@ +[CCode (cprefix="", cheader_filename="omhacks/all.h")] +namespace Omhacks +{ + [CCode (cname = "struct om_led", cheader_filename = "omhacks/led.h", destroy_function = "")] + public struct Led + { + public char name[255]; + public string dir; + public int dir_len; + public int brightness; + public char trigger[255]; + public int delay_on; + public int delay_off; + + [CCode (cname = "om_led_init")] + public int init(string name); + [CCode (cname = "om_led_get")] + public int get(); + [CCode (cname = "om_led_set")] + public int set(); + } + + namespace Screen + { + namespace Brightness + { + [CCode (cname = "om_screen_brightness_get")] + public int get(); + [CCode (cname = "om_screen_brightness_get_max")] + public int get_max(); + [CCode (cname = "om_screen_brightness_set")] + public int set(int val); + } + } + + namespace UEvent + { + [CCode (cname = "struct om_uevent", cheader_filename = "omhacks/uevent.h", destroy_function = "")] + public struct Event + { + public string buffer; + size_t buflen; + weak string action; + weak string devpath; + weak string[] envp; + } + + [CCode (cname = "om_uevent_open")] + public int open(); + [CCode (cname = "om_uevent_read")] + public int read(int sock, ref Event ou); + [CCode (cname = "om_uevent_parse")] + public int parse(ref Event ou); + } +} diff --git a/zavai/linux-input.vapi b/zavai/linux-input.vapi new file mode 100644 index 0000000..211eab5 --- /dev/null +++ b/zavai/linux-input.vapi @@ -0,0 +1,42 @@ +[CCode (lower_case_cprefix="", cprefix="", cheader_filename="linux/input.h")] +namespace LinuxInput +{ + [CCode (cname = "struct input_event")] + public struct Event + { + public Posix.timeval time; + public uint16 type; + public uint16 code; + [CCode (cname="value")] + public int32 val; + } + + [CCode (cprefix="KEY_")] + public enum Key + { + POWER + } + + [CCode (cprefix="EV_")] + public enum Type + { + SYN, + KEY, + REL, + ABS, + MSC, + SW, + LED, + SND, + REP, + FF, + PWR, + FF_STATUS + } + + [CCode (cprefix="EVIO")] + public enum Evio + { + CGRAB + } +} diff --git a/zavai/log.vala b/zavai/log.vala new file mode 100644 index 0000000..eb78363 --- /dev/null +++ b/zavai/log.vala @@ -0,0 +1,317 @@ +/* + * log - logging functions + * + * 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 log { + +public class Waypoint : Object +{ + public time_t ts; + public double lat; + public double lon; + + public Waypoint() + { + if (gps.gps.fix_status() != libgps.STATUS_NO_FIX) + { + lat = gps.gps.info().fix.latitude; + lon = gps.gps.info().fix.longitude; + ts = (time_t)gps.gps.info().fix.time; + } else { + // Use 1000 as missing values + lat = 1000; + lon = 1000; + ts = time_t(); + } + } + + public void writeInside(FileStream outfd) + { + var t = Time.gm(ts); + outfd.printf(" \n", t.format("%Y-%m-%dT%H:%M:%SZ")); + } +} + + +public class LogEntry : Waypoint +{ + public string msg; + + public LogEntry() + { + base(); + } + + public void write(FileStream outfd) + { + outfd.printf(" \n", lat, lon); + writeInside(outfd); + outfd.printf(" %s\n", Markup.escape_text(msg)); + outfd.puts(" \n"); + } +} + +public class TrackEntry : Waypoint +{ + public TrackEntry() + { + base(); + } + + public void write(FileStream outfd) + { + outfd.printf(" \n", lat, lon); + writeInside(outfd); + outfd.puts(" \n"); + } +} + + +public class Log : Object +{ + public uint id; + public string tag; + public string title; + public List entries; + public List track; + + public Log(uint id, string tag, string title) + { + this.id = id; + this.tag = tag; + this.title = title; + entries = null; + track = null; + } + + public void add(string msg) + { + var entry = new LogEntry(); + entry.msg = msg; + entries.append(entry); + } + + public void add_trackpoint() + { + track.append(new TrackEntry()); + } + + public void save() + { + if (entries == null) return; + + // Directory where we save the log + string dir = config.homedir + "/log-" + tag; + DirUtils.create(dir, 0777); + + // First try with a plain name + var t = Time.local(entries.data.ts); + string basename = dir + "/" + t.format("%Y%m%d-%H%M%S"); + + string pathname = basename + ".gpx"; + + // Find a pathname that does not exist already + for (int i = 1; FileUtils.test(pathname, FileTest.EXISTS); ++i) + pathname = "%s-%d.gpx".printf(basename, i); + + // Write out + var outfd = FileStream.open(pathname, "w"); + if (outfd == null) + { + zavai.log.error("opening " + pathname + ": " + strerror(errno)); + return; + } + + write(outfd); + outfd.flush(); + } + + protected void writeTrack(FileStream outfd) + { + outfd.puts(" \n"); + outfd.puts(" \n"); + for (weak List i = track; i != null; i = i.next) + i.data.write(outfd); + outfd.puts(" \n"); + outfd.puts(" \n"); + } + + protected void writeEntries(FileStream outfd) + { + outfd.puts(" \n"); + for (weak List i = entries; i != null; i = i.next) + i.data.write(outfd); + outfd.puts(" \n"); + } + + protected void write(FileStream outfd) + { + outfd.puts("\n"); + outfd.puts("\n"); + outfd.puts(" \n"); + outfd.printf(" %s\n", Markup.escape_text(title)); + outfd.puts(" \n"); + if (track != null) writeTrack(outfd); + if (entries != null) writeEntries(outfd); + outfd.puts(" \n"); + } +} + +public class Logger : Resource, Object +{ + protected List logs; + protected uint seq; + + public Logger() + { + logs = null; + seq = 0; + + zavai.registry.register(this); + } + + protected void start_trace() + { + gps.gps.pos_changed += on_pos_changed; + } + + protected void end_trace() + { + gps.gps.pos_changed -= on_pos_changed; + } + + protected void on_pos_changed() + { + for (weak List i = logs; i != null; i = i.next) + i.data.add_trackpoint(); + } + + protected uint gen_seq() + { + // Increase avoiding 0 on rollover + while (true) + { + if (++seq == 0) ++seq; + bool found = false; + for (weak List i = logs; i != null; i = i.next) + { + if (i.data.id == seq) + { + found = true; + break; + } + } + if (!found) break; + } + return seq; + } + + protected weak Log? find(uint id) + { + for (weak List i = logs; i != null; i = i.next) + if (i.data.id == id) + return i.data; + return null; + } + + protected Log? pop(uint id) + { + for (weak List i = logs; i != null; i = i.next) + if (i.data.id == id) + { + Log res = i.data; + logs.delete_link(i); + return res; + } + return null; + } + + public uint start(string tag, string title) + { + bool was_empty = (logs == null); + uint id = gen_seq(); + logs.append(new Log(id, tag, title)); + if (was_empty) start_trace(); + return id; + } + + public void add(uint id, string msg) + { + Log log = find(id); + if (log == null) return; + log.add(msg); + } + + public void end(uint id) + { + Log log = pop(id); + log.save(); + if (log == null) end_trace(); + } + + public void instant(string tag, string msg) + { + var log = new Log(0, tag, msg); + log.add(msg); + log.save(); + } + + public void shutdown() + { + while (logs != null) + { + var log = pop(logs.data.id); + log.save(); + } + } +} + +public void error(string s) +{ + stderr.printf("%s\n", s); +} +public void warning(string s) +{ + stderr.printf("%s\n", s); +} +public void info(string s) +{ + stderr.printf("%s\n", s); +} +public void debug(string s) +{ + stderr.printf("%s\n", s); +} + +Logger log = null; + +public void init() +{ + log = new Logger(); +} + +} +} diff --git a/zavai/lua5.1.vapi b/zavai/lua5.1.vapi new file mode 120000 index 0000000..e730dfc --- /dev/null +++ b/zavai/lua5.1.vapi @@ -0,0 +1 @@ +/usr/share/vala/vapi/lua.vapi \ No newline at end of file diff --git a/zavai/menu.py b/zavai/menu.py deleted file mode 100644 index 629495a..0000000 --- a/zavai/menu.py +++ /dev/null @@ -1,68 +0,0 @@ -# menu - zavai menus -# -# Copyright (C) 2009 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 - -import sys -from gettext import gettext as _ -import zavai -import gtk - -class MenuButton(gtk.Button): - def __init__(self, *args, **kw): - super(MenuButton, self).__init__(*args, **kw) - # TODO: take this from the configuration - self.set_size_request(0, 80) - -class Menu(gtk.VBox, zavai.Resource): - def __init__(self, registry, name, parent = None, *args, **kw): - super(Menu, self).__init__() - self.vbox = self - - if parent is not None: - self.vbox = gtk.VBox() - self.pack_start(self.vbox, False, False) - self.pack_start(gtk.Label(""), True, True) - self.pack_start(LinkButton(registry, parent, _("Back")), False, False) - - def add_child(self, widget): - self.vbox.pack_start(widget, False, False) - -class LinkButton(MenuButton, zavai.Resource): - def __init__(self, registry, targetName, label=None, action=None): - if action is not None: - super(LinkButton, self).__init__() - self.target = targetName - self.registry = registry - self.action = action - action.connect_proxy(self) - self.connect("clicked", self.on_click) - else: - super(LinkButton, self).__init__(label) - self.target = targetName - self.registry = registry - self.action = None - self.connect("clicked", self.on_click) - - def on_click(self, *args): - self.registry.resource("app").activate_resource(self.target) - -class ToggleButton(gtk.ToggleButton): - def __init__(self, registry, targetName, action, *args, **kw): - super(ToggleButton, self).__init__() - # TODO: take this from the configuration - self.set_size_request(0, 80) - action.connect_proxy(self) diff --git a/zavai/plugins.py b/zavai/plugins.py deleted file mode 100644 index d736610..0000000 --- a/zavai/plugins.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python -# -# File: plugins.py -# -# Copyright (C) 2008 Christopher R. Gabriel -# -# 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. -# - -import os -import os.path -import imp -import sys - -def load_plugins(pluginpath=None, nick="octofuss"): - """return a list of all available plugins - in the given directory""" - - if not pluginpath: - pluginpath = os.environ.get(nick.upper() + "_PLUGINS", "plugins") - - # if the plugin path need to be auto-discovered - # starting from a specified module - #pluginpath = os.path.join(os.path.dirname(imp.find_module("octofussd")[1]), "extensions/") - #pluginpath = "." - pluginfiles = [fname[:-3] for fname in os.listdir(pluginpath) if fname.endswith(".py") and not fname.startswith(".") and not fname.endswith("~")] - - for fname in sorted(pluginfiles): - oldpath = sys.path - try: - sys.path.append(os.path.abspath(pluginpath)) - res = imp.load_source(fname, os.path.join(pluginpath, fname) + ".py") - finally: - sys.path = oldpath - yield res - diff --git a/zavai/power.vala b/zavai/power.vala new file mode 100644 index 0000000..5583708 --- /dev/null +++ b/zavai/power.vala @@ -0,0 +1,192 @@ +/* + * power - zavai power event handling + * + * Copyright (C) 2009 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 power { + +class Power : Service +{ + public enum State + { + UNKNOWN, + CHARGING, + DISCHARGING, + FULLY_CHARGED, + } + + protected string battery_device; + protected uint timeout; + public signal void changed(); + public State state; + public int percentage; + + public Power() + { + battery_device = "/sys/class/power_supply/battery/"; + if (Posix.access(battery_device, Posix.R_OK) != 0) + battery_device = null; + timeout = 0; + state = State.UNKNOWN; + percentage = 0; + } + + /// Activate the service + protected override void start() + { + if (started) return; + + uint poll_time; + if (uevent.uevent != null) + { + zavai.log.info("We have uevent: poll rarely"); + uevent.uevent.event += on_uevent; + uevent.uevent.request("zavai.power"); + // If we can get plug/unplug notifications, it's ok to just poll + // every 5 minutes + poll_time = 300 * 1000; + } else { + if (battery_device == null) + { + zavai.log.warning("No battery device found that I know how to read: try building with devkit-power"); + poll_time = 0; + } else { + zavai.log.info("Polling battery device only"); + // Else poll every 30 seconds to be somehow reactive to plug/unplug + // events + poll_time = 30 * 1000; + } + } + + poll(); + + // Poll battery every minute + if (poll_time != 0) + timeout = Timeout.add(poll_time, on_timeout); + + base.start(); + } + + /// Deactivate the service + protected override void stop() + { + if (!started) return; + + // Stop polling + if (timeout != 0) + Source.remove(timeout); + + if (uevent.uevent != null) + { + uevent.uevent.release("zavai.power"); + uevent.uevent.event -= on_uevent; + } + + base.stop(); + } + + protected void poll() + { + if (battery_device == null) + return; + + char buf[200]; + State new_state = State.UNKNOWN; + int new_percentage = 0; + + FileStream state_fd = FileStream.open(battery_device + "/status", "r"); + string val = state_fd.gets(buf); + if (val == "Charging") + new_state = State.CHARGING; + else if (val == "Discharging") + new_state = State.DISCHARGING; + else if (val == "Not charging") + new_state = State.FULLY_CHARGED; + + FileStream cap_fd = FileStream.open(battery_device + "/capacity", "r"); + val = cap_fd.gets(buf); + new_percentage = val.to_int(); + + if (new_state != state || new_percentage != percentage) + { + state = new_state; + percentage = new_percentage; + changed(); + } + } + + protected bool on_timeout() + { + poll(); + return true; + } + + protected void on_uevent() + { + /* if (uevent.uevent.event_data.buffer.has_prefix("change@/class/power_supply/ac")) + { + changed(); + } + else */ + if (uevent.uevent.event_data.buffer.has_prefix("change@/class/power_supply/battery")) + { + State new_state = State.UNKNOWN; + int new_percentage = 0; + + Omhacks.UEvent.parse(ref uevent.uevent.event_data); + for (int i = 0; uevent.uevent.event_data.envp[i] != null; ++i) + { + if (uevent.uevent.event_data.envp[i].has_prefix("POWER_SUPPLY_STATUS=")) + { + var val = uevent.uevent.event_data.envp[i].offset(20); + if (val == "Charging") + new_state = State.CHARGING; + else if (val == "Discharging") + new_state = State.DISCHARGING; + else if (val == "Not charging") + new_state = State.FULLY_CHARGED; + else + zavai.log.warning("Unknown state: " + uevent.uevent.event_data.envp[i]); + } + else if (uevent.uevent.event_data.envp[i].has_prefix("POWER_SUPPLY_CAPACITY=")) + { + new_percentage = uevent.uevent.event_data.envp[i].offset(22).to_int(); + } + } + if (new_state != state || new_percentage != percentage) + { + state = new_state; + percentage = new_percentage; + changed(); + } + } + } +} + +Power power; + +public void init() +{ + power = new Power(); +} + +} +} diff --git a/zavai/registry.py b/zavai/registry.py deleted file mode 100644 index 4fc2101..0000000 --- a/zavai/registry.py +++ /dev/null @@ -1,210 +0,0 @@ -# registry - zavai resource registry -# -# Copyright (C) 2009 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 - -import zavai -import gtk - -def get_parent(s): - "Get the parent name for s" - pos = s.rfind(".") - if pos == -1: return None - res = s[:pos] - if res == "menu": return None - return res - -def default_label(s): - "Compute a default label given the last element of a path" - pos = s.rfind(".") - if pos == -1: return s.capitalize() - return s[pos+1:].capitalize() - - -class Registry(object): - """Collection of resources. - - Various factories can be registered by name on the registry. Then when an - object is requested for the first time, it is created using the factory. - When it is requested again, the existing object is reused. - """ - - def __init__(self): - self.factories = dict() - self.objects = dict() - self.labels = dict() - - def register(self, obj, name=None): - """Register an object at the given path. - - Name the path to this object, like "menu.gps.monitor". - """ - if name is None: - name = obj.props.name - - if name in self.objects: - return KeyError("%s is already registered", name) - zavai.info("Registering", name) - self.objects[name] = obj - - if name.startswith("menu."): - self.add_to_menu(name) - - def register_factory(self, fac, name, label = None): - """Register an object factory at the given path. - - Name the path to this object, like "menu.gps.monitor". - """ - if name in self.factories: - return KeyError("Factory %s is already registered", name) - zavai.info("Registering factory", name) - self.factories[name] = fac - if label is not None: self.labels[name] = label - - def add_to_menu(self, name): - "Add the applet with the given name to the menu structure" - parent = get_parent(name) - if parent is not None: - zavai.info("Add to menu", name, parent) - menu = self.menu(parent) - - obj = self.resource(name) - if isinstance(obj, gtk.ToggleAction): - menu.add_child(zavai.ToggleButton(self, name, action=obj)) - elif isinstance(obj, gtk.Action): - menu.add_child(zavai.LinkButton(self, name, action=obj)) - else: - menu.add_child(zavai.LinkButton(self, name, self.label(name))) - - def label(self, name): - "Return the label for the object with the given name" - res = self.labels.get(name) - if res is not None: - return res - try: - obj = self.resource(name) - return obj.props.label - except: - return default_label(name) - - def resource(self, name): - """Get a resource from the registry. - - If no resource exists at `name` but there is a factory, instantiate the - object using the factory. - - If not even a factory exists at `name`, returns None. - """ - res = self.objects.get(name, None) - if res is None: - fac = self.factories.get(name, None) - if fac is not None: - res = self.objects[name] = fac(self, name) - return res - - def menu(self, name): - """Get a menu resource, automatically creating it if it is missing. - - Menus are created automatically linked to a parent menu, according to - the hierarchy in `name`. - """ - res = self.resource(name) - if res is None: - # Check if it is a toplevel menu - if name.startswith("menu."): - parent = get_parent(name[5:]) - if parent is not None: - parent = "menu." + parent - else: - parent = get_parent(name) - - res = zavai.Menu(self, name, parent) - self.register(res, name) - return res - - def shutdown(self): - """Shut down all objects in this Registry. - - After shutting down, all objects cannot be used anymore""" - for o in self.objects.itervalues(): - if isinstance(o, Resource): - o.shutdown() - self.objects.clear() - -class Resource(object): - def __init__(self): - super(Resource, self).__init__() - - def shutdown(self): - """Shut down this resource. - - Normally one does nothing here, but it is important to give resources a - chance to do cleanup when the program quits. - - This can be used for tasks like closing the tags on a GPX track, - releasing a FSO resource, restoring mixer settings and so on. - """ - pass - -class Service(Resource): - "Service that is activated only when someone is listening" - def __init__(self, types = []): - """ - Initialise a service that can emit signals for the given event types - """ - super(Service, self).__init__() - self.callbacks = dict() - for t in types: - self.callbacks[t] = set() - self.started = False - - def shutdown(self): - if self.started: - self.stop() - - def start(self): - "Activate the service" - pass - - def stop(self): - "Deactivate the service" - pass - - def notify(self, type, *args, **kw): - "Call all callbacks with the given parameters" - for cb in self.callbacks[type]: - cb(*args, **kw) - - def has_callbacks(self): - for i in self.callbacks.values(): - if i: return True - return False - - def connect(self, type, callback): - "Connect a callback to this resource, activating it if needed" - do_start = not self.has_callbacks() - self.callbacks[type].add(callback) - if do_start: - self.start() - self.started = True - - def disconnect(self, type, callback): - "Disconnect a callback to this resource, activating it if needed" - if not self.has_callbacks(): return - self.callbacks[type].discard(callback) - if not self.has_callbacks(): - self.stop() - self.started = False diff --git a/zavai/registry.vala b/zavai/registry.vala new file mode 100644 index 0000000..3d549da --- /dev/null +++ b/zavai/registry.vala @@ -0,0 +1,83 @@ +/* + * registry - zavai resource registry + * + * Copyright (C) 2009 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 { + +public class Registry : Object, Resource +{ + List resources; + public DBus.Connection sbus; + public string bus_name; + + public Registry() + { + resources = new List(); + try { + sbus = DBus.Bus.get(DBus.BusType.SYSTEM); + } catch (DBus.Error e) { + stderr.printf("Cannot access system DBus bus: %s\n", e.message); + sbus = null; + } + + bus_name = DBus.bus_get_unique_name(sbus.get_connection()); + zavai.log.info("My bus name: " + bus_name); + + dynamic DBus.Object tmp_dbus = sbus.get_object( + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus"); + bus_name = "org.enricozini.zavai"; + uint res = tmp_dbus.RequestName(bus_name, (uint)DBus.NameFlag.DO_NOT_QUEUE); + switch (res) + { + case DBus.RequestNameReply.PRIMARY_OWNER: + zavai.log.info("Registered to dbus as " + bus_name); + break; + case DBus.RequestNameReply.IN_QUEUE: + zavai.log.info("In queue, but I asked not to"); + break; + case DBus.RequestNameReply.EXISTS: + zavai.log.info(bus_name + " already exists"); + break; + case DBus.RequestNameReply.ALREADY_OWNER: + zavai.log.info("I already own the name " + bus_name + " but I do not remember asking for it"); + break; + } + } + + public void shutdown() + { + // Shutdown in reverse registration order + for (weak List i = resources; i != null; i = i.next) + i.data.shutdown(); + } + + public void register(Resource obj) + { + resources.prepend(obj); + } +} + +public zavai.Registry registry; + +} + diff --git a/zavai/uevent.vala b/zavai/uevent.vala new file mode 100644 index 0000000..b9475ae --- /dev/null +++ b/zavai/uevent.vala @@ -0,0 +1,92 @@ +/* + * uevent - zavai uevent handling + * + * Copyright (C) 2009 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 uevent { + +class UEvent : Service +{ + protected IOChannel sock; + protected uint sock_watch = 0; + public Omhacks.UEvent.Event event_data; + public signal void event(); + + public UEvent() + { + event_data = Omhacks.UEvent.Event(); + } + + protected bool on_input_data(IOChannel source, IOCondition condition) + { + if (condition != IOCondition.IN) return true; + + Omhacks.UEvent.read(sock.unix_get_fd(), ref event_data); + event(); + + return true; + } + + /// Activate the service + protected override void start() + { + if (started) return; + + int sock_fd = Omhacks.UEvent.open(); + if (sock_fd < 0) + { + zavai.log.error("UEvent: error getting socket"); + return; + } + + sock = new IOChannel.unix_new(sock_fd); + sock_watch = sock.add_watch(IOCondition.IN, on_input_data); + + base.start(); + } + + /// Deactivate the service + protected override void stop() + { + if (!started) return; + Source.remove(sock_watch); + try { + sock.shutdown(false); + } catch (IOChannelError e) { + zavai.log.error("When closing UEvent socket: " + e.message); + } + sock = null; + base.stop(); + } +} + +UEvent uevent; + +public void init() +{ + if (Posix.getuid() == 0) + uevent = new UEvent(); + else + uevent = null; +} + +} +} diff --git a/zavai/wifi.vala b/zavai/wifi.vala new file mode 100644 index 0000000..55cf1cc --- /dev/null +++ b/zavai/wifi.vala @@ -0,0 +1,61 @@ +/* + * wifi - wifi resource for zavai + * + * 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 wifi { + +public class Wifi: zavai.ScriptService +{ + public Wifi() + { + Object(name: "wifi"); + started = script_status(); + } + + /// Start wifi + public override void start() + { + if (started) return; + if (!script_start()) return; + zavai.log.info("wifi turned on"); + base.start(); + } + + // Release usage of wifi + public override void stop() + { + if (!started) return; + script_stop(); + base.stop(); + } +} + +public Wifi wifi = null; + +public void init() +{ + wifi = new Wifi(); + +} + +} +} diff --git a/zavai/x11.vapi b/zavai/x11.vapi new file mode 100644 index 0000000..ec8b074 --- /dev/null +++ b/zavai/x11.vapi @@ -0,0 +1,883 @@ +/* x11.vapi + * + * Copyright (C) 2009 Jürg Billeter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Jürg Billeter + */ + +[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "X11/Xlib.h,X11/Xatom.h,X11/Xutil.h")] +namespace X { + // Note: must be called before opening a display or calling any other Xlib function, + // see http://tronche.com/gui/x/xlib/display/XInitThreads.html + [CCode (cname = "XInitThreads")] + public Status init_threads (); + + [Compact] + [CCode (cname = "Display", ref_function = "", unref_function = "")] + public class Display { + [CCode (cname = "XOpenDisplay")] + public Display (string? name = null); + + [CCode (cname = "XGetAtomName")] + public string get_atom_name(Atom a); + + [CCode (cname = "XAllPlanes")] + public static ulong get_all_planes (); + + [CCode (cname = "XAddToSaveSet")] + public int add_to_save_set (Window w); + + [CCode (cname = "XAllowEvents")] + public int allow_events (int event_mode, int time); + + [CCode (cname = "XBitmapBitOrder")] + public int bitmap_bit_order (); + + [CCode (cname = "XBitmapUnit")] + public int bitmap_scanline_unit (); + + [CCode (cname = "XBitmapPad")] + public int bitmap_scanline_padding (); + + [CCode (cname = "XChangeProperty")] + public int change_property (Window w, Atom property, Atom type, int format, int mode, [CCode (array_length = false)] uchar[] data, int nelements); + + [CCode (cname = "XChangeWindowAttributes")] + public int change_window_attributes (Window w, ulong valuemask, SetWindowAttributes attributes); + + [CCode (cname = "XConfigureWindow")] + public int configure_window (Window w, uint value_mask, WindowChanges values); + + [CCode (cname = "ConnectionNumber")] + public int connection_number (); + + [CCode (cname = "DefaultRootWindow")] + public Window default_root_window (); + + [CCode (cname = "XDefaultScreenOfDisplay")] + public unowned Screen default_screen (); + + [CCode (cname = "XScreenOfDisplay")] + public unowned Screen screen_by_id (int screen_number); + + [CCode (cname = "DisplayString")] + public string display_string (); + + [CCode (cname = "XQLength")] + public int event_queue_length (); + + [CCode (cname = "XFlush")] + public int flush (); + + [CCode (cname = "XGetKeyboardMapping", array_length = false)] + public weak uint[] get_keyboard_mapping (uint first_keycode, int keycode_count, ref int keysyms_per_keycode_return); + + [CCode (cname = "XGetModifierMapping")] + public ModifierKeymap get_modifier_mapping (); + + [CCode (cname = "XGetSelectionOwner")] + public Window get_selection_owner (Atom selection); + + [CCode (cname = "XGetWindowAttributes")] + public void get_window_attributes (Window w, out WindowAttributes window_attributes_return); + + [CCode (cname = "XGetWindowProperty")] + public int get_window_property (Window w, Atom property, long long_offset, long long_length, bool delete, Atom req_type, out Atom actual_type_return, out int actual_format_return, out ulong nitems_return, out ulong bytes_after_return, out void* prop_return); + + [CCode (cname = "XGrabButton")] + public int grab_button (uint button, uint modifiers, Window grab_window, bool owner_events, uint event_mask, int pointer_mode, int keyboard_mode, Window confine_to, uint cursor); + + [CCode (cname = "XGrabKey")] + public int grab_key (int keycode, uint modifiers, Window grab_window, bool owner_events, int pointer_mode, int keyboard_mode); + + [CCode (cname = "XGrabPointer")] + public int grab_pointer (Window grab_window, bool owner_events, uint event_mask, int pointer_mode, int keyboard_mode, Window confine_to, uint cursor, int time); + + [CCode (cname = "XGrabServer")] + public int grab_server (); + + [CCode (cname = "XImageByteOrder")] + public int image_byte_order (); + + [CCode (cname = "XInternAtom")] + public Atom intern_atom (string atom_name, bool only_if_exists); + + [CCode (cname = "XInternAtoms")] + public void intern_atoms (string[] names, bool only_if_exists, [CCode (array_length = false)] Atom[] atoms_return); + + [CCode (cname = "XInternalConnectionNumbers")] + public Status internal_connection_numbers (ref int[] fd_return); + + [CCode (cname = "XDisplayKeycodes")] + public int keycodes (ref int min_keycodes_return, ref int max_keycodes_return); + + [CCode (cname = "XKeysymToKeycode")] + public int keysym_to_keycode (uint keysym); + + [CCode (cname = "XLastKnownRequestProcessed")] + public ulong last_known_request_processed (); + + [CCode (cname = "XLockDisplay")] + public void lock_display (); + + [CCode (cname = "XMapWindow")] + public int map_window (Window w); + + [CCode (cname = "XMaxRequestSize")] + public long max_request_size (); + + [CCode (cname = "XExtendedMaxRequestSize")] + public long max_extended_request_size (); + + [CCode (cname = "XNextEvent")] + public int next_event (ref Event event_return); + + [CCode (cname = "XNextRequest")] + public ulong next_request (); + + [CCode (cname = "XNoOp")] + public void no_operation (); + + [CCode (cname = "XScreenCount")] + public int number_of_screens (); + + [CCode (cname = "XPending")] + public int pending (); + + [CCode (cname = "XProcessInternalConnection")] + public void process_internal_connection (int fd); + + [CCode (cname = "XProtocolVersion")] + public int protocol_version (); + + [CCode (cname = "XProtocolRevision")] + public int protocol_revision (); + + [CCode (cname = "XRaiseWindow")] + public int raise_window (Window w); + + [CCode (cname = "XReparentWindow")] + public int reparent_window (Window w, Window parent, int x, int y); + + [CCode (cname = "XResizeWindow")] + public int resize_window (Window w, uint width, uint height); + + [CCode (cname = "XRootWindow")] + public Window root_window (int screen_number); + + [CCode (cname = "ScreenCount")] + public int screen_count (); + + [CCode (cname = "XScreenOfDisplay")] + public weak Screen screen_of_display (int screen_number); + + [CCode (cname = "XSelectInput")] + public int select_input (Window w, long event_mask); + + [CCode (cname = "XSendEvent")] + public void send_event (Window w, bool prpagate, long event_mask, ref Event event_send); + + [CCode (cname = "XSetCloseDownMode")] + public void set_close_down_mode (int close_mode); + + [CCode (cname = "XSetSelectionOwner")] + public Window set_selection_owner (Atom selection, Window owner, int time); + + [CCode (cname = "XSetInputFocus")] + public int set_input_focus (Window focus, int revert_to, int time); + + [CCode (cname = "XUngrabButton")] + public int ungrab_button (uint button, uint modifiers, Window grab_window); + + [CCode (cname = "XUngrabPointer")] + public int ungrab_pointer (int time); + + [CCode (cname = "XUngrabServer")] + public int ungrab_server (); + + [CCode (cname = "XUnlockDisplay")] + public void unlock_display (); + + [CCode (cname = "XUnmapWindow")] + public int unmap_window (Window w); + + [CCode (cname = "XQueryTree")] + public void query_tree (Window w, out Window root_return, out Window parent_return, out Window[] children_return); + + [CCode (cname = "XWindowEvent")] + public int window_event (Window w, EventMask event_mask, out Event event_return); + + [CCode (cname = "XServerVendor")] + public string xserver_vendor_name (); + + [CCode (cname = "XVendorRelease")] + public string xserver_vendor_release (); + + [CCode (cname = "XMoveWindow")] + public void move_window (Window window, int x, int y); + } + + [Compact] + [CCode (cname = "XModifierKeymap", free_function = "XFreeModifiermap")] + public class ModifierKeymap { + // The server's max # of keys per modifier + public int max_keypermod; + // An 8 by max_keypermod array of modifiers + public uchar[] modifiermap; + } + + [SimpleType] + [IntegerType (rank = 9)] + [CCode (cname = "Atom")] + public struct Atom { + } + + [SimpleType] + [IntegerType (rank = 9)] + [CCode (cname = "Colormap")] + public struct Colormap { + } + + [SimpleType] + [CCode (cname = "GC")] + public struct GC { + } + + [SimpleType] + [IntegerType (rank = 9)] + [CCode (cname = "Status")] + public struct Status { + } + + [SimpleType] + [IntegerType (rank = 9)] + [CCode (cname = "Window", type_id = "G_TYPE_INT", + marshaller_type_name = "INT", + get_value_function = "g_value_get_int", + set_value_function = "g_value_set_int", default_value = "0", + type_signature = "i")] + public struct Window { + } + + public struct Visual { + } + + public struct WindowChanges { + public int x; + public int y; + public int width; + public int height; + public int border_width; + public Window sibling; + public int stack_mode; + } + public struct SizeHints { + public long @flags; + public int x; + public int y; + public int width; + public int height; + } + + [CCode (cname = "XCreateWindow")] + public Window create_window (Display display, Window parent, int x, int y, uint width, uint height, uint border_width, int depth, uint @class, Visual? visual, X.CW valuemask, ref SetWindowAttributes attributes); + + [CCode (cname = "XSetWindowAttributes")] + public struct SetWindowAttributes { + // public Pixmap background_pixmap; /* background or None or ParentRelative */ + public ulong background_pixel; /* background pixel */ + // public Pixmap border_pixmap; /* border of the window */ + public ulong border_pixel; /* border pixel value */ + public int bit_gravity; /* one of bit gravity values */ + public int win_gravity; /* one of the window gravity values */ + public int backing_store; /* NotUseful, WhenMapped, Always */ + public ulong backing_planes;/* planes to be preseved if possible */ + public ulong backing_pixel;/* value to use in restoring planes */ + public bool save_under; /* should bits under be saved? (popups) */ + public long event_mask; /* set of events that should be saved */ + public long do_not_propagate_mask; /* set of events that should not propagate */ + public bool override_redirect; /* boolean value for override-redirect */ + // public Colormap colormap; /* color map to be associated with window */ + // public Cursor cursor; /* cursor to be displayed (or None) */ + } + + [CCode(cname = "XWindowAttributes", + cheader_filename = "X11/Xlib.h,X11/Xatom.h,X11/Xutil.h")] + public struct WindowAttributes { + public int x; + public int y; /* location of window */ + public int width; + public int height; /* width and height of window */ + public int border_width; /* border width of window */ + public int depth; /* depth of window */ + public Visual visual; /* the associated visual structure */ + public Window root; /* root of screen containing window */ + public int @class; /* InputOutput, InputOnly*/ + public int bit_gravity; /* one of bit gravity values */ + public int win_gravity; /* one of the window gravity values */ + public int backing_store; /* NotUseful, WhenMapped, Always */ + public ulong backing_planes;/* planes to be preserved if possible */ + public ulong backing_pixel;/* value to be used when restoring planes */ + public bool save_under; /* boolean, should bits under be saved? */ + // public Colormap colormap; /* color map to be associated with window */ + public bool map_installed; /* boolean, is color map currently installed*/ + public int map_state; /* IsUnmapped, IsUnviewable, IsViewable */ + public long all_event_masks; /* set of events all people have interest in*/ + public long your_event_mask; /* my event mask */ + public long do_not_propagate_mask; /* set of events that should not propagate */ + public bool override_redirect; /* boolean value for override-redirect */ + // public Screen screen; /* back pointer to correct screen */ + } + + [CCode (cname = "CopyFromParent")] + public const int COPY_FROM_PARENT; + + [CCode (cname = "CurrentTime")] + public const ulong CURRENT_TIME; + + [CCode (cname = "Success")] + public int Success; + + [CCode (cname = "XFree")] + public int free (void* data); + + [CCode (cprefix = "CW", cname = "int")] + public enum CW { + BackPixmap, + BackPixel, + BackingStore, + BackingPlanes, + BackingPixel, + BitGravity, + BorderPixmap, + BorderPixel, + BorderWidth, + Colormap, + Cursor, + DontPropagate, + EventMask, + Height, + OverrideRedirect, + SaveUnder, + Sibling, + StackMode, + X, + Y, + Width, + WinGravity + } + + [CCode (cprefix = "GrabMode")] + public enum GrabMode { + Sync, + Async + } + + [CCode (cprefix = "")] + public enum EventMask { + NoEventMask, + KeyPressMask, + KeyReleaseMask, + ButtonPressMask, + ButtonReleaseMask, + EnterWindowMask, + LeaveWindowMask, + PointerMotionMask, + PointerMotionHintMask, + Button1MotionMask, + Button2MotionMask, + Button3MotionMask, + Button4MotionMask, + Button5MotionMask, + ButtonMotionMask, + KeymapStateMask, + ExposureMask, + VisibilityChangeMask, + StructureNotifyMask, + ResizeRedirectMask, + SubstructureNotifyMask, + SubstructureRedirectMask, + FocusChangeMask, + PropertyChangeMask, + ColormapChangeMask, + OwnerGrabButtonMask + } + + [CCode (cprefix = "")] + public enum KeyMask { + ShiftMask, + LockMask, + ControlMask, + Mod1Mask, + Mod2Mask, + Mod3Mask, + Mod4Mask, + Mod5Mask + } + + [CCode (cprefix = "")] + public enum EventType { + KeyPress, + KeyRelease, + ButtonPress, + ButtonRelease, + MotionNotify, + EnterNotify, + LeaveNotify, + FocusIn, + FocusOut, + KeymapNotify, + Expose, + GraphicsExpose, + NoExpose, + VisibilityNotify, + CreateNotify, + DestroyNotify, + UnmapNotify, + MapNotify, + MapRequest, + ReparentNotify, + ConfigureNotify, + ConfigureRequest, + GravityNotify, + ResizeRequest, + CirculateNotify, + CirculateRequest, + PropertyNotify, + SelectionClear, + SelectionRequest, + SelectionNotify, + ColormapNotify, + ClientMessage, + MappingNotify + } + + // union + [CCode (cname = "XEvent")] + public struct Event { + public int type; + public AnyEvent xany; + public KeyEvent xkey; + public ButtonEvent xbutton; + public MotionEvent xmotion; + public CrossingEvent xcrossing; + public CreateWindowEvent xcreatewindow; + public DestroyWindowEvent xdestroywindow; + public UnmapEvent xunmap; + public MapEvent xmap; + public MapRequestEvent xmaprequest; + public ReparentEvent xreparent; + public ConfigureEvent xconfigure; + public GravityEvent xgravity; + public ConfigureRequestEvent xconfigurerequest; + public CirculateEvent xcirculate; + public CirculateRequestEvent xcirculaterequest; + public PropertyEvent xproperty; + public SelectionEvent xselection; + public ClientMessageEvent xclient; + } + + [CCode (cname = "XAnyEvent")] + public struct AnyEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window window; + } + + [CCode (cname = "XKeyEvent")] + public struct KeyEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window window; + public Window root; + public Window subwindow; + public ulong time; + public int x; + public int y; + public int x_root; + public int y_root; + public uint state; + public uint keycode; + public bool same_screen; + } + + [CCode (cname = "XButtonEvent")] + public struct ButtonEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window window; + public Window subwindow; + public ulong time; + public int x; + public int y; + public int x_root; + public int y_root; + public uint state; + public uint button; + public bool same_screen; + } + + [CCode (cname = "XMotionEvent")] + public struct MotionEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window window; + public Window subwindow; + public ulong time; + public int x; + public int y; + public int x_root; + public int y_root; + public uint state; + public char is_hint; + public bool same_screen; + } + + [CCode (cname = "XCrossingEvent")] + public struct CrossingEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window window; + public Window root; + public Window subwindow; + public ulong time; + public int x; + public int y; + public int x_root; + public int y_root; + public int mode; + public int detail; + public bool same_screen; + public bool focus; + public uint state; + } + + [CCode (cname = "XCreateWindowEvent")] + public struct CreateWindowEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window parent; + public Window window; + public int x; + public int y; + public int width; + public int height; + public int border_width; + public bool override_redirect; + } + + [CCode (cname = "XDestroyWindowEvent")] + public struct DestroyWindowEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window event; + public Window window; + } + + [CCode (cname = "XUnmapEvent")] + public struct UnmapEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window event; + public Window window; + public bool from_configure; + } + + [CCode (cname = "XMapEvent")] + public struct MapEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window event; + public Window window; + public bool override_redirect; + } + + [CCode (cname = "XMapRequestEvent")] + public struct MapRequestEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window parent; + public Window window; + } + + [CCode (cname = "XReparentEvent")] + public struct ReparentEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window event; + public Window window; + public Window parent; + public int x; + public int y; + public bool override_redirect; + } + + [CCode (cname = "XConfigureEvent")] + public struct ConfigureEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window event; + public Window window; + public int x; + public int y; + public int width; + public int height; + public int border_width; + public Window above; + public bool override_redirect; + } + + [CCode (cname = "XGravityEvent")] + public struct GravityEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window event; + public Window window; + public int x; + public int y; + } + + [CCode (cname = "XConfigureRequestEvent")] + public struct ConfigureRequestEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window parent; + public Window window; + public int x; + public int y; + public int width; + public int height; + public int border_width; + public Window above; + public int detail; + public ulong value_mask; + } + + [CCode (cname = "XCirculateEvent")] + public struct CirculateEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window event; + public Window window; + public int place; + } + + [CCode (cname = "XCirculateRequestEvent")] + public struct CirculateRequestEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window parent; + public Window window; + public int place; + } + + [CCode (cname = "XPropertyEvent")] + public struct PropertyEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window window; + public Atom atom; + public ulong time; + public int state; + } + + [CCode (cname = "XSelectionEvent")] + public struct SelectionEvent { + public int type; + public ulong serial; + public bool send_event; + public unowned Display display; + public Window requestor; + public Atom selection; + public Atom target; + public Atom property; + public ulong time; + } + + [CCode (cname = "XClientMessageEvent")] + public struct ClientMessageEvent { + public int type; + public ulong serial; /* # of last request processed by server */ + public bool send_event; /* true if this came from a SendEvent request */ + public unowned Display display; /* Display the event was read from */ + public Window window; + public Atom message_type; + public int format; + public ClientMessageEventData data; + } + + // union + public struct ClientMessageEventData { + public unowned char[] b; + public unowned short[] s; + public unowned long[] l; + } + + [CCode (cprefix = "PropMode")] + public enum PropMode { + Replace, + Prepend, + Append + } + + [CCode (cprefix = "")] + public enum AllowEventsMode { + AsyncPointer, + SyncPointer, + ReplayPointer, + AsyncKeyboard, + SyncKeyboard, + ReplayKeyboard, + AsyncBoth, + SyncBoth + } + + [CCode (cprefix = "")] + public enum MapState { + IsUnmapped, + IsUnviewable, + IsViewable + } + + [CCode (cprefix = "RevertTo")] + public enum RevertTo { + None, + PointerRoot, + Parent + } + + [Compact] + [CCode (cname = "Screen")] + public class Screen { + public Display display; + public Window root; + public int width; + public int height; + + [CCode (cname = "XScreenOfDisplay")] + public static unowned Screen get_screen (Display disp, int screen_number); + + [CCode (cname = "XBlackPixelOfScreen")] + public ulong black_pixel_of_screen (); + + [CCode (cname = "XCellsOfScreen")] + public int cells_of_screen (); + + [CCode (cname = "XDefaultColormapOfScreen")] + public Colormap default_colormap_of_screen (); + + [CCode (cname = "XDefaultDepthOfScreen")] + public int default_depth_of_screen (); + + [CCode (cname = "XDefaultGCOfScreen")] + public GC default_gc_of_screen (); + + [CCode (cname = "XDefaultVisualOfScreen")] + public Visual default_visual_of_screen (); + + [CCode (cname = "XDisplayOfScreen")] + public unowned Display display_of_screen (); + + [CCode (cname = "XDoesBackingStore")] + public int does_backing_store (); + + [CCode (cname = "XDoesSaveUnders")] + public bool does_save_unders (); + + [CCode (cname = "XEventMaskOfScreen")] + public long event_mask_of_Screen (); + + [CCode (cname = "XHeightMMOfScreen")] + public int height_in_mm_of_screen (); + + [CCode (cname = "XHeightOfScreen")] + public int height_of_screen (); + + [CCode (cname = "XMaxCmapsOfScreen")] + public int max_colormaps_of_screen (); + + [CCode (cname = "XMinCmapsOfScreen")] + public int min_colormaps_of_screen (); + + [CCode (cname = "XPlanesOfScreen")] + public int planes_of_screen (); + + [CCode (cname = "XRootWindowOfScreen")] + public Window root_window_of_screen (); + + [CCode (cname = "XScreenNumberOfScreen")] + public int screen_number_of_screen (); + + [CCode (cname = "XWhitePixelOfScreen")] + public ulong white_pixel_of_screen (); + + [CCode (cname = "XWidthMMOfScreen")] + public int width_in_mm_of_screen (); + + [CCode (cname = "XWidthOfScreen")] + public int width_of_screen (); + } + + public const X.Atom XA_ATOM; + public const X.Atom XA_CARDINAL; + public const X.Atom XA_WINDOW; + public const X.Atom XA_WM_CLASS; + public const X.Atom XA_WM_HINTS; + public const X.Atom XA_WM_ICON_NAME; + public const X.Atom XA_WM_NAME; + public const X.Atom XA_WM_NORMAL_HINTS; + public const X.Atom XA_WM_TRANSIENT_FOR; + + public const uint XK_Num_Lock; + public const uint XK_Scroll_Lock; +} +