efm2 hal handling API - full changes.
authorGustavo Sverzut Barbieri <barbieri@gmail.com>
Sun, 7 Jun 2009 00:00:41 +0000 (00:00 +0000)
committerGustavo Sverzut Barbieri <barbieri@gmail.com>
Sun, 7 Jun 2009 00:00:41 +0000 (00:00 +0000)
1. Added E_FM_OP_EJECT command to e_fm_main. It unmounts volume
   before eject, if it necessary.
2. Added timeouts of mounting/unmounting/ejecting media, and
   it's moved to slave e_fm_main.c. Each timeout will generate
   *_MOUNT_ERROR, *_UNMOUNT_ERROR and *_EJECT_ERROR message.
3. Added auto mount on insert media and auto showing efm2 window
   on mount volume options to filemanager config.
4. Added mounted/unmounted glyphs to efm2 icons and track state
   code. Now each removable device have "M" glyph on icon if mounted
   and "U" when unmounted.
5. Added mount/unmount/eject commands to icon dropdown menu.
6. Russian translation of mew messages.
7. Other bugfixes and improvements for co-operation.

Now, efm2 contains all code to mount/umnount/eject removable media and
all code to provide corresponding user interface.
It can working independently from 'places' or co-operate with it.

By: Sergey Semernin

SVN revision: 40928

12 files changed:
data/themes/default.edc
po/ru.po
src/bin/e_config.c
src/bin/e_config.h
src/bin/e_fm.c
src/bin/e_fm_hal.c
src/bin/e_fm_hal.h
src/bin/e_fm_main.c
src/bin/e_fm_op.h
src/bin/e_fm_shared.h
src/modules/fileman/e_mod_config.c
src/modules/fileman/e_mod_main.c

index 0bf68d5..45592b8 100644 (file)
@@ -13669,6 +13669,9 @@ collections { /* begin the collection of edje groups that are in this file */
         image: "icon_efm_dnd_copy.png" COMP;
         image: "icon_efm_dnd_ask.png" COMP;
         image: "icon_efm_dnd_move.png" COMP;
+
+        image: "icon_efm_vol_unmounted.png" COMP;
+        image: "icon_efm_vol_mounted.png" COMP;
       }
       parts {
         part { name: "label2";
@@ -13952,6 +13955,36 @@ collections { /* begin the collection of edje groups that are in this file */
               color: 0 0 0 0;
            }
         }
+        part { name: "vol_state";
+           type: IMAGE;
+           mouse_events: 0;
+           repeat_events: 0;
+           description { state: "default" 0.0;
+              color:      0 0 0 0;
+           }
+           description { state: "visible" 0.0;
+              aspect: 1.0 1.0;
+              aspect_preference: BOTH;
+              align: 1.0 1.0;
+              min: 16 16;
+              rel1 {
+                 relative: 0.75 0.0;
+                 to: "icon";
+              }
+              rel2 {
+                 relative: 1.0 1.0;
+                 to: "icon";
+              }
+           }
+           description { state: "unmounted" 0.0;
+              inherit: "visible" 0.0;
+              image.normal:  "icon_efm_vol_unmounted.png";
+           }
+           description { state: "mounted" 0.0;
+              inherit: "visible" 0.0;
+              image.normal:  "icon_efm_vol_mounted.png";
+           }
+        }
         part { name: "dnd_action";
            type: IMAGE;
            mouse_events:  0;
@@ -14029,6 +14062,24 @@ collections { /* begin the collection of edje groups that are in this file */
            action: STATE_SET "copy" 0.0;
            target: "dnd_action";
         }
+        program { name: "vol_off";
+           signal: "e,state,volume,off";
+           source: "e";
+           action: STATE_SET "default" 0.0;
+           target: "vol_state";
+        }
+        program { name: "vol_unmounted";
+           signal: "e,state,volume,unmounted";
+           source: "e";
+           action: STATE_SET "unmounted" 0.0;
+           target: "vol_state";
+        }
+        program { name: "vol_mounted";
+           signal: "e,state,volume,mounted";
+           source: "e";
+           action: STATE_SET "mounted" 0.0;
+           target: "vol_state";
+        }
         program { name: "thumb_gen";
            signal:  "e,action,thumb,gen";
            source:  "e";
@@ -14089,6 +14140,9 @@ collections { /* begin the collection of edje groups that are in this file */
         image: "icon_efm_dnd_copy.png" COMP;
         image: "icon_efm_dnd_ask.png" COMP;
         image: "icon_efm_dnd_move.png" COMP;
+
+        image: "icon_efm_vol_unmounted.png" COMP;
+        image: "icon_efm_vol_mounted.png" COMP;
       }
       parts {
         part { name: "label2";
@@ -14372,6 +14426,36 @@ collections { /* begin the collection of edje groups that are in this file */
               color: 0 0 0 0;
            }
         }
+        part { name: "vol_state";
+           type: IMAGE;
+           mouse_events: 0;
+           repeat_events: 0;
+           description { state: "default" 0.0;
+              color:      0 0 0 0;
+           }
+           description { state: "visible" 0.0;
+              aspect: 1.0 1.0;
+              aspect_preference: BOTH;
+              align: 1.0 1.0;
+              min: 16 16;
+              rel1 {
+                 relative: 0.75 0.0;
+                 to: "icon";
+              }
+              rel2 {
+                 relative: 1.0 1.0;
+                 to: "icon";
+              }
+           }
+           description { state: "unmounted" 0.0;
+              inherit: "visible" 0.0;
+              image.normal:  "icon_efm_vol_unmounted.png";
+           }
+           description { state: "mounted" 0.0;
+              inherit: "visible" 0.0;
+              image.normal:  "icon_efm_vol_mounted.png";
+           }
+        }
         part { name: "dnd_action";
            type: IMAGE;
            mouse_events:  0;
@@ -14449,6 +14533,24 @@ collections { /* begin the collection of edje groups that are in this file */
            action: STATE_SET "copy" 0.0;
            target: "dnd_action";
         }
+        program { name: "vol_off";
+           signal: "e,state,volume,off";
+           source: "e";
+           action: STATE_SET "default" 0.0;
+           target: "vol_state";
+        }
+        program { name: "vol_unmounted";
+           signal: "e,state,volume,unmounted";
+           source: "e";
+           action: STATE_SET "unmounted" 0.0;
+           target: "vol_state";
+        }
+        program { name: "vol_mounted";
+           signal: "e,state,volume,mounted";
+           source: "e";
+           action: STATE_SET "mounted" 0.0;
+           target: "vol_state";
+        }
         program { name: "thumb_gen";
            signal:  "e,action,thumb,gen";
            source:  "e";
@@ -14509,6 +14611,9 @@ collections { /* begin the collection of edje groups that are in this file */
         image: "icon_efm_dnd_copy.png" COMP;
         image: "icon_efm_dnd_ask.png" COMP;
         image: "icon_efm_dnd_move.png" COMP;
+
+        image: "icon_efm_vol_unmounted.png" COMP;
+        image: "icon_efm_vol_mounted.png" COMP;
       }
       parts {
         part { name: "bg";
@@ -14768,6 +14873,36 @@ collections { /* begin the collection of edje groups that are in this file */
               color: 0 0 0 0;
            }
         }
+        part { name: "vol_state";
+           type: IMAGE;
+           mouse_events: 0;
+           repeat_events: 0;
+           description { state: "default" 0.0;
+              color:      0 0 0 0;
+           }
+           description { state: "visible" 0.0;
+              aspect: 1.0 1.0;
+              aspect_preference: BOTH;
+              align: 1.0 1.0;
+              min: 16 16;
+              rel1 {
+                 relative: 0.75 0.0;
+                 to: "icon";
+              }
+              rel2 {
+                 relative: 1.0 1.0;
+                 to: "icon";
+              }
+           }
+           description { state: "unmounted" 0.0;
+              inherit: "visible" 0.0;
+              image.normal:  "icon_efm_vol_unmounted.png";
+           }
+           description { state: "mounted" 0.0;
+              inherit: "visible" 0.0;
+              image.normal:  "icon_efm_vol_mounted.png";
+           }
+        }
         part { name: "dnd_action";
            type: IMAGE;
            mouse_events:  0;
@@ -14836,6 +14971,24 @@ collections { /* begin the collection of edje groups that are in this file */
            action: STATE_SET "copy" 0.0;
            target: "dnd_action";
         }
+        program { name: "vol_off";
+           signal: "e,state,volume,off";
+           source: "e";
+           action: STATE_SET "default" 0.0;
+           target: "vol_state";
+        }
+        program { name: "vol_unmounted";
+           signal: "e,state,volume,unmounted";
+           source: "e";
+           action: STATE_SET "unmounted" 0.0;
+           target: "vol_state";
+        }
+        program { name: "vol_mounted";
+           signal: "e,state,volume,mounted";
+           source: "e";
+           action: STATE_SET "mounted" 0.0;
+           target: "vol_state";
+        }
         program { name: "thumb_gen";
            signal:  "e,action,thumb,gen";
            source:  "e";
@@ -14896,6 +15049,9 @@ collections { /* begin the collection of edje groups that are in this file */
         image: "icon_efm_dnd_copy.png" COMP;
         image: "icon_efm_dnd_ask.png" COMP;
         image: "icon_efm_dnd_move.png" COMP;
+
+        image: "icon_efm_vol_unmounted.png" COMP;
+        image: "icon_efm_vol_mounted.png" COMP;
       }
       parts {
         part { name: "bg";
@@ -15155,6 +15311,36 @@ collections { /* begin the collection of edje groups that are in this file */
               color: 0 0 0 0;
            }
         }
+        part { name: "vol_state";
+           type: IMAGE;
+           mouse_events: 0;
+           repeat_events: 0;
+           description { state: "default" 0.0;
+              color:      0 0 0 0;
+           }
+           description { state: "visible" 0.0;
+              aspect: 1.0 1.0;
+              aspect_preference: BOTH;
+              align: 1.0 1.0;
+              min: 16 16;
+              rel1 {
+                 relative: 0.75 0.0;
+                 to: "icon";
+              }
+              rel2 {
+                 relative: 1.0 1.0;
+                 to: "icon";
+              }
+           }
+           description { state: "unmounted" 0.0;
+              inherit: "visible" 0.0;
+              image.normal:  "icon_efm_vol_unmounted.png";
+           }
+           description { state: "mounted" 0.0;
+              inherit: "visible" 0.0;
+              image.normal:  "icon_efm_vol_mounted.png";
+           }
+        }
         part { name: "dnd_action";
            type: IMAGE;
            mouse_events:  0;
@@ -15223,6 +15409,24 @@ collections { /* begin the collection of edje groups that are in this file */
            action: STATE_SET "copy" 0.0;
            target: "dnd_action";
         }
+        program { name: "vol_off";
+           signal: "e,state,volume,off";
+           source: "e";
+           action: STATE_SET "default" 0.0;
+           target: "vol_state";
+        }
+        program { name: "vol_unmounted";
+           signal: "e,state,volume,unmounted";
+           source: "e";
+           action: STATE_SET "unmounted" 0.0;
+           target: "vol_state";
+        }
+        program { name: "vol_mounted";
+           signal: "e,state,volume,mounted";
+           source: "e";
+           action: STATE_SET "mounted" 0.0;
+           target: "vol_state";
+        }
         program { name: "thumb_gen";
            signal:  "e,action,thumb,gen";
            source:  "e";
@@ -15287,6 +15491,9 @@ collections { /* begin the collection of edje groups that are in this file */
         image: "icon_efm_dnd_copy.png" COMP;
         image: "icon_efm_dnd_ask.png" COMP;
         image: "icon_efm_dnd_move.png" COMP;
+
+        image: "icon_efm_vol_unmounted.png" COMP;
+        image: "icon_efm_vol_mounted.png" COMP;
       }
       parts {
         part {
@@ -15599,6 +15806,35 @@ collections { /* begin the collection of edje groups that are in this file */
               color: 255 255 255 255;
            }
         }
+        part { name: "vol_state";
+           type: IMAGE;
+           mouse_events: 0;
+           repeat_events: 0;
+           description { state: "default" 0.0;
+              color:      0 0 0 0;
+           }
+           description { state: "visible" 0.0;
+              aspect: 1.0 1.0;
+              aspect_preference: BOTH;
+              align: 1.0 1.0;
+              rel1 {
+                 relative: 0.5 0.0;
+                 to: "icon";
+              }
+              rel2 {
+                 relative: 1.0 1.0;
+                 to: "icon";
+              }
+           }
+           description { state: "unmounted" 0.0;
+              inherit: "visible" 0.0;
+              image.normal:  "icon_efm_vol_unmounted.png";
+           }
+           description { state: "mounted" 0.0;
+              inherit: "visible" 0.0;
+              image.normal:  "icon_efm_vol_mounted.png";
+           }
+        }
         part { name: "dnd_action";
            type:          IMAGE;
            mouse_events:  0;
@@ -15695,6 +15931,24 @@ collections { /* begin the collection of edje groups that are in this file */
            action: STATE_SET "copy" 0.0;
            target: "dnd_action";
         }
+        program { name: "vol_off";
+           signal: "e,state,volume,off";
+           source: "e";
+           action: STATE_SET "default" 0.0;
+           target: "vol_state";
+        }
+        program { name: "vol_unmounted";
+           signal: "e,state,volume,unmounted";
+           source: "e";
+           action: STATE_SET "unmounted" 0.0;
+           target: "vol_state";
+        }
+        program { name: "vol_mounted";
+           signal: "e,state,volume,mounted";
+           source: "e";
+           action: STATE_SET "mounted" 0.0;
+           target: "vol_state";
+        }
         program { name: "thumb_gen";
            signal:  "e,action,thumb,gen";
            source:  "e";
@@ -15759,6 +16013,9 @@ collections { /* begin the collection of edje groups that are in this file */
         image: "icon_efm_dnd_copy.png" COMP;
         image: "icon_efm_dnd_ask.png" COMP;
         image: "icon_efm_dnd_move.png" COMP;
+
+        image: "icon_efm_vol_unmounted.png" COMP;
+        image: "icon_efm_vol_mounted.png" COMP;
       }
       parts {
         part {
@@ -16071,6 +16328,35 @@ collections { /* begin the collection of edje groups that are in this file */
               color: 255 255 255 255;
            }
         }
+        part { name: "vol_state";
+           type: IMAGE;
+           mouse_events: 0;
+           repeat_events: 0;
+           description { state: "default" 0.0;
+              color:      0 0 0 0;
+           }
+           description { state: "visible" 0.0;
+              aspect: 1.0 1.0;
+              aspect_preference: BOTH;
+              align: 1.0 1.0;
+              rel1 {
+                 relative: 0.5 0.0;
+                 to: "icon";
+              }
+              rel2 {
+                 relative: 1.0 1.0;
+                 to: "icon";
+              }
+           }
+           description { state: "unmounted" 0.0;
+              inherit: "visible" 0.0;
+              image.normal:  "icon_efm_vol_unmounted.png";
+           }
+           description { state: "mounted" 0.0;
+              inherit: "visible" 0.0;
+              image.normal:  "icon_efm_vol_mounted.png";
+           }
+        }
         part { name: "dnd_action";
            type:          IMAGE;
            mouse_events:  0;
@@ -16167,6 +16453,24 @@ collections { /* begin the collection of edje groups that are in this file */
            action: STATE_SET "copy" 0.0;
            target: "dnd_action";
         }
+        program { name: "vol_off";
+           signal: "e,state,volume,off";
+           source: "e";
+           action: STATE_SET "default" 0.0;
+           target: "vol_state";
+        }
+        program { name: "vol_unmounted";
+           signal: "e,state,volume,unmounted";
+           source: "e";
+           action: STATE_SET "unmounted" 0.0;
+           target: "vol_state";
+        }
+        program { name: "vol_mounted";
+           signal: "e,state,volume,mounted";
+           source: "e";
+           action: STATE_SET "mounted" 0.0;
+           target: "vol_state";
+        }
         program { name: "thumb_gen";
            signal:  "e,action,thumb,gen";
            source:  "e";
@@ -16232,6 +16536,9 @@ collections { /* begin the collection of edje groups that are in this file */
         image: "icon_efm_dnd_copy.png" COMP;
         image: "icon_efm_dnd_ask.png" COMP;
         image: "icon_efm_dnd_move.png" COMP;
+
+        image: "icon_efm_vol_unmounted.png" COMP;
+        image: "icon_efm_vol_mounted.png" COMP;
       }
       parts {
         part {
@@ -16545,6 +16852,35 @@ collections { /* begin the collection of edje groups that are in this file */
               color: 255 255 255 255;
            }
         }
+        part { name: "vol_state";
+           type: IMAGE;
+           mouse_events: 0;
+           repeat_events: 0;
+           description { state: "default" 0.0;
+              color:      0 0 0 0;
+           }
+           description { state: "visible" 0.0;
+              aspect: 1.0 1.0;
+              aspect_preference: BOTH;
+              align: 1.0 1.0;
+              rel1 {
+                 relative: 0.5 0.0;
+                 to: "icon";
+              }
+              rel2 {
+                 relative: 1.0 1.0;
+                 to: "icon";
+              }
+           }
+           description { state: "unmounted" 0.0;
+              inherit: "visible" 0.0;
+              image.normal:  "icon_efm_vol_unmounted.png";
+           }
+           description { state: "mounted" 0.0;
+              inherit: "visible" 0.0;
+              image.normal:  "icon_efm_vol_mounted.png";
+           }
+        }
         part { name: "dnd_action";
            type:          IMAGE;
            mouse_events:  0;
@@ -16641,6 +16977,24 @@ collections { /* begin the collection of edje groups that are in this file */
            action: STATE_SET "copy" 0.0;
            target: "dnd_action";
         }
+        program { name: "vol_off";
+           signal: "e,state,volume,off";
+           source: "e";
+           action: STATE_SET "default" 0.0;
+           target: "vol_state";
+        }
+        program { name: "vol_unmounted";
+           signal: "e,state,volume,unmounted";
+           source: "e";
+           action: STATE_SET "unmounted" 0.0;
+           target: "vol_state";
+        }
+        program { name: "vol_mounted";
+           signal: "e,state,volume,mounted";
+           source: "e";
+           action: STATE_SET "mounted" 0.0;
+           target: "vol_state";
+        }
         program { name: "thumb_gen";
            signal:  "e,action,thumb,gen";
            source:  "e";
@@ -16706,6 +17060,9 @@ collections { /* begin the collection of edje groups that are in this file */
         image: "icon_efm_dnd_copy.png" COMP;
         image: "icon_efm_dnd_ask.png" COMP;
         image: "icon_efm_dnd_move.png" COMP;
+
+        image: "icon_efm_vol_unmounted.png" COMP;
+        image: "icon_efm_vol_mounted.png" COMP;
       }
       parts {
         part {
@@ -17018,6 +17375,35 @@ collections { /* begin the collection of edje groups that are in this file */
               color: 255 255 255 255;
            }
         }
+        part { name: "vol_state";
+           type: IMAGE;
+           mouse_events: 0;
+           repeat_events: 0;
+           description { state: "default" 0.0;
+              color:      0 0 0 0;
+           }
+           description { state: "visible" 0.0;
+              aspect: 1.0 1.0;
+              aspect_preference: BOTH;
+              align: 1.0 1.0;
+              rel1 {
+                 relative: 0.5 0.0;
+                 to: "icon";
+              }
+              rel2 {
+                 relative: 1.0 1.0;
+                 to: "icon";
+              }
+           }
+           description { state: "unmounted" 0.0;
+              inherit: "visible" 0.0;
+              image.normal:  "icon_efm_vol_unmounted.png";
+           }
+           description { state: "mounted" 0.0;
+              inherit: "visible" 0.0;
+              image.normal:  "icon_efm_vol_mounted.png";
+           }
+        }
         part { name: "dnd_action";
            type:          IMAGE;
            mouse_events:  0;
@@ -17114,6 +17500,24 @@ collections { /* begin the collection of edje groups that are in this file */
            action: STATE_SET "copy" 0.0;
            target: "dnd_action";
         }
+        program { name: "vol_off";
+           signal: "e,state,volume,off";
+           source: "e";
+           action: STATE_SET "default" 0.0;
+           target: "vol_state";
+        }
+        program { name: "vol_unmounted";
+           signal: "e,state,volume,unmounted";
+           source: "e";
+           action: STATE_SET "unmounted" 0.0;
+           target: "vol_state";
+        }
+        program { name: "vol_mounted";
+           signal: "e,state,volume,mounted";
+           source: "e";
+           action: STATE_SET "mounted" 0.0;
+           target: "vol_state";
+        }
         program { name: "thumb_gen";
            signal:  "e,action,thumb,gen";
            source:  "e";
@@ -23758,6 +24162,9 @@ ICON("computer","icon_efm_root.png", 64)                        // "fileman/root
 ICON("drive-harddisk","icon_efm_hdd.png", 128)                  // "fileman/hd" "fileman/hdd"
 ICON("drive-optical","icon_efm_cd.png", 128)                    // "fileman/??"
 ICON("media-flash","icon_efm_flash.png", 128)                   // "fileman/??"
+ICON("drive-removable-media","icon_efm_usbmedia.png", 128);
+
+ICON("media-eject","icon_efm_eject.png", 64)
 
 /* End of FreeDesktop.Org icons */
 
index c77cab1..8c63e83 100644 (file)
--- a/po/ru.po
+++ b/po/ru.po
@@ -7469,3 +7469,23 @@ msgstr "Система"
 
 #~ msgid "Add To Favorites Menu"
 #~ msgstr "Добавить в Избранное"
+
+#: ../src/bin/e_fm.c:8045
+msgid "Mount"
+msgstr "Подключить"
+
+#: ../src/bin/e_fm.c:8040
+msgid "Unmount"
+msgstr "Отключить"
+
+#: ../src/bin/e_fm.c:8050
+msgid "Eject"
+msgstr "Извлечь"
+
+#: ../src/modules/fileman/e_mod_config.c:273
+msgid "Mount volumes on insert"
+msgstr "Монтировать тома при подключении"
+
+#: ../src/modules/fileman/e_mod_config.c:276
+msgid "Open filemanager on mount"
+msgstr "Открыть менеджер файлов при монтировании"
index b74c7d3..fe5a48e 100644 (file)
@@ -656,6 +656,8 @@ e_config_init(void)
    E_CONFIG_VAL(D, T, thumbscroll_friction, DOUBLE);
    
    E_CONFIG_VAL(D, T, hal_desktop, INT);
+   E_CONFIG_VAL(D, T, hal_auto_mount, INT);
+   E_CONFIG_VAL(D, T, hal_auto_open, INT);
 
    E_CONFIG_VAL(D, T, border_keyboard.timeout, DOUBLE);
    E_CONFIG_VAL(D, T, border_keyboard.move.dx, UCHAR);
@@ -663,8 +665,6 @@ e_config_init(void)
    E_CONFIG_VAL(D, T, border_keyboard.resize.dx, UCHAR);
    E_CONFIG_VAL(D, T, border_keyboard.resize.dy, UCHAR);
 
-   E_CONFIG_VAL(D, T, hal_desktop, INT);
-
    E_CONFIG_VAL(D, T, scale.min, DOUBLE);
    E_CONFIG_VAL(D, T, scale.max, DOUBLE);
    E_CONFIG_VAL(D, T, scale.factor, DOUBLE);
index 2fac4c8..53d7f31 100644 (file)
@@ -302,6 +302,8 @@ struct _E_Config
    double thumbscroll_friction; // GUI
 
    int hal_desktop;
+   int hal_auto_mount;
+   int hal_auto_open;
 
    struct {
       double timeout;
index 644ff04..07f9a2c 100644 (file)
@@ -359,6 +359,8 @@ static void _e_fm_error_abort_cb(void *data, E_Dialog *dialog);
 static void _e_fm_error_ignore_this_cb(void *data, E_Dialog *dialog);
 static void _e_fm_error_ignore_all_cb(void *data, E_Dialog *dialog);
 
+static void _e_fm_hal_error_dialog(const char *title, const char *msg, const char *pstr);
+
 static void _e_fm2_file_delete(Evas_Object *obj);
 static void _e_fm2_file_delete_menu(void *data, E_Menu *m, E_Menu_Item *mi);
 static void _e_fm2_file_delete_delete_cb(void *obj);
@@ -408,6 +410,15 @@ static int _e_fm2_context_list_sort(const void *data1, const void *data2);
 static char *_e_fm_string_append_char(char *str, size_t *size, size_t *len, char c);
 static char *_e_fm_string_append_quoted(char *str, size_t *size, size_t *len, const char *src);
 
+void _e_fm2_path_parent_set(Evas_Object *obj, const char *path);
+
+static void _e_fm2_volume_mount(void *data, E_Menu *m, E_Menu_Item *mi);
+static void _e_fm2_volume_unmount(void *data, E_Menu *m, E_Menu_Item *mi);
+static void _e_fm2_volume_eject(void *data, E_Menu *m, E_Menu_Item *mi);
+
+static void _e_fm2_icon_removable_update(E_Fm2_Icon *ic);
+static void _e_fm2_volume_icon_update(E_Volume *v);
+
 static char *_e_fm2_meta_path = NULL;
 static Evas_Smart *_e_fm2_smart = NULL;
 static Eina_List *_e_fm2_list = NULL;
@@ -809,12 +820,31 @@ _e_fm2_cb_mount_fail(void *data)
 
    sd = evas_object_smart_data_get(data);
    if (!sd) return; // safety
-   /* FIXME; some dialog */
    if (sd->mount)
      {
-       e_fm2_hal_unmount(sd->mount);
+        // At this moment E_Fm2_Mount object already deleted in e_fm_hal.c
        sd->mount = NULL;
-       evas_object_smart_callback_call(data, "dir_deleted", NULL);
+        if (sd->config->view.open_dirs_in_place)
+           e_fm2_path_set(data, "favorites", "/");
+        else
+           evas_object_smart_callback_call(data, "dir_deleted", NULL);
+     }
+}
+
+static void
+_e_fm2_cb_unmount_ok(void *data)
+{
+   E_Fm2_Smart_Data *sd;
+
+   sd = evas_object_smart_data_get(data);
+   if (!sd) return;
+   if (sd->mount)
+     {
+        sd->mount = NULL;
+        if (sd->config->view.open_dirs_in_place)
+           _e_fm2_path_parent_set(data, sd->realpath);
+        else
+           evas_object_smart_callback_call(data, "dir_deleted", NULL);
      }
 }
 
@@ -945,7 +975,7 @@ e_fm2_path_set(Evas_Object *obj, const char *dev, const char *path)
        if (v)
          sd->mount = e_fm2_hal_mount(v,
                                     _e_fm2_cb_mount_ok, _e_fm2_cb_mount_fail,
-                                    NULL, NULL, obj);
+                                    _e_fm2_cb_unmount_ok, NULL, obj);
      }
    else if (sd->config->view.open_dirs_in_place == 0)
      {
@@ -954,7 +984,7 @@ e_fm2_path_set(Evas_Object *obj, const char *dev, const char *path)
        if (m)
          sd->mount = e_fm2_hal_mount(m->volume,
                                     _e_fm2_cb_mount_ok, _e_fm2_cb_mount_fail,
-                                    NULL, NULL, obj);
+                                    _e_fm2_cb_unmount_ok, NULL, obj);
      }
 
    if (!sd->mount || sd->mount->mounted)
@@ -2578,6 +2608,19 @@ _e_fm2_client_unmount(const char *udi)
    return _e_fm_client_send_new(E_FM_OP_UNMOUNT, (void *)d, l);
 }
 
+EAPI int
+_e_fm2_client_eject(const char *udi)
+{
+   char *data;
+   int size;
+
+   size = strlen(udi) + 1;
+   data = alloca(size);
+   strcpy(data, udi);
+
+   return _e_fm_client_send_new(E_FM_OP_EJECT, data, size);
+}
+
 static void
 _e_fm2_client_monitor_list_end(Evas_Object *obj)
 {
@@ -2907,7 +2950,13 @@ e_fm2_client_data(Ecore_Ipc_Event_Client_Data *e)
             E_Volume *v;
 
             v = eet_data_descriptor_decode(_e_volume_edd, e->data, e->size);
-            if (v) e_fm2_hal_volume_add(v);
+            if (v) 
+              {
+                 e_fm2_hal_volume_add(v);
+                 if (e_config->hal_auto_mount && !v->mounted && !v->first_time)
+                    _e_fm2_client_mount(v->udi, v->mount_point);
+                 v->first_time = 0;
+              }
          }
        break;
 
@@ -2932,7 +2981,21 @@ e_fm2_client_data(Ecore_Ipc_Event_Client_Data *e)
             udi = e->data;
             mountpoint = udi + strlen(udi) + 1;
             v = e_fm2_hal_volume_find(udi);
-            if (v) e_fm2_hal_mount_add(v, mountpoint);
+            if (v) 
+               {
+                  e_fm2_hal_mount_add(v, mountpoint);
+                  _e_fm2_volume_icon_update(v);
+                  if (e_config->hal_auto_open && !eina_list_count(v->mounts))
+                    {
+                       E_Action *a;
+                       Eina_List *m;
+
+                       a = e_action_find("fileman");
+                       m = e_manager_list();
+                       if (a && a->func.go && m && m->data)
+                          a->func.go(E_OBJECT(m->data), mountpoint);
+                    }
+               }
          }
        break;
 
@@ -2944,15 +3007,62 @@ e_fm2_client_data(Ecore_Ipc_Event_Client_Data *e)
 
             udi = e->data;
             v = e_fm2_hal_volume_find(udi);
-            if (v)
-              {
-                 v->mounted = 0;
-                 if (v->mount_point) free(v->mount_point);
-                 v->mount_point = NULL;
-              }
+            if (v) 
+               {
+                  e_fm2_hal_mount_del(v);
+                  _e_fm2_volume_icon_update(v);
+               }
          }
        break;
 
+      case E_FM_OP_EJECT_DONE:
+        break;
+        
+      case E_FM_OP_MOUNT_ERROR:/*mount error*/
+        if (e->data && (e->size > 1))
+          {
+             E_Volume *v;
+             char *udi;
+
+             udi = e->data;
+             v = e_fm2_hal_volume_find(udi);
+             if (v) 
+               {
+                  _e_fm_hal_error_dialog(_("Mount Error"), _("Can't mount device"), e->data);
+                  e_fm2_hal_mount_fail(v);
+               }
+          }
+        break;
+        
+      case E_FM_OP_UNMOUNT_ERROR:/*unmount error*/
+        if (e->data && (e->size > 1))
+          {
+             E_Volume *v;
+             char *udi;
+
+             udi = e->data;
+             v = e_fm2_hal_volume_find(udi);
+             if (v)
+               {
+                  _e_fm_hal_error_dialog(_("Unmount Error"), _("Can't unmount device"), e->data);
+                  e_fm2_hal_unmount_fail(v);
+               }
+          }
+        break;
+        
+      case E_FM_OP_EJECT_ERROR:
+        if (e->data && (e->size > 1))
+          {
+             E_Volume *v;
+             char *udi;
+
+             udi = e->data;
+             v = e_fm2_hal_volume_find(udi);
+             if (v)
+                _e_fm_hal_error_dialog(_("Eject Error"), _("Can't eject device"), e->data);
+          }
+        break;
+        
       case E_FM_OP_ERROR:/*error*/
         printf("%s:%s(%d) Error from slave #%d: %s\n", __FILE__, __FUNCTION__, __LINE__, e->ref, (char *)e->data);
         _e_fm_error_dialog(e->ref, e->data);
@@ -4601,10 +4711,9 @@ _e_fm2_icon_realize(E_Fm2_Icon *ic)
         if ((selectraise) && (!strcmp(selectraise, "on")))
          evas_object_stack_below(ic->obj, ic->sd->drop);
      }
-   if (ic->info.removable_full)
-     edje_object_signal_emit(ic->obj_icon, "e,state,removable,full", "e");
-//   else
-//     edje_object_signal_emit(ic->obj_icon, "e,state,removable,empty", "e");
+
+   if (ic->info.removable)
+      _e_fm2_icon_removable_update(ic);
 }
 
 static void
@@ -7817,6 +7926,7 @@ _e_fm2_icon_menu(E_Fm2_Icon *ic, Evas_Object *obj, unsigned int timestamp)
                  e_menu_item_callback_set(mi, _e_fm2_new_directory, sd);
               }
          }
+       if (!ic->info.removable) {
        if (!(sd->icon_menu.flags & E_FM2_MENU_NO_CUT))
          {
             if (ecore_file_can_write(sd->realpath))
@@ -7865,7 +7975,8 @@ _e_fm2_icon_menu(E_Fm2_Icon *ic, Evas_Object *obj, unsigned int timestamp)
                  e_menu_item_callback_set(mi, _e_fm2_file_symlink_menu, sd);
               }
          }
-
+       }
+       
        can_w = 0;
        can_w2 = 1;
        if (ic->sd->order_file)
@@ -7909,7 +8020,7 @@ _e_fm2_icon_menu(E_Fm2_Icon *ic, Evas_Object *obj, unsigned int timestamp)
          protect = 0;
        sel = eina_list_free(sel);
 
-       if ((can_w) && (can_w2) && !(protect))
+       if ((can_w) && (can_w2) && !(protect) && !ic->info.removable)
          {
             mi = e_menu_item_new(mn);
             e_menu_item_separator_set(mi, 1);
@@ -7931,10 +8042,42 @@ _e_fm2_icon_menu(E_Fm2_Icon *ic, Evas_Object *obj, unsigned int timestamp)
               }
          }
 
-       mi = e_menu_item_new(mn);
-       e_menu_item_label_set(mi, _("Properties"));
-       e_util_menu_item_theme_icon_set(mi, "document-properties");
-       e_menu_item_callback_set(mi, _e_fm2_file_properties, ic);
+       if (ic->info.removable)
+         {
+            E_Volume *v;
+            
+             v = e_fm2_hal_volume_find(ic->info.link);
+             if (v)
+               {
+                  mi = e_menu_item_new(mn);
+                  e_menu_item_separator_set(mi, 1);
+
+                  mi = e_menu_item_new(mn);
+                  if (v->mounted)
+                    {
+                       e_menu_item_label_set(mi, _("Unmount"));
+                       e_menu_item_callback_set(mi, _e_fm2_volume_unmount, v);
+                    }
+                  else
+                    {
+                       e_menu_item_label_set(mi, _("Mount"));
+                       e_menu_item_callback_set(mi, _e_fm2_volume_mount, v);
+                    }
+                  
+                  mi = e_menu_item_new(mn);
+                  e_menu_item_label_set(mi, _("Eject"));
+                  e_util_menu_item_theme_icon_set(mi, "media-eject");
+                  e_menu_item_callback_set(mi, _e_fm2_volume_eject, v);
+
+                  mi = e_menu_item_new(mn);
+                  e_menu_item_separator_set(mi, 1);
+               }
+         }
+       
+        mi = e_menu_item_new(mn);
+        e_menu_item_label_set(mi, _("Properties"));
+        e_util_menu_item_theme_icon_set(mi, "document-properties");
+        e_menu_item_callback_set(mi, _e_fm2_file_properties, ic);
 
        if (ic->info.mime)
          {
@@ -9002,6 +9145,37 @@ _e_fm_error_ignore_all_cb(void *data, E_Dialog *dialog)
 }
 
 static void
+_e_fm_hal_error_dialog(const char *title, const char *msg, const char *pstr)
+{
+   E_Manager *man;
+   E_Container *con;
+   E_Dialog *dialog;
+   char text[4096];
+   const char *u, *d, *n, *m;
+
+   man = e_manager_current_get();
+   if (!man) return;
+   con = e_container_current_get(man);
+   if (!con) return;
+
+   dialog = e_dialog_new(con, "E", "_fm_hal_error_dialog");
+   e_dialog_title_set(dialog, title);
+   e_dialog_icon_set(dialog, "drive-harddisk", 64);
+   e_dialog_button_add(dialog, _("OK"), NULL, NULL, NULL);
+   
+   u = pstr;
+   d = pstr += strlen(pstr) + 1;
+   n = pstr += strlen(pstr) + 1;
+   m = pstr += strlen(pstr) + 1;
+   snprintf(text, sizeof(text), "%s<br>%s<br>%s<br>%s<br>%s", msg, u, d, n, m);
+   e_dialog_text_set(dialog, text);
+
+   e_win_centered_set(dialog->win, 1);
+   e_dialog_button_focus_num(dialog, 0);
+   e_dialog_show(dialog);
+}
+
+static void
 _e_fm2_file_properties(void *data, E_Menu *m, E_Menu_Item *mi)
 {
    E_Fm2_Icon *ic;
@@ -9369,10 +9543,7 @@ _e_fm2_live_process(Evas_Object *obj)
                                 ic->removable_state_change = 0;
                                 if ((ic->realized) && (ic->obj_icon))
                                   {
-                                     if (ic->info.removable_full)
-                                       edje_object_signal_emit(ic->obj_icon, "e,state,removable,full", "e");
-                                     else
-                                       edje_object_signal_emit(ic->obj_icon, "e,state,removable,empty", "e");
+                                     _e_fm2_icon_removable_update(ic);
                                      _e_fm2_icon_label_set(ic, ic->obj);
                                   }
                              }
@@ -9510,3 +9681,101 @@ _e_fm2_theme_edje_icon_object_set(E_Fm2_Smart_Data *sd, Evas_Object *o, const ch
    ret = e_theme_edje_object_set(o, category, buf);
    return ret;
 }
+
+static void 
+_e_fm2_volume_mount(void *data, E_Menu *m, E_Menu_Item *mi)
+{
+   E_Volume *v;
+   char *mp;
+   
+   v = data;
+   if (!v) return;
+   
+   mp = e_fm2_hal_volume_mountpoint_get(v);
+   _e_fm2_client_mount(v->udi, mp);
+   free(mp);
+}
+
+static void 
+_e_fm2_volume_unmount(void *data, E_Menu *m, E_Menu_Item *mi)
+{
+   E_Volume *v;
+   
+   v = data;
+   if (!v) return;
+   
+   v->auto_unmount = 0;
+   _e_fm2_client_unmount(v->udi);
+}
+
+static void 
+_e_fm2_volume_eject(void *data, E_Menu *m, E_Menu_Item *mi)
+{
+   E_Volume *v;
+   
+   v = data;
+   if (!v) return;
+   
+   v->auto_unmount = 0;
+   _e_fm2_client_eject(v->udi);
+}
+
+static void
+_update_volume_icon(E_Volume *v, E_Fm2_Icon *ic)
+{
+   if (ic->info.removable_full)
+     edje_object_signal_emit(ic->obj_icon, "e,state,removable,full", "e");
+   else
+     edje_object_signal_emit(ic->obj_icon, "e,state,removable,empty", "e");
+
+   if (v)
+     {
+        if (v->mounted)
+           edje_object_signal_emit(ic->obj, "e,state,volume,mounted", "e");
+        else
+           edje_object_signal_emit(ic->obj, "e,state,volume,unmounted", "e");
+     }
+   else
+      edje_object_signal_emit(ic->obj, "e,state,volume,off", "e");
+}
+
+static void
+_e_fm2_volume_icon_update(E_Volume *v)
+{
+   Evas_Object *o;
+   char file[PATH_MAX], fav[PATH_MAX], desk[PATH_MAX];
+   Eina_List *l;
+   E_Fm2_Icon *ic;
+
+   if (!v || !v->storage) return;
+   
+   e_user_dir_snprintf(fav, sizeof(fav), "fileman/favorites");
+   e_user_homedir_snprintf(desk, sizeof(desk), "Desktop");
+   snprintf(file, sizeof(file), "|%s_%d.desktop", 
+            ecore_file_file_get(v->storage->udi), v->partition_number);
+   
+   EINA_LIST_FOREACH(_e_fm2_list, l, o)
+     {
+        const char *rp;
+        
+        if ((_e_fm2_list_walking > 0) &&
+            (eina_list_data_find(_e_fm2_list_remove, o))) continue;
+        
+        rp = e_fm2_real_path_get(o);
+        if (strcmp(rp, fav) && strcmp(rp, desk)) continue;
+        
+        ic = _e_fm2_icon_find(l->data, file);
+        if (ic)
+           _update_volume_icon(v, ic);
+     }
+}
+
+static void
+_e_fm2_icon_removable_update(E_Fm2_Icon *ic)
+{
+   E_Volume *v;
+   
+   if (!ic) return;
+   v = e_fm2_hal_volume_find(ic->info.link);
+   _update_volume_icon(v, ic);
+}
index 76044d0..9cfa396 100644 (file)
@@ -9,8 +9,11 @@
 
 static void _e_fm2_volume_write(E_Volume *v) EINA_ARG_NONNULL(1);
 static void _e_fm2_volume_erase(E_Volume *v) EINA_ARG_NONNULL(1);
+static void _e_fm2_hal_mount_free(E_Fm2_Mount *m); EINA_ARG_NONNULL(1);
 static void _e_fm2_hal_mount_ok(E_Fm2_Mount *m) EINA_ARG_NONNULL(1);
-static int  _e_fm2_hal_mount_timeout(E_Fm2_Mount *m) EINA_ARG_NONNULL(1);
+static void _e_fm2_hal_mount_fail(E_Fm2_Mount *m) EINA_ARG_NONNULL(1);
+static void _e_fm2_hal_unmount_ok(E_Fm2_Mount *m) EINA_ARG_NONNULL(1);
+static void _e_fm2_hal_unmount_fail(E_Fm2_Mount *m) EINA_ARG_NONNULL(1);
 
 static Eina_List *_e_stores = NULL;
 static Eina_List *_e_vols   = NULL;
@@ -268,11 +271,20 @@ e_fm2_hal_volume_add(E_Volume *v)
 EAPI void
 e_fm2_hal_volume_del(E_Volume *v)
 {
+   Eina_List *l, *l_nxt;
+   E_Fm2_Mount *m;
+   
 //   printf("VOL- %s\n", v->udi);
    if (v->storage) 
      v->storage->volumes = eina_list_remove(v->storage->volumes, v);
    _e_vols = eina_list_remove(_e_vols, v);
    _e_fm2_volume_erase(v);
+   EINA_LIST_FOREACH_SAFE(v->mounts, l, l_nxt, m)
+     {
+        _e_fm2_hal_unmount_ok(m);
+        v->mounts = eina_list_remove_list(v->mounts, l);
+        _e_fm2_hal_mount_free(m);
+     }
    _e_volume_free(v);
 }
 
@@ -403,7 +415,12 @@ e_fm2_hal_mount_add(E_Volume *v, const char *mountpoint)
    Eina_List *l;
 
    v->mounted = 1;
-   v->mount_point = strdup(mountpoint);
+   if (mountpoint && (*mountpoint != 0))
+     {
+        if (v->mount_point) 
+           free(v->mount_point);
+        v->mount_point = strdup(mountpoint);
+     }
 
    for (l = v->mounts; l; l = l->next)
      _e_fm2_hal_mount_ok(l->data);
@@ -412,18 +429,34 @@ e_fm2_hal_mount_add(E_Volume *v, const char *mountpoint)
 }
 
 EAPI void
-e_fm2_hal_mount_del(E_Fm2_Mount *m)
+e_fm2_hal_mount_del(E_Volume *v)
+{
+   Eina_List *l, *l_nxt;
+   E_Fm2_Mount *m;
+   
+   v->mounted = 0;
+   if (v->mount_point) 
+     {
+        free(v->mount_point);
+        v->mount_point = NULL;
+     }
+
+   EINA_LIST_FOREACH_SAFE(v->mounts, l, l_nxt, m)
+     {
+        _e_fm2_hal_unmount_ok(m);
+        v->mounts = eina_list_remove_list(v->mounts, l);
+        _e_fm2_hal_mount_free(m);
+     }
+}
+
+EAPI void
+_e_fm2_hal_mount_free(E_Fm2_Mount *m)
 {
    if (!m) return;
 
    if (m->udi) eina_stringshare_del(m->udi);
    if (m->mount_point) eina_stringshare_del(m->mount_point);
 
-   if (m->timeout) 
-     {
-       ecore_timer_del(m->timeout);
-       m->timeout = NULL;
-     }
    free(m);
 }
 
@@ -469,49 +502,109 @@ e_fm2_hal_mount(E_Volume *v,
    v->mounts = eina_list_prepend(v->mounts, m);
 
 //   printf("BEGIN MOUNT %p '%s'\n", m, v->mount_point);
-   
+
    if (!v->mounted)
      {
-       if (m->timeout) ecore_timer_del(m->timeout);
-       m->timeout = ecore_timer_add(10.0, (int (*)(void*))_e_fm2_hal_mount_timeout, m);
+        v->auto_unmount = 1;
        _e_fm2_client_mount(v->udi, v->mount_point);
      }
+   else
+     {
+        v->auto_unmount = 0;
+        m->mount_point = eina_stringshare_add(v->mount_point);
+     }
+
    return m;
 }
 
 EAPI void
+e_fm2_hal_mount_fail(E_Volume *v)
+{
+   Eina_List *l, *l_nxt;
+   E_Fm2_Mount *m;
+
+   v->mounted = 0;
+   if (v->mount_point) 
+     {
+        free(v->mount_point);
+        v->mount_point = NULL;
+     }
+
+   EINA_LIST_FOREACH_SAFE(v->mounts, l, l_nxt, m)
+     {
+        _e_fm2_hal_mount_fail(m);
+        v->mounts = eina_list_remove_list(v->mounts, l);
+        _e_fm2_hal_mount_free(m);
+     }
+}
+
+EAPI void
 e_fm2_hal_unmount(E_Fm2_Mount *m)
 {
    E_Volume *v;
 
    if (!(v = m->volume)) return;
    v->mounts = eina_list_remove(v->mounts, m);
-   e_fm2_hal_mount_del(m);
+   _e_fm2_hal_mount_free(m);
 
-   if (!eina_list_count(v->mounts))
+   if (v->auto_unmount && v->mounted && !eina_list_count(v->mounts))
      _e_fm2_client_unmount(v->udi);
 }
 
+EAPI void
+e_fm2_hal_unmount_fail(E_Volume *v)
+{
+   Eina_List *l;
+
+   v->mounted = 1;
+
+   for (l = v->mounts; l; l = l->next)
+     _e_fm2_hal_unmount_fail(l->data);
+}
+
 static void
 _e_fm2_hal_mount_ok(E_Fm2_Mount *m)
 {
    m->mounted = 1;
-   if (m->volume) m->mount_point = eina_stringshare_add(m->volume->mount_point);
-   if (m->timeout)
+   if (m->volume) 
+      m->mount_point = eina_stringshare_add(m->volume->mount_point);
+   if (m->mount_ok) 
+      m->mount_ok(m->data);
+//   printf("MOUNT OK '%s'\n", m->mount_point);
+}
+
+static void
+_e_fm2_hal_mount_fail(E_Fm2_Mount *m)
+{
+   m->mounted = 0;
+   if (m->mount_point)
      {
-       ecore_timer_del(m->timeout);
-       m->timeout = NULL;
+        eina_stringshare_del(m->mount_point);
+        m->mount_point = NULL;
      }
-   if (m->mount_ok) m->mount_ok(m->data);
-//   printf("MOUNT OK '%s'\n", m->mount_point);
+   if (m->mount_fail) 
+     m->mount_fail(m->data);
+}
+
+static void
+_e_fm2_hal_unmount_ok(E_Fm2_Mount *m)
+{
+   m->mounted = 0;
+   if (m->mount_point)
+     {
+        eina_stringshare_del(m->mount_point);
+        m->mount_point = NULL;
+     }
+   if (m->unmount_ok) 
+      m->unmount_ok(m->data);
 }
 
-static int
-_e_fm2_hal_mount_timeout(E_Fm2_Mount *m)
+static void
+_e_fm2_hal_unmount_fail(E_Fm2_Mount *m)
 {
-   m->mount_fail(m->data);
-   m->timeout = NULL;
-   return 0;
+   m->mounted = 1;
+   if (m->unmount_fail) 
+     m->unmount_fail(m->data);
 }
 
 EAPI void
index 9c7e708..521daa4 100644 (file)
@@ -17,13 +17,15 @@ EAPI E_Volume    *e_fm2_hal_volume_find(const char *udi);
 EAPI char        *e_fm2_hal_volume_mountpoint_get(E_Volume *v);
 
 EAPI void         e_fm2_hal_mount_add(E_Volume *v, const char *mountpoint);
-EAPI void         e_fm2_hal_mount_del(E_Fm2_Mount *m);
+EAPI void         e_fm2_hal_mount_del(E_Volume *v);
 EAPI E_Fm2_Mount *e_fm2_hal_mount_find(const char *path);
 EAPI E_Fm2_Mount *e_fm2_hal_mount(E_Volume *v,
                                   void (*mount_ok) (void *data), void (*mount_fail) (void *data), 
                                  void (*unmount_ok) (void *data), void (*unmount_fail) (void *data), 
                                  void *data);
+EAPI void         e_fm2_hal_mount_fail(E_Volume *v);
 EAPI void         e_fm2_hal_unmount(E_Fm2_Mount *m);
+EAPI void         e_fm2_hal_unmount_fail(E_Volume *v);
 
 EAPI void         e_fm2_hal_show_desktop_icons(void);
 EAPI void         e_fm2_hal_hide_desktop_icons(void);
index 158d69b..60386fb 100644 (file)
 #define DEF_ROUND_TRIP_TOLERANCE 0.01
 #define DEF_MOD_BACKOFF 0.2
 
+#define E_FM_MOUNT_TIMEOUT 30.0
+#define E_FM_UNMOUNT_TIMEOUT 60.0
+#define E_FM_EJECT_TIMEOUT 15.0
+
 typedef struct _E_Dir E_Dir;
 typedef struct _E_Fop E_Fop;
 typedef struct _E_Mod E_Mod;
@@ -189,17 +193,26 @@ static void _e_dbus_cb_vol_prop(void *data, void *reply_data, DBusError *error);
 static void _e_dbus_cb_vol_prop_mount_modified(void *data, void *reply_data, DBusError *error);
 static void _e_dbus_cb_vol_mounted(void *user_data, void *method_return, DBusError *error);
 static void _e_dbus_cb_vol_unmounted(void *user_data, void *method_return, DBusError *error);
+static void _e_dbus_cb_vol_unmounted_before_eject(void *user_data, void *method_return, DBusError *error);
+static int  _e_dbus_vb_vol_ejecting_after_unmount(void *data);
+static void _e_dbus_cb_vol_ejected(void *user_data, void *method_return, DBusError *error);
+static int  _e_dbus_format_error_msg(char **buf, E_Volume *v, DBusError *error);
+
+static int  _e_dbus_vol_mount_timeout(void *data);
+static int  _e_dbus_vol_unmount_timeout(void *data);
+static int  _e_dbus_vol_eject_timeout(void *data);
 
 EAPI E_Storage *e_storage_add(const char *udi);
 EAPI void       e_storage_del(const char *udi);
 EAPI E_Storage *e_storage_find(const char *udi);
 
-EAPI E_Volume *e_volume_add(const char *udi);
+EAPI E_Volume *e_volume_add(const char *udi, char first_time);
 EAPI void      e_volume_del(const char *udi);
 EAPI E_Volume *e_volume_find(const char *udi);
 
 EAPI void      e_volume_mount(E_Volume *v);
 EAPI void      e_volume_unmount(E_Volume *v);
+EAPI void      e_volume_eject(E_Volume *v);
 
 /* local subsystem globals */
 static Ecore_Ipc_Server *_e_ipc_server = NULL;
@@ -366,7 +379,7 @@ _e_dbus_cb_dev_vol(void *user_data, void *reply_data, DBusError *error)
    EINA_LIST_FOREACH(ret->strings, l, device)
      {
 //     printf("DB VOL+: %s\n", device);
-       e_volume_add(device);
+       e_volume_add(device, 1);
      }
 }
 
@@ -407,7 +420,7 @@ _e_dbus_cb_vol_is(void *user_data, void *reply_data, DBusError *error)
    if (ret && ret->boolean)
      {
 //     printf("DB VOL IS+: %s\n", udi);
-       e_volume_add(udi);
+       e_volume_add(udi, 0);
      }
    
    error:
@@ -720,6 +733,26 @@ _e_dbus_cb_vol_prop(void *data, void *reply_data, DBusError *error)
    return;
 }
 
+static int
+_e_dbus_format_error_msg(char **buf, E_Volume *v, DBusError *error)
+{
+   int size, vu, vm, en;
+   char *tmp;
+   
+   vu = strlen(v->udi) + 1;
+   vm = strlen(v->mount_point) + 1;
+   en = strlen(error->name) + 1;
+   size = vu + vm + en + strlen(error->message) + 1;
+   tmp = *buf = malloc(size);
+   
+   strcpy(tmp, v->udi);
+   strcpy(tmp += vu, v->mount_point);
+   strcpy(tmp += vm, error->name);
+   strcpy(tmp += en, error->message);
+   
+   return size;
+}
+
 static void
 _e_dbus_cb_vol_prop_mount_modified(void *data, void *reply_data, DBusError *error)
 {
@@ -730,7 +763,18 @@ _e_dbus_cb_vol_prop_mount_modified(void *data, void *reply_data, DBusError *erro
    if (!ret) return;
    if (dbus_error_is_set(error))
      {
+        char *buf;
+        int size;
+   
+        size = _e_dbus_format_error_msg(&buf, v, error);
+        if (v->mounted)
+           ecore_ipc_server_send(_e_ipc_server, 6/*E_IPC_DOMAIN_FM*/, E_FM_OP_UNMOUNT_ERROR,
+                                 0, 0, 0, buf, size);
+        else
+           ecore_ipc_server_send(_e_ipc_server, 6/*E_IPC_DOMAIN_FM*/, E_FM_OP_MOUNT_ERROR,
+                                 0, 0, 0, buf, size);
        dbus_error_free(error);
+       free(buf);
        return;
      }
    
@@ -767,7 +811,7 @@ _e_dbus_cb_vol_prop_mount_modified(void *data, void *reply_data, DBusError *erro
 static Eina_List *_e_vols = NULL;
 
 EAPI E_Volume *
-e_volume_add(const char *udi)
+e_volume_add(const char *udi, char first_time)
 {
    E_Volume *v;
    
@@ -778,6 +822,7 @@ e_volume_add(const char *udi)
 //   printf("VOL+ %s\n", udi);
    v->udi = strdup(udi);
    v->icon = NULL;
+   v->first_time = first_time;
    _e_vols = eina_list_append(_e_vols, v);
    e_hal_device_get_all_properties(_e_dbus_conn, v->udi,
                                   _e_dbus_cb_vol_prop, v);
@@ -785,7 +830,8 @@ e_volume_add(const char *udi)
                                               udi,
                                               "org.freedesktop.Hal.Device",
                                               "PropertyModified", _e_dbus_cb_prop_modified, v);
-
+   v->guard = NULL;
+   
    return v;
 }
 
@@ -796,6 +842,11 @@ e_volume_del(const char *udi)
    
    v = e_volume_find(udi);
    if (!v) return;
+   if (v->guard)
+     {
+        ecore_timer_del(v->guard);
+        v->guard = NULL;      
+     }
    if (v->prop_handler) e_dbus_signal_handler_del(_e_dbus_conn, v->prop_handler);
    if (v->validated)
      {
@@ -825,6 +876,26 @@ e_volume_find(const char *udi)
    return NULL;
 }
 
+static int
+_e_dbus_vol_mount_timeout(void *data)
+{
+   E_Volume *v = data;
+   DBusError error;
+   char *buf;
+   int size;
+
+   v->guard = NULL;
+   dbus_pending_call_cancel(v->op);
+   error.name = "org.enlightenment.fm2.MountTimeout";
+   error.message = "Unable to mount the volume with specified time-out.";
+   size = _e_dbus_format_error_msg(&buf, v, &error);
+   ecore_ipc_server_send(_e_ipc_server, 6/*E_IPC_DOMAIN_FM*/, E_FM_OP_MOUNT_ERROR,
+                         0, 0, 0, buf, size);
+   free(buf);
+   
+   return 0;
+}
+
 static void
 _e_dbus_cb_vol_mounted(void *user_data, void *method_return, DBusError *error)
 {
@@ -832,11 +903,23 @@ _e_dbus_cb_vol_mounted(void *user_data, void *method_return, DBusError *error)
    char *buf;
    int size;
    
+   if (v->guard)
+     {
+        ecore_timer_del(v->guard);
+        v->guard = NULL;
+     }
+   
    if (dbus_error_is_set(error))
      {
-       dbus_error_free(error);
-       return;
+        size = _e_dbus_format_error_msg(&buf, v, error);
+        ecore_ipc_server_send(_e_ipc_server, 6/*E_IPC_DOMAIN_FM*/, E_FM_OP_MOUNT_ERROR,
+                              0, 0, 0, buf, size);
+        dbus_error_free(error);
+        free(buf);
+        return;
      }
+
+/*
    v->mounted = 1;
 //   printf("MOUNT: %s from %s\n", v->udi, v->mount_point);
    size = strlen(v->udi) + 1 + strlen(v->mount_point) + 1;
@@ -844,9 +927,10 @@ _e_dbus_cb_vol_mounted(void *user_data, void *method_return, DBusError *error)
    strcpy(buf, v->udi);
    strcpy(buf + strlen(buf) + 1, v->mount_point);
    ecore_ipc_server_send(_e_ipc_server,
-                        6/*E_IPC_DOMAIN_FM*/,
+                        6/*E_IPC_DOMAIN_FM*//*,
                         E_FM_OP_MOUNT_DONE,
                         0, 0, 0, buf, size);
+*/
 }
 
 EAPI void
@@ -856,7 +940,7 @@ e_volume_mount(E_Volume *v)
    char *mount_point;
    Eina_List *opt = NULL;
 
-   if (!v || !v->mount_point || strncmp(v->mount_point, "/media/", 7))
+   if (!v || v->guard || !v->mount_point || strncmp(v->mount_point, "/media/", 7))
      return;
 
    mount_point = v->mount_point + 7;
@@ -869,11 +953,32 @@ e_volume_mount(E_Volume *v)
        snprintf(buf, sizeof(buf), "uid=%i", (int)getuid());
        opt = eina_list_append(opt, buf);
      }
-   e_hal_device_volume_mount(_e_dbus_conn, v->udi, mount_point,
-                            v->fstype, opt, NULL, v);
+   v->guard = ecore_timer_add(E_FM_MOUNT_TIMEOUT, _e_dbus_vol_mount_timeout, v);
+   v->op = e_hal_device_volume_mount(_e_dbus_conn, v->udi, mount_point,
+                                     v->fstype, opt, _e_dbus_cb_vol_mounted, v);
    opt = eina_list_free(opt);
 }
 
+static int
+_e_dbus_vol_unmount_timeout(void *data)
+{
+   E_Volume *v = data;
+   DBusError error;
+   char *buf;
+   int size;
+
+   v->guard = NULL;
+   dbus_pending_call_cancel(v->op);
+   error.name = "org.enlightenment.fm2.UnmountTimeout";
+   error.message = "Unable to unmount the volume with specified time-out.";
+   size = _e_dbus_format_error_msg(&buf, v, &error);
+   ecore_ipc_server_send(_e_ipc_server, 6/*E_IPC_DOMAIN_FM*/, E_FM_OP_UNMOUNT_ERROR,
+                         0, 0, 0, buf, size);
+   free(buf);
+   
+   return 0;
+}
+
 static void
 _e_dbus_cb_vol_unmounted(void *user_data, void *method_return, DBusError *error)
 {
@@ -881,11 +986,23 @@ _e_dbus_cb_vol_unmounted(void *user_data, void *method_return, DBusError *error)
    char *buf;
    int size;
 
+   if (v->guard)
+     {
+        ecore_timer_del(v->guard);
+        v->guard = NULL;
+     }
+   
    if (dbus_error_is_set(error))
      {
-       dbus_error_free(error);
-       return;
+        size = _e_dbus_format_error_msg(&buf, v, error);
+        ecore_ipc_server_send(_e_ipc_server, 6/*E_IPC_DOMAIN_FM*/, E_FM_OP_UNMOUNT_ERROR,
+                              0, 0, 0, buf, size);
+        dbus_error_free(error);
+        free(buf);
+        return;
      }
+
+/*
    v->mounted = 0;
 //   printf("UNMOUNT: %s from %s\n", v->udi, v->mount_point);
    size = strlen(v->udi) + 1 + strlen(v->mount_point) + 1;
@@ -893,17 +1010,118 @@ _e_dbus_cb_vol_unmounted(void *user_data, void *method_return, DBusError *error)
    strcpy(buf, v->udi);
    strcpy(buf + strlen(buf) + 1, v->mount_point);
    ecore_ipc_server_send(_e_ipc_server,
-                        6/*E_IPC_DOMAIN_FM*/,
+                        6/*E_IPC_DOMAIN_FM*//*,
                         E_FM_OP_UNMOUNT_DONE,
                         0, 0, 0, buf, size);
+*/
 }
 
 EAPI void
 e_volume_unmount(E_Volume *v)
 {
 //   printf("unmount %s %s\n", v->udi, v->mount_point);
-   e_hal_device_volume_unmount(_e_dbus_conn, v->udi, NULL,
-                              _e_dbus_cb_vol_unmounted, v);
+   if (!v || v->guard) return;
+   
+   v->guard = ecore_timer_add(E_FM_UNMOUNT_TIMEOUT, _e_dbus_vol_unmount_timeout, v);
+   v->op = e_hal_device_volume_unmount(_e_dbus_conn, v->udi, NULL,
+                                       _e_dbus_cb_vol_unmounted, v);
+}
+
+static int
+_e_dbus_vol_eject_timeout(void *data)
+{
+   E_Volume *v = data;
+   DBusError error;
+   char *buf;
+   int size;
+
+   v->guard = NULL;
+   dbus_pending_call_cancel(v->op);
+   error.name = "org.enlightenment.fm2.EjectTimeout";
+   error.message = "Unable to eject the media with specified time-out.";
+   size = _e_dbus_format_error_msg(&buf, v, &error);
+   ecore_ipc_server_send(_e_ipc_server, 6/*E_IPC_DOMAIN_FM*/, E_FM_OP_EJECT_ERROR,
+                         0, 0, 0, buf, size);
+   free(buf);
+   
+   return 0;
+}
+
+static int
+_e_dbus_vb_vol_ejecting_after_unmount(void *data)
+{
+   E_Volume *v = data;
+   
+   v->guard = ecore_timer_add(E_FM_EJECT_TIMEOUT, _e_dbus_vol_eject_timeout, v);
+   v->op = e_hal_device_volume_eject(_e_dbus_conn, v->udi, NULL,
+                                     _e_dbus_cb_vol_ejected, v);
+   
+   return 0;
+}
+
+static void
+_e_dbus_cb_vol_unmounted_before_eject(void *user_data, void *method_return, DBusError *error)
+{
+   E_Volume *v = user_data;
+   char err;
+
+   err = dbus_error_is_set(error) ? 1 : 0;
+   _e_dbus_cb_vol_unmounted(user_data, method_return, error);
+   
+   // delay is required for all message handlers were executed after unmount
+   if (!err)
+      ecore_timer_add(1.0, _e_dbus_vb_vol_ejecting_after_unmount, v);
+}
+
+static void
+_e_dbus_cb_vol_ejected(void *user_data, void *method_return, DBusError *error)
+{
+   E_Volume *v = user_data;
+   char *buf;
+   int size;
+
+   if (v->guard)
+     {
+        ecore_timer_del(v->guard);
+        v->guard = NULL;
+     }
+   
+   if (dbus_error_is_set(error))
+     {
+        size = _e_dbus_format_error_msg(&buf, v, error);
+        ecore_ipc_server_send(_e_ipc_server, 6/*E_IPC_DOMAIN_FM*/, E_FM_OP_EJECT_ERROR,
+                              0, 0, 0, buf, size);
+        dbus_error_free(error);
+        free(buf);
+        return;
+     }
+   
+   size = strlen(v->udi) + 1;
+   buf = alloca(size);
+   strcpy(buf, v->udi);
+   ecore_ipc_server_send(_e_ipc_server,
+                         6/*E_IPC_DOMAIN_FM*/,
+                         E_FM_OP_EJECT_DONE,
+                         0, 0, 0, buf, size);
+}
+
+EAPI void
+e_volume_eject(E_Volume *v)
+{
+   if (!v || v->guard) return;
+
+   if (v->mounted)
+     {
+        v->guard = ecore_timer_add(E_FM_UNMOUNT_TIMEOUT, _e_dbus_vol_unmount_timeout, v);
+        v->op = e_hal_device_volume_unmount(_e_dbus_conn, v->udi, NULL,
+                                            _e_dbus_cb_vol_unmounted_before_eject, v);
+     }
+   else
+     {
+        v->guard = ecore_timer_add(E_FM_EJECT_TIMEOUT, _e_dbus_vol_eject_timeout, v);
+        v->op = e_hal_device_volume_eject(_e_dbus_conn, v->udi, NULL,
+                                          _e_dbus_cb_vol_ejected, v);
+     }
 }
 
 /* local subsystem functions */
@@ -1376,6 +1594,17 @@ _e_ipc_cb_server_data(void *data, int type, void *event)
               }
          }
        break;
+      case E_FM_OP_EJECT:/* eject udi */
+          {
+             E_Volume *v;
+             const char *udi;
+             
+             udi = e->data;
+             v = e_volume_find(udi);
+             if (v)
+               e_volume_eject(v);
+          }
+        break;
       case E_FM_OP_QUIT: /* quit */
        ecore_main_loop_quit();
        break;
index f7f8d97..08af888 100644 (file)
@@ -47,7 +47,12 @@ typedef enum _E_Fm_Op_Type
    E_FM_OP_SYMLINK,
    E_FM_OP_OK,
    E_FM_OP_ERROR_RETRY_ABORT,
-   E_FM_OP_REORDER
+   E_FM_OP_REORDER,
+   E_FM_OP_MOUNT_ERROR,
+   E_FM_OP_UNMOUNT_ERROR,
+   E_FM_OP_EJECT,
+   E_FM_OP_EJECT_DONE,
+   E_FM_OP_EJECT_ERROR
 } E_Fm_Op_Type;
 
 #else
index 849cb50..4c5e9b0 100644 (file)
@@ -58,6 +58,11 @@ struct _E_Volume
    Eina_List *mounts;
    
    unsigned char validated;
+   
+   char auto_unmount;                  // unmount, when last associated fm window closed
+   char first_time;                    // volume discovery in init sequence
+   Ecore_Timer *guard;                 // operation guard timer
+   DBusPendingCall *op;                // d-bus call handle
 };
 
 struct _E_Fm2_Mount
@@ -65,7 +70,6 @@ struct _E_Fm2_Mount
    const char   *udi;
    const char   *mount_point;
    
-   Ecore_Timer  *timeout;
    void        (*mount_ok) (void *data);
    void        (*mount_fail) (void *data);
    void        (*unmount_ok) (void *data);
@@ -161,6 +165,7 @@ _e_volume_edd_new(void)
    DAT("mounted", mounted, EET_T_CHAR);
    DAT("mount_point", mount_point, EET_T_STRING);
    DAT("parent", parent, EET_T_STRING);
+   DAT("first_time", first_time, EET_T_CHAR);
 #undef DAT
    return edd;
 }
index 330a7ab..f68a0cb 100644 (file)
@@ -65,6 +65,8 @@ struct _E_Config_Dialog_Data
    struct
      {
         int desktop;
+        int auto_mount;
+        int auto_open;
      } hal;
 
    E_Config_Dialog *cfd;
@@ -124,6 +126,8 @@ _fill_data(E_Config_Dialog_Data *cfdata)
    cfdata->list.sort.dirs.first = fileman_config->list.sort.dirs.first;
    cfdata->list.sort.case_sen = !(fileman_config->list.sort.no_case);
    cfdata->hal.desktop = e_config->hal_desktop;
+   cfdata->hal.auto_mount = e_config->hal_auto_mount;
+   cfdata->hal.auto_open = e_config->hal_auto_open;
 }
 
 static void 
@@ -159,7 +163,10 @@ _basic_apply(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata)
      e_fm2_hal_show_desktop_icons();
    else
      e_fm2_hal_hide_desktop_icons();
-     
+
+   e_config->hal_auto_mount = cfdata->hal.auto_mount;
+   e_config->hal_auto_open = cfdata->hal.auto_open;
+   
    e_config_save_queue();
    
    /* FIXME: reload/refresh existing fm's */
@@ -184,7 +191,9 @@ _basic_check_changed(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata)
       (fileman_config->list.sort.dirs.first != cfdata->list.sort.dirs.first) ||
       (fileman_config->list.sort.dirs.last != !(cfdata->list.sort.dirs.first)) ||
       (fileman_config->list.sort.no_case != !(cfdata->list.sort.case_sen)) ||
-      (e_config->hal_desktop != cfdata->hal.desktop));
+      (e_config->hal_desktop != cfdata->hal.desktop) ||
+      (e_config->hal_auto_mount != cfdata->hal.auto_mount) ||
+      (e_config->hal_auto_open != cfdata->hal.auto_open));
 }
 
 static Evas_Object *
@@ -254,12 +263,22 @@ _basic_create(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata)
    ob = e_widget_check_add(evas, _("Show Toolbar"), 
                           &(cfdata->view.show_toolbar));
    e_widget_list_object_append(o, ob, 1, 1, 0.5);
-   ob = e_widget_check_add(evas, _("Show HAL icons on desktop"), 
-                          &(cfdata->hal.desktop));
-   e_widget_list_object_append(o, ob, 1, 1, 0.5);
 
    e_widget_toolbook_page_append(otb, NULL, _("Behavior"), o, 0, 0, 0, 0, 0.5, 0.0);
 
+   o = e_widget_list_add(evas, 2, 0);
+   ob = e_widget_check_add(evas, _("Show HAL icons on desktop"), 
+                           &(cfdata->hal.desktop));
+   e_widget_list_object_append(o, ob, 1, 1, 0.5);
+   ob = e_widget_check_add(evas, _("Mount volumes on insert"), 
+                           &(cfdata->hal.auto_mount));
+   e_widget_list_object_append(o, ob, 1, 1, 0.5);
+   ob = e_widget_check_add(evas, _("Open filemanager on mount"),
+                           &(cfdata->hal.auto_open));
+   e_widget_list_object_append(o, ob, 1, 1, 0.5);
+   
+   e_widget_toolbook_page_append(otb, NULL, _("HAL"), o, 0, 0, 0, 0, 0.5, 0.0);
+
    e_widget_toolbook_page_show(otb, 0);
    return otb;
 }
index 6d69e3c..588c01a 100644 (file)
@@ -216,21 +216,6 @@ _e_mod_action_fileman_cb(E_Object *obj, const char *params)
 //~ }
 
 static void
-_mount_ok(void *data)
-{
-   E_Volume *vol = data;
-   e_fwin_new(e_container_current_get(e_manager_current_get()),
-             NULL, vol->mount_point);
-}
-
-static void
-_mount_fail(void *data)
-{
-   //TODO make a better dialog
-   e_util_dialog_internal(_("Mount error"), _("Mount of device failed"));
-}
-
-static void
 _e_mod_menu_gtk_cb(void *data, E_Menu *m, E_Menu_Item *mi)
 {
    char *path = data;
@@ -253,8 +238,13 @@ _e_mod_menu_volume_cb(void *data, E_Menu *m, E_Menu_Item *mi)
        if (m->zone)
          e_fwin_new(m->zone->container, NULL, vol->mount_point);
      }
-   else //TODO need to remove the mount?
-      e_fm2_hal_mount(vol, _mount_ok, _mount_fail, NULL, NULL, vol);
+   else
+     {
+        char buf[PATH_MAX];
+        snprintf(buf, sizeof(buf), "removable:%s", vol->udi);
+        e_fwin_new(e_container_current_get(e_manager_current_get()),
+                   buf, "/");
+     }
 }
 
 static void