/** * Feed Handler * Copyright © 2009 Thomas Perl **/ using Gtk; using GLib; using Osso; using Pango; public static const string FEEDINGIT_SERVICE = "/usr/share/dbus-1/services/feedingit.service"; public enum Reader { RSS = 1, GOOGLE, GPODDER, FEEDINGIT, } public class DesktopFile : GLib.KeyFile { public DesktopFile(string basename) { string filename = "/usr/share/applications/" + basename.replace("hildon-", "hildon/"); try { load_from_file(filename, KeyFileFlags.NONE); } catch (KeyFileError e) { stderr.printf("Cannot open key file: %s\n", e.message); } catch (FileError e) { stderr.printf("Cannot open key file: %s\n", e.message); } } public string? get_name() { try { return get_string("Desktop Entry", "Name"); } catch (KeyFileError e) { stderr.printf("Cannot read exec key: %s\n", e.message); } return null; } public string? get_executable() { try { return get_string("Desktop Entry", "Exec"); } catch (KeyFileError e) { stderr.printf("Cannot read exec key: %s\n", e.message); } return null; } } public class MimeCache : GLib.KeyFile { public MimeCache(string filename="/usr/share/applications/mimeinfo.cache") { try { load_from_file(filename, KeyFileFlags.NONE); } catch (KeyFileError e) { stderr.printf("Cannot open key file: %s\n", e.message); } catch (FileError e) { stderr.printf("Cannot open key file: %s\n", e.message); } } public string [] get_desktop_files(string mimetype="application/news_reader") { try { return get_string("MIME Cache", mimetype).split(";"); } catch (KeyFileError e) { stderr.printf("Cannot get desktop files for %s\n", mimetype); return new string [0]; } } } [DBus (name="org.maemo.garage.feedhandler")] public class FeedHandler : GLib.Object { private MainLoop loop; private DBus.Connection conn; private Osso.Context context; private string args_url; private MimeCache mime_cache; public FeedHandler(MainLoop loop, DBus.Connection conn) { this.loop = loop; this.conn = conn; this.context = new Osso.Context("feedhandler", "2.0", false, null); this.args_url = null; this.mime_cache = new MimeCache(); foreach (string file in mime_cache.get_desktop_files("application/rss+xml")) { if (file != "") { var desktop_file = new DesktopFile(file); var name = desktop_file.get_name(); var exec = desktop_file.get_executable(); if (name != null && exec != null) { stderr.printf("File in Mime CACHE: %s (%s)\n", name, exec); /* XXX: Add "Name" as option and on select, start exec + URL */ } } } } [DBus (name = "mime_open")] public void mime_open(string url) { int result; Gtk.Dialog dlg = new Gtk.Dialog(); dlg.add_button("RSS Reader", Reader.RSS); dlg.add_button("Google Reader", Reader.GOOGLE); if (FileUtils.test("/usr/bin/gpodder", FileTest.EXISTS)) { dlg.add_button("gPodder", Reader.GPODDER); } if (FileUtils.test(FEEDINGIT_SERVICE, FileTest.EXISTS)) { dlg.add_button("FeedingIt", Reader.FEEDINGIT); } dlg.add_button("Cancel", Gtk.ResponseType.CLOSE); dlg.title = "Select application for handling this feed"; var label = new Gtk.Label(url); label.ellipsize = Pango.EllipsizeMode.END; dlg.vbox.add(label); dlg.show_all(); result = dlg.run(); dlg.destroy(); switch (result) { case Reader.RSS: add_to_rss_reader(url); break; case Reader.GOOGLE: add_to_google(url); break; case Reader.GPODDER: try { GLib.Process.spawn_async(null, {"gpodder", "--fremantle", "-s", url}, null, GLib.SpawnFlags.SEARCH_PATH, null, null); } catch (GLib.SpawnError e) { stderr.printf("Can't launch: %s\n", e.message); } break; case Reader.FEEDINGIT: add_to_feedingit(url); break; } message("URL received: %s", url); loop.quit(); } private void add_to_google(string url) { open_browser("http://fusion.google.com/add?feedurl=" + Uri.escape_string(url, "", false)); } private void add_to_rss_reader(string url) { dynamic DBus.Object obj = conn.get_object( "com.nokia.osso_rss_feed_reader_refresh", "/com/nokia/osso_rss_feed_reader_refresh", "com.nokia.osso_rss_feed_reader_refresh"); obj.mime_open(url); } private void add_to_feedingit(string url) { dynamic DBus.Object obj = conn.get_object( "org.maemo.feedingit", "/org/maemo/feedingit", "org.maemo.feedingit"); obj.AddFeed(url); } private void open_browser(string url) { context.rpc_run_with_defaults("osso_browser", "open_new_window", null, (int)'s', url, (int)'\0'); /* DBUS_TYPE_STRING is (int)'s' */ /* DBUS_TYPE_INVALID is (int)'\0' */ } public void set_args_url(string url) { args_url = url; } public bool open_url_later() { mime_open(args_url); return false; } } static int main(string [] args) { MainLoop loop = new MainLoop(null, false); Gtk.init(ref args); if (args.length != 1 && args.length != 2) { stderr.printf("Usage: %s [URL]\n", args[0]); return 1; } try { DBus.Connection conn = DBus.Bus.get(DBus.BusType.SESSION); dynamic DBus.Object bus = conn.get_object("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus"); uint request_name_result = bus.RequestName( "org.maemo.garage.feedhandler", (uint)0); if (request_name_result == DBus.RequestNameReply.PRIMARY_OWNER) { FeedHandler server = new FeedHandler(loop, conn); conn.register_object("/org/maemo/garage/feedhandler", server); if (args.length == 2) { /* Add URL when the main loop is running */ server.set_args_url(args[1]); Idle.add(server.open_url_later); } loop.run(); } else { stderr.printf("feedhandler is already running.\n"); } } catch (Error e) { stderr.printf("OOps: %s\n", e.message); } return 0; }