215951cfd8df17c99a96258ec45a3ed6ff547257
[framework/uifw/edbus.git] / src / bin / hal.c
1 #include "E_Hal.h"
2 #include <config.h>
3
4 #if EWL_GUI
5 #include <Ewl.h>
6 #include <Efreet.h>
7 #endif
8
9 #include <string.h>
10
11 /* test app */
12
13 static E_DBus_Connection *conn;
14 #if EWL_GUI
15 static int mount_id = 0;
16 #endif
17
18 #define DEVICE_TYPE_STORAGE 1
19 #define DEVICE_TYPE_VOLUME  2
20 typedef struct Device Device;
21 struct Device {
22   int type;
23   char *udi;
24 };
25
26 typedef struct Storage Storage;
27 struct Storage {
28   int type;
29   char *udi;
30   char *bus;
31   char *drive_type;
32
33   char *model;
34   char *vendor;
35   char *serial;
36
37   char removable;
38   char media_available;
39   unsigned long media_size;
40
41   char requires_eject;
42   char hotpluggable;
43   char media_check_enabled;
44
45   struct {
46     char *drive;
47     char *volume;
48   } icon;
49
50   Ecore_List *volumes;
51 };
52
53
54 typedef struct Volume Volume;
55 struct Volume {
56   int type;
57   char *udi;
58   char *uuid;
59   char *label;
60   char *fstype;
61
62   char partition;
63   char *partition_label;
64   char mounted;
65   char *mount_point;
66
67   Storage *storage;
68 };
69
70 static Ecore_List *storage_devices;
71 static Ecore_List *volumes;
72
73 void
74 devices_dirty(void)
75 {
76 #if EWL_GUI
77   Ewl_Widget *mvc;
78
79   mvc = ewl_widget_name_find("device_mvc");
80   ewl_mvc_dirty_set(EWL_MVC(mvc), 1);
81 #endif
82 }
83
84
85 Storage *
86 storage_new(void)
87 {
88   Storage *s;
89   s = calloc(1, sizeof(Storage));
90   s->type = DEVICE_TYPE_STORAGE;
91   s->volumes = ecore_list_new();
92   return s;
93 }
94
95 void
96 storage_free(Storage *storage)
97 {
98   Volume *v;
99   printf("storage_free: %s\n", storage->udi);
100
101   /* disconnect storage from volume */
102   ecore_list_first_goto(storage->volumes);
103   while ((v = ecore_list_next(storage->volumes)))
104     v->storage = NULL;
105   ecore_list_destroy(storage->volumes);
106     
107   if (storage->udi) free(storage->udi);
108   if (storage->bus) free(storage->bus);
109   if (storage->drive_type) free(storage->drive_type);
110
111   if (storage->model) free(storage->model);
112   if (storage->vendor) free(storage->vendor);
113   if (storage->serial) free(storage->serial);
114   if (storage->icon.drive) free(storage->icon.drive);
115   if (storage->icon.volume) free(storage->icon.volume);
116
117   free(storage);
118 }
119
120 static int
121 storage_find_helper(Storage *s, const char *udi)
122 {
123   if (!s->udi) return -1;
124   return strcmp(s->udi, udi);
125 }
126
127 Storage *
128 storage_find(const char *udi)
129 {
130   Storage *s = NULL;
131   if (!udi) return NULL;
132   s = ecore_list_find(storage_devices, ECORE_COMPARE_CB(storage_find_helper), udi);
133   return s;
134 }
135
136 void
137 storage_remove(const char *udi)
138 {
139   if (storage_find(udi))
140   {
141     ecore_list_remove_destroy(storage_devices);
142     devices_dirty();
143   }
144 }
145
146 static void
147 cb_storage_properties(void *data, void *reply_data, DBusError *error)
148 {
149   Storage *s = data;
150   E_Hal_Properties *ret = reply_data;
151   int err = 0;
152
153   if (dbus_error_is_set(error)) 
154   {
155     // XXX handle...
156     dbus_error_free(error);
157     goto error;
158   }
159
160   s->bus = e_hal_property_string_get(ret, "storage.bus", &err);
161   if (err) goto error;
162   s->drive_type = e_hal_property_string_get(ret, "storage.drive_type", &err);
163   if (err) goto error;
164   s->model = e_hal_property_string_get(ret, "storage.model", &err);
165   if (err) goto error;
166   s->vendor = e_hal_property_string_get(ret, "storage.vendor", &err);
167   if (err) goto error;
168   s->serial = e_hal_property_string_get(ret, "storage.serial", &err);
169
170   s->removable = e_hal_property_bool_get(ret, "storage.removable", &err);
171   if (err) goto error;
172
173   if (s->removable)
174   {
175     s->media_available = e_hal_property_bool_get(ret, "storage.removable.media_available", &err);
176     s->media_size = e_hal_property_uint64_get(ret, "storage.removable.media_size", &err);
177   }
178
179   s->requires_eject = e_hal_property_bool_get(ret, "storage.requires_eject", &err);
180   s->hotpluggable = e_hal_property_bool_get(ret, "storage.hotpluggable", &err);
181   s->media_check_enabled = e_hal_property_bool_get(ret, "storage.media_check_enabled", &err);
182
183   s->icon.drive = e_hal_property_string_get(ret, "storage.icon.drive", &err);
184   s->icon.volume = e_hal_property_string_get(ret, "storage.icon.volume", &err);
185
186   devices_dirty();
187   /* now fetch the children (volumes?) */
188
189   //printf("Got storage:\n  udi: %s\n  bus: %s\n  drive_type: %s\n  model: %s\n  vendor: %s\n  serial: %s\n  icon.drive: %s\n  icon.volume: %s\n\n", s->udi, s->bus, s->drive_type, s->model, s->vendor, s->serial, s->icon.drive, s->icon.volume);
190   return;
191
192 error:
193   storage_remove(s->udi);
194 }
195
196 Storage *
197 storage_append(const char *udi)
198 {
199   Storage *s;
200   if (!udi) return NULL;
201   s = storage_new();
202   s->udi = strdup(udi);
203   ecore_list_append(storage_devices, s);
204   e_hal_device_get_all_properties(conn, s->udi, cb_storage_properties, s);
205   devices_dirty();
206   return s;
207 }
208
209 Volume *
210 volume_new(void)
211 {
212   Volume *v;
213   v = calloc(1, sizeof(Volume));
214   v->type = DEVICE_TYPE_VOLUME;
215   return v;
216 }
217
218 void
219 volume_free(Volume *volume)
220 {
221   if (!volume) return;
222
223   /* disconnect volume from storage */
224   if (volume->storage)
225   {
226     if (ecore_list_goto(volume->storage->volumes, volume))
227       ecore_list_remove(volume->storage->volumes);
228   }
229
230   if (volume->udi) free(volume->udi);
231   if (volume->uuid) free(volume->uuid);
232   if (volume->label) free(volume->label);
233   if (volume->fstype) free(volume->fstype);
234   if (volume->partition_label) free(volume->partition_label);
235   if (volume->mount_point) free(volume->mount_point);
236
237   free(volume);
238 }
239
240 static int
241 volume_find_helper(Volume *v, const char *udi)
242 {
243   if (!v->udi) return -1;
244   return strcmp(v->udi, udi);
245 }
246
247 Volume *
248 volume_find(const char *udi)
249 {
250   if (!udi) return NULL;
251   return ecore_list_find(volumes, ECORE_COMPARE_CB(volume_find_helper), udi);
252 }
253
254 void
255 volume_remove(const char *udi)
256 {
257   if (volume_find(udi))
258   {
259     ecore_list_remove_destroy(volumes);
260     devices_dirty();
261   }
262 }
263
264 static void
265 cb_volume_properties(void *data, void *reply_data, DBusError *error)
266 {
267   Volume *v = data;
268   Storage *s = NULL;
269   E_Hal_Device_Get_All_Properties_Return *ret = reply_data;
270   int err = 0;
271   char *str = NULL;
272
273   if (dbus_error_is_set(error)) 
274   {
275     // XXX handle...
276     dbus_error_free(error);
277     goto error;
278   }
279
280   /* skip volumes with volume.ignore set */
281   if (e_hal_property_bool_get(ret, "volume.ignore", &err) || err)
282     goto error;
283
284   /* skip volumes that aren't filesystems */
285   str = e_hal_property_string_get(ret, "volume.fsusage", &err);
286   if (err || !str) goto error;
287   if (strcmp(str, "filesystem")) goto error;
288   free(str);
289   str = NULL;
290
291   v->uuid = e_hal_property_string_get(ret, "volume.uuid", &err);
292   if (err) goto error;
293
294   v->label = e_hal_property_string_get(ret, "volume.label", &err);
295   if (err) goto error;
296
297   v->fstype = e_hal_property_string_get(ret, "volume.fstype", &err);
298   if (err) goto error;
299
300   v->mounted = e_hal_property_bool_get(ret, "volume.is_mounted", &err);
301   if (err) goto error;
302
303   v->partition = e_hal_property_bool_get(ret, "volume.is_partition", &err);
304   if (err) goto error;
305
306   v->mount_point = e_hal_property_string_get(ret, "volume.mount_point", &err);
307   if (err) goto error;
308
309   if (v->partition)
310   {
311     v->partition_label = e_hal_property_string_get(ret, "volume.partition.label", &err);
312     if (err) goto error;
313   }
314
315   str = e_hal_property_string_get(ret, "info.parent", &err);
316   if (!err && str)
317   {
318     s = storage_find(str);
319     if (s)
320     {
321       v->storage = s;
322       ecore_list_append(s->volumes, v);
323     }
324     free(str);
325     str = NULL;
326   }
327   
328   //printf("Got volume\n  udi: %s\n  uuid: %s\n  fstype: %s\n  label: %s\n  partition: %d\n  partition_label: %s\n  mounted: %d\n  mount_point: %s\n\n", v->udi, v->uuid, v->fstype,  v->label, v->partition, v->partition ? v->partition_label : "(not a partition)", v->mounted, v->mount_point);
329   //if (s) printf("  for storage: %s\n", s->udi);
330   //else printf("  storage unknown\n");
331
332   devices_dirty();
333   return;
334
335 error:
336   if (str) free(str);
337   volume_remove(v->udi);
338   return;
339   
340 }
341
342 void
343 volume_setup(Volume *v)
344 {
345   e_hal_device_get_all_properties(conn, v->udi, cb_volume_properties, v);
346 }
347
348 Volume *
349 volume_append(const char *udi)
350 {
351   Volume *v;
352   if (!udi) return NULL;
353   printf("ADDING %s\n", udi);
354   v = volume_new();
355   v->udi = strdup(udi);
356   ecore_list_append(volumes, v);
357   volume_setup(v);
358
359   //this will get called when volume_setup() returns, which is more important
360   //devices_dirty();
361
362   return v;
363 }
364
365 static void
366 cb_test_get_all_devices(void *user_data, void *reply_data, DBusError *error)
367 {
368   E_Hal_Manager_Get_All_Devices_Return *ret = reply_data;
369   char *device;
370   
371   if (!ret || !ret->strings) return;
372
373   if (dbus_error_is_set(error)) 
374   {
375     // XXX handle...
376     dbus_error_free(error);
377     return;
378   }
379
380   ecore_list_first_goto(ret->strings);
381   while ((device = ecore_list_next(ret->strings)))
382   {
383     printf("device: %s\n", device);
384   }
385 }
386
387 static void
388 cb_test_find_device_by_capability_storage(void *user_data, void *reply_data, DBusError *error)
389 {
390   E_Hal_Manager_Find_Device_By_Capability_Return *ret = reply_data;
391   char *device;
392   
393   if (!ret || !ret->strings) return;
394
395   if (dbus_error_is_set(error)) 
396   {
397     // XXX handle...
398     dbus_error_free(error);
399     return;
400   }
401
402   ecore_list_first_goto(ret->strings);
403   while ((device = ecore_list_next(ret->strings)))
404     storage_append(device);
405 }
406
407 static void
408 cb_test_find_device_by_capability_volume(void *user_data, void *reply_data, DBusError *error)
409 {
410   E_Hal_Manager_Find_Device_By_Capability_Return *ret = reply_data;
411   char *device;
412   
413   if (!ret || !ret->strings) return;
414
415   if (dbus_error_is_set(error)) 
416   {
417     // XXX handle...
418     dbus_error_free(error);
419     return;
420   }
421
422   ecore_list_first_goto(ret->strings);
423   while ((device = ecore_list_next(ret->strings)))
424     volume_append(device);
425 }
426
427 static void
428 cb_is_storage(void *user_data, void *reply_data, DBusError *error)
429 {
430   char *udi = user_data;
431   E_Hal_Device_Query_Capability_Return *ret = reply_data;
432
433   if (dbus_error_is_set(error)) 
434   {
435     // XXX handle...
436     dbus_error_free(error);
437     goto error;
438   }
439
440   if (ret && ret->boolean)
441     storage_append(udi);
442
443 error:
444   free(udi);
445 }
446
447 static void
448 cb_is_volume(void *user_data, void *reply_data, DBusError *error)
449 {
450   char *udi = user_data;
451   E_Hal_Device_Query_Capability_Return *ret = reply_data;
452
453   if (dbus_error_is_set(error)) 
454   {
455     // XXX handle...
456     dbus_error_free(error);
457     goto error;
458   }
459
460   if (ret && ret->boolean)
461     volume_append(udi);
462
463 error:
464   free(udi);
465 }
466
467 static void
468 cb_signal_device_added(void *data, DBusMessage *msg)
469 {
470   DBusError err;
471   char *udi;
472   int ret;
473
474   dbus_error_init(&err);
475   dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &udi, DBUS_TYPE_INVALID);
476   udi = strdup(udi);
477   printf("Device added: %s\n", udi); 
478   ret = e_hal_device_query_capability(conn, udi, "storage", cb_is_storage, strdup(udi));
479   e_hal_device_query_capability(conn, udi, "volume", cb_is_volume, strdup(udi));
480 }
481
482 void
483 cb_signal_device_removed(void *data, DBusMessage *msg)
484 {
485   DBusError err;
486   char *udi;
487
488   dbus_error_init(&err);
489
490   dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &udi, DBUS_TYPE_INVALID);
491   printf("Removed: %s\n", udi);
492   storage_remove(udi);
493   volume_remove(udi);
494 }
495
496 void
497 cb_signal_new_capability(void *data, DBusMessage *msg)
498 {
499   DBusError err;
500   char *udi, *capability;
501
502   dbus_error_init(&err);
503
504   dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &udi, DBUS_TYPE_STRING, &capability, DBUS_TYPE_INVALID);
505   if (!strcmp(capability, "storage"))
506     storage_append(udi);
507
508 }
509
510 /*** gui ***/
511
512 #if EWL_GUI
513 static void
514 cb_window_destroy(Ewl_Widget *w, void *ev, void *data)
515 {
516   ewl_main_quit();
517 }
518
519 static void
520 cb_window_close(Ewl_Widget *w, void *ev, void *data)
521 {
522   ewl_widget_destroy(w);
523 }
524
525 static void
526 cb_volume_unmounted(void *user_data, void *method_return, DBusError *error)
527 {
528   Volume *vol = user_data;
529   vol->mounted = 0;
530   printf("Volume unmounted reply: %s\n", vol->udi);
531 }
532
533 static void
534 cb_volume_mounted(void *user_data, void *method_return, DBusError *error)
535 {
536   Volume *vol = user_data;
537   vol->mounted = 1;
538   printf("Volume mounted reply: %s\n", vol->udi);
539 }
540
541 static void
542 cb_device_view_clicked(Ewl_Widget *w, void *ev, void *data)
543 {
544   Device *dev = data;
545   char buf[4096];
546
547   printf("Device clicked: %s\n", dev->udi);
548   if (dev->type == DEVICE_TYPE_VOLUME)
549   {
550     Volume *vol = (Volume *)dev;
551     if (vol->mounted)
552     {
553       e_hal_device_volume_unmount(conn, vol->udi, NULL, cb_volume_unmounted, vol);
554     }
555     else
556     {
557       char *mount_point;
558 #if 0
559       if (vol->mount_point && vol->mount_point[0])
560         mount_point = vol->mount_point;
561 #endif
562       if (vol->label && vol->label[0])
563         mount_point = vol->label;
564       else if (vol->uuid && vol->uuid[0])
565         mount_point = vol->uuid;
566       else
567       {
568         // XXX need to check this...
569         snprintf(buf, sizeof(buf), "%d\n", mount_id++);
570         mount_point = buf;
571       }
572
573       printf("Attempting to mount %s to %s\n", vol->udi, mount_point);
574       e_hal_device_volume_mount(conn, vol->udi, mount_point, vol->fstype, NULL, cb_volume_mounted, vol);
575     }
576   }
577 }
578
579
580 static Ewl_Widget *
581 cb_device_view_constructor(void)
582 {
583   Ewl_Widget *icon;
584
585   icon = ewl_icon_simple_new();
586   ewl_box_orientation_set(EWL_BOX(icon), EWL_ORIENTATION_HORIZONTAL);
587   return icon;
588 }
589
590 static void
591 device_view_device_set(Ewl_Icon *icon, Device *dev)
592 {
593   char buf[500];
594   const char *path;
595   const char *icon_name = NULL;
596
597   if (dev->type == DEVICE_TYPE_STORAGE)
598   {
599     Storage *s = (Storage *)dev;
600
601     if (s->icon.drive && s->icon.drive[0])
602       icon_name = s->icon.drive;
603
604     snprintf(buf, sizeof(buf), "%s", (s->model && s->model[0]) ? s->model : "Unknown drive");
605   }
606   else if (dev->type == DEVICE_TYPE_VOLUME)
607   {
608     Volume *v = (Volume *)dev;
609     if (v->storage && v->storage->icon.volume && v->storage->icon.volume[0])
610       icon_name = v->storage->icon.volume;
611     snprintf(buf, sizeof(buf), "%s (%s)", (v->label && v->label[0]) ? v->label : "Unlabeled Volume", v->fstype ? v->fstype : "Unknown");
612   }
613   else
614   {
615     fprintf(stderr, "Invalid device type.");
616     buf[0] = 0;
617   }
618
619   ewl_icon_label_set(icon, buf);
620   if (icon_name)
621   {
622     //printf("find icon path: %s\n", icon_name);
623     path = efreet_icon_path_find("Tango", icon_name, 32);
624     //printf("found: %s\n", path);
625     if (path)
626     {
627       ewl_icon_image_set(icon, path, NULL);
628       free(path);
629     }
630   }
631   ewl_callback_append(EWL_WIDGET(icon), EWL_CALLBACK_CLICKED, cb_device_view_clicked, dev);
632
633 }
634
635 static void
636 cb_device_view_assign(Ewl_Widget *w, void *data)
637 {
638   Device *dev = data;
639   device_view_device_set(EWL_ICON(w), dev);
640 }
641
642 static Ewl_Widget *
643 cb_device_view_header_fetch(void *data, int column)
644 {
645   Ewl_Widget *label;
646
647   label = ewl_label_new();
648   ewl_label_text_set(EWL_LABEL(label), "Device");
649   ewl_widget_show(label);
650   return label;
651 }
652
653 static int
654 cb_device_tree_expandable_get(void *data, unsigned int row)
655 {
656   Ecore_List *devices;
657   Device *dev;
658
659   devices = data;
660   if (!devices) return FALSE;
661
662   dev = ecore_list_index_goto(devices, row);
663   if (!dev) return FALSE;
664
665   if (dev->type == DEVICE_TYPE_STORAGE)
666   {
667     Storage *s = (Storage *)dev;
668     if (ecore_list_count(s->volumes) > 0)
669       return TRUE;
670   }
671
672   return FALSE;
673 }
674
675 static void *
676 cb_device_tree_expansion_data_fetch(void *data, unsigned int parent)
677 {
678   Ecore_List *devices;
679   Device *dev;
680   Storage *s;
681   dev = data;
682
683   devices = data;
684   if (!devices) return NULL;
685
686   dev = ecore_list_index_goto(devices, parent);
687   
688   if (!dev) return NULL;
689   if (dev->type != DEVICE_TYPE_STORAGE) return NULL;
690   s = (Storage *)dev;
691   return s->volumes;
692 }
693
694 #if 0
695 Ewl_Widget *
696 mountbox_list_new(void)
697 {
698   Ewl_Widget *list;
699   Ewl_Model *model;
700   Ewl_View *view;
701
702   model = ewl_model_ecore_list_get();
703
704   view = ewl_view_new();
705   ewl_view_constructor_set(view, cb_device_view_constructor);
706   ewl_view_assign_set(view, EWL_VIEW_ASSIGN(cb_device_view_assign));
707
708   list = ewl_list_new();
709   ewl_mvc_model_set(EWL_MVC(list), model);
710   ewl_mvc_view_set(EWL_MVC(list), view);
711   ewl_mvc_data_set(EWL_MVC(list), volumes);
712
713   ewl_widget_name_set(list, "volume_mvc");
714
715   return list;
716 }
717 #endif
718
719 Ewl_Widget *
720 mountbox_tree_new(void)
721 {
722   Ewl_Widget *tree;
723   Ewl_Model *model;
724   Ewl_View *view;
725
726   model = ewl_model_ecore_list_get();
727   ewl_model_expandable_set(model, cb_device_tree_expandable_get);
728   ewl_model_expansion_data_fetch_set(model, cb_device_tree_expansion_data_fetch);
729
730   view = ewl_view_new();
731   ewl_view_constructor_set(view, cb_device_view_constructor);
732   ewl_view_assign_set(view, EWL_VIEW_ASSIGN(cb_device_view_assign));
733   ewl_view_header_fetch_set(view, cb_device_view_header_fetch);
734
735   tree = ewl_tree2_new();
736   ewl_mvc_model_set(EWL_MVC(tree), model);
737   ewl_mvc_data_set(EWL_MVC(tree), storage_devices);
738   ewl_tree2_column_append(EWL_TREE2(tree), view, FALSE);
739
740   ewl_widget_name_set(tree, "device_mvc");
741
742   return tree;
743 }
744
745 Ewl_Widget *
746 mountbox_mainwin_new(void)
747 {
748   Ewl_Widget *win, *box, *list;
749   win = ewl_window_new();
750   ewl_window_title_set(EWL_WINDOW(win), "EWL Mountbox");
751   ewl_window_class_set(EWL_WINDOW(win), "ewl_mountbox");
752   ewl_window_name_set(EWL_WINDOW(win), "ewl_mountbox");
753
754   ewl_object_fill_policy_set(EWL_OBJECT(win), EWL_FLAG_FILL_ALL);
755   ewl_object_size_request(EWL_OBJECT(win), 400, 400);
756
757   ewl_callback_append(win, EWL_CALLBACK_DELETE_WINDOW, cb_window_close, NULL);
758   ewl_callback_append(win, EWL_CALLBACK_DESTROY, cb_window_destroy, NULL);
759
760   box = ewl_vbox_new();
761   ewl_container_child_append(EWL_CONTAINER(win), box);
762   ewl_widget_show(box);
763
764   list = mountbox_tree_new();
765   ewl_container_child_append(EWL_CONTAINER(box), list);
766   ewl_widget_show(list);
767
768   return win;
769 }
770 #endif
771 int 
772 main(int argc, char **argv)
773 {
774 #if EWL_GUI
775   Ewl_Widget *win;
776 #endif
777
778   ecore_init();
779   ecore_string_init();
780   e_dbus_init();
781
782 #if EWL_GUI
783   efreet_init();
784   if (!ewl_init(&argc, argv))
785   {
786     fprintf(stderr, "Unable to init EWL.\n");
787     return 1;
788   }
789 #endif
790
791   conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
792   if (!conn)
793   {
794     printf("Error connecting to system bus. Is it running?\n");
795     return 1;
796   }
797
798   storage_devices = ecore_list_new();
799   ecore_list_free_cb_set(storage_devices, ECORE_FREE_CB(storage_free));
800   volumes = ecore_list_new();
801   ecore_list_free_cb_set(volumes, ECORE_FREE_CB(volume_free));
802
803 #if EWL_GUI
804   win = mountbox_mainwin_new();
805   ewl_widget_show(win);
806 #endif
807
808   e_hal_manager_get_all_devices(conn, cb_test_get_all_devices, NULL);
809   e_hal_manager_find_device_by_capability(conn, "storage", cb_test_find_device_by_capability_storage, NULL);
810   e_hal_manager_find_device_by_capability(conn, "volume", cb_test_find_device_by_capability_volume, NULL);
811   
812   e_dbus_signal_handler_add(conn, "org.freedesktop.Hal", "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager", "DeviceAdded", cb_signal_device_added, NULL);
813   e_dbus_signal_handler_add(conn, "org.freedesktop.Hal", "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager", "DeviceRemoved", cb_signal_device_removed, NULL);
814   e_dbus_signal_handler_add(conn, "org.freedesktop.Hal", "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager", "NewCapability", cb_signal_new_capability, NULL);
815
816 #if EWL_GUI
817   ewl_main();
818   efreet_shutdown();
819   ewl_shutdown();
820 #else
821   ecore_main_loop_begin();
822 #endif
823   ecore_list_destroy(storage_devices);
824   ecore_list_destroy(volumes);
825   e_dbus_connection_close(conn);
826   e_dbus_shutdown();
827   ecore_string_shutdown();
828   ecore_shutdown();
829   return 1;
830 }