~ubuntu-branches/ubuntu/vivid/liferea/vivid-proposed

« back to all changes in this revision

Viewing changes to src/main.c

  • Committer: Package Import Robot
  • Author(s): bojo42
  • Date: 2012-03-29 14:17:21 UTC
  • mfrom: (1.3.9) (3.2.5 sid)
  • Revision ID: package-import@ubuntu.com-20120329141721-tbfopcrc5797wxt7
Tags: 1.8.3-0.1ubuntu1
* New upstream release (LP: #290666, #371754, #741543, #716688)
* Merge from Debian unstable (LP: #935147), remaining changes:
* debian/patches:
  - drop gtk-status-icon.patch & notification-append as in upstream
  - drop fix_systray_behavior as mostly upstreamed and rest seems unused
  - 01_ubuntu_feedlists: update & rename, move planets to "Open Source"  
  - add_X-Ubuntu-Gettext-Domain: rebase
  - libunity.patch: rebase, apply before indicator patch (liferea_shell.c)
  - libindicate_increase_version.patch: exclude from libindicate.patch
  - deactivate libindicate.patch, seems partly upstreamed and needs rework
* debian/control: libindicate-dev, libindicate-gtk-dev & libunity-dev
* debian/liferea.indicate & liferea.install: ship indicator desktop file
* debian/rules: enable libindicate

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/**
2
2
 * @file main.c Liferea main program
3
3
 *
4
 
 * Copyright (C) 2003-2008 Lars Lindner <lars.lindner@gmail.com>
 
4
 * Copyright (C) 2003-2012 Lars Lindner <lars.lindner@gmail.com>
5
5
 * Copyright (C) 2004-2006 Nathan J. Conrad <t98502@users.sourceforge.net>
6
6
 *  
7
7
 * Some code like the command line handling was inspired by 
29
29
#endif
30
30
 
31
31
#include <gtk/gtk.h>
32
 
#include <locale.h> /* For setlocale */
 
32
#include <unique/unique.h>
33
33
 
34
34
#include <string.h>
35
35
#include <stdlib.h>
41
41
#include "db.h"
42
42
#include "dbus.h"
43
43
#include "debug.h"
44
 
#include "plugin.h"
45
 
#include "script.h"
 
44
#include "feedlist.h"
46
45
#include "social.h"
47
46
#include "update.h"
48
 
#include "vfolder.h"            // FIXME: should not be necessary
49
47
#include "xml.h"
50
 
#include "ui/ui_feedlist.h"     // FIXME: should not be necessary
51
48
#include "ui/ui_session.h"
52
49
#include "ui/liferea_shell.h"
53
 
#include "sync/avahi_publisher.h"
54
 
 
55
 
#include "bacon-message-connection.h"
56
 
 
57
 
static BaconMessageConnection *bacon_connection = NULL;
 
50
#include "notification/notification.h"
58
51
 
59
52
static enum {
60
53
        STATE_STARTING,
62
55
        STATE_SHUTDOWN
63
56
} runState = STATE_STARTING;
64
57
 
65
 
gboolean on_quit(GtkWidget *widget, GdkEvent *event, gpointer user_data);
66
 
 
67
 
 
68
 
/** bacon message callback */
69
 
static void
70
 
on_bacon_message_received (const char *message, gpointer data)
 
58
enum {
 
59
        COMMAND_0 = 0, /* 0 is not a valid command */
 
60
        COMMAND_ADD_FEED
 
61
};
 
62
 
 
63
static UniqueResponse
 
64
message_received_cb (UniqueApp         *app,
 
65
                     UniqueCommand      command,
 
66
                     UniqueMessageData *message,
 
67
                     guint              time_,
 
68
                     gpointer           user_data)
71
69
{
72
 
        debug1(DEBUG_GUI, "bacon message received >>>%s<<<", message);
73
 
        
74
 
        /* Currently we only know a single simple command "raise"
75
 
           which tells the program to raise the window because
76
 
           another instance was requested which is not supported */
77
 
           
78
 
        if (g_str_equal (message, "raise")) {
79
 
                debug0 (DEBUG_GUI, "-> raise window requested");
80
 
                liferea_shell_present ();
81
 
        } else {
82
 
                g_warning ("Received unknown bacon command: >>>%s<<<", message);
 
70
        UniqueResponse res;
 
71
        gchar *feed;
 
72
 
 
73
        debug1(DEBUG_GUI, "libunique command received >>>%d<<<", command);
 
74
 
 
75
        switch (command)
 
76
        {
 
77
                case UNIQUE_ACTIVATE:
 
78
                        /* Raise the liferea window */
 
79
                        debug0 (DEBUG_GUI, "-> raise window requested");
 
80
                        liferea_shell_present ();
 
81
                        res = UNIQUE_RESPONSE_OK;
 
82
                        break;
 
83
                case COMMAND_ADD_FEED:
 
84
                        feed = unique_message_data_get_text (message);
 
85
                        feedlist_add_subscription (feed, NULL, NULL, 0);
 
86
 
 
87
                        res = UNIQUE_RESPONSE_OK;
 
88
                        break;
 
89
                default:
 
90
                        g_warning ("Received unknown libunique command: >>>%d<<<", command);
 
91
                        res = UNIQUE_RESPONSE_OK;
 
92
                        break;
83
93
        }
 
94
 
 
95
        return res;
84
96
}
85
97
 
86
 
static void fatal_signal_handler(int sig) {
 
98
static void G_GNUC_NORETURN
 
99
fatal_signal_handler (int sig)
 
100
{
87
101
        sigset_t sigset;
88
102
 
89
 
        sigemptyset(&sigset);
90
 
        sigprocmask(SIG_SETMASK, &sigset, NULL);
91
 
 
92
 
        g_print("\nLiferea did receive signal %d (%s).\n", sig, g_strsignal(sig));
93
 
 
94
 
        if(debug_level) {
95
 
                g_print("You have probably triggered a program bug. I will now try to \n");
96
 
                g_print("create a backtrace which you can attach to any support requests.\n\n");
97
 
                g_on_error_stack_trace(PACKAGE);
98
 
        }
99
 
 
100
 
        _exit(1);
 
103
        sigemptyset (&sigset);
 
104
        sigprocmask (SIG_SETMASK, &sigset, NULL);
 
105
 
 
106
        g_print ("\nLiferea did receive signal %d (%s).\n", sig, g_strsignal (sig));
 
107
 
 
108
        g_print ("You have probably triggered a program bug. I will now try to \n");
 
109
        g_print ("create a backtrace which you can attach to any support requests.\n\n");
 
110
        g_on_error_stack_trace (PACKAGE);
 
111
 
 
112
        _exit (1);
101
113
}
102
114
 
103
115
static void
132
144
                *debug_flags |= DEBUG_PARSING;
133
145
        } else if (g_str_equal (option_name, "--debug-performance")) {
134
146
                *debug_flags |= DEBUG_PERF;
135
 
        } else if (g_str_equal (option_name, "--debug-plugins")) {
136
 
                *debug_flags |= DEBUG_PLUGINS;
137
147
        } else if (g_str_equal (option_name, "--debug-trace")) {
138
148
                *debug_flags |= DEBUG_TRACE;
139
149
        } else if (g_str_equal (option_name, "--debug-update")) {
140
150
                *debug_flags |= DEBUG_UPDATE;
 
151
        } else if (g_str_equal (option_name, "--debug-vfolder")) {
 
152
                *debug_flags |= DEBUG_VFOLDER;
141
153
        } else if (g_str_equal (option_name, "--debug-verbose")) {
142
154
                *debug_flags |= DEBUG_VERBOSE;
143
155
        } else {
147
159
        return TRUE;
148
160
}
149
161
 
150
 
static gboolean
 
162
static gboolean G_GNUC_NORETURN
151
163
show_version (const gchar *option_name,
152
164
              const gchar *value,
153
165
              gpointer data,
160
172
int
161
173
main (int argc, char *argv[])
162
174
{
 
175
        UniqueApp       *app;
 
176
        UniqueMessageData       *msg;
163
177
        GError          *error = NULL;
164
178
        GOptionContext  *context;
165
179
        GOptionGroup    *debug;
166
180
        gulong          debug_flags = 0;
167
181
        LifereaDBus     *dbus = NULL;
168
 
        gchar           *initial_state = "shown";
 
182
        const gchar     *initial_state = "shown";
 
183
        gchar           *feed = NULL;
169
184
        int             initialState;
 
185
        gboolean        show_tray_icon, start_in_tray;
170
186
 
171
187
#ifdef USE_SM
172
188
        gchar *opt_session_arg = NULL;
178
194
                { "session", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &opt_session_arg, NULL, NULL },
179
195
#endif
180
196
                { "version", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version, N_("Show version information and exit"), NULL },
 
197
                { "add-feed", 'a', 0, G_OPTION_ARG_STRING, &feed, N_("Add a new subscription"), N_("uri") },
181
198
                { NULL }
182
199
        };
183
200
 
184
201
        GOptionEntry debug_entries[] = {
185
202
                { "debug-all", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages of all types"), NULL },
186
203
                { "debug-cache", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages for the cache handling"), NULL },
187
 
                { "debug-conf", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages of the configuration handling"), NULL },
 
204
                { "debug-conf", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages for the configuration handling"), NULL },
188
205
                { "debug-db", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages of the database handling"), NULL },
189
206
                { "debug-gui", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages of all GUI functions"), NULL },
190
 
                { "debug-html", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Enables HTML rendering debugging. Each time Liferea renders HTML output it will also dump the generated HTML into ~/.liferea_1.6/output.xhtml"), NULL },
 
207
                { "debug-html", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Enables HTML rendering debugging. Each time Liferea renders HTML output it will also dump the generated HTML into ~/.liferea_1.8/output.xhtml"), NULL },
191
208
                { "debug-net", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages of all network activity"), NULL },
192
209
                { "debug-parsing", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages of all parsing functions"), NULL },
193
210
                { "debug-performance", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages when a function takes too long to process"), NULL },
194
 
                { "debug-plugins", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages for the plugin loading"), NULL },
195
211
                { "debug-trace", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages when entering/leaving functions"), NULL },
196
212
                { "debug-update", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages of the feed update processing"), NULL },
 
213
                { "debug-vfolder", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages of the search folder matching"), NULL },
197
214
                { "debug-verbose", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print verbose debugging messages"), NULL },
198
215
                { NULL }
199
216
        };
207
224
#endif
208
225
 
209
226
        debug = g_option_group_new ("debug",
210
 
                                    N_("Print debugging messages for the given topic"),
211
 
                                    N_("Print debugging messages for the given topic"),
 
227
                                    _("Print debugging messages for the given topic"),
 
228
                                    _("Print debugging messages for the given topic"),
212
229
                                    &debug_flags,
213
230
                                    NULL);
214
 
        g_option_group_set_translation_domain (debug, GETTEXT_PACKAGE);
 
231
        g_option_group_set_translation_domain(debug, GETTEXT_PACKAGE);
215
232
        g_option_group_add_entries (debug, debug_entries);
216
233
 
217
234
        context = g_option_context_new (NULL);
234
251
           has to be initialized before update_init() */
235
252
        conf_init ();
236
253
 
237
 
#ifdef USE_DBUS
238
 
        dbus_g_thread_init ();
239
 
#endif
240
 
 
241
254
        /* We need to do the network initialization here to allow
242
255
           network-manager to be setup before gtk_init() */
243
256
        update_init ();
244
257
 
245
258
        gtk_init (&argc, &argv);
246
259
 
 
260
        /* Single instance checks */
 
261
        app = unique_app_new_with_commands ("net.sourceforge.liferea", NULL,
 
262
                                            "add_feed", COMMAND_ADD_FEED,
 
263
                                            NULL);
 
264
        if (unique_app_is_running (app)) {
 
265
                g_print ("Liferea is already running\n");
 
266
                unique_app_send_message (app, UNIQUE_ACTIVATE, NULL);
 
267
                if (feed) {
 
268
                        msg = unique_message_data_new ();
 
269
                        unique_message_data_set_text (msg, feed, -1);
 
270
                        unique_app_send_message (app, COMMAND_ADD_FEED, msg);
 
271
                }
 
272
                return 1;
 
273
        } else {
 
274
                g_signal_connect (app, "message-received", G_CALLBACK (message_received_cb), NULL);
 
275
        }
 
276
 
247
277
        /* GTK theme support */
248
278
        g_set_application_name (_("Liferea"));
249
279
        gtk_window_set_default_icon_name ("liferea");
250
280
 
251
 
        /* Note: bacon connection check needs to be done after the
252
 
           command line parameter checking to allow help and version
253
 
           switches to be used when we are already running */
254
 
        bacon_connection = bacon_message_connection_new ("liferea");
255
 
        if (bacon_connection)   {
256
 
                if (!bacon_message_connection_get_is_server (bacon_connection)) {
257
 
                        g_warning(_("Liferea seems to be running already!"));
258
 
                        
259
 
                        debug0(DEBUG_VERBOSE, "Startup as bacon client...");
260
 
                        bacon_message_connection_send (bacon_connection, "raise");
261
 
                        bacon_message_connection_free (bacon_connection);
262
 
                        
263
 
                        gdk_notify_startup_complete ();
264
 
                        exit (0);
265
 
                } else {
266
 
                        debug0 (DEBUG_VERBOSE, "Startup as bacon server...");
267
 
                        bacon_message_connection_set_callback (bacon_connection,
268
 
                                                               on_bacon_message_received,
269
 
                                                               NULL);
270
 
                }
271
 
        } else {
272
 
                g_warning ("Cannot create IPC connection for Liferea!");
273
 
        }
274
 
        
275
281
        debug_start_measurement (DEBUG_DB);
276
282
 
277
283
        /* order is important! */
278
284
        db_init ();                     /* initialize sqlite */
279
285
        xml_init ();                    /* initialize libxml2 */
280
 
        plugin_mgmt_init ();            /* get list of plugins and initialize them */
281
 
        conf_load ();                   /* load global feed settings */
282
 
        script_init ();                 /* setup scripting if supported */
283
 
        social_init ();                 /* initialized social bookmarking */
284
 
#ifdef USE_DBUS 
285
 
        dbus = liferea_dbus_new ();     
286
 
#else
287
 
        debug0 (DEBUG_GUI, "Compiled without DBUS support.");
288
 
#endif
289
 
 
290
 
#ifdef USE_AVAHI
291
 
        if (conf_get_bool_value (SYNC_AVAHI_ENABLED)) {
292
 
                LifereaAvahiPublisher   *avahiPublisher = NULL;
293
 
 
294
 
                debug0 (DEBUG_CACHE, "Registering with AVAHI");
295
 
                avahiPublisher = liferea_avahi_publisher_new ();
296
 
                liferea_avahi_publisher_publish (avahiPublisher, conf_get_str_value (SYNC_AVAHI_SERVICE_NAME), 23632);
297
 
        } else {
298
 
                debug0 (DEBUG_CACHE, "Avahi support available, but disabled by preferences.");
299
 
        }
300
 
#else
301
 
        debug0 (DEBUG_CACHE, "Compiled without AVAHI support");
302
 
#endif
 
286
#ifdef HAVE_LIBNOTIFY
 
287
        notification_plugin_register (&libnotify_plugin);
 
288
#endif
 
289
        social_init ();                 /* initialize social bookmarking */
 
290
 
 
291
        dbus = liferea_dbus_new ();
303
292
 
304
293
        /* how to start liferea, command line takes precedence over preferences */
 
294
        conf_get_bool_value (SHOW_TRAY_ICON, &show_tray_icon);
 
295
        conf_get_bool_value (START_IN_TRAY, &start_in_tray);
305
296
        if (g_str_equal(initial_state, "iconified")) {
306
297
                initialState = MAINWINDOW_ICONIFIED;
307
298
        } else if (g_str_equal(initial_state, "hidden") ||
308
 
            (conf_get_bool_value (SHOW_TRAY_ICON) &&
309
 
             conf_get_bool_value (START_IN_TRAY))) {
 
299
            (show_tray_icon && start_in_tray)) {
310
300
                initialState = MAINWINDOW_HIDDEN;
311
301
        } else {
312
302
                initialState = MAINWINDOW_SHOWN;
315
305
        liferea_shell_create (initialState);
316
306
        g_set_prgname ("liferea");
317
307
        
318
 
        script_run_for_hook (SCRIPT_HOOK_STARTUP);
319
 
        
320
308
#ifdef USE_SM
321
309
        /* This must be after feedlist reading because some session
322
310
           managers will tell Liferea to exit if Liferea does not
341
329
        runState = STATE_STARTING;
342
330
        
343
331
        debug_end_measurement (DEBUG_DB, "startup");
344
 
        
 
332
 
 
333
        if (feed)
 
334
                feedlist_add_subscription (feed, NULL, NULL, 0);
 
335
 
345
336
        gtk_main ();
346
337
        
347
338
        g_object_unref (G_OBJECT (dbus));
348
 
        bacon_message_connection_free (bacon_connection);
349
339
        return 0;
350
340
}
351
341
 
361
351
        runState = STATE_SHUTDOWN;
362
352
 
363
353
        /* order is important ! */
364
 
                
365
 
        script_run_for_hook (SCRIPT_HOOK_SHUTDOWN);
366
 
        
367
 
        itemlist_free ();
368
354
        update_deinit ();
369
355
        db_deinit ();
370
 
        script_deinit ();
371
356
        social_free ();
372
357
 
373
358
        liferea_shell_destroy ();