using Gee; public Gee.HashMap searches; public DBus.Connection conn; [DBus (name = "org.maemo.cinaest.MovieSearch", signals="movies_found")] public class MovieSearch : Object { public int id; bool aborted; string title; GoogleParser parser; GLib.List results; GoogleMovieService service; public string path; public string sender; // D-Bus API public void abort () { print ("aborting\n"); aborted = true; } public void start (string query) { parser = new GoogleParser (); title = query; query_async.begin (); } public signal void movies_found (string[] movies, bool finished); // Internal methods internal MovieSearch (GoogleMovieService _service, string _sender, string _path) { service = _service; sender = _sender; path = _path; } private async void query_async () { var gc = GConf.Client.get_default (); results = new GLib.List (); string location = null; try { location = gc.get_string ("/apps/cinaest/location"); } catch (Error e) { stdout.printf ("Error getting GConf option: %s\n", e.message); } if (location == null) location = ""; int n = yield parser.query (title, location, receive_movie); try { var locations = ((SList) gc.get_list ("/apps/cinaest/locations", GConf.ValueType.STRING)).copy (); if (insert_location_sorted (parser.location, ref locations)) { gc.set_list ("/apps/cinaest/locations", GConf.ValueType.STRING, locations); } if (location != parser.location) { location = parser.location; gc.set_string ("/apps/cinaest/location", location); } } catch (Error e2) { stdout.printf ("GConf error: %s\n", e2.message); } print ("got %d movies\n", n); var m = new string[results.length ()]; int i = 0; for (unowned GLib.List node = results.first (); node != null; node = node.next) { m[i++] = "{\"title\":\"%s\",\"rating\":%f,\"runtime\":%d,\"showtimes\":\"%s\",\"cinema_name\":\"%s\",\"cinema_phone\":\"%s\"}".printf (node.data.title, node.data.rating, node.data.runtime, node.data.showtimes, node.data.theater.name, node.data.theater.phone); } movies_found (m, true); service.timeout_quit (); } private bool insert_location_sorted (string? location, ref SList locations) { if (location == null) return false; if (locations != null) { for (unowned SList l = locations; l != null; l = l.next) { if (l.data == location) { return false; } if (l.data > location) { l.insert (location, 0); return true; } } } locations.append (location); return true; } private void receive_movie (GoogleMovie movie) { // print ("received %s\n", movie.title); results.append (movie); } } [DBus (name = "org.maemo.cinaest.MovieService")] public class GoogleMovieService : Object { private MainLoop loop; private uint source_id; int id = 0; // D-Bus API public string new_search (DBus.BusName sender) { var path = "/org/maemo/cinaest/moviepilot/search%d".printf (id); var search = new MovieSearch (this, sender, path); search.id = id++; conn.register_object (path, search); print ("creating new search %s for %s\n", path, sender); searches.set (path, search); return path; } public void unregister (string path) { print ("unregistering search %s\n", path); searches.remove (path); print ("%d\n", searches.size); } // Internal methods internal GoogleMovieService () { loop = new MainLoop (null); } internal void timeout_quit () { // With every change we reset the timer to 3min if (source_id != 0) { Source.remove (source_id); } source_id = Timeout.add_seconds (180, quit); } private bool quit () { loop.quit (); // One-shot only return false; } internal void run () { loop.run (); } } void on_client_lost (DBus.Object sender, string name, string prev, string newp) { if (newp == "") { var remove_list = new SList (); // We lost a client print ("lost a client: %s\n", prev); foreach (MovieSearch search in searches.values) { if (search.sender == prev) { print ("removing %s\n", search.path); remove_list.append (search.path); } } foreach (string path in remove_list) searches.remove (path); } } void main () { try { conn = DBus.Bus.get (DBus.BusType. SESSION); searches = new Gee.HashMap (); dynamic DBus.Object bus = conn.get_object ("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus"); uint res = bus.request_name ("org.maemo.cinaest.GoogleShowtimes", (uint) 0); if (res == DBus.RequestNameReply.PRIMARY_OWNER) { var server = new GoogleMovieService (); conn.register_object ("/org/maemo/cinaest/googleshowtimes", server); bus.NameOwnerChanged.connect (on_client_lost); server.timeout_quit (); server.run (); } } catch (Error e) { stderr.printf ("Oops: %s\n", e.message); } }