Split non-ui functions in separate lib
authorEnrico Zini <enrico@enricozini.org>
Fri, 26 Mar 2010 00:15:49 +0000 (00:15 +0000)
committerEnrico Zini <enrico@enricozini.org>
Fri, 26 Mar 2010 00:15:49 +0000 (00:15 +0000)
58 files changed:
CMakeLists.txt
README
src/CMakeLists.txt
src/app.vala
src/app_power.vala
src/at.vala [deleted file]
src/audio.vala [deleted file]
src/bluetooth.vala [deleted file]
src/clock.vala [deleted file]
src/config.vala [deleted file]
src/core.vala [deleted file]
src/dbus-extra.vapi [deleted file]
src/devkit-power-gobject.vapi [deleted file]
src/gps.py [new file with mode: 0755]
src/gps.vala [deleted file]
src/gsm.vala [deleted file]
src/input.vala [deleted file]
src/libgps.vapi [deleted file]
src/libomhacks.vapi [deleted file]
src/linux-input.vapi [deleted file]
src/log.vala [deleted file]
src/lua5.1.vapi [deleted symlink]
src/power.vala [deleted file]
src/registry.vala [deleted file]
src/uevent.vala [deleted file]
src/wifi.vala [deleted file]
src/x11.vapi [deleted file]
src/zavai.vala
zavai/__init__.py [deleted file]
zavai/app.py [deleted file]
zavai/at.vala [new file with mode: 0644]
zavai/audio.py [deleted file]
zavai/audio.vala [new file with mode: 0644]
zavai/bluetooth.vala [new file with mode: 0644]
zavai/clock.vala [new file with mode: 0644]
zavai/conf.py [deleted file]
zavai/config.py [deleted file]
zavai/config.vala [new file with mode: 0644]
zavai/core.vala [new file with mode: 0644]
zavai/dbus-extra.vapi [new file with mode: 0644]
zavai/devkit-power-gobject.vapi [new file with mode: 0644]
zavai/gps.py [deleted file]
zavai/gps.vala [new file with mode: 0644]
zavai/gsm.vala [new file with mode: 0644]
zavai/input.vala [new file with mode: 0644]
zavai/libgps.vapi [new file with mode: 0644]
zavai/libomhacks.vapi [new file with mode: 0644]
zavai/linux-input.vapi [new file with mode: 0644]
zavai/log.vala [new file with mode: 0644]
zavai/lua5.1.vapi [new symlink]
zavai/menu.py [deleted file]
zavai/plugins.py [deleted file]
zavai/power.vala [new file with mode: 0644]
zavai/registry.py [deleted file]
zavai/registry.vala [new file with mode: 0644]
zavai/uevent.vala [new file with mode: 0644]
zavai/wifi.vala [new file with mode: 0644]
zavai/x11.vapi [new file with mode: 0644]

index a022b788d460754ee43bd6a6aa567fc70715272b..ae82bc471119868ee441f02dabd6ee71197af767 100644 (file)
@@ -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 0bfa0a0c283f42a8485571a1a617a949fc13eb1a..0d17b4ca8aa52d078adcf9c6e41062bdbcb613d7 100644 (file)
--- 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
index 657b95d057efe46d58b2b2ad6138acf9fc446ce6..06cacbd24af4981a1bdd7369afb890176ec5f950 100644 (file)
@@ -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})
index 5281f56aeccd09531b180d64a53fc9e8372f35e8..6366b6a4d20285381a131b9c5490a533ad8a5d08 100644 (file)
@@ -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
index 33be3e93f4a51fb1fd232015e19723fdab91343b..8fedf3f4e5545ccd44a9e1d5238375f8e2f3c7c6 100644 (file)
@@ -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 (file)
index 33cdf27..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * at - at interface
- *
- * Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-using GLib;
-
-namespace 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 (file)
index 1c39420..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * audio - audio resource for zavai
- *
- * Copyright (C) 2009--2010  Enrico Zini <enrico@enricozini.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-using GLib;
-
-namespace zavai {
-namespace 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 (file)
index 0103d0f..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * bluetooth - bluetooth resource for zavai
- *
- * Copyright (C) 2010  Enrico Zini <enrico@enricozini.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-using GLib;
-
-namespace zavai {
-namespace 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 (file)
index d08717b..0000000
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * clock - clock resource for zavai
- *
- * Copyright (C) 2009--2010  Enrico Zini <enrico@enricozini.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-using GLib;
-
-namespace zavai {
-namespace 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<AlarmTriggerInfo> queue;
-
-    public signal void triggered(AlarmTriggerInfo info);
-    public signal void acked(AlarmTriggerInfo info);
-    public signal void canceled(AlarmTriggerInfo info);
-
-    public AlarmTriggerQueue()
-    {
-        queue = new List<AlarmTriggerInfo>();
-    }
-
-    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<Alarm> 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 (file)
index 3f9ff41..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * config - zavai configuration
- *
- * Copyright (C) 2009--2010  Enrico Zini <enrico@enricozini.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-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 (file)
index 27c621b..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * app - zavai main window
- *
- * Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-using GLib;
-
-namespace zavai {
-
-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<Request> 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<Request> 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<Request> el = null;
-        for (weak List<Request> 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 (file)
index 5213899..0000000
+++ /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 (file)
index 139abc2..0000000
+++ /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 (executable)
index 0000000..2b73da7
--- /dev/null
@@ -0,0 +1,345 @@
+# gps - gps resource for zavai
+#
+# Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#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, """<?xml version="1.0" encoding="UTF-8"?>
+<gpx
+    version="1.0"
+    creator="audiomap %s"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns="http://www.topografix.com/GPX/1/0"
+    xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
+  <trk>
+    <trkseg>""" % zavai.VERSION
+
+        self.wpt = open(self.basename + "-wpt.gpx", "wt")
+        print >>self.wpt, """<?xml version="1.0" encoding="UTF-8"?>
+<gpx
+    version="1.0"
+    creator="audiomap %s"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns="http://www.topografix.com/GPX/1/0"
+    xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">""" % zavai.VERSION
+
+        self.wpt_seq = 1;
+        self.notify_activity_monitors()
+
+    def stop_track(self):
+        if self.trk is not None:
+            print >>self.trk, "</trkseg></trk></gpx>"
+            self.trk.close()
+            self.trk = None
+        if self.wpt is not None:
+            print >>self.wpt, "</gpx>"
+            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, """<trkpt lat="%f" lon="%f">
+  <time>%s</time>
+  <ele>%f</ele>""" % (lat, lon, time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(tstamp)), ele)
+        #if course is not None: print >>self.trk, "    <course>%f</course>" % course
+        #if speed is not None: print >>self.trk, "    <speed>%f</speed>" % speed
+        #if fix is not None: print >>self.trk, "    <fix>%f</fix>" % fix
+        #if hdop is not None: print >>self.trk, "    <hdop>%f</hdop>" % hdop
+        print >>self.trk, "</trkpt>"
+
+    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, """<wpt lat="%f" lon="%f">
+    <name>%s</name>
+    <time>%s</time>
+    <ele>%f</ele>
+</wpt>""" % (
+            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 (file)
index 950d76b..0000000
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * gps - gps resource for zavai
- *
- * Copyright (C) 2009--2010  Enrico Zini <enrico@enricozini.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-using GLib;
-
-namespace zavai {
-namespace 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 (file)
index b11065d..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * gsm - gsm resource for zavai
- *
- * Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-using GLib;
-
-namespace zavai {
-namespace 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 (file)
index ffa0add..0000000
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
- * devinput - zavai /dev/input device handling
- *
- * Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-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<int> grabbed;
-    public signal bool hotkey(uint keycode, ulong time, bool pressed);
-
-    public HotKeys()
-    {
-        Object(name: "input.hotkeys");
-
-        grabbed = new List<int>();
-    }
-
-    // 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 (file)
index da29fcd..0000000
+++ /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 (file)
index 83434f3..0000000
+++ /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 (file)
index 835f849..0000000
+++ /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 (file)
index eb78363..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * log - logging functions
- *
- * Copyright (C) 2009--2010  Enrico Zini <enrico@enricozini.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-using GLib;
-
-namespace zavai {
-namespace 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("   <time>%s</time>\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("   <wpt lat=\"%f\" lon=\"%f\">\n", lat, lon);
-        writeInside(outfd);
-        outfd.printf("   <name>%s</name>\n", Markup.escape_text(msg));
-        outfd.puts("   </wpt>\n");
-    }
-}
-
-public class TrackEntry : Waypoint
-{
-    public TrackEntry()
-    {
-        base();
-    }
-
-    public void write(FileStream outfd)
-    {
-        outfd.printf("   <trkpt lat=\"%f\" lon=\"%f\">\n", lat, lon);
-        writeInside(outfd);
-        outfd.puts("   </trkpt>\n");
-    }
-}
-
-
-public class Log : Object
-{
-    public uint id;
-    public string tag;
-    public string title;
-    public List<LogEntry> entries;
-    public List<TrackEntry> 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("   <trk>\n");
-        outfd.puts("     <trkseg>\n");
-        for (weak List<TrackEntry> i = track; i != null; i = i.next)
-            i.data.write(outfd);
-        outfd.puts("     </trkseg>\n");
-        outfd.puts("   </trk>\n");
-    }
-
-    protected void writeEntries(FileStream outfd)
-    {
-        outfd.puts("   <wpt>\n");
-        for (weak List<LogEntry> i = entries; i != null; i = i.next)
-            i.data.write(outfd);
-        outfd.puts("   </wpt>\n");
-    }
-
-    protected void write(FileStream outfd)
-    {
-        outfd.puts("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
-        outfd.puts("<gpx version=\"1.0\"\n");
-        outfd.printf("     creator=\"zavai %s\"\n", zavai.config.version);
-        outfd.puts("     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
-        outfd.puts("     xmlns=\"http://www.topografix.com/GPX/1/0\"\n");
-        outfd.puts("     xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">\n");
-        outfd.puts("  <metadata>\n");
-        outfd.printf("    <name>%s</name>\n", Markup.escape_text(title));
-        outfd.puts("  </metadata>\n");
-        if (track != null) writeTrack(outfd);
-        if (entries != null) writeEntries(outfd);
-        outfd.puts(" </gpx>\n");
-    }
-}
-
-public class Logger : Resource, Object
-{
-    protected List<Log> 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<Log> 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<Log> 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<Log> 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<Log> 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 (symlink)
index e730dfc..0000000
+++ /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 (file)
index 5583708..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * power - zavai power event handling
- *
- * Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-using GLib;
-
-namespace zavai {
-namespace 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 (file)
index 3d549da..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/* 
- * registry - zavai resource registry
- *
- * Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-using GLib;
-
-namespace zavai {
-
-public class Registry : Object, Resource
-{
-    List<Resource> resources;
-    public DBus.Connection sbus;
-    public string bus_name;
-
-    public Registry()
-    {
-        resources = new List<Resource>();
-        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<Resource> 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 (file)
index b9475ae..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * uevent - zavai uevent handling
- *
- * Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-using GLib;
-
-namespace zavai {
-namespace 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 (file)
index 55cf1cc..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * wifi - wifi resource for zavai
- *
- * Copyright (C) 2010  Enrico Zini <enrico@enricozini.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-using GLib;
-
-namespace zavai {
-namespace 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 (file)
index ec8b074..0000000
+++ /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 <j@bitron.ch>
- */
-
-[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;
-}
-
index 50a2c39386795047861889b5d7de5d26308f0aa9..d1dede55f8208a3884af2d800873aa3f899bb98e 100644 (file)
@@ -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 (file)
index 4d48db9..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-# zavai shared code
-#
-# Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-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 (file)
index 4ce7852..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-# app - zavai main window
-#
-# Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-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 (file)
index 0000000..33cdf27
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * at - at interface
+ *
+ * Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+using GLib;
+
+namespace 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 (executable)
index 9d7835e..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-# audio - zavai audio resource
-#
-# Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-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 (file)
index 0000000..1c39420
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * audio - audio resource for zavai
+ *
+ * Copyright (C) 2009--2010  Enrico Zini <enrico@enricozini.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+using GLib;
+
+namespace zavai {
+namespace 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 (file)
index 0000000..0103d0f
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * bluetooth - bluetooth resource for zavai
+ *
+ * Copyright (C) 2010  Enrico Zini <enrico@enricozini.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+using GLib;
+
+namespace zavai {
+namespace 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 (file)
index 0000000..d08717b
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ * clock - clock resource for zavai
+ *
+ * Copyright (C) 2009--2010  Enrico Zini <enrico@enricozini.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+using GLib;
+
+namespace zavai {
+namespace 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<AlarmTriggerInfo> queue;
+
+    public signal void triggered(AlarmTriggerInfo info);
+    public signal void acked(AlarmTriggerInfo info);
+    public signal void canceled(AlarmTriggerInfo info);
+
+    public AlarmTriggerQueue()
+    {
+        queue = new List<AlarmTriggerInfo>();
+    }
+
+    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<Alarm> 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 (file)
index ba253a4..0000000
+++ /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 (file)
index e328cb8..0000000
+++ /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 (file)
index 0000000..444bbc2
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * config - zavai configuration
+ *
+ * Copyright (C) 2009--2010  Enrico Zini <enrico@enricozini.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+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 (file)
index 0000000..3c31ccd
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * app - zavai main window
+ *
+ * Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+using GLib;
+
+namespace zavai {
+
+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<Request> 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<Request> 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<Request> el = null;
+        for (weak List<Request> 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 (file)
index 0000000..5213899
--- /dev/null
@@ -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 (file)
index 0000000..139abc2
--- /dev/null
@@ -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 (executable)
index 2b73da7..0000000
+++ /dev/null
@@ -1,345 +0,0 @@
-# gps - gps resource for zavai
-#
-# Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-#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, """<?xml version="1.0" encoding="UTF-8"?>
-<gpx
-    version="1.0"
-    creator="audiomap %s"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xmlns="http://www.topografix.com/GPX/1/0"
-    xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
-  <trk>
-    <trkseg>""" % zavai.VERSION
-
-        self.wpt = open(self.basename + "-wpt.gpx", "wt")
-        print >>self.wpt, """<?xml version="1.0" encoding="UTF-8"?>
-<gpx
-    version="1.0"
-    creator="audiomap %s"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xmlns="http://www.topografix.com/GPX/1/0"
-    xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">""" % zavai.VERSION
-
-        self.wpt_seq = 1;
-        self.notify_activity_monitors()
-
-    def stop_track(self):
-        if self.trk is not None:
-            print >>self.trk, "</trkseg></trk></gpx>"
-            self.trk.close()
-            self.trk = None
-        if self.wpt is not None:
-            print >>self.wpt, "</gpx>"
-            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, """<trkpt lat="%f" lon="%f">
-  <time>%s</time>
-  <ele>%f</ele>""" % (lat, lon, time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(tstamp)), ele)
-        #if course is not None: print >>self.trk, "    <course>%f</course>" % course
-        #if speed is not None: print >>self.trk, "    <speed>%f</speed>" % speed
-        #if fix is not None: print >>self.trk, "    <fix>%f</fix>" % fix
-        #if hdop is not None: print >>self.trk, "    <hdop>%f</hdop>" % hdop
-        print >>self.trk, "</trkpt>"
-
-    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, """<wpt lat="%f" lon="%f">
-    <name>%s</name>
-    <time>%s</time>
-    <ele>%f</ele>
-</wpt>""" % (
-            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 (file)
index 0000000..950d76b
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * gps - gps resource for zavai
+ *
+ * Copyright (C) 2009--2010  Enrico Zini <enrico@enricozini.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+using GLib;
+
+namespace zavai {
+namespace 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 (file)
index 0000000..b11065d
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * gsm - gsm resource for zavai
+ *
+ * Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+using GLib;
+
+namespace zavai {
+namespace 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 (file)
index 0000000..ffa0add
--- /dev/null
@@ -0,0 +1,425 @@
+/*
+ * devinput - zavai /dev/input device handling
+ *
+ * Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+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<int> grabbed;
+    public signal bool hotkey(uint keycode, ulong time, bool pressed);
+
+    public HotKeys()
+    {
+        Object(name: "input.hotkeys");
+
+        grabbed = new List<int>();
+    }
+
+    // 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 (file)
index 0000000..da29fcd
--- /dev/null
@@ -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 (file)
index 0000000..83434f3
--- /dev/null
@@ -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 (file)
index 0000000..211eab5
--- /dev/null
@@ -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 (file)
index 0000000..eb78363
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * log - logging functions
+ *
+ * Copyright (C) 2009--2010  Enrico Zini <enrico@enricozini.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+using GLib;
+
+namespace zavai {
+namespace 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("   <time>%s</time>\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("   <wpt lat=\"%f\" lon=\"%f\">\n", lat, lon);
+        writeInside(outfd);
+        outfd.printf("   <name>%s</name>\n", Markup.escape_text(msg));
+        outfd.puts("   </wpt>\n");
+    }
+}
+
+public class TrackEntry : Waypoint
+{
+    public TrackEntry()
+    {
+        base();
+    }
+
+    public void write(FileStream outfd)
+    {
+        outfd.printf("   <trkpt lat=\"%f\" lon=\"%f\">\n", lat, lon);
+        writeInside(outfd);
+        outfd.puts("   </trkpt>\n");
+    }
+}
+
+
+public class Log : Object
+{
+    public uint id;
+    public string tag;
+    public string title;
+    public List<LogEntry> entries;
+    public List<TrackEntry> 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("   <trk>\n");
+        outfd.puts("     <trkseg>\n");
+        for (weak List<TrackEntry> i = track; i != null; i = i.next)
+            i.data.write(outfd);
+        outfd.puts("     </trkseg>\n");
+        outfd.puts("   </trk>\n");
+    }
+
+    protected void writeEntries(FileStream outfd)
+    {
+        outfd.puts("   <wpt>\n");
+        for (weak List<LogEntry> i = entries; i != null; i = i.next)
+            i.data.write(outfd);
+        outfd.puts("   </wpt>\n");
+    }
+
+    protected void write(FileStream outfd)
+    {
+        outfd.puts("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+        outfd.puts("<gpx version=\"1.0\"\n");
+        outfd.printf("     creator=\"zavai %s\"\n", zavai.config.version);
+        outfd.puts("     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
+        outfd.puts("     xmlns=\"http://www.topografix.com/GPX/1/0\"\n");
+        outfd.puts("     xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">\n");
+        outfd.puts("  <metadata>\n");
+        outfd.printf("    <name>%s</name>\n", Markup.escape_text(title));
+        outfd.puts("  </metadata>\n");
+        if (track != null) writeTrack(outfd);
+        if (entries != null) writeEntries(outfd);
+        outfd.puts(" </gpx>\n");
+    }
+}
+
+public class Logger : Resource, Object
+{
+    protected List<Log> 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<Log> 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<Log> 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<Log> 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<Log> i = logs; i != null; i = i.next)
+            if (i.data.id == id)
+            {
+                Log res = i.data;
+  &