Add single-instance detection
[tilda-gobject.git] / tilda.c
1 #include <glib.h>
2 #include <stdlib.h>
3
4 #include "tilda.h"
5 #include "tilda-window.h"
6 #include "tilda-terminal.h"
7 #include "tomboykeybinder.h"
8
9 DBusGConnection *dbus_connection;
10 GPtrArray *windows;
11
12 static void
13 tilda_initialize_dbus ()
14 {
15         debug_enter  ();
16
17         static const gchar service_name[] = "net.sourceforge.Tilda";
18         GError *error = NULL;
19         DBusGProxy *driver_proxy;
20         guint request_ret;
21         gboolean ret;
22
23         // Initialize the DBus connection
24         dbus_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
25         if (dbus_connection == NULL)
26         {
27                 g_warning (_("Unable to connect to DBus: %s\n"), error->message);
28                 g_error_free (error);
29                 return;
30         }
31
32         // Register the service name
33         driver_proxy = dbus_g_proxy_new_for_name (dbus_connection,
34                                                                                           DBUS_SERVICE_DBUS,
35                                                                                           DBUS_PATH_DBUS,
36                                                                                           DBUS_INTERFACE_DBUS);
37
38         ret = org_freedesktop_DBus_request_name (driver_proxy,
39                                                                                          service_name,
40                                                                                          DBUS_NAME_FLAG_DO_NOT_QUEUE,
41                                                                                          &request_ret,
42                                                                                          &error);
43
44         if (!ret)
45         {
46                 g_warning (_("Unable to communicate with DBus: %s\n"), error->message);
47                 g_error_free (error);
48         }
49
50         if (request_ret == DBUS_REQUEST_NAME_REPLY_EXISTS)
51         {
52                 g_critical (_("There is already an instance of Tilda running\n"));
53                 exit (EXIT_FAILURE);
54         }
55
56         g_object_unref (driver_proxy);
57 }
58
59 static gint
60 tilda_find_next_free_window_number ()
61 {
62         debug_enter  ();
63
64         gint i, j;
65         gboolean found;
66
67         for (i=0; i<INT_MAX; ++i)
68         {
69                 found = FALSE;
70
71                 for (j=0; j<windows->len; ++j)
72                 {
73                         TildaWindow *tw = g_ptr_array_index (windows, j);
74
75                         if (tw->number == i)
76                         {
77                                 found = TRUE;
78                                 break;
79                         }
80                 }
81
82                 if (!found)
83                         return i;
84         }
85
86         return 0;
87 }
88
89 static TildaWindow *
90 tilda_add_window ()
91 {
92         debug_enter ();
93
94         TildaWindow *ret;
95         gint number;
96
97         number = tilda_find_next_free_window_number ();
98         ret = g_object_new (TILDA_TYPE_WINDOW, "number", number, NULL);
99
100         g_ptr_array_add (windows, ret);
101
102         debug_printf ("Adding window: 0x%x (number %d of %d)\n", ret, ret->number, windows->len-1);
103         return ret;
104 }
105
106 static void
107 tilda_del_window (gint number)
108 {
109         debug_enter ();
110
111         gint i;
112         TildaWindow *win;
113
114         for (i=0; i<windows->len; ++i)
115         {
116                 win = g_ptr_array_index (windows, i);
117
118                 if (win->number == number)
119                 {
120                         debug_printf ("Deleting window 0x%x (number %d of %d)\n", win, win->number, windows->len-1);
121                         g_ptr_array_remove_index (windows, i);
122                         g_object_unref (G_OBJECT(win));
123                         break;
124                 }
125         }
126 }
127
128 static void
129 tilda_parse_command_line (gint argc, gchar *argv[])
130 {
131         debug_enter ();
132
133         gboolean version = FALSE;
134
135         /* All of the various command-line options */
136         const GOptionEntry cl_opts[] = {
137                 { "version",                    'V', 0, G_OPTION_ARG_NONE,              &version,                       N_("Show version information"), NULL },
138                 { NULL },
139         };
140
141         /* Set up the command-line parser */
142         GError *error = NULL;
143         GOptionContext *context = g_option_context_new (NULL);
144         g_option_context_add_main_entries (context, cl_opts, NULL);
145         g_option_context_add_group (context, gtk_get_option_group (TRUE));
146         g_option_context_parse (context, &argc, &argv, &error);
147         g_option_context_free (context);
148
149         /* Check for unknown options, and give a nice message if there are some */
150         if (error)
151         {
152                 g_printerr (_("Error parsing command-line options: %s\n"), error->message);
153                 g_printerr (_("The command \"tilda --help\" will show all possible options\n"));
154                 g_error_free (error);
155                 exit (EXIT_FAILURE);
156         }
157
158         /* If we need to show the version, show it then exit normally */
159         if (version)
160         {
161                 g_print ("%s\n\n", TILDA_VERSION);
162
163                 g_print ("Copyright (c) 2005-2008 Tristan Sloughter (sloutri@iit.edu)\n");
164                 g_print ("Copyright (c) 2005-2008 Ira W. Snyder (tilda@irasnyder.com)\n\n");
165
166                 g_print ("This program comes with ABSOLUTELY NO WARRANTY.\n");
167                 g_print ("This is free software, and you are welcome to redistribute it\n");
168                 g_print ("under certain conditions. See the file COPYING for details.\n");
169
170                 exit (EXIT_SUCCESS);
171         }
172 }
173
174 int main (int argc, char *argv[])
175 {
176         debug_enter ();
177
178         TildaWindow *tw;
179
180 #if ENABLE_NLS
181         /* Gettext Initialization */
182         setlocale (LC_ALL, "");
183         bindtextdomain (PACKAGE, LOCALEDIR);
184         textdomain (PACKAGE);
185 #endif
186
187         /* Parse the command-line options */
188         tilda_parse_command_line (argc, argv);
189
190         /* Initialize GTK+ (and the GObject system) */
191         gtk_init (&argc, &argv);
192
193         /* Initialize the keybinder */
194         tomboy_keybinder_init ();
195
196         /* Start our connection to DBus */
197         tilda_initialize_dbus ();
198
199         /* Initialize the array of windows */
200         windows = g_ptr_array_new ();
201
202         /* Create a TildaWindow, run it, and exit when it does, basically.
203          *
204          * This is nothing like what the real main() will be, but it's
205          * a good start for testing and integration of more of TildaWindow
206          * and TildaTerminal. */
207         tw = tilda_add_window ();
208
209         debug_printf ("Starting gtk_main()!\n");
210         gtk_main ();
211         debug_printf ("Out of gtk_main(), going down\n");
212
213         return 0;
214 }
215
216 /* vim: set ts=4 sts=4 sw=4 noet tw=112: */