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