Something went wrong. Try again.
Mixxx DJ software with MCP, Subsonic/Navidrome streaming library support — browse and load tracks from your self-hosted music server mixxx.org
subsonic navidrome streaming audio dj mac linux midi
Something went wrong. Try again.
6.4 kB · 185 lines
C++
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186#include "controllers/controller.h"
#include <QJSEngine>#include <algorithm>
#include "controllers/scripting/legacy/controllerscriptenginelegacy.h"#include "moc_controller.cpp"#include "util/cmdlineargs.h"#include "util/screensaver.h"
namespace {QString loggingCategoryPrefix(const QString& deviceName) { return QStringLiteral("controller.") + RuntimeLoggingCategory::removeInvalidCharsFromCategory(deviceName.toLower());}} // namespace
Controller::Controller(const QString& deviceName) : m_sDeviceName(deviceName), m_logBase(loggingCategoryPrefix(deviceName)), m_logInput(loggingCategoryPrefix(deviceName) + QStringLiteral(".input")), m_logOutput(loggingCategoryPrefix(deviceName) + QStringLiteral(".output")), m_pScriptEngineLegacy(nullptr), m_bIsOutputDevice(false), m_bIsInputDevice(false), m_bIsOpen(false), m_bLearning(false) { m_userActivityInhibitTimer.start();}
Controller::~Controller() { // Don't close the device here. Sub-classes should close the device in their // destructors.}
ControllerJSProxy* Controller::jsProxy() { return new ControllerJSProxy(this);}
QString Controller::physicalTransport2String(PhysicalTransportProtocol protocol) { switch (protocol) { case PhysicalTransportProtocol::USB: return QStringLiteral("USB"); case PhysicalTransportProtocol::BlueTooth: return QStringLiteral("Bluetooth"); case PhysicalTransportProtocol::I2C: return QStringLiteral("I2C"); case PhysicalTransportProtocol::SPI: return QStringLiteral("SPI"); case PhysicalTransportProtocol::FireWire: return QStringLiteral("Firewire - IEEE 1394"); case PhysicalTransportProtocol::UNKNOWN: break; // Effectively fallthrough } return tr("Unknown");}
void Controller::startEngine() { qCInfo(m_logBase) << "Starting engine"; if (m_pScriptEngineLegacy) { qCWarning(m_logBase) << "startEngine(): Engine already exists! Restarting:"; stopEngine(); } m_pScriptEngineLegacy = std::make_shared<ControllerScriptEngineLegacy>(this, m_logBase); QObject::connect(m_pScriptEngineLegacy.get(), &ControllerScriptEngineBase::beforeShutdown, this, &Controller::slotBeforeEngineShutdown); emit engineStarted(m_pScriptEngineLegacy.get());}
void Controller::stopEngine() { qCInfo(m_logBase) << "Shutting down engine"; if (!m_pScriptEngineLegacy) { qCWarning(m_logBase) << "No engine exists!"; return; } m_pScriptEngineLegacy.reset(); emit engineStopped();}
bool Controller::applyMapping(const QString& resourcePath) { qCInfo(m_logBase) << "Applying controller mapping...";
// Load the script code into the engine if (!m_pScriptEngineLegacy) { qCWarning(m_logBase) << "No engine exists!"; return false; }
QList<LegacyControllerMapping::ScriptFileInfo> scriptFiles = getMappingScriptFiles(); if (scriptFiles.isEmpty()) { qCWarning(m_logBase) << "No script functions available! Did the XML file(s) load " "successfully? See above for any errors."; return true; }
m_pScriptEngineLegacy->setScriptFiles(scriptFiles);
m_pScriptEngineLegacy->setSettings(getMappingSettings());#ifdef MIXXX_USE_QML m_pScriptEngineLegacy->setModulePaths(getMappingModules()); m_pScriptEngineLegacy->setInfoScreens(getMappingInfoScreens()); m_pScriptEngineLegacy->setResourcePath(resourcePath);#else Q_UNUSED(resourcePath);#endif return m_pScriptEngineLegacy->initialize();}
void Controller::startLearning() { qCDebug(m_logBase) << m_sDeviceName << "started learning"; m_bLearning = true;}
void Controller::stopLearning() { //qDebug() << m_sDeviceName << "stopped learning."; m_bLearning = false;
}
void Controller::send(const QList<int>& data, unsigned int length) { // If you change this implementation, also change it in HidController (That // function is required due to HID devices having report IDs)
Q_UNUSED(length); // The length parameter is here for backwards compatibility for when scripts // were required to specify it.
QByteArray msg; msg.resize(data.size()); std::copy(data.cbegin(), data.cend(), msg.begin()); sendBytes(msg);}
void Controller::triggerActivity() { // Inhibit Updates for 1000 milliseconds if (m_userActivityInhibitTimer.elapsed() > 1000) { mixxx::ScreenSaverHelper::triggerUserActivity(); m_userActivityInhibitTimer.start(); }}
void Controller::receive(const QByteArray& data, mixxx::Duration timestamp) { if (!m_pScriptEngineLegacy) { //qWarning() << "Controller::receive called with no active engine!"; // Don't complain, since this will always show after closing a device as // queued signals flush out return; } triggerActivity();
int length = data.size(); if (CmdlineArgs::Instance() .getControllerDebug() && m_logInput().isDebugEnabled()) { // Formatted packet display QString message = QString("t:%2, %3 bytes:\n") .arg(timestamp.formatMillisWithUnit(), QString::number(length)); for (int i = 0; i < length; i++) { QString spacer; if ((i + 1) % 16 == 0) { spacer = QStringLiteral("\n"); } else if ((i + 1) % 4 == 0) { spacer = QStringLiteral(" "); } else { spacer = QStringLiteral(" "); } // cast to quint8 to avoid that negative chars are for instance displayed as ffffffff instead of the desired ff message += QString::number(static_cast<quint8>(data.at(i)), 16) .toUpper() .rightJustified(2, QChar('0')) + spacer; } qCDebug(m_logInput).noquote() << message; }
m_pScriptEngineLegacy->handleIncomingData(data);}void Controller::slotBeforeEngineShutdown() { /* Override this to get called before the JS engine shuts down */ qCDebug(m_logInput) << "Engine shutdown";}