2
* @file hss1394controller.cpp
3
* @author Sean M. Pappalardo spappalardo@mixxx.org
4
* @date Thu 15 Mar 2012
5
* @brief HSS1394-based MIDI backend
8
#include "controllers/midi/hss1394controller.h"
10
DeviceChannelListener::DeviceChannelListener(QObject* pParent, QString name)
12
hss1394::ChannelListener(),
16
DeviceChannelListener::~DeviceChannelListener() {
19
void DeviceChannelListener::Process(const hss1394::uint8 *pBuffer, hss1394::uint uBufferSize) {
22
// If multiple three-byte messages arrive right next to each other, handle them all
23
while (i < uBufferSize) {
24
unsigned char status = pBuffer[i];
25
unsigned char opcode = status & 0xF0;
26
unsigned char channel = status & 0x0F;
28
unsigned char velocity;
29
switch (status & 0xF0) {
35
if (i + 2 < uBufferSize) {
37
velocity = pBuffer[i+2];
38
emit(incomingData(status, note, velocity));
40
qWarning() << "Buffer underflow in DeviceChannelListener::Process()";
45
// Handle platter messages and any others that are not 3 bytes
46
QByteArray outArray((char*)pBuffer,uBufferSize);
47
emit(incomingData(outArray));
54
void DeviceChannelListener::Disconnected() {
55
qDebug() << "HSS1394 device" << m_sName << "disconnected";
58
void DeviceChannelListener::Reconnected() {
59
qDebug() << "HSS1394 device" << m_sName << "re-connected";
62
Hss1394Controller::Hss1394Controller(const hss1394::TNodeInfo deviceInfo,
65
m_deviceInfo(deviceInfo),
66
m_iDeviceIndex(deviceIndex) {
67
// Note: We prepend the input stream's index to the device's name to prevent
68
// duplicate devices from causing mayhem.
69
//setDeviceName(QString("H%1. %2").arg(QString::number(m_iDeviceIndex), QString(deviceInfo.sName.c_str())));
70
setDeviceName(QString("%1").arg(QString(deviceInfo.sName.c_str())));
72
// All HSS1394 devices are full-duplex
74
setOutputDevice(true);
77
Hss1394Controller::~Hss1394Controller() {
81
int Hss1394Controller::open() {
83
qDebug() << "HSS1394 device" << getName() << "already open";
87
if (getName() == MIXXX_HSS1394_NO_DEVICE_STRING) {
92
qDebug() << "Hss1394Controller: Opening" << getName() << "index" << m_iDeviceIndex;
95
using namespace hss1394;
97
m_pChannel = Node::Instance()->OpenChannel(m_iDeviceIndex);
98
if (m_pChannel == NULL) {
99
qDebug() << "HSS1394 device" << getName() << "could not be opened";
100
m_pChannelListener = NULL;
104
m_pChannelListener = new DeviceChannelListener(this, getName());
105
connect(m_pChannelListener, SIGNAL(incomingData(QByteArray)),
106
this, SLOT(receive(QByteArray)));
107
connect(m_pChannelListener, SIGNAL(incomingData(unsigned char, unsigned char, unsigned char)),
108
this, SLOT(receive(unsigned char, unsigned char, unsigned char)));
110
if (!m_pChannel->InstallChannelListener(m_pChannelListener)) {
111
qDebug() << "HSS1394 channel listener could not be installed for device" << getName();
112
delete m_pChannelListener;
113
m_pChannelListener = NULL;
117
// TODO(XXX): Should be done in script, not in Mixxx
118
if (getName().contains("SCS.1d",Qt::CaseInsensitive)) {
119
// If we are an SCS.1d, set the record encoder event timer to fire at 1ms intervals
120
// to match the 1ms scratch timer in the controller engine
122
// By default on f/w version 1.25, a new record encoder event (one new position)
123
// is sent at 500 Hz max, 2ms. When this event occurs, a second timer is reset.
124
// By default this second timer expires periodically at 60 Hz max, around 16.6ms.
126
int iPeriod = 60000/1000; // 1000Hz = 1ms. (Internal clock is 60kHz.)
127
int iTimer = 3; // 3 for new event timer, 4 for second �same position repeated� timer
128
if (m_pChannel->SendUserControl(iTimer, (const hss1394::uint8*)&iPeriod, 3) == 0)
129
qWarning() << "Unable to set SCS.1d platter timer period.";
137
int Hss1394Controller::close() {
139
qDebug() << "HSS1394 device" << getName() << "already closed";
143
disconnect(m_pChannelListener, SIGNAL(incomingData(QByteArray)),
144
this, SLOT(receive(QByteArray)));
145
disconnect(m_pChannelListener, SIGNAL(incomingData(unsigned char, unsigned char, unsigned char)),
146
this, SLOT(receive(unsigned char, unsigned char, unsigned char)));
149
MidiController::close();
151
// Clean up the HSS1394Node
152
using namespace hss1394;
153
if (!Node::Instance()->ReleaseChannel(m_pChannel)) {
154
qDebug() << "HSS1394 device" << getName() << "could not be released";
157
if (m_pChannelListener != NULL) {
158
delete m_pChannelListener;
159
m_pChannelListener = NULL;
166
void Hss1394Controller::send(unsigned int word) {
167
unsigned char data[2];
168
data[0] = word & 0xFF;
169
data[1] = (word >> 8) & 0xFF;
170
data[2] = (word >> 16) & 0xFF;
172
QString message = QString("%1 %2 %3").arg(
173
QString("%1").arg(data[0], 2, 16, QChar('0')),
174
QString("%1").arg(data[1], 2, 16, QChar('0')),
175
QString("%1").arg(data[2], 2, 16, QChar('0')));
177
int bytesSent = m_pChannel->SendChannelBytes(data, 3);
179
//if (bytesSent != 3) {
180
// qDebug()<<"ERROR: Sent" << bytesSent << "of 3 bytes:" << message;
181
// //m_pChannel->Flush();
185
void Hss1394Controller::send(QByteArray data) {
186
int bytesSent = m_pChannel->SendChannelBytes(
187
(unsigned char*)data.constData(), data.size());
189
//if (bytesSent != length) {
190
// qDebug()<<"ERROR: Sent" << bytesSent << "of" << length << "bytes (SysEx)";
191
// //m_pChannel->Flush();