# HG changeset patch # User Chris Cannam # Date 1235411417 0 # Node ID ecce042cc374bbe36e7588fa43d90a6f7c493745 # Parent 863ad4b1f841ec78fae64fb098d16ae91dad6dc0 * Wire up MIDI input port (as far as printing a message when an event comes in, anyway) diff -r 863ad4b1f841 -r ecce042cc374 data/data.pro --- a/data/data.pro Mon Feb 23 14:40:17 2009 +0000 +++ b/data/data.pro Mon Feb 23 17:50:17 2009 +0000 @@ -14,6 +14,11 @@ OBJECTS_DIR = tmp_obj MOC_DIR = tmp_moc +# Set up suitable platform defines for RtMidi +linux*: DEFINES += __LINUX_ALSASEQ__ +macx*: DEFINES += __MACOSX_CORE__ +win*: DEFINES += __WINDOWS_MM__ + # Input HEADERS += fft/FFTapi.h \ fft/FFTCacheReader.h \ @@ -48,6 +53,8 @@ fileio/WavFileWriter.h \ midi/MIDIEvent.h \ midi/MIDIInput.h \ + midi/rtmidi/RtError.h \ + midi/rtmidi/RtMidi.h \ model/AggregateWaveModel.h \ model/AlignmentModel.h \ model/Dense3DModelPeakCache.h \ @@ -104,6 +111,7 @@ fileio/WavFileReader.cpp \ fileio/WavFileWriter.cpp \ midi/MIDIInput.cpp \ + midi/rtmidi/RtMidi.cpp \ model/AggregateWaveModel.cpp \ model/AlignmentModel.cpp \ model/Dense3DModelPeakCache.cpp \ diff -r 863ad4b1f841 -r ecce042cc374 data/midi/MIDIInput.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/midi/MIDIInput.cpp Mon Feb 23 17:50:17 2009 +0000 @@ -0,0 +1,86 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006-2009 Chris Cannam and QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "MIDIInput.h" + +#include "rtmidi/RtMidi.h" + +MIDIInput::MIDIInput(QString name) : + m_rtmidi(), + m_buffer(1023) +{ + try { + m_rtmidi = new RtMidiIn(name.toStdString()); + m_rtmidi->setCallback(staticCallback, this); + m_rtmidi->openPort(); + } catch (RtError e) { + e.printMessage(); + delete m_rtmidi; + m_rtmidi = 0; + } +} + +MIDIInput::~MIDIInput() +{ + delete m_rtmidi; +} + +void +MIDIInput::staticCallback(double timestamp, std::vector *message, + void *userData) +{ + ((MIDIInput *)userData)->callback(timestamp, message); +} + +void +MIDIInput::callback(double timestamp, std::vector *message) +{ + std::cerr << "MIDIInput::callback(" << timestamp << ")" << std::endl; + +} + +MIDIEvent +MIDIInput::readEvent() +{ + MIDIEvent *event = m_buffer.readOne(); + MIDIEvent revent = *event; + delete event; + return revent; +} + +void +MIDIInput::postEvent(MIDIEvent e) +{ + int count = 0, max = 5; + while (m_buffer.getWriteSpace() == 0) { + if (count == max) { + std::cerr << "ERROR: MIDIInput::postEvent: MIDI event queue is full and not clearing -- abandoning incoming event" << std::endl; + return; + } + std::cerr << "WARNING: MIDIInput::postEvent: MIDI event queue (capacity " << m_buffer.getSize() << " is full!" << std::endl; + std::cerr << "Waiting for something to be processed" << std::endl; +#ifdef _WIN32 + Sleep(1); +#else + sleep(1); +#endif + count++; + } + + MIDIEvent *me = new MIDIEvent(e); + m_buffer.write(&me, 1); + emit eventsAvailable(); +} + diff -r 863ad4b1f841 -r ecce042cc374 data/midi/MIDIInput.h --- a/data/midi/MIDIInput.h Mon Feb 23 14:40:17 2009 +0000 +++ b/data/midi/MIDIInput.h Mon Feb 23 17:50:17 2009 +0000 @@ -29,7 +29,7 @@ Q_OBJECT public: - MIDIInput(); + MIDIInput(QString name); virtual ~MIDIInput(); bool isOK() const { return m_rtmidi != 0; } diff -r 863ad4b1f841 -r ecce042cc374 data/midi/rtmidi/RtMidi.cpp --- a/data/midi/rtmidi/RtMidi.cpp Mon Feb 23 14:40:17 2009 +0000 +++ b/data/midi/rtmidi/RtMidi.cpp Mon Feb 23 17:50:17 2009 +0000 @@ -69,9 +69,9 @@ // Common RtMidiIn Definitions //*********************************************************************// -RtMidiIn :: RtMidiIn() : RtMidi() +RtMidiIn :: RtMidiIn(std::string name) : RtMidi() { - this->initialize(); + this->initialize(name); } void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) @@ -144,9 +144,9 @@ // Common RtMidiOut Definitions //*********************************************************************// -RtMidiOut :: RtMidiOut() : RtMidi() +RtMidiOut :: RtMidiOut(std::string name) : RtMidi() { - this->initialize(); + this->initialize(name); } @@ -311,11 +311,11 @@ } } -void RtMidiIn :: initialize( void ) +void RtMidiIn :: initialize(std::string name) { // Set up our client. MIDIClientRef client; - OSStatus result = MIDIClientCreate( CFSTR("RtMidi Input Client"), NULL, NULL, &client ); + OSStatus result = MIDIClientCreate( CFSTR(name.c_str()), NULL, NULL, &client ); if ( result != noErr ) { errorString_ = "RtMidiIn::initialize: error creating OS-X MIDI client object."; error( RtError::DRIVER_ERROR ); @@ -479,11 +479,11 @@ return stringName; } -void RtMidiOut :: initialize( void ) +void RtMidiOut :: initialize(std::string name) { // Set up our client. MIDIClientRef client; - OSStatus result = MIDIClientCreate( CFSTR("RtMidi Output Client"), NULL, NULL, &client ); + OSStatus result = MIDIClientCreate( CFSTR(name.c_str()), NULL, NULL, &client ); if ( result != noErr ) { errorString_ = "RtMidiOut::initialize: error creating OS-X MIDI client object."; error( RtError::DRIVER_ERROR ); @@ -813,7 +813,7 @@ return 0; } -void RtMidiIn :: initialize( void ) +void RtMidiIn :: initialize(std::string name) { // Set up the ALSA sequencer client. snd_seq_t *seq; @@ -824,7 +824,7 @@ } // Set client name. - snd_seq_set_client_name(seq, "RtMidi Input Client"); + snd_seq_set_client_name(seq, name.c_str()); // Save our api-specific connection information. AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; @@ -885,8 +885,8 @@ error( RtError::NO_DEVICES_FOUND ); } - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); std::ostringstream ost; AlsaMidiData *data = static_cast (apiData_); if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) == 0 ) { @@ -895,6 +895,8 @@ error( RtError::INVALID_PARAMETER ); } + char name[20]; + sprintf(name, "Input %d", portNumber + 1); snd_seq_addr_t sender, receiver; sender.client = snd_seq_port_info_get_client( pinfo ); @@ -913,7 +915,7 @@ snd_seq_port_info_set_timestamping(pinfo, 1); snd_seq_port_info_set_timestamp_real(pinfo, 1); snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id); - snd_seq_port_info_set_name(pinfo, "RtMidi Input"); + snd_seq_port_info_set_name(pinfo, name); data->vport = snd_seq_create_port(data->seq, pinfo); if ( data->vport < 0 ) { @@ -1095,7 +1097,7 @@ return 0; } -void RtMidiOut :: initialize( void ) +void RtMidiOut :: initialize(std::string name) { // Set up the ALSA sequencer client. snd_seq_t *seq; @@ -1106,7 +1108,7 @@ } // Set client name. - snd_seq_set_client_name(seq, "RtMidi Output Client"); + snd_seq_set_client_name(seq, name.c_str()); // Save our api-specific connection information. AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; @@ -1145,8 +1147,8 @@ error( RtError::NO_DEVICES_FOUND ); } - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); std::ostringstream ost; AlsaMidiData *data = static_cast (apiData_); if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) == 0 ) { @@ -1160,8 +1162,11 @@ receiver.port = snd_seq_port_info_get_port( pinfo ); sender.client = snd_seq_client_id( data->seq ); + char name[20]; + sprintf(name, "Output %d", portNumber + 1); + if ( data->vport < 0 ) { - data->vport = snd_seq_create_simple_port( data->seq, "RtMidi Output", + data->vport = snd_seq_create_simple_port( data->seq, name, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC ); if ( data->vport < 0 ) { @@ -1423,7 +1428,7 @@ return 0; } -void RtMidiIn :: initialize( void ) +void RtMidiIn :: initialize(std::string name) { // Initialize the Irix MIDI system. At the moment, we will not // worry about a return value of zero (ports) because there is a @@ -1564,7 +1569,7 @@ return stringName; } -void RtMidiOut :: initialize( void ) +void RtMidiOut :: initialize(std::string name) { // Initialize the Irix MIDI system. At the moment, we will not // worry about a return value of zero (ports) because there is a @@ -1789,7 +1794,7 @@ apiData->message.bytes.clear(); } -void RtMidiIn :: initialize( void ) +void RtMidiIn :: initialize(std::string name) { // We'll issue a warning here if no devices are available but not // throw an error since the user can plugin something later. @@ -1970,7 +1975,7 @@ return stringName; } -void RtMidiOut :: initialize( void ) +void RtMidiOut :: initialize(std::string name) { // We'll issue a warning here if no devices are available but not // throw an error since the user can plug something in later. diff -r 863ad4b1f841 -r ecce042cc374 data/midi/rtmidi/RtMidi.h --- a/data/midi/rtmidi/RtMidi.h Mon Feb 23 14:40:17 2009 +0000 +++ b/data/midi/rtmidi/RtMidi.h Mon Feb 23 17:50:17 2009 +0000 @@ -109,7 +109,7 @@ /*! An exception will be thrown if a MIDI system initialization error occurs. */ - RtMidiIn(); + RtMidiIn(std::string inputName = std::string("RtMidi Input Client")); //! If a MIDI connection is still open, it will be closed by the destructor. ~RtMidiIn(); @@ -217,7 +217,7 @@ private: - void initialize( void ); + void initialize(std::string name); RtMidiInData inputData_; }; @@ -244,7 +244,7 @@ /*! An exception will be thrown if a MIDI system initialization error occurs. */ - RtMidiOut(); + RtMidiOut(std::string outputName = "RtMidi Output Client"); //! The destructor closes any open MIDI connections. ~RtMidiOut(); @@ -290,7 +290,7 @@ private: - void initialize( void ); + void initialize(std::string name); }; #endif