Re: [linux-minidisc] netmd support for qhimdtransfer gui application
Am 28.12.2013 20:38, schrieb Thomas Arp:
Am 25.12.2013 20:59, schrieb Thomas Arp:
Hi,
here is a new feature corresponding to my netmd integration patch.
This can be applied after patch #10.
Sorry, forgot to atach the file.
>From fcf83dfaa1ead86397358129a0f1e7ec24c99fc8 Mon Sep 17 00:00:00 2001
From: Thomas Arp <manner,moe@gmx.de>
Date: Sat, 28 Dec 2013 20:05:57 +0100
Subject: [PATCH 12/12] netmd support: add unix autodetection during application
runtime, TODO: add unix himd device detection at
application start
---
netmd/etc/60-minidisc.rules | 116 ++++++++++++++++++++++++++++
netmd/etc/minidisc_notify.sh | 25 ++++++
qhimdtransfer/qhimdtransfer.pro | 5 ++
qhimdtransfer/qhimdunixdetection.cpp | 141 ++++++++++++++++++++++++++++++++++
qhimdtransfer/qhimdunixdetection.h | 71 +++++++++++++++++
5 files changed, 358 insertions(+)
create mode 100644 netmd/etc/60-minidisc.rules
create mode 100644 netmd/etc/minidisc_notify.sh
create mode 100644 qhimdtransfer/qhimdunixdetection.cpp
create mode 100644 qhimdtransfer/qhimdunixdetection.h
diff --git a/netmd/etc/60-minidisc.rules b/netmd/etc/60-minidisc.rules
new file mode 100644
index 0000000..07ce8b4
--- /dev/null
+++ b/netmd/etc/60-minidisc.rules
@@ -0,0 +1,116 @@
+## Rules file for Minidisc devices
+## based on source: https://usb-ids.gowdy.us/read/UD/054c
+## last changed: 2013-12-28
+
+# send message through session bus (needs qdbus to be installed), already running qhimdtransfer application will recieve this
+# also needs minidisc_notify.sh to be installed in /etc/udev
+
+# check himd devices
+# Sony MZ-NH1
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="017f", GOTO="notify"
+# Sony MZ-NH3D
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0181", GOTO="notify"
+# Sony MZ-NH900
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0183", GOTO="notify"
+# Sony MZ-NH700
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0185", GOTO="notify"
+# Sony MZ-NH600
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0187", GOTO="notify"
+# Sony LAM-3
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="018a", GOTO="notify"
+# Sony MZ-DH10P
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="01ea", GOTO="notify"
+# Sony MZ-RH10
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="021a", GOTO="notify"
+# Sony MZ-RH910
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="021c", GOTO="notify"
+# Sony CMT-AH10
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="022d", GOTO="notify"
+# Sony DS-HMD1
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="023d", GOTO="notify"
+# Sony MZ-RH1
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0287", GOTO="notify"
+
+# check himd devices in netmd mode
+# Sony MZ-NH1
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="017e", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony MZ-NH3D
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0180", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony MZ-NH900
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0182", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony MZ-NH700/800
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0184", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony MZ-NH600/600D
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0186", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony MZ-DH10P
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="01e9", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony MZ-RH10
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0219", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony MZ-RH910
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="021b", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony CMT-AH10
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="022c", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony DS-HMD1
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="023c", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony MZ-RH1
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0286", MODE="0664", GROUP="plugdev", GOTO="notify"
+
+# check netmd devices
+# Aiwa AM-NX1
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0113", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Aiwa AM-NX9
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="014c", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sharp IM-MT880H/MT899H
+ATTRS{idVendor}=="04dd", ATTRS{idProduct}=="7202", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sharp IM-DR400/DR410
+ATTRS{idVendor}=="04dd", ATTRS{idProduct}=="9013", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sharp IM-DR420/DR80/DR580 - Kenwood DMC-S9NET
+ATTRS{idVendor}=="04dd", ATTRS{idProduct}=="9014", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony NetMD (unknown model)
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0036", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony NetMD MZ-N1
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0075", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony NetMD (unknown model)
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="007c", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony NetMD LAM-1
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0080", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony NetMD MDS-JE780/JB980
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0081", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony MZ-N505
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0084", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony NetMD MZ-S1
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0085", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony NetMD MZ-N707
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0086", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony MZ-N10
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="00c6", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony NetMD MZ-N910
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="00c7", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony NetMD MZ-N710/NF810/NE810
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="00c8", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony NetMD MZ-N510/NF610
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="00c9", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony MZ-N410/NF520D
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="00ca", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony NetMD MZ-NE810/NE910/DN430
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="00eb", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony NetMD LAM-10
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0101", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony MZ-N920
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0188", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony NetMD LAM-3
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="018a", MODE="0664", GROUP="plugdev", GOTO="notify"
+# Sony NetMD CMT-AH10
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="021d", MODE="0664", GROUP="plugdev", GOTO="notify"
+
+# send all "remove" messages, some usb device specific remove messages does not contain idVendor/idProduct,
+# corresponding device will be checked by qhimdtransfer
+ACTION=="remove", RUN+="/etc/udev/minidisc_notify.sh"
+
+# end here if device is not a minidisc device
+GOTO="minidisc_end"
+
+LABEL="notify"
+RUN+="/etc/udev/minidisc_notify.sh"
+
+LABEL="minidisc_end"
diff --git a/netmd/etc/minidisc_notify.sh b/netmd/etc/minidisc_notify.sh
new file mode 100644
index 0000000..94bf138
--- /dev/null
+++ b/netmd/etc/minidisc_notify.sh
@@ -0,0 +1,25 @@
+#!/bin/sh -e
+
+ case $ACTION in
+ add)
+ ACT=AddMDDevice
+ ;;
+ remove)
+ ACT=RemoveMDDevice
+ ;;
+ *)
+ ;;
+ esac
+
+# run as current user, else dbus message cannot be recieved
+username=`who | head -n 1 | cut -d " " -f 1`
+export HOME=/home/$username
+export XAUTHORITY=$HOME/.Xauthority
+export DISPLAY=:0.0
+
+# convert vendor and product id to int
+vid=$(echo $((0x$ID_VENDOR_ID)))
+pid=$(echo $((0x$ID_MODEL_ID)))
+
+# send message to session bus
+su $username -c "qdbus --session com.trolltech.Qt /QHiMDUnixDetection $ACT $DEVNAME $vid $pid" -m
diff --git a/qhimdtransfer/qhimdtransfer.pro b/qhimdtransfer/qhimdtransfer.pro
index 0fc2de1..e70230e 100644
--- a/qhimdtransfer/qhimdtransfer.pro
+++ b/qhimdtransfer/qhimdtransfer.pro
@@ -73,6 +73,11 @@ SOURCES += main.cpp \
qmdtrack.cpp \
qmddevice.cpp
win32:SOURCES += qhimdwindetection.cpp
+unix: {
+ HEADERS += qhimdunixdetection.h
+ SOURCES += qhimdunixdetection.cpp
+ QT += dbus
+}
else:SOURCES += qhimddummydetection.cpp
RESOURCES += icons.qrc
PKGCONFIG += sox \
diff --git a/qhimdtransfer/qhimdunixdetection.cpp b/qhimdtransfer/qhimdunixdetection.cpp
new file mode 100644
index 0000000..3cb59c8
--- /dev/null
+++ b/qhimdtransfer/qhimdunixdetection.cpp
@@ -0,0 +1,141 @@
+#include "qhimdunixdetection.h"
+#include <QVariantList>
+#include <QDebug>
+#include <QApplication>
+
+QHiMDDetection * createDetection(QObject * parent)
+{
+ return new QHiMDUnixDetection(parent);
+}
+
+QHiMDUnixDetection::QHiMDUnixDetection(QObject *parent)
+ : QHiMDDetection(parent), had(new QHiMDAdaptor(this)),
+ dbus_sys(QDBusConnection::connectToBus( QDBusConnection::SystemBus, "system" ) ),
+ dbus_ses(QDBusConnection::connectToBus(QDBusConnection::SessionBus, "com.trolltech.Qt"))
+{
+ if(!dbus_sys.isConnected())
+ qDebug() << "cannot connect to system bus";
+ if(!dbus_ses.isConnected())
+ qDebug() << "cannot connect to session bus";
+
+ if(!dbus_ses.registerObject("/QHiMDUnixDetection", this, QDBusConnection::ExportAllSlots))
+ qDebug() << "cannot register dbus interface object ";
+
+ // register interface to session bus to make it visible to all other connections
+ dbus_ses.interface()->registerService("com.trolltech.Qt");
+ dbus_ses.interface()->startService("com.trolltech.Qt");
+
+ // now connect method calls to our slots
+ QDBusConnection::sessionBus().connect("com.trolltech.Qt", "/com/trolltech/Qt/QHiMDUnixDetection", "com.trolltech.Qt", "AddMDDevice", this, SLOT(AddMDDevice(QString, int, int)));
+ QDBusConnection::sessionBus().connect("com.trolltech.Qt", "/com/trolltech/Qt/QHiMDUnixDetection", "com.trolltech.Qt", "RemoveMDDevice", this, SLOT(RemoveMDDevice(QString,int,int)));
+}
+
+QVariant QHiMDUnixDetection::get_property(QString udiskPath, QString property, QString interface)
+{
+ QDBusMessage msg = QDBusMessage::createMethodCall(UDISK_SERVICE, udiskPath, UDISK_PROPERTIES, "Get");
+ QVariant var;
+ QList<QVariant> args;
+ QDBusMessage reply;
+
+ /* set arguments */
+ args.append(interface);
+ args.append(property);
+ msg.setArguments(args);
+
+ /* send message */
+ reply = dbus_sys.call(msg);
+
+ if (!reply.signature().compare(QString(QChar('v'))) && reply.arguments().length() >0)
+ var = reply.arguments().at(0);
+ else
+ return QVariant();
+
+ return var;
+}
+
+QString QHiMDUnixDetection::mountpoint(QString devpath)
+{
+ QString udev_path = UDISK_DEVICE_PATH;
+ QVariant mp;
+
+ // setup correct path for UDisk operations, just need sd* instead fo /dev/sd*
+ devpath.remove(0, devpath.lastIndexOf("/")+1);
+ udev_path.append(devpath);
+
+ /* TODO: convert return value of get_property() in order to extract needed data, the returned value is marked as INVALID and cannot be converted,
+ * it should contain something like this (this is a sample of what qdbusviewer returns, here: "/media/man2/disk"):
+ * Arguments: [Variant: [Argument: aay {{47, 109, 101, 100, 105, 97, 47, 109, 97, 110, 50, 47, 100, 105, 115, 107, 0}}]]
+ * so we have to convert the udev "aay" format (array of filepaths) to something readable
+ */
+ mp = get_property(udev_path, PROP_MOUNTPATH, UDISK_FILESYSTEM);
+ return mp.toString();
+}
+
+void QHiMDUnixDetection::AddMDDevice(QString deviceFile, int vid, int pid)
+{
+ QString mountpt;
+ QString name = QString(identify_usb_device(vid, pid));
+
+ // check if this is valid minidisc device depending on vendor and product id, for all known devices identify_usb_device() should return a name
+ if(name.isEmpty())
+ return;
+
+ /* check if it is a netmd device, reenumerate netmd devices at this point to make libnetmd find it
+ */
+ if(name.contains("NetMD"))
+ {
+ qDebug() << "qhimdtransfer detection: netmd device detected: " + name;
+ QThread::msleep(5000); // wait for TOC to be loaded by the device, else tracklist may not be shown correctly (no tiltles, unknown codec etc.)
+ rescan_netmd_devices();
+ return;
+ }
+
+ // check if driver file is /dev/sd*, this is what we need, for future use (formating etc.) also check for /dev/sg* scsi driver file
+ if(!deviceFile.startsWith("/dev/sd"))
+ return;
+
+
+ qDebug() << QString("qhimdtransfer detection: himd device detected at %1: %2").arg(deviceFile).arg(name);
+
+ // wait for device to be mounted by polling for mountpoint, this could take some time
+ // break if mount process did not finish within 30 seconds
+ for(int i = 0; i < 30; i++)
+ {
+ QThread::msleep(1000);
+ QApplication::processEvents(); // prevent application to be blocked completely
+ if(!(mountpt = mountpoint(deviceFile)).isEmpty())
+ break;
+ }
+ qDebug() << (mountpt.isEmpty() ? "no mountpoint detected" : QString("device mounted at: %1").arg(mountpt));
+
+ /* TODO: add new QHiMDDevice object to device list here,
+ * as mountpoint() function does not work correctly yet, this cannot be done at current stage of the code
+ */
+
+}
+
+void QHiMDUnixDetection::RemoveMDDevice(QString deviceFile, int vid, int pid)
+{
+ QString name = QString(identify_usb_device(vid, pid));
+
+ // check if this is valid minidisc device, for all known devices identify_usb_device() should return a name
+ if(name.isEmpty())
+ return;
+
+ if(name.contains("NetMD"))
+ {
+ qDebug() << "qhimdtransfer detection: netmd device removed: " + name;
+ rescan_netmd_devices();
+ return;
+ }
+
+ // check if driver file is /dev/sd*, this is what we need, for future use (formating etc.) also check for /dev/sg* scsi driver file
+ if(!deviceFile.startsWith("/dev/sd"))
+ return;
+
+ qDebug() << QString("qhimdtransfer detection: himd device removed at %1: %2").arg(deviceFile).arg(name);
+
+ /* TODO: remove corresponding QHiMDDevice object from device list here */
+
+}
+
diff --git a/qhimdtransfer/qhimdunixdetection.h b/qhimdtransfer/qhimdunixdetection.h
new file mode 100644
index 0000000..74e0fe9
--- /dev/null
+++ b/qhimdtransfer/qhimdunixdetection.h
@@ -0,0 +1,71 @@
+#ifndef QHIMDUNIXDETECTION_H
+#define QHIMDUNIXDETECTION_H
+
+#include <QtDBus>
+#include <qhimddetection.h>
+
+/* define constants for udev */
+#define UDISK_SERVICE "org.freedesktop.UDisks2"
+#define UDISK_PATH "/org/freedesktop/UDisks2"
+#define UDISK_INTERFACE "org.freedesktop.UDisks2"
+#define UDISK_PROPERTIES "org.freedesktop.DBus.Properties"
+#define UDISK_FILESYSTEM "org.freedesktop.UDisks2.Filesystem"
+#define UDISK_DEVICE_PATH "/org/freedesktop/UDisks2/block_devices/"
+
+#define PROP_MOUNTPATH "MountPoints"
+
+
+/* qhimdtransfer adaptor class, can be accessed through dbus session bus with
+ * service=com.trolltech.Qt
+ * path=/QHiMDUnixDetection
+ * interface=com.trolltech.Qt.QHiMDUnixDetection
+ *
+ * following methods provided
+ * "AddMDDevice" and "RemoveMDDevice"
+ * with args: QString deviceFile, int vid, int pid
+ */
+class QHiMDAdaptor: public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "com.trolltech.Qt")
+ Q_CLASSINFO("D-Bus Introspection", ""
+" <interface name=\"com.trolltech.Qt\">\n"
+" <method name=\"AddMDDevice\">\n"
+" <arg direction=\"in\" type=\"s\" name=\"deviceFile\"/>\n"
+" <arg direction=\"in\" type=\"i\" name=\"vendorId\"/>\n"
+" <arg direction=\"in\" type=\"i\" name=\"productId\"/>\n"
+" </method>\n"
+" <method name=\"RemoveMDDevice\">\n"
+" <arg direction=\"in\" type=\"s\" name=\"deviceFile\"/>\n"
+" <arg direction=\"in\" type=\"i\" name=\"vendorId\"/>\n"
+" <arg direction=\"in\" type=\"i\" name=\"productId\"/>\n"
+" </method>\n"
+" </interface>\n"
+ "")
+public:
+ QHiMDAdaptor(QObject *parent) : QDBusAbstractAdaptor(parent) {}
+ virtual ~QHiMDAdaptor() {}
+};
+
+
+class QHiMDUnixDetection : public QHiMDDetection{
+ Q_OBJECT
+
+ QHiMDAdaptor *had;
+ QDBusConnection dbus_sys; // system bus connection: needed for getting mountpoint
+ QDBusConnection dbus_ses; // session bus connection: needed for providing method calls AddMDDevice and RemoveMDDevice
+
+public:
+ QHiMDUnixDetection(QObject * parent = NULL);
+ ~QHiMDUnixDetection() {}
+
+private:
+ QVariant get_property(QString udiskPath, QString property, QString interface);
+ QString mountpoint(QString devpath);
+
+public slots:
+ void AddMDDevice(QString deviceFile, int vid, int pid);
+ void RemoveMDDevice(QString deviceFile, int vid, int pid);
+};
+
+#endif // QHIMDUNIXDETECTION_H
--
1.7.10.4