Add GMountUnmountFlags to all unmount and eject calls. Add
[platform/upstream/glib.git] / gio / gdrive.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  *         David Zeuthen <davidz@redhat.com>
22  */
23
24 #include <config.h>
25 #include "gdrive.h"
26 #include "gsimpleasyncresult.h"
27 #include "glibintl.h"
28
29 #include "gioalias.h"
30
31 /**
32  * SECTION:gdrive
33  * @short_description: Virtual File System drive management
34  * @include: gio.h
35  * 
36  * #GDrive is a container class for #GVolume objects that stem from
37  * the same piece of media. As such, #GDrive abstracts a drive with
38  * (or without) removable media and provides operations for querying
39  * whether media is available, determing whether media change is
40  * automatically detected and ejecting the media.
41  *
42  * If the #GDrive reports that media isn't automatically detected, one
43  * can poll for media; typically one should not do this periodically
44  * as a poll for media operation is potententially expensive and may
45  * spin up the drive creating noise.
46  *
47  * For porting from GnomeVFS note that there is no equivalent of
48  * #GDrive in that API.
49  **/
50
51 static void g_drive_base_init (gpointer g_class);
52 static void g_drive_class_init (gpointer g_class,
53                                  gpointer class_data);
54
55 GType
56 g_drive_get_type (void)
57 {
58   static GType drive_type = 0;
59
60   if (! drive_type)
61     {
62       static const GTypeInfo drive_info =
63       {
64         sizeof (GDriveIface), /* class_size */
65         g_drive_base_init,   /* base_init */
66         NULL,           /* base_finalize */
67         g_drive_class_init,
68         NULL,           /* class_finalize */
69         NULL,           /* class_data */
70         0,
71         0,              /* n_preallocs */
72         NULL
73       };
74
75       drive_type =
76         g_type_register_static (G_TYPE_INTERFACE, I_("GDrive"),
77                                 &drive_info, 0);
78
79       g_type_interface_add_prerequisite (drive_type, G_TYPE_OBJECT);
80     }
81
82   return drive_type;
83 }
84
85 static void
86 g_drive_class_init (gpointer g_class,
87                     gpointer class_data)
88 {
89 }
90
91 static void
92 g_drive_base_init (gpointer g_class)
93 {
94   static gboolean initialized = FALSE;
95
96   if (! initialized)
97     {
98       /**
99       * GDrive::changed:
100       * @drive: a #GDrive.
101       * 
102       * Emitted when the drive's state has changed.
103       **/
104       g_signal_new (I_("changed"),
105                     G_TYPE_DRIVE,
106                     G_SIGNAL_RUN_LAST,
107                     G_STRUCT_OFFSET (GDriveIface, changed),
108                     NULL, NULL,
109                     g_cclosure_marshal_VOID__VOID,
110                     G_TYPE_NONE, 0);
111
112       /**
113       * GDrive::disconnected:
114       * @drive: a #GDrive.
115       * 
116       * This signal is emitted when the #GDrive have been
117       * disconnected. If the recipient is holding references to the
118       * object they should release them so the object can be
119       * finalized.
120       **/
121       g_signal_new (I_("disconnected"),
122                     G_TYPE_DRIVE,
123                     G_SIGNAL_RUN_LAST,
124                     G_STRUCT_OFFSET (GDriveIface, disconnected),
125                     NULL, NULL,
126                     g_cclosure_marshal_VOID__VOID,
127                     G_TYPE_NONE, 0);
128
129       /**
130       * GDrive::eject-button:
131       * @drive: a #GDrive.
132       * 
133       * Emitted when the physical eject button (if any) of a drive have been pressed.
134       * 
135       **/
136       g_signal_new (I_("eject-button"),
137                     G_TYPE_DRIVE,
138                     G_SIGNAL_RUN_LAST,
139                     G_STRUCT_OFFSET (GDriveIface, eject_button),
140                     NULL, NULL,
141                     g_cclosure_marshal_VOID__VOID,
142                     G_TYPE_NONE, 0);
143
144       initialized = TRUE;
145     }
146 }
147
148 /**
149  * g_drive_get_name:
150  * @drive: a #GDrive.
151  * 
152  * Gets the name of @drive.
153  *
154  * Returns: a string containing @drive's name. The returned 
155  *     string should be freed when no longer needed.
156  **/
157 char *
158 g_drive_get_name (GDrive *drive)
159 {
160   GDriveIface *iface;
161
162   g_return_val_if_fail (G_IS_DRIVE (drive), NULL);
163
164   iface = G_DRIVE_GET_IFACE (drive);
165
166   return (* iface->get_name) (drive);
167 }
168
169 /**
170  * g_drive_get_icon:
171  * @drive: a #GDrive.
172  * 
173  * Gets the icon for @drive.
174  * 
175  * Returns: #GIcon for the @drive.
176  **/
177 GIcon *
178 g_drive_get_icon (GDrive *drive)
179 {
180   GDriveIface *iface;
181   
182   g_return_val_if_fail (G_IS_DRIVE (drive), NULL);
183
184   iface = G_DRIVE_GET_IFACE (drive);
185
186   return (* iface->get_icon) (drive);
187 }
188
189 /**
190  * g_drive_has_volumes:
191  * @drive: a #GDrive.
192  * 
193  * Check if @drive has any mountable volumes.
194  * 
195  * Returns: %TRUE if the @drive contains volumes, %FALSE otherwise.
196  **/
197 gboolean
198 g_drive_has_volumes (GDrive *drive)
199 {
200   GDriveIface *iface;
201
202   g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
203
204   iface = G_DRIVE_GET_IFACE (drive);
205
206   return (* iface->has_volumes) (drive);
207 }
208
209 /**
210  * g_drive_get_volumes:
211  * @drive: a #GDrive.
212  * 
213  * Get a list of mountable volumes for @drive.
214  * 
215  * Returns: #GList containing any #GVolume<!---->s on the given @drive.
216  **/
217 GList *
218 g_drive_get_volumes (GDrive *drive)
219 {
220   GDriveIface *iface;
221
222   g_return_val_if_fail (G_IS_DRIVE (drive), NULL);
223
224   iface = G_DRIVE_GET_IFACE (drive);
225
226   return (* iface->get_volumes) (drive);
227 }
228
229 /**
230  * g_drive_is_media_check_automatic:
231  * @drive: a #GDrive.
232  * 
233  * Checks if @drive is capabable of automatically detecting media changes.
234  * 
235  * Returns: %TRUE if the @drive is capabable of automatically detecting media changes, %FALSE otherwise.
236  **/
237 gboolean
238 g_drive_is_media_check_automatic (GDrive *drive)
239 {
240   GDriveIface *iface;
241
242   g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
243
244   iface = G_DRIVE_GET_IFACE (drive);
245
246   return (* iface->is_media_check_automatic) (drive);
247 }
248
249 /**
250  * g_drive_is_media_removable:
251  * @drive: a #GDrive.
252  * 
253  * Checks if the @drive supports removable media.
254  * 
255  * Returns: %TRUE if @drive supports removable media, %FALSE otherwise.
256  **/
257 gboolean
258 g_drive_is_media_removable (GDrive *drive)
259 {
260   GDriveIface *iface;
261
262   g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
263
264   iface = G_DRIVE_GET_IFACE (drive);
265
266   return (* iface->is_media_removable) (drive);
267 }
268
269 /**
270  * g_drive_has_media:
271  * @drive: a #GDrive.
272  * 
273  * Checks if the @drive has media. Note that the OS may not be polling
274  * the drive for media changes; see g_drive_is_media_check_automatic()
275  * for more details.
276  * 
277  * Returns: %TRUE if @drive has media, %FALSE otherwise.
278  **/
279 gboolean
280 g_drive_has_media (GDrive *drive)
281 {
282   GDriveIface *iface;
283
284   g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
285
286   iface = G_DRIVE_GET_IFACE (drive);
287
288   return (* iface->has_media) (drive);
289 }
290
291 /**
292  * g_drive_can_eject:
293  * @drive: pointer to a #GDrive.
294  * 
295  * Checks if a drive can be ejected.
296  * 
297  * Returns: %TRUE if the @drive can be ejected. %FALSE otherwise.
298  **/
299 gboolean
300 g_drive_can_eject (GDrive *drive)
301 {
302   GDriveIface *iface;
303
304   g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
305
306   iface = G_DRIVE_GET_IFACE (drive);
307
308   if (iface->can_eject == NULL)
309     return FALSE;
310
311   return (* iface->can_eject) (drive);
312 }
313
314 /**
315  * g_drive_can_poll_for_media:
316  * @drive: a #GDrive.
317  * 
318  * Checks if a drive can be polled for media changes.
319  * 
320  * Returns: %TRUE if the @drive can be polled for media changes. %FALSE otherwise.
321  **/
322 gboolean
323 g_drive_can_poll_for_media (GDrive *drive)
324 {
325   GDriveIface *iface;
326
327   g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
328
329   iface = G_DRIVE_GET_IFACE (drive);
330
331   if (iface->poll_for_media == NULL)
332     return FALSE;
333
334   return (* iface->can_poll_for_media) (drive);
335 }
336
337 /**
338  * g_drive_eject:
339  * @drive: a #GDrive.
340  * @flags: flags affecting the unmount if required for eject
341  * @cancellable: optional #GCancellable object, %NULL to ignore.
342  * @callback: a #GAsyncReadyCallback.
343  * @user_data: a #gpointer.
344  * 
345  * Ejects a drive.
346  * 
347  **/
348 void
349 g_drive_eject (GDrive              *drive,
350                GMountUnmountFlags   flags,
351                GCancellable        *cancellable,
352                GAsyncReadyCallback  callback,
353                gpointer             user_data)
354 {
355   GDriveIface *iface;
356
357   g_return_if_fail (G_IS_DRIVE (drive));
358
359   iface = G_DRIVE_GET_IFACE (drive);
360
361   if (iface->eject == NULL)
362     {
363       g_simple_async_report_error_in_idle (G_OBJECT (drive), callback, user_data,
364                                            G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
365                                            _("drive doesn't implement eject"));
366       
367       return;
368     }
369   
370   (* iface->eject) (drive, flags, cancellable, callback, user_data);
371 }
372
373 /**
374  * g_drive_eject_finish
375  * @drive: a #GDrive.
376  * @result: a #GAsyncResult.
377  * @error: a #GError.
378  * 
379  * Finishes ejecting a drive.
380  * 
381  * Returns: %TRUE if the drive has been ejected successfully,
382  * %FALSE otherwise.
383  **/
384 gboolean
385 g_drive_eject_finish (GDrive        *drive,
386                       GAsyncResult  *result,
387                       GError       **error)
388 {
389   GDriveIface *iface;
390
391   g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
392   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
393
394   if (G_IS_SIMPLE_ASYNC_RESULT (result))
395     {
396       GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
397       if (g_simple_async_result_propagate_error (simple, error))
398         return FALSE;
399     }
400   
401   iface = G_DRIVE_GET_IFACE (drive);
402   
403   return (* iface->eject_finish) (drive, result, error);
404 }
405
406 /**
407  * g_drive_poll_for_media:
408  * @drive: a #GDrive.
409  * @cancellable: optional #GCancellable object, %NULL to ignore.
410  * @callback: a #GAsyncReadyCallback.
411  * @user_data: a #gpointer.
412  * 
413  * Polls @drive to see if media has been inserted or removed.
414  * 
415  **/
416 void
417 g_drive_poll_for_media (GDrive              *drive,
418                         GCancellable        *cancellable,
419                         GAsyncReadyCallback  callback,
420                         gpointer             user_data)
421 {
422   GDriveIface *iface;
423
424   g_return_if_fail (G_IS_DRIVE (drive));
425
426   iface = G_DRIVE_GET_IFACE (drive);
427
428   if (iface->poll_for_media == NULL)
429     {
430       g_simple_async_report_error_in_idle (G_OBJECT (drive), callback, user_data,
431                                            G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
432                                            _("drive doesn't implement polling for media"));
433       
434       return;
435     }
436   
437   (* iface->poll_for_media) (drive, cancellable, callback, user_data);
438 }
439
440 /**
441  * g_drive_poll_for_media_finish
442  * @drive: a #GDrive.
443  * @result: a #GAsyncResult.
444  * @error: a #GError.
445  * 
446  * Finishes poll_for_mediaing a drive.
447  * 
448  * Returns: %TRUE if the drive has been poll_for_mediaed successfully,
449  * %FALSE otherwise.
450  **/
451 gboolean
452 g_drive_poll_for_media_finish (GDrive        *drive,
453                                GAsyncResult  *result,
454                                GError       **error)
455 {
456   GDriveIface *iface;
457
458   g_return_val_if_fail (G_IS_DRIVE (drive), FALSE);
459   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
460
461   if (G_IS_SIMPLE_ASYNC_RESULT (result))
462     {
463       GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
464       if (g_simple_async_result_propagate_error (simple, error))
465         return FALSE;
466     }
467   
468   iface = G_DRIVE_GET_IFACE (drive);
469   
470   return (* iface->poll_for_media_finish) (drive, result, error);
471 }
472
473 #define __G_DRIVE_C__
474 #include "gioaliasdef.c"