Fix bugtracker field and URL
[feedhandler] / feedhandler.vala
1 /**
2  * Feed Handler
3  * Copyright © 2009 Thomas Perl <thp@thpinfo.com>
4  **/
5
6 using Gtk;
7 using GLib;
8 using Osso;
9 using Pango;
10
11 public enum Reader {
12     RSS = 1,
13     GOOGLE,
14     GPODDER,
15 }
16
17 public class DesktopFile : GLib.KeyFile {
18     public DesktopFile(string basename) {
19         string filename = "/usr/share/applications/" + basename.replace("hildon-", "hildon/");
20         try {
21             load_from_file(filename, KeyFileFlags.NONE);
22         } catch (KeyFileError e) {
23             stderr.printf("Cannot open key file: %s\n", e.message);
24         } catch (FileError e) {
25             stderr.printf("Cannot open key file: %s\n", e.message);
26         }
27     }
28
29     public string? get_name() {
30         try {
31             return get_string("Desktop Entry", "Name");
32         } catch (KeyFileError e) {
33             stderr.printf("Cannot read exec key: %s\n", e.message);
34         }
35         return null;
36     }
37
38     public string? get_executable() {
39         try {
40             return get_string("Desktop Entry", "Exec");
41         } catch (KeyFileError e) {
42             stderr.printf("Cannot read exec key: %s\n", e.message);
43         }
44         return null;
45     }
46 }
47
48 public class MimeCache : GLib.KeyFile {
49     public MimeCache(string filename="/usr/share/applications/mimeinfo.cache") {
50         try {
51             load_from_file(filename, KeyFileFlags.NONE);
52         } catch (KeyFileError e) {
53             stderr.printf("Cannot open key file: %s\n", e.message);
54         } catch (FileError e) {
55             stderr.printf("Cannot open key file: %s\n", e.message);
56         }
57     }
58
59     public string [] get_desktop_files(string mimetype="application/news_reader") {
60         try {
61             return get_string("MIME Cache", mimetype).split(";");
62         } catch (KeyFileError e) {
63             stderr.printf("Cannot get desktop files for %s\n", mimetype);
64             return new string [0];
65         }
66     }
67 }
68
69 [DBus (name="org.maemo.garage.feedhandler")]
70 public class FeedHandler : GLib.Object {
71     private MainLoop loop;
72     private DBus.Connection conn;
73     private Osso.Context context;
74     private string args_url;
75     private MimeCache mime_cache;
76
77     public FeedHandler(MainLoop loop, DBus.Connection conn) {
78         this.loop = loop;
79         this.conn = conn;
80         this.context = new Osso.Context("feedhandler", "2.0", false, null);
81         this.args_url = null;
82         this.mime_cache = new MimeCache();
83
84         foreach (string file in mime_cache.get_desktop_files("application/rss+xml")) {
85             if (file != "") {
86                 var desktop_file = new DesktopFile(file);
87                 var name = desktop_file.get_name();
88                 var exec = desktop_file.get_executable();
89                 if (name != null && exec != null) {
90                     stderr.printf("File in Mime CACHE: %s (%s)\n", name, exec);
91                     /* XXX: Add "Name" as option and on select, start exec + URL */
92                 }
93             }
94         }
95     }
96
97     [DBus (name = "mime_open")]
98     public void mime_open(string url) {
99         int result;
100
101         Gtk.Dialog dlg = new Gtk.Dialog();
102         dlg.add_button("RSS Reader", Reader.RSS);
103         dlg.add_button("Google Reader", Reader.GOOGLE);
104         if (FileUtils.test("/usr/bin/gpodder", FileTest.EXISTS)) {
105             dlg.add_button("gPodder", Reader.GPODDER);
106         }
107         dlg.add_button("Cancel", Gtk.ResponseType.CLOSE);
108         dlg.title = "Select application for handling this feed";
109         var label = new Gtk.Label(url);
110         label.ellipsize = Pango.EllipsizeMode.END;
111         dlg.vbox.add(label);
112         dlg.show_all();
113         result = dlg.run();
114         dlg.destroy();
115
116         switch (result) {
117             case Reader.RSS:
118                 add_to_rss_reader(url);
119                 break;
120             case Reader.GOOGLE:
121                 add_to_google(url);
122                 break;
123             case Reader.GPODDER:
124                 try {
125                     GLib.Process.spawn_async(null,
126                         {"gpodder",
127                         "--fremantle",
128                         "-s",
129                         url}, null, GLib.SpawnFlags.SEARCH_PATH, null, null);
130                 } catch (GLib.SpawnError e) {
131                     stderr.printf("Can't launch: %s\n", e.message);
132                 }
133                 break;
134         }
135
136         message("URL received: %s", url);
137         loop.quit();
138     }
139
140     private void add_to_google(string url)
141     {
142         open_browser("http://fusion.google.com/add?feedurl=" +
143             Uri.escape_string(url, "", false));
144     }
145
146     private void add_to_rss_reader(string url)
147     {
148         dynamic DBus.Object obj = conn.get_object(
149             "com.nokia.osso_rss_feed_reader_refresh",
150             "/com/nokia/osso_rss_feed_reader_refresh",
151             "com.nokia.osso_rss_feed_reader_refresh");
152         obj.mime_open(url);
153     }
154
155     private void open_browser(string url)
156     {
157         context.rpc_run_with_defaults("osso_browser",
158                                       "open_new_window",
159                                       null,
160                                       (int)'s', url,
161                                       (int)'\0');
162         /* DBUS_TYPE_STRING is (int)'s' */
163         /* DBUS_TYPE_INVALID is (int)'\0' */
164     }
165
166     public void set_args_url(string url)
167     {
168         args_url = url;
169     }
170
171     public bool open_url_later()
172     {
173         mime_open(args_url);
174         return false;
175     }
176 }
177
178 static int main(string [] args) {
179     MainLoop loop = new MainLoop(null, false);
180     Gtk.init(ref args);
181     if (args.length != 1 && args.length != 2) {
182         stderr.printf("Usage: %s [URL]\n", args[0]);
183         return 1;
184     }
185     try {
186         DBus.Connection conn = DBus.Bus.get(DBus.BusType.SESSION);
187         dynamic DBus.Object bus = conn.get_object("org.freedesktop.DBus",
188                                                   "/org/freedesktop/DBus",
189                                                   "org.freedesktop.DBus");
190         uint request_name_result = bus.RequestName(
191                                  "org.maemo.garage.feedhandler", (uint)0);
192         if (request_name_result == DBus.RequestNameReply.PRIMARY_OWNER) {
193             FeedHandler server = new FeedHandler(loop, conn);
194             conn.register_object("/org/maemo/garage/feedhandler", server);
195             if (args.length == 2) {
196                 /* Add URL when the main loop is running */
197                 server.set_args_url(args[1]);
198                 Idle.add(server.open_url_later);
199             }
200             loop.run();
201         } else {
202             stderr.printf("feedhandler is already running.\n");
203         }
204     }
205     catch (Error e) {
206         stderr.printf("OOps: %s\n", e.message);
207     }
208     return 0;
209 }
210