![]() |
Mixxx
|
00001 00016 /*************************************************************************** 00017 * * 00018 * This program is free software; you can redistribute it and/or modify * 00019 * it under the terms of the GNU General Public License as published by * 00020 * the Free Software Foundation; either version 2 of the License, or * 00021 * (at your option) any later version. * 00022 * * 00023 ***************************************************************************/ 00024 00025 #include <QtCore> 00026 #include "configobject.h" 00027 #include "midimapping.h" 00028 #include "mididevicehss1394.h" 00029 00030 // HSS1394 Channel listener stuff 00031 00032 DeviceChannelListener::DeviceChannelListener(int id, QString name, MidiDevice* midiDevice) : hss1394::ChannelListener() { 00033 m_iId = id; 00034 m_sName = name; 00035 m_pMidiDevice = midiDevice; 00036 } 00037 00038 void DeviceChannelListener::Process(const hss1394::uint8 *pBuffer, hss1394::uint uBufferSize) { 00039 // Called when data has arrived. 00041 00042 unsigned int i = 0; 00043 00044 // If multiple three-byte messages arrive right next to each other, handle them all 00045 while (i<uBufferSize) { 00046 unsigned char status = pBuffer[i]; 00047 unsigned char opcode = status & 0xF0; 00048 unsigned char channel = status & 0x0F; 00049 unsigned char note; 00050 unsigned char velocity; 00051 switch (status & 0xF0) { 00052 case MIDI_STATUS_NOTE_OFF: 00053 case MIDI_STATUS_NOTE_ON: 00054 case MIDI_STATUS_AFTERTOUCH: 00055 case MIDI_STATUS_CC: 00056 case MIDI_STATUS_PITCH_BEND: 00057 note = pBuffer[i+1]; 00058 velocity = pBuffer[i+2]; 00059 00060 m_pMidiDevice->receive((MidiStatusByte)status, channel, note, velocity); 00061 i+=3; 00062 break; 00063 default: 00064 // Handle platter messages and any others that are not 3 bytes 00065 m_pMidiDevice->receive(pBuffer, uBufferSize); 00066 i=uBufferSize; 00067 break; 00068 } 00069 } 00070 } 00071 00072 void DeviceChannelListener::Disconnected() { 00073 qDebug()<<"HSS1394 device" << m_sName << "disconnected"; 00074 } 00075 00076 void DeviceChannelListener::Reconnected() { 00077 qDebug()<<"HSS1394 device" << m_sName << "re-connected"; 00078 } 00079 00080 // Main MidiDeviceHss1394 code 00081 00082 QMutex MidiDeviceHss1394::m_sHSSLock; // HSS1394 is not thread-safe 00083 00084 MidiDeviceHss1394::MidiDeviceHss1394(MidiMapping* mapping, 00085 const hss1394::TNodeInfo deviceInfo, 00086 int deviceIndex) 00087 : MidiDevice(mapping) 00088 { 00089 m_deviceInfo = deviceInfo; 00090 m_iDeviceIndex = deviceIndex; 00091 00092 //Note: We prepend the input stream's index to the device's name to prevent duplicate devices from causing mayhem. 00093 m_strDeviceName = QString("H%1. %2").arg(QString::number(m_iDeviceIndex)).arg(QString(deviceInfo.sName.c_str())); 00094 00095 // All HSS1394 devices are full-duplex 00096 m_bIsInputDevice = true; 00097 m_bIsOutputDevice = true; 00098 00099 m_pMidiMapping->setName(m_strDeviceName); 00100 } 00101 00102 MidiDeviceHss1394::~MidiDeviceHss1394() 00103 { 00104 close(); 00105 } 00106 00107 int MidiDeviceHss1394::open() 00108 { 00109 QMutexLocker Locker(&m_mutex); //Make this function thread safe. 00110 00111 if (m_bIsOpen) { 00112 qDebug() << "HSS1394 device" << m_strDeviceName << "already open"; 00113 return -1; 00114 } 00115 00116 setReceiveInhibit(false); 00117 00118 startup(); 00119 00120 if (m_strDeviceName == MIXXX_HSS1394_NO_DEVICE_STRING) 00121 return -1; 00122 00123 if (midiDebugging()) qDebug() << "MidiDeviceHss1394: Opening" << m_strDeviceName << "index" << m_iDeviceIndex; 00124 00125 using namespace hss1394; 00126 00127 m_sHSSLock.lock(); 00128 m_pChannel = Node::Instance()->OpenChannel(m_iDeviceIndex); 00129 m_sHSSLock.unlock(); 00130 if( m_pChannel == NULL ) 00131 { 00132 qDebug() << "HSS1394 device" << m_strDeviceName << "could not be opened"; 00133 m_pChannelListener = NULL; 00134 return -1; 00135 } 00136 00137 m_pChannelListener = new DeviceChannelListener(m_iDeviceIndex, m_strDeviceName, this); 00138 if (false == m_pChannel->InstallChannelListener(m_pChannelListener)) { 00139 qDebug() << "HSS1394 channel listener could not be installed for device" << m_strDeviceName; 00140 delete m_pChannelListener; 00141 m_pChannelListener = NULL; 00142 m_pChannel = NULL; 00143 } 00144 00145 if (m_pChannel != NULL && m_strDeviceName.contains("SCS.1d",Qt::CaseInsensitive)) { 00146 // If we are an SCS.1d, set the record encoder event timer to fire at 1ms intervals 00147 // to match the 1ms scratch timer in the MIDI script engine 00148 // 00149 // By default on f/w version 1.25, a new record encoder event (one new position) 00150 // is sent at 500 Hz max, 2ms. When this event occurs, a second timer is reset. 00151 // By default this second timer expires periodically at 60 Hz max, around 16.6ms. 00152 00153 int iPeriod = 60000/1000; // 1000Hz = 1ms. (Internal clock is 60kHz.) 00154 int iTimer = 3; // 3 for new event timer, 4 for second “same position repeated” timer 00155 if (m_pChannel->SendUserControl(iTimer, (const hss1394::uint8*)&iPeriod, 3) == 0) 00156 qWarning() << "Unable to set SCS.1d platter timer period."; 00157 } 00158 00159 m_bIsOpen = true; 00160 00161 return 0; 00162 00163 } 00164 00165 int MidiDeviceHss1394::close() 00166 { 00167 setReceiveInhibit(true); // Prevent deadlock 00168 00169 if (!m_bIsOpen) { 00170 qDebug() << "HSS1394 device" << m_strDeviceName << "already closed"; 00171 return -1; 00172 } 00173 00174 shutdown(); 00175 00176 //shutdown() locks so we must lock after it. 00177 QMutexLocker Locker(&m_mutex); 00178 00179 // Clean up the HSS1394Node 00180 using namespace hss1394; 00181 m_sHSSLock.lock(); 00182 if (!Node::Instance()->ReleaseChannel(m_pChannel)) { 00183 qDebug() << "HSS1394 device" << m_strDeviceName << "could not be released"; 00184 return -1; 00185 } 00186 if (m_pChannelListener != NULL) { 00187 delete m_pChannelListener; 00188 m_pChannelListener = NULL; 00189 } 00190 m_sHSSLock.unlock(); 00191 00192 m_bIsOpen = false; 00193 00194 return 0; 00195 } 00196 00197 void MidiDeviceHss1394::sendShortMsg(unsigned int word) 00198 { 00199 QMutexLocker Locker(&m_mutex); 00200 00201 unsigned char data[2]; 00202 data[0] = word & 0xFF; 00203 data[1] = (word >> 8) & 0xFF; 00204 data[2] = (word >> 16) & 0xFF; 00205 00206 QString message = QString("%1 %2 %3") 00207 .arg(data[0], 2, 16, QChar('0')) 00208 .arg(data[1], 2, 16, QChar('0')) 00209 .arg(data[2], 2, 16, QChar('0')); 00210 00211 m_sHSSLock.lock(); 00212 int bytesSent = m_pChannel->SendChannelBytes(data,3); 00213 00214 //if (bytesSent != 3) { 00215 // qDebug()<<"ERROR: Sent" << bytesSent << "of 3 bytes:" << message; 00216 // //m_pChannel->Flush(); 00217 //} 00218 m_sHSSLock.unlock(); 00219 00220 } 00221 00222 // The sysex data must already contain the start byte 0xf0 and the end byte 0xf7. 00223 void MidiDeviceHss1394::sendSysexMsg(unsigned char data[], unsigned int length) 00224 { 00225 QMutexLocker Locker(&m_mutex); 00226 00227 m_sHSSLock.lock(); 00228 int bytesSent = m_pChannel->SendChannelBytes(data,length); 00229 00230 //if (bytesSent != length) { 00231 // qDebug()<<"ERROR: Sent" << bytesSent << "of" << length << "bytes (SysEx)"; 00232 // //m_pChannel->Flush(); 00233 //} 00234 m_sHSSLock.unlock(); 00235 }