int HidController::close() { if (!isOpen()) { qDebug() << "HID device" << getName() << "already closed"; return -1; } qDebug() << "Shutting down HID device" << getName(); // Stop the reading thread if (m_pReader == NULL) { qWarning() << "HidReader not present for" << getName() << "yet the device is open!"; } else { disconnect(m_pReader, SIGNAL(incomingData(QByteArray, mixxx::Duration)), this, SLOT(receive(QByteArray, mixxx::Duration))); m_pReader->stop(); hid_set_nonblocking(m_pHidDevice, 1); // Quit blocking controllerDebug(" Waiting on reader to finish"); m_pReader->wait(); delete m_pReader; m_pReader = NULL; } // Stop controller engine here to ensure it's done before the device is closed // incase it has any final parting messages stopEngine(); // Close device controllerDebug(" Closing device"); hid_close(m_pHidDevice); setOpen(false); return 0; }
int BulkController::close() { if (!isOpen()) { qDebug() << " device" << getName() << "already closed"; return -1; } qDebug() << "Shutting down USB Bulk device" << getName(); // Stop the reading thread if (m_pReader == NULL) { qWarning() << "BulkReader not present for" << getName() << "yet the device is open!"; } else { disconnect(m_pReader, SIGNAL(incomingData(QByteArray, mixxx::Duration)), this, SLOT(receive(QByteArray, mixxx::Duration))); m_pReader->stop(); controllerDebug(" Waiting on reader to finish"); m_pReader->wait(); delete m_pReader; m_pReader = NULL; } // Stop controller engine here to ensure it's done before the device is // closed incase it has any final parting messages stopEngine(); // Close device controllerDebug(" Closing device"); libusb_close(m_phandle); m_phandle = NULL; setOpen(false); return 0; }
int HidController::open() { if (isOpen()) { qDebug() << "HID device" << getName() << "already open"; return -1; } // Open device by path controllerDebug("Opening HID device" << getName() << "by HID path" << hid_path); m_pHidDevice = hid_open_path(hid_path); // If that fails, try to open device with vendor/product/serial # if (m_pHidDevice == NULL) { controllerDebug("Failed. Trying to open with make, model & serial no:" << hid_vendor_id << hid_product_id << hid_serial); m_pHidDevice = hid_open(hid_vendor_id, hid_product_id, hid_serial_raw); } // If it does fail, try without serial number WARNING: This will only open // one of multiple identical devices if (m_pHidDevice == NULL) { qWarning() << "Unable to open specific HID device" << getName() << "Trying now with just make and model." << "(This may only open the first of multiple identical devices.)"; m_pHidDevice = hid_open(hid_vendor_id, hid_product_id, NULL); } // If that fails, we give up! if (m_pHidDevice == NULL) { qWarning() << "Unable to open HID device" << getName(); return -1; } setConnected(true); setOpen(true); startEngine(); if (m_pReader != NULL) { qWarning() << "HidReader already present for" << getName(); } else { m_pReader = new HidReader(m_pHidDevice); m_pReader->setObjectName(QString("HidReader %1").arg(getName())); connect(m_pReader, SIGNAL(incomingData(QByteArray, mixxx::Duration)), this, SLOT(receive(QByteArray, mixxx::Duration))); // Controller input needs to be prioritized since it can affect the // audio directly, like when scratching m_pReader->start(QThread::HighPriority); } return 0; }
void MidiOutputHandler::controlChanged(double value) { // Don't update with out of date messages. value = m_cos.get(); unsigned char byte3 = m_mapping.output.off; if (value >= m_mapping.output.min && value <= m_mapping.output.max) { byte3 = m_mapping.output.on; } if (static_cast<int>(byte3) == m_lastVal) { // Don't send redundant messages. return; } if (!m_pController->isOpen()) { qWarning() << "MIDI device" << m_pController->getName() << "not open for output!"; } else if (byte3 != 0xFF) { controllerDebug("sending MIDI bytes:" << m_mapping.output.status << "," << m_mapping.output.control << "," << byte3); m_pController->sendShortMsg(m_mapping.output.status, m_mapping.output.control, byte3); m_lastVal = static_cast<int>(byte3); } }
void MidiController::createOutputHandlers() { if (m_preset.outputMappings.isEmpty()) { return; } QHashIterator<ConfigKey, MidiOutputMapping> outIt(m_preset.outputMappings); QStringList failures; while (outIt.hasNext()) { outIt.next(); const MidiOutputMapping& mapping = outIt.value(); QString group = mapping.control.group; QString key = mapping.control.item; unsigned char status = mapping.output.status; unsigned char control = mapping.output.control; unsigned char on = mapping.output.on; unsigned char off = mapping.output.off; double min = mapping.output.min; double max = mapping.output.max; controllerDebug(QString( "Creating output handler for %1,%2 between %3 and %4 to MIDI out: 0x%5 0x%6, on: 0x%7 off: 0x%8") .arg(group, key, QString::number(min), QString::number(max), QString::number(status, 16).toUpper(), QString::number(control, 16).toUpper().rightJustified(2,'0'), QString::number(on, 16).toUpper().rightJustified(2,'0'), QString::number(off, 16).toUpper().rightJustified(2,'0'))); MidiOutputHandler* moh = new MidiOutputHandler(this, mapping); if (!moh->validate()) { QString errorLog = QString("MIDI output message 0x%1 0x%2 has invalid MixxxControl %3, %4") .arg(QString::number(status, 16).toUpper(), QString::number(control, 16).toUpper().rightJustified(2,'0')) .arg(group, key).toUtf8(); qWarning() << errorLog; int deckNum = 0; if (ControllerDebug::enabled()) { failures.append(errorLog); } else if (PlayerManager::isDeckGroup(group, &deckNum)) { int numDecks = PlayerManager::numDecks(); if (deckNum <= numDecks) { failures.append(errorLog); } } delete moh; continue; } m_outputs.append(moh); } if (!failures.isEmpty()) { ErrorDialogProperties* props = ErrorDialogHandler::instance()->newDialogProperties(); props->setType(DLG_WARNING); props->setTitle(tr("MixxxControl(s) not found")); props->setText(tr("One or more MixxxControls specified in the " "outputs section of the loaded preset were invalid.")); props->setInfoText(tr("Some LEDs or other feedback may not work correctly.")); QString detailsText = tr("* Check to see that the MixxxControl " "names are spelled correctly in the mapping " "file (.xml)\n"); detailsText += tr("* Make sure the MixxxControls in question actually exist." " Visit this wiki page for a complete list: "); detailsText += "http://mixxx.org/wiki/doku.php/mixxxcontrols\n\n"; detailsText += failures.join("\n"); props->setDetails(detailsText); ErrorDialogHandler::instance()->requestErrorDialog(props); } }
MidiOutputHandler::~MidiOutputHandler() { ConfigKey cKey = m_cos.getKey(); controllerDebug(QString("Destroying static MIDI output handler on %1 for %2,%3") .arg(m_pController->getName(), cKey.group, cKey.item)); }