Mixxx

/home/maxime/Projets/Mixxx/1.10/mixxx/src/midi/mididevicehss1394.cpp

Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines