Index: rbutil/rbutilqt/configure.cpp =================================================================== --- rbutil/rbutilqt/configure.cpp (revision 20614) +++ rbutil/rbutilqt/configure.cpp (working copy) @@ -27,6 +27,7 @@ #include "encoders.h" #include "tts.h" #include "detect.h" +#include "detecteddeviceswindow.h" #include #if defined(Q_OS_WIN32) @@ -549,9 +550,28 @@ this->setCursor(Qt::WaitCursor); QCoreApplication::processEvents(); + if(detector.detect()) //let it detect { - QString devicename = detector.getDevice(); + SDevice device; + QList deviceList = detector.getDevices(); + QString mountpoint; + if(deviceList.size() == 1) + { + device = deviceList.at(0); + } + else //multiple devices detected + { + DetectedDevicesWindow deviceDlg(this,deviceList,settings); + deviceDlg.exec(); + if(deviceDlg.state() == false) + { + this->unsetCursor(); + return; + } + device = deviceDlg.device(); + } + // deexpand all items for(int a = 0; a < ui.treeDevices->topLevelItemCount(); a++) ui.treeDevices->topLevelItem(a)->setExpanded(false); @@ -569,46 +589,31 @@ { QString data = itmList.at(i)->child(j)->data(0, Qt::UserRole).toString(); - if(devicename == data) // item found + if(device.device == data) // item found { itmList.at(i)->child(j)->setSelected(true); //select the item itmList.at(i)->setExpanded(true); //expand the platform item - //ui.treeDevices->indexOfTopLevelItem(itmList.at(i)->child(j)); break; } } } this->unsetCursor(); - if(!detector.errdev().isEmpty()) { - QString text; - if(detector.errdev() == "sansae200") - text = tr("Sansa e200 in MTP mode found!\n" - "You need to change your player to MSC mode for installation. "); - if(detector.errdev() == "h10") - text = tr("H10 20GB in MTP mode found!\n" - "You need to change your player to UMS mode for installation. "); - text += tr("Unless you changed this installation will fail!"); - - QMessageBox::critical(this, tr("Fatal error"), text, QMessageBox::Ok); + if(device.status == SDevice::eWARNING) + { + QMessageBox::critical(this, tr("Error"), device.errstring, QMessageBox::Ok); return; } - if(!detector.incompatdev().isEmpty()) { - QString text; - // we need to set the platform here to get the brand from the - // settings object - settings->setCurPlatform(detector.incompatdev()); - text = tr("Detected an unsupported %1 player variant. Sorry, " - "Rockbox doesn't run on your player.").arg(settings->curBrand()); - + if(device.status == SDevice::eERROR) + { QMessageBox::critical(this, tr("Fatal error: incompatible player found"), - text, QMessageBox::Ok); - return; - } + device.errstring, QMessageBox::Ok); + return; + } - if(detector.getMountPoint() != "" ) + if(device.mountpoint != "" ) { - ui.mountPoint->setText(QDir::toNativeSeparators(detector.getMountPoint())); + ui.mountPoint->setText(QDir::toNativeSeparators(mountpoint)); } else { Index: rbutil/rbutilqt/rbutilqt.pro =================================================================== --- rbutil/rbutilqt/rbutilqt.pro (revision 20614) +++ rbutil/rbutilqt/rbutilqt.pro (working copy) @@ -55,6 +55,7 @@ installtalkwindow.cpp \ talkfile.cpp \ base/autodetection.cpp \ + detecteddeviceswindow.cpp \ ../ipodpatcher/ipodpatcher.c \ ../sansapatcher/sansapatcher.c \ browsedirtree.cpp \ @@ -99,6 +100,7 @@ installtalkwindow.h \ talkfile.h \ base/autodetection.h \ + detecteddeviceswindow.h \ progressloggerinterface.h \ progressloggergui.h \ ../ipodpatcher/ipodpatcher.h \ @@ -151,7 +153,7 @@ } !dbg { CONFIG += release thread qt - DEFINES += QT_NO_DEBUG_OUTPUT + DEFINES -= QT_NO_DEBUG_OUTPUT message("release") } @@ -173,7 +175,8 @@ sapicfgfrm.ui \ ttsfestivalcfgform.ui \ createvoicefrm.ui \ - sysinfofrm.ui + sysinfofrm.ui \ + detecteddevicesfrm.ui RESOURCES += rbutilqt.qrc win32 { Index: rbutil/rbutilqt/base/autodetection.cpp =================================================================== --- rbutil/rbutilqt/base/autodetection.cpp (revision 20614) +++ rbutil/rbutilqt/base/autodetection.cpp (working copy) @@ -60,15 +60,16 @@ bool Autodetection::detect() { - m_device = ""; - m_mountpoint = ""; - m_errdev = ""; + // prepare lists + m_deviceList.clear(); + QList detectionList; - detectUsb(); + // general detection methods + detectionList = detectUsb(); - // Try detection via rockbox.info / rbutil.log + + // detection based n moutpoints QStringList mounts = mountpoints(); - for(int i=0; i< mounts.size();i++) { // do the file checking @@ -77,128 +78,335 @@ if(dir.exists()) { // check logfile first. - if(QFile(mounts.at(i) + "/.rockbox/rbutil.log").exists()) { - QSettings log(mounts.at(i) + "/.rockbox/rbutil.log", - QSettings::IniFormat, this); - if(!log.value("platform").toString().isEmpty()) { - if(m_device.isEmpty()) - m_device = log.value("platform").toString(); - m_mountpoint = mounts.at(i); - qDebug() << "rbutil.log detected:" << m_device << m_mountpoint; - return true; - } - } + detectionList += detectLogFile(mounts.at(i)); // check rockbox-info.txt afterwards. - RockboxInfo info(mounts.at(i)); - if(info.open()) - { - if(m_device.isEmpty()) - { - m_device = info.target(); - } - m_mountpoint = mounts.at(i); - qDebug() << "rockbox-info.txt detected:" << m_device << m_mountpoint; - return true; - } + detectionList += detectInfoFile(mounts.at(i)); // check for some specific files in root folder - QDir root(mounts.at(i)); - QStringList rootentries = root.entryList(QDir::Files); - if(rootentries.contains("archos.mod", Qt::CaseInsensitive)) + detectionList += detectFiles(mounts.at(i)); + + // detection based on player specific folders + detectionList += detectFolders(mounts.at(i)); + + } + + } + + // try ipodpatcher + detectionList +=detectIpod(); + + // try sansapatcher + detectionList +=detectSansa(); + + qDebug() << detectionList.size(); + // create the list of devices from all collected info + transformList(detectionList); + + if(m_deviceList.isEmpty()) + return false; + return true; +} + +void Autodetection::transformList(QList deviceList) +{ + // merge all devices with mount and device info + for(int i=0; i < deviceList.size();i++) + { + SDevice device = deviceList.at(i); + if(device.type == SDevice::eALL) + { + mergeItem(device); + } + } + // merge all devices with only device info + for(int i=0; i < deviceList.size();i++) + { + SDevice device = deviceList.at(i); + if(device.type == SDevice::eDEVICEONLY) + { + mergeItem(device); + } + } + // merge all devices wih only mount info + for(int i=0; i < deviceList.size();i++) + { + SDevice device = deviceList.at(i); + if(device.type == SDevice::eMOUNTONLY) + { + mergeItem(device); + } + } +} + +void Autodetection::mergeItem(SDevice device) +{ + qDebug() << device.device; + // its a complete info item + if(device.type == SDevice::eALL) + { + //check for dublicate + int dublicateIndex = findDublicate(device); + if(dublicateIndex == -1) //new item + { + m_deviceList.append(device); + } + else //merge item + { + if(device.status > m_deviceList.at(dublicateIndex).status) { - // archos.mod in root folder -> Archos Player - m_device = "player"; - m_mountpoint = mounts.at(i); - return true; + m_deviceList[dublicateIndex].status = device.status; + m_deviceList[dublicateIndex].errstring = device.errstring; } - if(rootentries.contains("ONDIOST.BIN", Qt::CaseInsensitive)) + } + } // we have only a device + else if(device.type == SDevice::eDEVICEONLY) + { + int dublicateIndex = findDublicate(device); + if(dublicateIndex == -1) //new item + { + m_deviceList.append(device); + } + else + { + if(device.status > m_deviceList.at(dublicateIndex).status) { - // ONDIOST.BIN in root -> Ondio FM - m_device = "ondiofm"; - m_mountpoint = mounts.at(i); - return true; + m_deviceList[dublicateIndex].status = device.status; + m_deviceList[dublicateIndex].errstring = device.errstring; } - if(rootentries.contains("ONDIOSP.BIN", Qt::CaseInsensitive)) + } + } // we have only a mountpoint, + else if(device.type == SDevice::eMOUNTONLY) + { + for(int i =0; i < m_deviceList.size();i++) + { + //if we find a device which contains the name (ie ipod in ipodcolor) + if(m_deviceList.at(i).device.contains(device.device)) { - // ONDIOSP.BIN in root -> Ondio SP - m_device = "ondiosp"; - m_mountpoint = mounts.at(i); - return true; + if(m_deviceList.at(i).type == SDevice::eDEVICEONLY) //add the mountpoint + { + m_deviceList[i].mountpoint = device.mountpoint; + if(device.status > m_deviceList.at(i).status) + { + m_deviceList[i].status = device.status; + m_deviceList[i].errstring = device.errstring; + } + m_deviceList[i].type = SDevice::eALL; + } + else // create a new device with new mountpoint + { + SDevice newdevice = m_deviceList.at(i); + newdevice.mountpoint = device.mountpoint; + m_deviceList.append(newdevice); + } } - if(rootentries.contains("ajbrec.ajz", Qt::CaseInsensitive)) - { - qDebug() << "ajbrec.ajz found. Trying detectAjbrec()"; - if(detectAjbrec(mounts.at(i))) { - m_mountpoint = mounts.at(i); - qDebug() << m_device; - return true; - } - } - // detection based on player specific folders - QStringList rootfolders = root.entryList(QDir::Dirs - | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System); - if(rootfolders.contains("GBSYSTEM", Qt::CaseInsensitive)) - { - // GBSYSTEM folder -> Gigabeat - m_device = "gigabeatf"; - m_mountpoint = mounts.at(i); - return true; - } -#if defined(Q_OS_WIN32) - // on windows, try to detect the drive letter of an Ipod - if(rootfolders.contains("iPod_Control", Qt::CaseInsensitive)) - { - // iPod_Control folder -> Ipod found - // detecting of the Ipod type is done below using ipodpatcher - m_mountpoint = mounts.at(i); - } -#endif } + } +} + +int Autodetection::findDublicate(SDevice device) +{ + for(int i =0; i < m_deviceList.size();i++) + { + if(device.device == m_deviceList.at(i).device && + device.mountpoint == m_deviceList.at(i).mountpoint) + { + return i; + } } + return -1; +} +QList Autodetection::detectLogFile(QString mountpoint) +{ + QList detectedDevices; + + if(QFile(mountpoint + "/.rockbox/rbutil.log").exists()) + { + QSettings log(mountpoint + "/.rockbox/rbutil.log", + QSettings::IniFormat, this); + if(!log.value("platform").toString().isEmpty()) + { + SDevice device; + device.device = log.value("platform").toString(); + device.mountpoint = mountpoint; + device.status = SDevice::eOK; + device.type = SDevice::eALL; + detectedDevices.append(device); + qDebug() << "rbutil.log detected:" << device.device << mountpoint; + } + } + return detectedDevices; +} + +// TODO, map configure modelname to rbutil internal targetname +QList Autodetection::detectInfoFile(QString mountpoint) +{ + QList detectedDevices; + + RockboxInfo info(mountpoint); + if(info.open()) + { + SDevice device; + device.device = info.target(); + device.mountpoint = mountpoint; + device.status = SDevice::eOK; + device.type = SDevice::eALL; + detectedDevices.append(device); + qDebug() << "rockbox-info.txt detected:" << device.device << mountpoint; + } + + return detectedDevices; +} + +QList Autodetection::detectFiles(QString mountpoint) +{ + QList detectedDevices; + + QDir root(mountpoint); + QStringList rootentries = root.entryList(QDir::Files); + if(rootentries.contains("archos.mod", Qt::CaseInsensitive)) + { + // archos.mod in root folder -> Archos Player + SDevice device; + device.device = "player"; + device.mountpoint = mountpoint; + device.status = SDevice::eOK; + device.type = SDevice::eALL; + detectedDevices.append(device); + } + if(rootentries.contains("ONDIOST.BIN", Qt::CaseInsensitive)) + { + // ONDIOST.BIN in root -> Ondio FM + SDevice device; + device.device = "ondiofm"; + device.mountpoint = mountpoint; + device.status = SDevice::eOK; + device.type = SDevice::eALL; + detectedDevices.append(device); + } + if(rootentries.contains("ONDIOSP.BIN", Qt::CaseInsensitive)) + { + // ONDIOSP.BIN in root -> Ondio SP + SDevice device; + device.device = "ondiosp"; + device.mountpoint= mountpoint; + device.status = SDevice::eOK; + device.type = SDevice::eALL; + detectedDevices.append(device); + } + if(rootentries.contains("ajbrec.ajz", Qt::CaseInsensitive)) + { + qDebug() << "ajbrec.ajz found. Trying detectAjbrec()"; + + QString dev = detectAjbrec(mountpoint); + if(!dev.isEmpty()) + { + // ONDIOST.BIN in root -> Ondio FM + SDevice device; + device.device = dev; + device.mountpoint = mountpoint; + device.status = SDevice::eOK; + device.type = SDevice::eALL; + detectedDevices.append(device); + } + } + return detectedDevices; +} + +QList Autodetection::detectFolders(QString mountpoint) +{ + QList detectedDevices; + + QDir root(mountpoint); + QStringList rootfolders = root.entryList(QDir::Dirs + | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System); + if(rootfolders.contains("GBSYSTEM", Qt::CaseInsensitive)) + { + // GBSYSTEM folder -> Gigabeat + SDevice device; + device.device = "gigabeatf"; + device.mountpoint = mountpoint; + device.status = SDevice::eOK; + device.type = SDevice::eALL; + detectedDevices.append(device); + } + + // try to detect the drive letter of an Ipod + if(rootfolders.contains("iPod_Control", Qt::CaseInsensitive)) + { + // iPod_Control folder -> Ipod found + // detecting of the Ipod type is done later + SDevice device; + device.device = "ipod"; + device.mountpoint = mountpoint; + device.status = SDevice::eOK; + device.type = SDevice::eMOUNTONLY; + detectedDevices.append(device); + } + + return detectedDevices; +} + +QList Autodetection::detectIpod() +{ + QList detectedDevices; + + // initialize sector buffer. Needed. int n; - // try ipodpatcher - // initialize sector buffer. Needed. ipod_sectorbuf = NULL; ipod_alloc_buffer(&ipod_sectorbuf, BUFFER_SIZE); struct ipod_t ipod; n = ipod_scan(&ipod); - if(n == 1) { + if(n == 1) + { qDebug() << "Ipod found:" << ipod.modelstr << "at" << ipod.diskname; - m_device = ipod.targetname; - m_mountpoint = resolveMountPoint(ipod.diskname); - return true; + SDevice device; + device.device = ipod.targetname; + device.mountpoint = resolveMountPoint(ipod.diskname); + device.status = SDevice::eOK; + device.type = SDevice::eALL; + detectedDevices.append(device); } - else { + else + { qDebug() << "ipodpatcher: no Ipod found." << n; } free(ipod_sectorbuf); ipod_sectorbuf = NULL; - // try sansapatcher + return detectedDevices; +} + +QList Autodetection::detectSansa() +{ + QList detectedDevices; + // initialize sector buffer. Needed. + int n; sansa_sectorbuf = NULL; sansa_alloc_buffer(&sansa_sectorbuf, BUFFER_SIZE); struct sansa_t sansa; n = sansa_scan(&sansa); - if(n == 1) { + if(n == 1) + { qDebug() << "Sansa found:" << sansa.targetname << "at" << sansa.diskname; - m_device = QString("sansa%1").arg(sansa.targetname); - m_mountpoint = resolveMountPoint(sansa.diskname); - return true; + SDevice device; + device.device = QString("sansa%1").arg(sansa.targetname); + device.mountpoint = resolveMountPoint(sansa.diskname); + device.status = SDevice::eOK; + device.type = SDevice::eALL; + detectedDevices.append(device); } - else { + else + { qDebug() << "sansapatcher: no Sansa found." << n; } free(sansa_sectorbuf); sansa_sectorbuf = NULL; - if(m_mountpoint.isEmpty() && m_device.isEmpty() - && m_errdev.isEmpty() && m_incompat.isEmpty()) - return false; - return true; + return detectedDevices; } @@ -328,8 +536,10 @@ /** @brief detect devices based on usb pid / vid. * @return true upon success, false otherwise. */ -bool Autodetection::detectUsb() +QList Autodetection::detectUsb() { + QList detectedDevices; + // usbids holds the mapping in the form // ((VID<<16)|(PID)), targetname // the ini file needs to hold the IDs as hex values. @@ -342,33 +552,69 @@ attached = Detect::listUsbIds(); int i = attached.size(); - while(i--) { - if(usbids.contains(attached.at(i))) { - m_device = usbids.value(attached.at(i)); - qDebug() << "[USB] detected supported player" << m_device; - return true; + while(i--) + { + if(usbids.contains(attached.at(i))) + { + SDevice device; + device.device = usbids.value(attached.at(i)); + device.status = SDevice::eOK; + device.type = SDevice::eDEVICEONLY; + detectedDevices.append(device); + qDebug() << "[USB] detected supported player" << device.device; } - if(usberror.contains(attached.at(i))) { - m_errdev = usberror.value(attached.at(i)); - qDebug() << "[USB] detected problem with player" << m_errdev; - return true; + if(usberror.contains(attached.at(i))) + { + SDevice device; + device.device = usbids.value(attached.at(i)); + device.status = SDevice::eWARNING; + device.type = SDevice::eDEVICEONLY; + if(device.device == "sansae200") + { + device.errstring = tr("Sansa e200 in MTP mode found!\n" + "You need to change your player to MSC mode for installation. "); + } + else if(device.device == "h10") + { + device.errstring = tr("H10 20GB in MTP mode found!\n" + "You need to change your player to UMS mode for installation. "); + } + else + { + device.errstring = tr("Problems found!\n" + "Your player seems to be in the wrong configuration. "); + } + detectedDevices.append(device); + + qDebug() << "[USB] detected problem with player" << device.device; + } - if(usbincompat.contains(attached.at(i))) { - m_incompat = usbincompat.value(attached.at(i)); - qDebug() << "[USB] detected incompatible player" << m_incompat; - return true; + if(usbincompat.contains(attached.at(i))) + { + SDevice device; + device.device = usbids.value(attached.at(i)); + device.status = SDevice::eERROR; + device.type = SDevice::eDEVICEONLY; + device.errstring = tr("Detected an unsupported player variant.\n" + "Sorry, Rockbox doesn't run on your player." ); + detectedDevices.append(device); + + qDebug() << "[USB] detected incompatible player" << device.device; + } } - return false; + + return detectedDevices; } -bool Autodetection::detectAjbrec(QString root) +QString Autodetection::detectAjbrec(QString root) { + QString device; QFile f(root + "/ajbrec.ajz"); char header[24]; f.open(QIODevice::ReadOnly); - if(!f.read(header, 24)) return false; + if(!f.read(header, 24)) return ""; // check the header of the file. // recorder v1 had a 6 bytes sized header @@ -380,24 +626,24 @@ qDebug() << "possible bin length:" << len; qDebug() << "file len:" << f.size(); if((f.size() - 6) == len) - m_device = "recorder"; + device = "recorder"; // size didn't match, now we need to assume we have a headerlength of 24. switch(header[11]) { case 2: - m_device = "recorderv2"; + device = "recorderv2"; break; case 4: - m_device = "fmrecorder"; + device = "fmrecorder"; break; case 8: - m_device = "ondiofm"; + device = "ondiofm"; break; case 16: - m_device = "ondiosp"; + device = "ondiosp"; break; default: @@ -405,7 +651,6 @@ } f.close(); - if(m_device.isEmpty()) return false; - return true; + return device; } Index: rbutil/rbutilqt/base/autodetection.h =================================================================== --- rbutil/rbutilqt/base/autodetection.h (revision 20614) +++ rbutil/rbutilqt/base/autodetection.h (working copy) @@ -26,34 +26,63 @@ #include #include "rbsettings.h" +struct SDevice +{ + enum EStatus + { + eOK, + eWARNING, + eERROR + }; + enum EType + { + eALL, + eDEVICEONLY, + eMOUNTONLY + }; + QString device; + QString mountpoint; + EStatus status; + EType type; + QString errstring; +}; + class Autodetection :public QObject { Q_OBJECT public: - Autodetection(QObject* parent=0); + Autodetection(QObject* parent); void setSettings(RbSettings* sett) {settings = sett;} bool detect(); - QString getDevice() {return m_device;} - QString getMountPoint() {return m_mountpoint;} - QString errdev(void) { return m_errdev; } - QString incompatdev(void) { return m_incompat; } static QStringList mountpoints(void); + QList getDevices() {return m_deviceList; } private: QString resolveMountPoint(QString); - bool detectUsb(void); - bool detectAjbrec(QString); + QString detectAjbrec(QString); - QString m_device; - QString m_mountpoint; - QString m_errdev; - QString m_incompat; + void transformList(QList); + // new detect functions + QList detectUsb(); + QList detectLogFile(QString mountpoint); + QList detectInfoFile(QString mountpoint); + QList detectFiles(QString mountpoint); + QList detectFolders(QString mountpoint); + QList detectSansa(); + QList detectIpod(); + + int findDublicate(SDevice device); + void mergeItem(SDevice device); + + // list of detected devices + QList m_deviceList; QList m_usbconid; RbSettings* settings; + };