Fix warnings
[platform/upstream/glib.git] / gio / gunionvolumemonitor.c
1 /* GIO - GLib Input, Output and Streaming Library
2  * 
3  * Copyright (C) 2006-2007 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  */
22
23 #include <config.h>
24
25 #include <string.h>
26
27 #include <glib.h>
28 #include "gunionvolumemonitor.h"
29 #include "gvolumeprivate.h"
30 #include "giomodule.h"
31 #ifdef G_OS_UNIX
32 #include "gunixvolumemonitor.h"
33 #endif
34 #include "gnativevolumemonitor.h"
35
36 #include "glibintl.h"
37
38 #include "gioalias.h"
39
40 struct _GUnionVolumeMonitor {
41   GVolumeMonitor parent;
42
43   GList *monitors;
44 };
45
46 static void g_union_volume_monitor_remove_monitor (GUnionVolumeMonitor *union_monitor,
47                                                    GVolumeMonitor *child_monitor);
48
49
50 #define g_union_volume_monitor_get_type _g_union_volume_monitor_get_type
51 G_DEFINE_TYPE (GUnionVolumeMonitor, g_union_volume_monitor, G_TYPE_VOLUME_MONITOR);
52
53
54 G_LOCK_DEFINE_STATIC(the_volume_monitor);
55 static GUnionVolumeMonitor *the_volume_monitor = NULL;
56
57 static void
58 g_union_volume_monitor_finalize (GObject *object)
59 {
60   GUnionVolumeMonitor *monitor;
61   
62   monitor = G_UNION_VOLUME_MONITOR (object);
63
64   while (monitor->monitors != NULL)
65     g_union_volume_monitor_remove_monitor (monitor,
66                                            monitor->monitors->data);
67   
68   if (G_OBJECT_CLASS (g_union_volume_monitor_parent_class)->finalize)
69     (*G_OBJECT_CLASS (g_union_volume_monitor_parent_class)->finalize) (object);
70 }
71
72 static void
73 g_union_volume_monitor_dispose (GObject *object)
74 {
75   GUnionVolumeMonitor *monitor;
76   
77   monitor = G_UNION_VOLUME_MONITOR (object);
78
79   G_LOCK (the_volume_monitor);
80   the_volume_monitor = NULL;
81   G_UNLOCK (the_volume_monitor);
82   
83   if (G_OBJECT_CLASS (g_union_volume_monitor_parent_class)->dispose)
84     (*G_OBJECT_CLASS (g_union_volume_monitor_parent_class)->dispose) (object);
85 }
86
87 static GList *
88 get_mounted_volumes (GVolumeMonitor *volume_monitor)
89 {
90   GUnionVolumeMonitor *monitor;
91   GVolumeMonitor *child_monitor;
92   GList *res;
93   GList *l;
94   
95   monitor = G_UNION_VOLUME_MONITOR (volume_monitor);
96
97   res = NULL;
98   
99   G_LOCK (the_volume_monitor);
100
101   for (l = monitor->monitors; l != NULL; l = l->next)
102     {
103       child_monitor = l->data;
104
105       res = g_list_concat (res,
106                            g_volume_monitor_get_mounted_volumes (child_monitor));
107     }
108   
109   G_UNLOCK (the_volume_monitor);
110
111   return res;
112 }
113
114 static GList *
115 get_connected_drives (GVolumeMonitor *volume_monitor)
116 {
117   GUnionVolumeMonitor *monitor;
118   GVolumeMonitor *child_monitor;
119   GList *res;
120   GList *l;
121   
122   monitor = G_UNION_VOLUME_MONITOR (volume_monitor);
123
124   res = NULL;
125   
126   G_LOCK (the_volume_monitor);
127
128   for (l = monitor->monitors; l != NULL; l = l->next)
129     {
130       child_monitor = l->data;
131
132       res = g_list_concat (res,
133                            g_volume_monitor_get_connected_drives (child_monitor));
134     }
135   
136   G_UNLOCK (the_volume_monitor);
137
138   return res;
139 }
140
141 static void
142 g_union_volume_monitor_class_init (GUnionVolumeMonitorClass *klass)
143 {
144   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
145   GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass);
146   
147   gobject_class->finalize = g_union_volume_monitor_finalize;
148   gobject_class->dispose = g_union_volume_monitor_dispose;
149
150   monitor_class->get_mounted_volumes = get_mounted_volumes;
151   monitor_class->get_connected_drives = get_connected_drives;
152 }
153
154 static void
155 child_volume_mounted (GVolumeMonitor      *child_monitor,
156                       GVolume             *child_volume,
157                       GUnionVolumeMonitor *union_monitor)
158 {
159   g_signal_emit_by_name (union_monitor,
160                          "volume_mounted",
161                          child_volume);
162 }
163
164 static void
165 child_volume_pre_unmount (GVolumeMonitor      *child_monitor,
166                           GVolume             *child_volume,
167                           GUnionVolumeMonitor *union_monitor)
168 {
169   g_signal_emit_by_name (union_monitor,
170                          "volume_pre_unmount",
171                          child_volume);
172 }
173
174 static void
175 child_volume_unmounted (GVolumeMonitor      *child_monitor,
176                         GVolume             *child_volume,
177                         GUnionVolumeMonitor *union_monitor)
178 {
179   g_signal_emit_by_name (union_monitor,
180                          "volume_unmounted",
181                          child_volume);
182 }
183
184 static void
185 child_drive_connected (GVolumeMonitor      *child_monitor,
186                        GDrive              *child_drive,
187                        GUnionVolumeMonitor *union_monitor)
188 {
189   g_signal_emit_by_name (union_monitor,
190                          "drive_connected",
191                          child_drive);
192 }
193
194 static void
195 child_drive_disconnected (GVolumeMonitor      *child_monitor,
196                           GDrive              *child_drive,
197                           GUnionVolumeMonitor *union_monitor)
198 {
199   g_signal_emit_by_name (union_monitor,
200                          "drive_disconnected",
201                          child_drive);
202 }
203
204 static void
205 g_union_volume_monitor_add_monitor (GUnionVolumeMonitor *union_monitor,
206                                     GVolumeMonitor      *volume_monitor)
207 {
208   if (g_list_find (union_monitor->monitors, volume_monitor))
209     return;
210
211   union_monitor->monitors =
212     g_list_prepend (union_monitor->monitors,
213                     g_object_ref (volume_monitor));
214
215   g_signal_connect (volume_monitor, "volume_mounted", (GCallback)child_volume_mounted, union_monitor);
216   g_signal_connect (volume_monitor, "volume_pre_unmount", (GCallback)child_volume_pre_unmount, union_monitor);
217   g_signal_connect (volume_monitor, "volume_unmounted", (GCallback)child_volume_unmounted, union_monitor);
218   g_signal_connect (volume_monitor, "drive_connected", (GCallback)child_drive_connected, union_monitor);
219   g_signal_connect (volume_monitor, "drive_disconnected", (GCallback)child_drive_disconnected, union_monitor);
220 }
221
222 static void
223 g_union_volume_monitor_remove_monitor (GUnionVolumeMonitor *union_monitor,
224                                        GVolumeMonitor      *child_monitor)
225 {
226   GList *l;
227
228   l = g_list_find (union_monitor->monitors, child_monitor);
229   if (l == NULL)
230     return;
231
232   union_monitor->monitors = g_list_delete_link (union_monitor->monitors, l);
233
234   g_signal_handlers_disconnect_by_func (child_monitor, child_volume_mounted, union_monitor);
235   g_signal_handlers_disconnect_by_func (child_monitor, child_volume_pre_unmount, union_monitor);
236   g_signal_handlers_disconnect_by_func (child_monitor, child_volume_unmounted, union_monitor);
237   g_signal_handlers_disconnect_by_func (child_monitor, child_drive_connected, union_monitor);
238   g_signal_handlers_disconnect_by_func (child_monitor, child_drive_disconnected, union_monitor);
239 }
240
241 static gpointer
242 get_default_native_type (gpointer data)
243 {
244   GNativeVolumeMonitorClass *klass;
245   GType *monitors;
246   guint n_monitors;
247   GType native_type;
248   GType *ret = (GType *) data;
249   int native_prio;
250   int i;
251       
252 #ifdef G_OS_UNIX
253   /* Ensure GUnixVolumeMonitor type is available */
254   {
255     volatile GType unix_type;
256     /* volatile is required to avoid any G_GNUC_CONST optimizations */
257     unix_type = _g_unix_volume_monitor_get_type ();
258   }
259 #endif
260       
261   /* Ensure vfs in modules loaded */
262   _g_io_modules_ensure_loaded ();
263       
264   monitors = g_type_children (G_TYPE_NATIVE_VOLUME_MONITOR, &n_monitors);
265   native_type = 0;
266   native_prio = -1;
267   
268   for (i = 0; i < n_monitors; i++)
269     {
270       klass = G_NATIVE_VOLUME_MONITOR_CLASS (g_type_class_ref (monitors[i]));
271       if (klass->priority > native_prio)
272         {
273           native_prio = klass->priority;
274           native_type = monitors[i];
275         }
276
277       g_type_class_unref (klass);
278     }
279       
280   g_free (monitors);
281
282   *ret = native_type;
283
284   return NULL;
285 }
286
287 static GType
288 get_native_type (void)
289 {
290   static GOnce once_init = G_ONCE_INIT;
291   static GType type = G_TYPE_INVALID;
292
293   g_once (&once_init, get_default_native_type, &type);
294   
295   return type;
296 }
297
298 static void
299 g_union_volume_monitor_init (GUnionVolumeMonitor *union_monitor)
300 {
301   GVolumeMonitor *monitor;
302   GType *monitors;
303   guint n_monitors;
304   GType native_type;
305   int i;
306
307   native_type = get_native_type ();
308
309   if (native_type != G_TYPE_INVALID)
310     {
311       monitor = g_object_new (native_type, NULL);
312       g_union_volume_monitor_add_monitor (union_monitor, monitor);
313       g_object_unref (monitor);
314     }
315   
316   monitors = g_type_children (G_TYPE_VOLUME_MONITOR, &n_monitors);
317   
318   for (i = 0; i < n_monitors; i++)
319     {
320       if (monitors[i] == G_TYPE_UNION_VOLUME_MONITOR ||
321           g_type_is_a (monitors[i], G_TYPE_NATIVE_VOLUME_MONITOR))
322         continue;
323       
324       monitor = g_object_new (monitors[i], NULL);
325       g_union_volume_monitor_add_monitor (union_monitor, monitor);
326       g_object_unref (monitor);
327     }
328       
329   g_free (monitors);
330 }
331
332 static GUnionVolumeMonitor *
333 g_union_volume_monitor_new (void)
334 {
335   GUnionVolumeMonitor *monitor;
336
337   monitor = g_object_new (G_TYPE_UNION_VOLUME_MONITOR, NULL);
338   
339   return monitor;
340 }
341
342
343 /**
344  * g_volume_monitor_get:
345  * 
346  * Gets the volume monitor used by gio.
347  *
348  * Returns: a reference to the #GVolumeMonitor used by gio. Call
349  *    g_object_unref() when done with it.
350  **/
351 GVolumeMonitor *
352 g_volume_monitor_get (void)
353 {
354   GVolumeMonitor *vm;
355   
356   G_LOCK (the_volume_monitor);
357
358   if (the_volume_monitor)
359     vm = G_VOLUME_MONITOR (g_object_ref (the_volume_monitor));
360   else
361     {
362       the_volume_monitor = g_union_volume_monitor_new ();
363       vm = G_VOLUME_MONITOR (the_volume_monitor);
364     }
365   
366   G_UNLOCK (the_volume_monitor);
367
368   return vm;
369 }
370
371 /**
372  * g_volume_get_for_mount_path:
373  * @mountpoint: a string.
374  * 
375  * Returns: a #GVolume for given @mountpoint or %NULL.  
376  **/
377 GVolume *
378 _g_volume_get_for_mount_path (const char *mountpoint)
379 {
380   GType native_type;
381   GNativeVolumeMonitorClass *klass;
382   GVolume *volume;
383   
384   native_type = get_native_type ();
385
386   if (native_type == G_TYPE_INVALID)
387     return NULL;
388
389   volume = NULL;
390   
391   klass = G_NATIVE_VOLUME_MONITOR_CLASS (g_type_class_ref (native_type));
392   if (klass->get_volume_for_mountpoint)
393     volume = klass->get_volume_for_mountpoint (mountpoint);
394   
395   g_type_class_unref (klass);
396
397   return volume;
398 }
399
400 #define __G_UNION_VOLUME_MONITOR_C__
401 #include "gioaliasdef.c"