diff --git a/rbutil/rbutilqt/base/utils.cpp b/rbutil/rbutilqt/base/utils.cpp
index 3821b67201..cffa4b1cad 100644
--- a/rbutil/rbutilqt/base/utils.cpp
+++ b/rbutil/rbutilqt/base/utils.cpp
@@ -692,3 +692,63 @@ QStringList Utils::findRunningProcess(QStringList names)
qDebug() << "[Utils] Found listed processes running:" << found;
return found;
}
+
+
+/** Eject device from PC.
+ * Request the OS to eject the player.
+ * @param device mountpoint of the device
+ * @return true on success, fals otherwise.
+ */
+bool Utils::ejectDevice(QString device)
+{
+#if defined(Q_OS_WIN32)
+ /* See http://support.microsoft.com/kb/165721 on the procedure to eject a
+ * device. */
+ bool success = false;
+ int i;
+ HANDLE hdl;
+ DWORD bytesReturned;
+ TCHAR volume[8];
+
+ /* CreateFile */
+ _stprintf(volume, _TEXT("\\\\.\\%c:"), device.toAscii().at(0));
+ hdl = CreateFile(volume, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, 0, NULL);
+ if(hdl == INVALID_HANDLE_VALUE)
+ return false;
+
+ /* lock volume to make sure no other application is accessing the volume.
+ * Try up to 10 times. */
+ for(i = 0; i < 10; i++) {
+ if(DeviceIoControl(hdl, FSCTL_LOCK_VOLUME,
+ NULL, 0, NULL, 0, &bytesReturned, NULL))
+ break;
+ /* short break before retry */
+ Sleep(100);
+ }
+ if(i < 10) {
+ /* successfully locked, now dismount */
+ if(DeviceIoControl(hdl, FSCTL_DISMOUNT_VOLUME,
+ NULL, 0, NULL, 0, &bytesReturned, NULL)) {
+ /* make sure media can be removed. */
+ PREVENT_MEDIA_REMOVAL pmr;
+ pmr.PreventMediaRemoval = false;
+ if(DeviceIoControl(hdl, IOCTL_STORAGE_MEDIA_REMOVAL,
+ &pmr, sizeof(PREVENT_MEDIA_REMOVAL),
+ NULL, 0, &bytesReturned, NULL)) {
+ /* eject the media */
+ if(DeviceIoControl(hdl, IOCTL_STORAGE_EJECT_MEDIA,
+ NULL, 0, NULL, 0, &bytesReturned, NULL))
+ success = true;
+ }
+ }
+ }
+ /* close handle */
+ CloseHandle(hdl);
+ return success;
+
+#endif
+ return false;
+}
+
diff --git a/rbutil/rbutilqt/base/utils.h b/rbutil/rbutilqt/base/utils.h
index 185c0323a6..db52bfb4e9 100644
--- a/rbutil/rbutilqt/base/utils.h
+++ b/rbutil/rbutilqt/base/utils.h
@@ -50,6 +50,7 @@ public:
static QString resolveDevicename(QString path);
static QString resolveMountPoint(QString device);
static QStringList findRunningProcess(QStringList names);
+ static bool ejectDevice(QString device);
};
#endif
diff --git a/rbutil/rbutilqt/icons/media-eject.png b/rbutil/rbutilqt/icons/media-eject.png
new file mode 100644
index 0000000000..2084067e94
Binary files /dev/null and b/rbutil/rbutilqt/icons/media-eject.png differ
diff --git a/rbutil/rbutilqt/rbutilqt.cpp b/rbutil/rbutilqt/rbutilqt.cpp
index 62a4f583f7..aa0c365303 100644
--- a/rbutil/rbutilqt/rbutilqt.cpp
+++ b/rbutil/rbutilqt/rbutilqt.cpp
@@ -110,6 +110,11 @@ RbUtilQt::RbUtilQt(QWidget *parent) : QMainWindow(parent)
RegCloseKey(hk);
}
#endif
+
+#if !defined(Q_OS_WIN32)
+ /* eject funtionality is only implemented on W32 right now. */
+ ui.buttonEject->setEnabled(false);
+#endif
updateDevice();
downloadInfo();
@@ -142,6 +147,7 @@ RbUtilQt::RbUtilQt(QWidget *parent) : QMainWindow(parent)
connect(ui.action_Configure, SIGNAL(triggered()), this, SLOT(configDialog()));
connect(ui.actionE_xit, SIGNAL(triggered()), this, SLOT(shutdown()));
connect(ui.buttonChangeDevice, SIGNAL(clicked()), this, SLOT(configDialog()));
+ connect(ui.buttonEject, SIGNAL(clicked()), this, SLOT(eject()));
connect(ui.buttonTalk, SIGNAL(clicked()), this, SLOT(createTalkFiles()));
connect(ui.buttonCreateVoice, SIGNAL(clicked()), this, SLOT(createVoiceFile()));
connect(ui.buttonVoice, SIGNAL(clicked()), this, SLOT(installVoice()));
@@ -733,3 +739,19 @@ void RbUtilQt::changeEvent(QEvent *e)
}
}
+void RbUtilQt::eject(void)
+{
+ QString mountpoint = RbSettings::value(RbSettings::Mountpoint).toString();
+ if(Utils::ejectDevice(mountpoint)) {
+ QMessageBox::information(this, tr("Device ejected"),
+ tr("Device successfully ejected. "
+ "You may now disconnect the player from the PC."));
+ }
+ else {
+ QMessageBox::critical(this, tr("Ejecting failed"),
+ tr("Ejecting the device failed. Please make sure no programs "
+ "are accessing files on the device. If ejecting still "
+ "fails please use your computers eject funtionality."));
+ }
+}
+
diff --git a/rbutil/rbutilqt/rbutilqt.h b/rbutil/rbutilqt/rbutilqt.h
index 1db100430a..350aca1956 100644
--- a/rbutil/rbutilqt/rbutilqt.h
+++ b/rbutil/rbutilqt/rbutilqt.h
@@ -79,6 +79,7 @@ class RbUtilQt : public QMainWindow
void help(void);
void sysinfo(void);
void trace(void);
+ void eject(void);
void configDialog(void);
void updateDevice(void);
void updateSettings(void);
diff --git a/rbutil/rbutilqt/rbutilqt.qrc b/rbutil/rbutilqt/rbutilqt.qrc
index 5305a98434..d1eea6872e 100644
--- a/rbutil/rbutilqt/rbutilqt.qrc
+++ b/rbutil/rbutilqt/rbutilqt.qrc
@@ -19,6 +19,7 @@
icons/edit-find.png
icons/font_btn.png
icons/go-next.png
+ icons/media-eject.png
icons/network-idle.png
icons/package-x-generic.png
icons/preferences-desktop-locale.png
diff --git a/rbutil/rbutilqt/rbutilqtfrm.ui b/rbutil/rbutilqt/rbutilqtfrm.ui
index 85da42ed01..65348dabfb 100644
--- a/rbutil/rbutilqt/rbutilqtfrm.ui
+++ b/rbutil/rbutilqt/rbutilqtfrm.ui
@@ -7,7 +7,7 @@
0
0
650
- 550
+ 399
@@ -31,24 +31,25 @@
Device
- -
-
-
- mountpoint unknown or invalid
+
-
+
+
+ 1
-
-
- -
-
- Mountpoint:
+
-
-
- -
-
-
- device unknown or invalid
+
+ :/icons/rockbox-32.png
+
+
+ false
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ 3
@@ -65,6 +66,13 @@
+ -
+
+
+ device unknown or invalid
+
+
+
-
@@ -78,17 +86,7 @@
- -
-
-
-
-
-
- true
-
-
-
- -
+
-
&Change
@@ -99,6 +97,31 @@
+ -
+
+
+ &Eject
+
+
+
+ :/icons/media-eject.png:/icons/media-eject.png
+
+
+
+ -
+
+
+ Mountpoint:
+
+
+
+ -
+
+
+ mountpoint unknown or invalid
+
+
+
@@ -130,7 +153,7 @@
-
- 7
+ 0
@@ -388,7 +411,7 @@
0
0
650
- 23
+ 21