Updated RtAudio/RtMidi for new release, plus additional documentation updates.

This commit is contained in:
Gary Scavone
2019-04-18 09:18:19 -04:00
parent 38970124ec
commit b6143915a9
14 changed files with 1545 additions and 872 deletions

View File

@@ -1,5 +1,5 @@
# Process this file with autoconf to produce a configure script. # Process this file with autoconf to produce a configure script.
AC_INIT(STK, 4.6.0, gary@music.mcgill.ca, stk) AC_INIT(STK, 4.6.1, gary@music.mcgill.ca, stk)
AC_CONFIG_AUX_DIR(config) AC_CONFIG_AUX_DIR(config)
AC_CONFIG_SRCDIR(src/Stk.cpp) AC_CONFIG_SRCDIR(src/Stk.cpp)
AC_CONFIG_FILES(Makefile src/Makefile projects/demo/Makefile projects/effects/Makefile projects/ragamatic/Makefile projects/examples/Makefile projects/examples/libMakefile projects/eguitar/Makefile) AC_CONFIG_FILES(Makefile src/Makefile projects/demo/Makefile projects/effects/Makefile projects/ragamatic/Makefile projects/examples/Makefile projects/examples/libMakefile projects/eguitar/Makefile)

View File

@@ -2,7 +2,7 @@ The Synthesis ToolKit in C++ (STK)
By Perry R. Cook and Gary P. Scavone, 1995--2019. By Perry R. Cook and Gary P. Scavone, 1995--2019.
v.4.6.1 (18 April 2017) v.4.6.1 (18 April 2019)
- see github site for complete details (github.com/thestk/stk) - see github site for complete details (github.com/thestk/stk)
- various documentation updates - various documentation updates
- new Recorder (flute a la Verge) class (thanks to Mathias Bredholt) - new Recorder (flute a la Verge) class (thanks to Mathias Bredholt)

View File

@@ -7,6 +7,7 @@
and OSS), Macintosh OS X (CoreAudio and Jack), and Windows and OSS), Macintosh OS X (CoreAudio and Jack), and Windows
(DirectSound, ASIO and WASAPI) operating systems. (DirectSound, ASIO and WASAPI) operating systems.
RtAudio GitHub site: https://github.com/thestk/rtaudio
RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/ RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/
RtAudio: realtime audio i/o C++ classes RtAudio: realtime audio i/o C++ classes
@@ -45,7 +46,21 @@
#ifndef __RTAUDIO_H #ifndef __RTAUDIO_H
#define __RTAUDIO_H #define __RTAUDIO_H
#define RTAUDIO_VERSION "5.0.0" #define RTAUDIO_VERSION "5.1.0"
#if defined _WIN32 || defined __CYGWIN__
#if defined(RTAUDIO_EXPORT)
#define RTAUDIO_DLL_PUBLIC __declspec(dllexport)
#else
#define RTAUDIO_DLL_PUBLIC
#endif
#else
#if __GNUC__ >= 4
#define RTAUDIO_DLL_PUBLIC __attribute__( (visibility( "default" )) )
#else
#define RTAUDIO_DLL_PUBLIC
#endif
#endif
#include <string> #include <string>
#include <vector> #include <vector>
@@ -179,6 +194,7 @@ static const RtAudioStreamStatus RTAUDIO_OUTPUT_UNDERFLOW = 0x2; // The output
\param userData A pointer to optional data provided by the client \param userData A pointer to optional data provided by the client
when opening the stream (default = NULL). when opening the stream (default = NULL).
\return
To continue normal stream operation, the RtAudioCallback function To continue normal stream operation, the RtAudioCallback function
should return a value of zero. To stop the stream and drain the should return a value of zero. To stop the stream and drain the
output buffer, the function should return a value of one. To abort output buffer, the function should return a value of one. To abort
@@ -200,7 +216,7 @@ typedef int (*RtAudioCallback)( void *outputBuffer, void *inputBuffer,
*/ */
/************************************************************************/ /************************************************************************/
class RtAudioError : public std::runtime_error class RTAUDIO_DLL_PUBLIC RtAudioError : public std::runtime_error
{ {
public: public:
//! Defined RtAudioError types. //! Defined RtAudioError types.
@@ -260,7 +276,7 @@ typedef void (*RtAudioErrorCallback)( RtAudioError::Type type, const std::string
class RtApi; class RtApi;
class RtAudio class RTAUDIO_DLL_PUBLIC RtAudio
{ {
public: public:
@@ -275,7 +291,8 @@ class RtAudio
WINDOWS_WASAPI, /*!< The Microsoft WASAPI API. */ WINDOWS_WASAPI, /*!< The Microsoft WASAPI API. */
WINDOWS_ASIO, /*!< The Steinberg Audio Stream I/O API. */ WINDOWS_ASIO, /*!< The Steinberg Audio Stream I/O API. */
WINDOWS_DS, /*!< The Microsoft DirectSound API. */ WINDOWS_DS, /*!< The Microsoft DirectSound API. */
RTAUDIO_DUMMY /*!< A compilable but non-functional API. */ RTAUDIO_DUMMY, /*!< A compilable but non-functional API. */
NUM_APIS /*!< Number of values in this enum. */
}; };
//! The public device information structure for returning queried values. //! The public device information structure for returning queried values.
@@ -387,6 +404,29 @@ class RtAudio
*/ */
static void getCompiledApi( std::vector<RtAudio::Api> &apis ); static void getCompiledApi( std::vector<RtAudio::Api> &apis );
//! Return the name of a specified compiled audio API.
/*!
This obtains a short lower-case name used for identification purposes.
This value is guaranteed to remain identical across library versions.
If the API is unknown, this function will return the empty string.
*/
static std::string getApiName( RtAudio::Api api );
//! Return the display name of a specified compiled audio API.
/*!
This obtains a long name used for display purposes.
If the API is unknown, this function will return the empty string.
*/
static std::string getApiDisplayName( RtAudio::Api api );
//! Return the compiled audio API having the given name.
/*!
A case insensitive comparison will check the specified name
against the list of compiled APIs, and return the one which
matches. On failure, the function returns UNSPECIFIED.
*/
static RtAudio::Api getCompiledApiByName( const std::string &name );
//! The class constructor. //! The class constructor.
/*! /*!
The constructor performs minor initialization tasks. An exception The constructor performs minor initialization tasks. An exception
@@ -583,6 +623,7 @@ class RtAudio
#endif #endif
#include <windows.h> #include <windows.h>
#include <process.h> #include <process.h>
#include <stdint.h>
typedef uintptr_t ThreadHandle; typedef uintptr_t ThreadHandle;
typedef CRITICAL_SECTION StreamMutex; typedef CRITICAL_SECTION StreamMutex;
@@ -651,7 +692,6 @@ class S24 {
return *this; return *this;
} }
S24( const S24& v ) { *this = v; }
S24( const double& d ) { *this = (int) d; } S24( const double& d ) { *this = (int) d; }
S24( const float& f ) { *this = (int) f; } S24( const float& f ) { *this = (int) f; }
S24( const signed short& s ) { *this = (int) s; } S24( const signed short& s ) { *this = (int) s; }
@@ -671,7 +711,7 @@ class S24 {
#include <sstream> #include <sstream>
class RtApi class RTAUDIO_DLL_PUBLIC RtApi
{ {
public: public:
@@ -864,7 +904,6 @@ public:
void startStream( void ); void startStream( void );
void stopStream( void ); void stopStream( void );
void abortStream( void ); void abortStream( void );
long getStreamLatency( void );
// This function is intended for internal use only. It must be // This function is intended for internal use only. It must be
// public because it is called by the internal callback handler, // public because it is called by the internal callback handler,
@@ -900,7 +939,6 @@ public:
void startStream( void ); void startStream( void );
void stopStream( void ); void stopStream( void );
void abortStream( void ); void abortStream( void );
long getStreamLatency( void );
// This function is intended for internal use only. It must be // This function is intended for internal use only. It must be
// public because it is called by the internal callback handler, // public because it is called by the internal callback handler,
@@ -935,7 +973,6 @@ public:
void startStream( void ); void startStream( void );
void stopStream( void ); void stopStream( void );
void abortStream( void ); void abortStream( void );
long getStreamLatency( void );
// This function is intended for internal use only. It must be // This function is intended for internal use only. It must be
// public because it is called by the internal callback handler, // public because it is called by the internal callback handler,
@@ -973,7 +1010,6 @@ public:
void startStream( void ); void startStream( void );
void stopStream( void ); void stopStream( void );
void abortStream( void ); void abortStream( void );
long getStreamLatency( void );
// This function is intended for internal use only. It must be // This function is intended for internal use only. It must be
// public because it is called by the internal callback handler, // public because it is called by the internal callback handler,
@@ -1003,7 +1039,7 @@ class RtApiWasapi : public RtApi
{ {
public: public:
RtApiWasapi(); RtApiWasapi();
~RtApiWasapi(); virtual ~RtApiWasapi();
RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_WASAPI; } RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_WASAPI; }
unsigned int getDeviceCount( void ); unsigned int getDeviceCount( void );

View File

@@ -5,7 +5,8 @@
This class implements some common functionality for the realtime This class implements some common functionality for the realtime
MIDI input/output subclasses RtMidiIn and RtMidiOut. MIDI input/output subclasses RtMidiIn and RtMidiOut.
RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/ RtMidi GitHub site: https://github.com/thestk/rtmidi
RtMidi WWW site: http://www.music.mcgill.ca/~gary/rtmidi/
RtMidi: realtime MIDI i/o C++ classes RtMidi: realtime MIDI i/o C++ classes
Copyright (c) 2003-2019 Gary P. Scavone Copyright (c) 2003-2019 Gary P. Scavone
@@ -43,7 +44,21 @@
#ifndef RTMIDI_H #ifndef RTMIDI_H
#define RTMIDI_H #define RTMIDI_H
#define RTMIDI_VERSION "3.0.0" #if defined _WIN32 || defined __CYGWIN__
#if defined(RTMIDI_EXPORT)
#define RTMIDI_DLL_PUBLIC __declspec(dllexport)
#else
#define RTMIDI_DLL_PUBLIC
#endif
#else
#if __GNUC__ >= 4
#define RTMIDI_DLL_PUBLIC __attribute__( (visibility( "default" )) )
#else
#define RTMIDI_DLL_PUBLIC
#endif
#endif
#define RTMIDI_VERSION "4.0.0"
#include <exception> #include <exception>
#include <iostream> #include <iostream>
@@ -60,7 +75,7 @@
*/ */
/************************************************************************/ /************************************************************************/
class RtMidiError : public std::exception class RTMIDI_DLL_PUBLIC RtMidiError : public std::exception
{ {
public: public:
//! Defined RtMidiError types. //! Defined RtMidiError types.
@@ -79,7 +94,8 @@ class RtMidiError : public std::exception
}; };
//! The constructor. //! The constructor.
RtMidiError( const std::string& message, Type type = RtMidiError::UNSPECIFIED ) throw() : message_(message), type_(type) {} RtMidiError( const std::string& message, Type type = RtMidiError::UNSPECIFIED ) throw()
: message_(message), type_(type) {}
//! The destructor. //! The destructor.
virtual ~RtMidiError( void ) throw() {} virtual ~RtMidiError( void ) throw() {}
@@ -113,10 +129,9 @@ typedef void (*RtMidiErrorCallback)( RtMidiError::Type type, const std::string &
class MidiApi; class MidiApi;
class RtMidi class RTMIDI_DLL_PUBLIC RtMidi
{ {
public: public:
//! MIDI API specifier arguments. //! MIDI API specifier arguments.
enum Api { enum Api {
UNSPECIFIED, /*!< Search for a working compiled API. */ UNSPECIFIED, /*!< Search for a working compiled API. */
@@ -124,7 +139,8 @@ class RtMidi
LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */
UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */
WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */
RTMIDI_DUMMY /*!< A compilable but non-functional API. */ RTMIDI_DUMMY, /*!< A compilable but non-functional API. */
NUM_APIS /*!< Number of values in this enum. */
}; };
//! A static function to determine the current RtMidi version. //! A static function to determine the current RtMidi version.
@@ -138,6 +154,29 @@ class RtMidi
*/ */
static void getCompiledApi( std::vector<RtMidi::Api> &apis ) throw(); static void getCompiledApi( std::vector<RtMidi::Api> &apis ) throw();
//! Return the name of a specified compiled MIDI API.
/*!
This obtains a short lower-case name used for identification purposes.
This value is guaranteed to remain identical across library versions.
If the API is unknown, this function will return the empty string.
*/
static std::string getApiName( RtMidi::Api api );
//! Return the display name of a specified compiled MIDI API.
/*!
This obtains a long name used for display purposes.
If the API is unknown, this function will return the empty string.
*/
static std::string getApiDisplayName( RtMidi::Api api );
//! Return the compiled MIDI API having the given name.
/*!
A case insensitive comparison will check the specified name
against the list of compiled APIs, and return the one which
matches. On failure, the function returns UNSPECIFIED.
*/
static RtMidi::Api getCompiledApiByName( const std::string &name );
//! Pure virtual openPort() function. //! Pure virtual openPort() function.
virtual void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi" ) ) = 0; virtual void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi" ) ) = 0;
@@ -153,6 +192,9 @@ class RtMidi
//! Pure virtual closePort() function. //! Pure virtual closePort() function.
virtual void closePort( void ) = 0; virtual void closePort( void ) = 0;
void setClientName( const std::string &clientName );
void setPortName( const std::string &portName );
//! Returns true if a port is open and false if not. //! Returns true if a port is open and false if not.
/*! /*!
Note that this only applies to connections made with the openPort() Note that this only applies to connections made with the openPort()
@@ -168,10 +210,8 @@ class RtMidi
virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ) = 0; virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ) = 0;
protected: protected:
RtMidi(); RtMidi();
virtual ~RtMidi(); virtual ~RtMidi();
MidiApi *rtapi_; MidiApi *rtapi_;
}; };
@@ -188,8 +228,6 @@ class RtMidi
time. With the OS-X, Linux ALSA, and JACK MIDI APIs, it is also time. With the OS-X, Linux ALSA, and JACK MIDI APIs, it is also
possible to open a virtual input port to which other MIDI software possible to open a virtual input port to which other MIDI software
clients can connect. clients can connect.
by Gary P. Scavone, 2003-2019.
*/ */
/**********************************************************************/ /**********************************************************************/
@@ -207,7 +245,7 @@ class RtMidi
// //
// **************************************************************** // // **************************************************************** //
class RtMidiIn : public RtMidi class RTMIDI_DLL_PUBLIC RtMidiIn : public RtMidi
{ {
public: public:
@@ -335,7 +373,6 @@ class RtMidiIn : public RtMidi
protected: protected:
void openMidiApi( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit ); void openMidiApi( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit );
}; };
/**********************************************************************/ /**********************************************************************/
@@ -349,15 +386,12 @@ class RtMidiIn : public RtMidi
connect to more than one MIDI device at the same time. With the connect to more than one MIDI device at the same time. With the
OS-X, Linux ALSA and JACK MIDI APIs, it is also possible to open a OS-X, Linux ALSA and JACK MIDI APIs, it is also possible to open a
virtual port to which other MIDI software clients can connect. virtual port to which other MIDI software clients can connect.
by Gary P. Scavone, 2003-2019.
*/ */
/**********************************************************************/ /**********************************************************************/
class RtMidiOut : public RtMidi class RTMIDI_DLL_PUBLIC RtMidiOut : public RtMidi
{ {
public: public:
//! Default constructor that allows an optional client name. //! Default constructor that allows an optional client name.
/*! /*!
An exception will be thrown if a MIDI system initialization error occurs. An exception will be thrown if a MIDI system initialization error occurs.
@@ -458,7 +492,7 @@ class RtMidiOut : public RtMidi
// //
// **************************************************************** // // **************************************************************** //
class MidiApi class RTMIDI_DLL_PUBLIC MidiApi
{ {
public: public:
@@ -468,6 +502,8 @@ class MidiApi
virtual void openPort( unsigned int portNumber, const std::string &portName ) = 0; virtual void openPort( unsigned int portNumber, const std::string &portName ) = 0;
virtual void openVirtualPort( const std::string &portName ) = 0; virtual void openVirtualPort( const std::string &portName ) = 0;
virtual void closePort( void ) = 0; virtual void closePort( void ) = 0;
virtual void setClientName( const std::string &clientName ) = 0;
virtual void setPortName( const std::string &portName ) = 0;
virtual unsigned int getPortCount( void ) = 0; virtual unsigned int getPortCount( void ) = 0;
virtual std::string getPortName( unsigned int portNumber ) = 0; virtual std::string getPortName( unsigned int portNumber ) = 0;
@@ -489,7 +525,7 @@ protected:
void *errorCallbackUserData_; void *errorCallbackUserData_;
}; };
class MidiInApi : public MidiApi class RTMIDI_DLL_PUBLIC MidiInApi : public MidiApi
{ {
public: public:
@@ -524,8 +560,7 @@ class MidiInApi : public MidiApi
: front(0), back(0), ringSize(0), ring(0) {} : front(0), back(0), ringSize(0), ring(0) {}
bool push( const MidiMessage& ); bool push( const MidiMessage& );
bool pop( std::vector<unsigned char>*, double* ); bool pop( std::vector<unsigned char>*, double* );
unsigned int size(unsigned int *back=0, unsigned int size( unsigned int *back=0, unsigned int *front=0 );
unsigned int *front=0);
}; };
// The RtMidiInData structure is used to pass private class data to // The RtMidiInData structure is used to pass private class data to
@@ -544,16 +579,15 @@ class MidiInApi : public MidiApi
// Default constructor. // Default constructor.
RtMidiInData() RtMidiInData()
: ignoreFlags(7), doInput(false), firstMessage(true), : ignoreFlags(7), doInput(false), firstMessage(true), apiData(0), usingCallback(false),
apiData(0), usingCallback(false), userCallback(0), userData(0), userCallback(0), userData(0), continueSysex(false) {}
continueSysex(false) {}
}; };
protected: protected:
RtMidiInData inputData_; RtMidiInData inputData_;
}; };
class MidiOutApi : public MidiApi class RTMIDI_DLL_PUBLIC MidiOutApi : public MidiApi
{ {
public: public:
@@ -573,12 +607,12 @@ inline void RtMidiIn :: openPort( unsigned int portNumber, const std::string &po
inline void RtMidiIn :: openVirtualPort( const std::string &portName ) { rtapi_->openVirtualPort( portName ); } inline void RtMidiIn :: openVirtualPort( const std::string &portName ) { rtapi_->openVirtualPort( portName ); }
inline void RtMidiIn :: closePort( void ) { rtapi_->closePort(); } inline void RtMidiIn :: closePort( void ) { rtapi_->closePort(); }
inline bool RtMidiIn :: isPortOpen() const { return rtapi_->isPortOpen(); } inline bool RtMidiIn :: isPortOpen() const { return rtapi_->isPortOpen(); }
inline void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) { ((MidiInApi *)rtapi_)->setCallback( callback, userData ); } inline void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) { static_cast<MidiInApi *>(rtapi_)->setCallback( callback, userData ); }
inline void RtMidiIn :: cancelCallback( void ) { ((MidiInApi *)rtapi_)->cancelCallback(); } inline void RtMidiIn :: cancelCallback( void ) { static_cast<MidiInApi *>(rtapi_)->cancelCallback(); }
inline unsigned int RtMidiIn :: getPortCount( void ) { return rtapi_->getPortCount(); } inline unsigned int RtMidiIn :: getPortCount( void ) { return rtapi_->getPortCount(); }
inline std::string RtMidiIn :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); } inline std::string RtMidiIn :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); }
inline void RtMidiIn :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) { ((MidiInApi *)rtapi_)->ignoreTypes( midiSysex, midiTime, midiSense ); } inline void RtMidiIn :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) { static_cast<MidiInApi *>(rtapi_)->ignoreTypes( midiSysex, midiTime, midiSense ); }
inline double RtMidiIn :: getMessage( std::vector<unsigned char> *message ) { return ((MidiInApi *)rtapi_)->getMessage( message ); } inline double RtMidiIn :: getMessage( std::vector<unsigned char> *message ) { return static_cast<MidiInApi *>(rtapi_)->getMessage( message ); }
inline void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); } inline void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); }
inline RtMidi::Api RtMidiOut :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); } inline RtMidi::Api RtMidiOut :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); }
@@ -588,207 +622,8 @@ inline void RtMidiOut :: closePort( void ) { rtapi_->closePort(); }
inline bool RtMidiOut :: isPortOpen() const { return rtapi_->isPortOpen(); } inline bool RtMidiOut :: isPortOpen() const { return rtapi_->isPortOpen(); }
inline unsigned int RtMidiOut :: getPortCount( void ) { return rtapi_->getPortCount(); } inline unsigned int RtMidiOut :: getPortCount( void ) { return rtapi_->getPortCount(); }
inline std::string RtMidiOut :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); } inline std::string RtMidiOut :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); }
inline void RtMidiOut :: sendMessage( const std::vector<unsigned char> *message ) { ((MidiOutApi *)rtapi_)->sendMessage( &message->at(0), message->size() ); } inline void RtMidiOut :: sendMessage( const std::vector<unsigned char> *message ) { static_cast<MidiOutApi *>(rtapi_)->sendMessage( &message->at(0), message->size() ); }
inline void RtMidiOut :: sendMessage( const unsigned char *message, size_t size ) { ((MidiOutApi *)rtapi_)->sendMessage( message, size ); } inline void RtMidiOut :: sendMessage( const unsigned char *message, size_t size ) { static_cast<MidiOutApi *>(rtapi_)->sendMessage( message, size ); }
inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); } inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); }
// **************************************************************** //
//
// MidiInApi and MidiOutApi subclass prototypes.
//
// **************************************************************** //
#if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__)
#define __RTMIDI_DUMMY__
#endif
#if defined(__MACOSX_CORE__)
class MidiInCore: public MidiInApi
{
public:
MidiInCore( const std::string &clientName, unsigned int queueSizeLimit );
~MidiInCore( void );
RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; };
void openPort( unsigned int portNumber, const std::string &portName );
void openVirtualPort( const std::string &portName );
void closePort( void );
unsigned int getPortCount( void );
std::string getPortName( unsigned int portNumber );
protected:
void initialize( const std::string& clientName );
};
class MidiOutCore: public MidiOutApi
{
public:
MidiOutCore( const std::string &clientName );
~MidiOutCore( void );
RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; };
void openPort( unsigned int portNumber, const std::string &portName );
void openVirtualPort( const std::string &portName );
void closePort( void );
unsigned int getPortCount( void );
std::string getPortName( unsigned int portNumber );
void sendMessage( const unsigned char *message, size_t size );
protected:
void initialize( const std::string& clientName );
};
#endif
#if defined(__UNIX_JACK__)
class MidiInJack: public MidiInApi
{
public:
MidiInJack( const std::string &clientName, unsigned int queueSizeLimit );
~MidiInJack( void );
RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; };
void openPort( unsigned int portNumber, const std::string &portName );
void openVirtualPort( const std::string &portName );
void closePort( void );
unsigned int getPortCount( void );
std::string getPortName( unsigned int portNumber );
protected:
std::string clientName;
void connect( void );
void initialize( const std::string& clientName );
};
class MidiOutJack: public MidiOutApi
{
public:
MidiOutJack( const std::string &clientName );
~MidiOutJack( void );
RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; };
void openPort( unsigned int portNumber, const std::string &portName );
void openVirtualPort( const std::string &portName );
void closePort( void );
unsigned int getPortCount( void );
std::string getPortName( unsigned int portNumber );
void sendMessage( const unsigned char *message, size_t size );
protected:
std::string clientName;
void connect( void );
void initialize( const std::string& clientName );
};
#endif
#if defined(__LINUX_ALSA__)
class MidiInAlsa: public MidiInApi
{
public:
MidiInAlsa( const std::string &clientName, unsigned int queueSizeLimit );
~MidiInAlsa( void );
RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; };
void openPort( unsigned int portNumber, const std::string &portName );
void openVirtualPort( const std::string &portName );
void closePort( void );
unsigned int getPortCount( void );
std::string getPortName( unsigned int portNumber );
protected:
void initialize( const std::string& clientName );
};
class MidiOutAlsa: public MidiOutApi
{
public:
MidiOutAlsa( const std::string &clientName );
~MidiOutAlsa( void );
RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; };
void openPort( unsigned int portNumber, const std::string &portName );
void openVirtualPort( const std::string &portName );
void closePort( void );
unsigned int getPortCount( void );
std::string getPortName( unsigned int portNumber );
void sendMessage( const unsigned char *message, size_t size );
protected:
void initialize( const std::string& clientName );
};
#endif
#if defined(__WINDOWS_MM__)
class MidiInWinMM: public MidiInApi
{
public:
MidiInWinMM( const std::string &clientName, unsigned int queueSizeLimit );
~MidiInWinMM( void );
RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; };
void openPort( unsigned int portNumber, const std::string &portName );
void openVirtualPort( const std::string &portName );
void closePort( void );
unsigned int getPortCount( void );
std::string getPortName( unsigned int portNumber );
protected:
void initialize( const std::string& clientName );
};
class MidiOutWinMM: public MidiOutApi
{
public:
MidiOutWinMM( const std::string &clientName );
~MidiOutWinMM( void );
RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; };
void openPort( unsigned int portNumber, const std::string &portName );
void openVirtualPort( const std::string &portName );
void closePort( void );
unsigned int getPortCount( void );
std::string getPortName( unsigned int portNumber );
void sendMessage( const unsigned char *message, size_t size );
protected:
void initialize( const std::string& clientName );
};
#endif
#if defined(__RTMIDI_DUMMY__)
class MidiInDummy: public MidiInApi
{
public:
MidiInDummy( const std::string &/*clientName*/, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { errorString_ = "MidiInDummy: This class provides no functionality."; error( RtMidiError::WARNING, errorString_ ); }
RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; }
void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {}
void openVirtualPort( const std::string &/*portName*/ ) {}
void closePort( void ) {}
unsigned int getPortCount( void ) { return 0; }
std::string getPortName( unsigned int /*portNumber*/ ) { return ""; }
protected:
void initialize( const std::string& /*clientName*/ ) {}
};
class MidiOutDummy: public MidiOutApi
{
public:
MidiOutDummy( const std::string &/*clientName*/ ) { errorString_ = "MidiOutDummy: This class provides no functionality."; error( RtMidiError::WARNING, errorString_ ); }
RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; }
void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {}
void openVirtualPort( const std::string &/*portName*/ ) {}
void closePort( void ) {}
unsigned int getPortCount( void ) { return 0; }
std::string getPortName( unsigned int /*portNumber*/ ) { return ""; }
void sendMessage( const unsigned char * /*message*/, size_t /*size*/ ) {}
protected:
void initialize( const std::string& /*clientName*/ ) {}
};
#endif
#endif #endif

View File

@@ -1,5 +1,5 @@
# Tcl/Tk Demo GUI for the Synthesis Toolkit (STK) # Tcl/Tk Demo GUI for the Synthesis Toolkit (STK)
# by Gary P. Scavone, CCRMA, Stanford University, 1995--2017. # by Gary P. Scavone, CCRMA, CAML, Stanford & McGill Universities, 1995--2019.
# Set initial control values # Set initial control values
set pitch 64.0 set pitch 64.0

View File

@@ -1,6 +1,6 @@
The Synthesis ToolKit in C++ (STK) The Synthesis ToolKit in C++ (STK)
By Perry R. Cook and Gary P. Scavone, 1995--2017. By Perry R. Cook and Gary P. Scavone, 1995--2019.
EFFECTS PROJECT: EFFECTS PROJECT:

View File

@@ -13,7 +13,7 @@
Stanford, bearing the names of Karplus and/or Stanford, bearing the names of Karplus and/or
Strong. Strong.
by Perry R. Cook and Gary P. Scavone, 1995--2017. by Perry R. Cook and Gary P. Scavone, 1995--2019.
*/ */
/***************************************************/ /***************************************************/

View File

@@ -24,7 +24,7 @@ namespace stk {
Stanford, bearing the names of Karplus and/or Stanford, bearing the names of Karplus and/or
Strong. Strong.
by Perry R. Cook and Gary P. Scavone, 1995--2017. by Perry R. Cook and Gary P. Scavone, 1995--2019.
*/ */
/***************************************************/ /***************************************************/

View File

@@ -8,7 +8,7 @@
sample rates. You can specify the maximum polyphony (maximum sample rates. You can specify the maximum polyphony (maximum
number of simultaneous voices) in Tabla.h. number of simultaneous voices) in Tabla.h.
by Perry R. Cook and Gary P. Scavone, 1995--2017. by Perry R. Cook and Gary P. Scavone, 1995--2019.
*/ */
/***************************************************/ /***************************************************/

View File

@@ -17,7 +17,7 @@ namespace stk {
sample rates. You can specify the maximum polyphony (maximum sample rates. You can specify the maximum polyphony (maximum
number of simultaneous voices) in Tabla.h. number of simultaneous voices) in Tabla.h.
by Perry R. Cook and Gary P. Scavone, 1995--2017. by Perry R. Cook and Gary P. Scavone, 1995--2019.
*/ */
/***************************************************/ /***************************************************/

View File

@@ -8,7 +8,7 @@
sample rates. You can specify the maximum polyphony (maximum sample rates. You can specify the maximum polyphony (maximum
number of simultaneous voices) in VoicDrum.h. number of simultaneous voices) in VoicDrum.h.
by Perry R. Cook and Gary P. Scavone, 1995--2017. by Perry R. Cook and Gary P. Scavone, 1995--2019.
*/ */
/***************************************************/ /***************************************************/

View File

@@ -17,7 +17,7 @@ namespace stk {
sample rates. You can specify the maximum polyphony (maximum sample rates. You can specify the maximum polyphony (maximum
number of simultaneous voices) in VoicDrum.h. number of simultaneous voices) in VoicDrum.h.
by Perry R. Cook and Gary P. Scavone, 1995--2017. by Perry R. Cook and Gary P. Scavone, 1995--2019.
*/ */
/***************************************************/ /***************************************************/

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,8 @@
This class implements some common functionality for the realtime This class implements some common functionality for the realtime
MIDI input/output subclasses RtMidiIn and RtMidiOut. MIDI input/output subclasses RtMidiIn and RtMidiOut.
RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/ RtMidi GitHub site: https://github.com/thestk/rtmidi
RtMidi WWW site: http://www.music.mcgill.ca/~gary/rtmidi/
RtMidi: realtime MIDI i/o C++ classes RtMidi: realtime MIDI i/o C++ classes
Copyright (c) 2003-2019 Gary P. Scavone Copyright (c) 2003-2019 Gary P. Scavone
@@ -47,8 +48,227 @@
#endif #endif
// Default for Windows is to add an identifier to the port names; this // Default for Windows is to add an identifier to the port names; this
// flag can be undefined to disable this behaviour. // flag can be defined (e.g. in your project file) to disable this behaviour.
#define RTMIDI_ENSURE_UNIQUE_PORTNAMES //#define RTMIDI_DO_NOT_ENSURE_UNIQUE_PORTNAMES
// **************************************************************** //
//
// MidiInApi and MidiOutApi subclass prototypes.
//
// **************************************************************** //
#if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__)
#define __RTMIDI_DUMMY__
#endif
#if defined(__MACOSX_CORE__)
class MidiInCore: public MidiInApi
{
public:
MidiInCore( const std::string &clientName, unsigned int queueSizeLimit );
~MidiInCore( void );
RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; };
void openPort( unsigned int portNumber, const std::string &portName );
void openVirtualPort( const std::string &portName );
void closePort( void );
void setClientName( const std::string &clientName );
void setPortName( const std::string &portName );
unsigned int getPortCount( void );
std::string getPortName( unsigned int portNumber );
protected:
void initialize( const std::string& clientName );
};
class MidiOutCore: public MidiOutApi
{
public:
MidiOutCore( const std::string &clientName );
~MidiOutCore( void );
RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; };
void openPort( unsigned int portNumber, const std::string &portName );
void openVirtualPort( const std::string &portName );
void closePort( void );
void setClientName( const std::string &clientName );
void setPortName( const std::string &portName );
unsigned int getPortCount( void );
std::string getPortName( unsigned int portNumber );
void sendMessage( const unsigned char *message, size_t size );
protected:
void initialize( const std::string& clientName );
};
#endif
#if defined(__UNIX_JACK__)
class MidiInJack: public MidiInApi
{
public:
MidiInJack( const std::string &clientName, unsigned int queueSizeLimit );
~MidiInJack( void );
RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; };
void openPort( unsigned int portNumber, const std::string &portName );
void openVirtualPort( const std::string &portName );
void closePort( void );
void setClientName( const std::string &clientName );
void setPortName( const std::string &portName);
unsigned int getPortCount( void );
std::string getPortName( unsigned int portNumber );
protected:
std::string clientName;
void connect( void );
void initialize( const std::string& clientName );
};
class MidiOutJack: public MidiOutApi
{
public:
MidiOutJack( const std::string &clientName );
~MidiOutJack( void );
RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; };
void openPort( unsigned int portNumber, const std::string &portName );
void openVirtualPort( const std::string &portName );
void closePort( void );
void setClientName( const std::string &clientName );
void setPortName( const std::string &portName);
unsigned int getPortCount( void );
std::string getPortName( unsigned int portNumber );
void sendMessage( const unsigned char *message, size_t size );
protected:
std::string clientName;
void connect( void );
void initialize( const std::string& clientName );
};
#endif
#if defined(__LINUX_ALSA__)
class MidiInAlsa: public MidiInApi
{
public:
MidiInAlsa( const std::string &clientName, unsigned int queueSizeLimit );
~MidiInAlsa( void );
RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; };
void openPort( unsigned int portNumber, const std::string &portName );
void openVirtualPort( const std::string &portName );
void closePort( void );
void setClientName( const std::string &clientName );
void setPortName( const std::string &portName);
unsigned int getPortCount( void );
std::string getPortName( unsigned int portNumber );
protected:
void initialize( const std::string& clientName );
};
class MidiOutAlsa: public MidiOutApi
{
public:
MidiOutAlsa( const std::string &clientName );
~MidiOutAlsa( void );
RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; };
void openPort( unsigned int portNumber, const std::string &portName );
void openVirtualPort( const std::string &portName );
void closePort( void );
void setClientName( const std::string &clientName );
void setPortName( const std::string &portName );
unsigned int getPortCount( void );
std::string getPortName( unsigned int portNumber );
void sendMessage( const unsigned char *message, size_t size );
protected:
void initialize( const std::string& clientName );
};
#endif
#if defined(__WINDOWS_MM__)
class MidiInWinMM: public MidiInApi
{
public:
MidiInWinMM( const std::string &clientName, unsigned int queueSizeLimit );
~MidiInWinMM( void );
RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; };
void openPort( unsigned int portNumber, const std::string &portName );
void openVirtualPort( const std::string &portName );
void closePort( void );
void setClientName( const std::string &clientName );
void setPortName( const std::string &portName );
unsigned int getPortCount( void );
std::string getPortName( unsigned int portNumber );
protected:
void initialize( const std::string& clientName );
};
class MidiOutWinMM: public MidiOutApi
{
public:
MidiOutWinMM( const std::string &clientName );
~MidiOutWinMM( void );
RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; };
void openPort( unsigned int portNumber, const std::string &portName );
void openVirtualPort( const std::string &portName );
void closePort( void );
void setClientName( const std::string &clientName );
void setPortName( const std::string &portName );
unsigned int getPortCount( void );
std::string getPortName( unsigned int portNumber );
void sendMessage( const unsigned char *message, size_t size );
protected:
void initialize( const std::string& clientName );
};
#endif
#if defined(__RTMIDI_DUMMY__)
class MidiInDummy: public MidiInApi
{
public:
MidiInDummy( const std::string &/*clientName*/, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { errorString_ = "MidiInDummy: This class provides no functionality."; error( RtMidiError::WARNING, errorString_ ); }
RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; }
void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {}
void openVirtualPort( const std::string &/*portName*/ ) {}
void closePort( void ) {}
void setClientName( const std::string &/*clientName*/ ) {};
void setPortName( const std::string &/*portName*/ ) {};
unsigned int getPortCount( void ) { return 0; }
std::string getPortName( unsigned int /*portNumber*/ ) { return ""; }
protected:
void initialize( const std::string& /*clientName*/ ) {}
};
class MidiOutDummy: public MidiOutApi
{
public:
MidiOutDummy( const std::string &/*clientName*/ ) { errorString_ = "MidiOutDummy: This class provides no functionality."; error( RtMidiError::WARNING, errorString_ ); }
RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; }
void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {}
void openVirtualPort( const std::string &/*portName*/ ) {}
void closePort( void ) {}
void setClientName( const std::string &/*clientName*/ ) {};
void setPortName( const std::string &/*portName*/ ) {};
unsigned int getPortCount( void ) { return 0; }
std::string getPortName( unsigned int /*portNumber*/ ) { return ""; }
void sendMessage( const unsigned char * /*message*/, size_t /*size*/ ) {}
protected:
void initialize( const std::string& /*clientName*/ ) {}
};
#endif
//*********************************************************************// //*********************************************************************//
// RtMidi Definitions // RtMidi Definitions
@@ -70,29 +290,92 @@ std::string RtMidi :: getVersion( void ) throw()
return std::string( RTMIDI_VERSION ); return std::string( RTMIDI_VERSION );
} }
void RtMidi :: getCompiledApi( std::vector<RtMidi::Api> &apis ) throw() // Define API names and display names.
{ // Must be in same order as API enum.
apis.clear(); extern "C" {
const char* rtmidi_api_names[][2] = {
{ "unspecified" , "Unknown" },
{ "core" , "CoreMidi" },
{ "alsa" , "ALSA" },
{ "jack" , "Jack" },
{ "winmm" , "Windows MultiMedia" },
{ "dummy" , "Dummy" },
};
const unsigned int rtmidi_num_api_names =
sizeof(rtmidi_api_names)/sizeof(rtmidi_api_names[0]);
// The order here will control the order of RtMidi's API search in // The order here will control the order of RtMidi's API search in
// the constructor. // the constructor.
extern "C" const RtMidi::Api rtmidi_compiled_apis[] = {
#if defined(__MACOSX_CORE__) #if defined(__MACOSX_CORE__)
apis.push_back( MACOSX_CORE ); RtMidi::MACOSX_CORE,
#endif #endif
#if defined(__LINUX_ALSA__) #if defined(__LINUX_ALSA__)
apis.push_back( LINUX_ALSA ); RtMidi::LINUX_ALSA,
#endif #endif
#if defined(__UNIX_JACK__) #if defined(__UNIX_JACK__)
apis.push_back( UNIX_JACK ); RtMidi::UNIX_JACK,
#endif #endif
#if defined(__WINDOWS_MM__) #if defined(__WINDOWS_MM__)
apis.push_back( WINDOWS_MM ); RtMidi::WINDOWS_MM,
#endif #endif
#if defined(__RTMIDI_DUMMY__) #if defined(__RTMIDI_DUMMY__)
apis.push_back( RTMIDI_DUMMY ); RtMidi::RTMIDI_DUMMY,
#endif #endif
RtMidi::UNSPECIFIED,
};
extern "C" const unsigned int rtmidi_num_compiled_apis =
sizeof(rtmidi_compiled_apis)/sizeof(rtmidi_compiled_apis[0])-1;
} }
// This is a compile-time check that rtmidi_num_api_names == RtMidi::NUM_APIS.
// If the build breaks here, check that they match.
template<bool b> class StaticAssert { private: StaticAssert() {} };
template<> class StaticAssert<true>{ public: StaticAssert() {} };
class StaticAssertions { StaticAssertions() {
StaticAssert<rtmidi_num_api_names == RtMidi::NUM_APIS>();
}};
void RtMidi :: getCompiledApi( std::vector<RtMidi::Api> &apis ) throw()
{
apis = std::vector<RtMidi::Api>(rtmidi_compiled_apis,
rtmidi_compiled_apis + rtmidi_num_compiled_apis);
}
std::string RtMidi :: getApiName( RtMidi::Api api )
{
if (api < 0 || api >= RtMidi::NUM_APIS)
return "";
return rtmidi_api_names[api][0];
}
std::string RtMidi :: getApiDisplayName( RtMidi::Api api )
{
if (api < 0 || api >= RtMidi::NUM_APIS)
return "Unknown";
return rtmidi_api_names[api][1];
}
RtMidi::Api RtMidi :: getCompiledApiByName( const std::string &name )
{
unsigned int i=0;
for (i = 0; i < rtmidi_num_compiled_apis; ++i)
if (name == rtmidi_api_names[rtmidi_compiled_apis[i]][0])
return rtmidi_compiled_apis[i];
return RtMidi::UNSPECIFIED;
}
void RtMidi :: setClientName( const std::string &clientName )
{
rtapi_->setClientName( clientName );
}
void RtMidi :: setPortName( const std::string &portName )
{
rtapi_->setPortName( portName );
}
//*********************************************************************// //*********************************************************************//
// RtMidiIn Definitions // RtMidiIn Definitions
//*********************************************************************// //*********************************************************************//
@@ -124,7 +407,7 @@ void RtMidiIn :: openMidiApi( RtMidi::Api api, const std::string &clientName, un
#endif #endif
} }
RtMidiIn :: RtMidiIn( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit ) RTMIDI_DLL_PUBLIC RtMidiIn :: RtMidiIn( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit )
: RtMidi() : RtMidi()
{ {
if ( api != UNSPECIFIED ) { if ( api != UNSPECIFIED ) {
@@ -192,7 +475,7 @@ void RtMidiOut :: openMidiApi( RtMidi::Api api, const std::string &clientName )
#endif #endif
} }
RtMidiOut :: RtMidiOut( RtMidi::Api api, const std::string &clientName) RTMIDI_DLL_PUBLIC RtMidiOut :: RtMidiOut( RtMidi::Api api, const std::string &clientName)
{ {
if ( api != UNSPECIFIED ) { if ( api != UNSPECIFIED ) {
// Attempt to open the specified API. // Attempt to open the specified API.
@@ -479,10 +762,12 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void *
// function. // function.
nBytes = packet->length; nBytes = packet->length;
if ( nBytes == 0 ) continue; if ( nBytes == 0 ) {
packet = MIDIPacketNext( packet );
continue;
}
// Calculate time stamp. // Calculate time stamp.
if ( data->firstMessage ) { if ( data->firstMessage ) {
message.timeStamp = 0.0; message.timeStamp = 0.0;
data->firstMessage = false; data->firstMessage = false;
@@ -497,11 +782,10 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void *
if ( !continueSysex ) if ( !continueSysex )
message.timeStamp = time * 0.000000001; message.timeStamp = time * 0.000000001;
} }
apiData->lastTime = packet->timeStamp;
if ( apiData->lastTime == 0 ) { // this happens when receiving asynchronous sysex messages // Track whether any non-filtered messages were found in this
apiData->lastTime = AudioGetCurrentHostTime(); // packet for timestamp calculation
} bool foundNonFiltered = false;
//std::cout << "TimeStamp = " << packet->timeStamp << std::endl;
iByte = 0; iByte = 0;
if ( continueSysex ) { if ( continueSysex ) {
@@ -570,6 +854,7 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void *
// Copy the MIDI data to our vector. // Copy the MIDI data to our vector.
if ( size ) { if ( size ) {
foundNonFiltered = true;
message.bytes.assign( &packet->data[iByte], &packet->data[iByte+size] ); message.bytes.assign( &packet->data[iByte], &packet->data[iByte+size] );
if ( !continueSysex ) { if ( !continueSysex ) {
// If not a continuing sysex message, invoke the user callback function or queue the message. // If not a continuing sysex message, invoke the user callback function or queue the message.
@@ -588,19 +873,29 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void *
} }
} }
} }
// Save the time of the last non-filtered message
if ( foundNonFiltered ) {
apiData->lastTime = packet->timeStamp;
if ( apiData->lastTime == 0 ) { // this happens when receiving asynchronous sysex messages
apiData->lastTime = AudioGetCurrentHostTime();
}
}
packet = MIDIPacketNext(packet); packet = MIDIPacketNext(packet);
} }
} }
MidiInCore :: MidiInCore( const std::string &clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) MidiInCore :: MidiInCore( const std::string &clientName, unsigned int queueSizeLimit )
: MidiInApi( queueSizeLimit )
{ {
initialize( clientName ); MidiInCore::initialize( clientName );
} }
MidiInCore :: ~MidiInCore( void ) MidiInCore :: ~MidiInCore( void )
{ {
// Close a connection if it exists. // Close a connection if it exists.
closePort(); MidiInCore::closePort();
// Cleanup. // Cleanup.
CoreMidiData *data = static_cast<CoreMidiData *> (apiData_); CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
@@ -658,9 +953,12 @@ void MidiInCore :: openPort( unsigned int portNumber, const std::string &portNam
MIDIPortRef port; MIDIPortRef port;
CoreMidiData *data = static_cast<CoreMidiData *> (apiData_); CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII );
OSStatus result = MIDIInputPortCreate( data->client, OSStatus result = MIDIInputPortCreate( data->client,
CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), portNameRef,
midiInputCallback, (void *)&inputData_, &port ); midiInputCallback, (void *)&inputData_, &port );
CFRelease( portNameRef );
if ( result != noErr ) { if ( result != noErr ) {
MIDIClientDispose( data->client ); MIDIClientDispose( data->client );
errorString_ = "MidiInCore::openPort: error creating OS-X MIDI input port."; errorString_ = "MidiInCore::openPort: error creating OS-X MIDI input port.";
@@ -700,9 +998,12 @@ void MidiInCore :: openVirtualPort( const std::string &portName )
// Create a virtual MIDI input destination. // Create a virtual MIDI input destination.
MIDIEndpointRef endpoint; MIDIEndpointRef endpoint;
CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII );
OSStatus result = MIDIDestinationCreate( data->client, OSStatus result = MIDIDestinationCreate( data->client,
CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), portNameRef,
midiInputCallback, (void *)&inputData_, &endpoint ); midiInputCallback, (void *)&inputData_, &endpoint );
CFRelease( portNameRef );
if ( result != noErr ) { if ( result != noErr ) {
errorString_ = "MidiInCore::openVirtualPort: error creating virtual OS-X MIDI destination."; errorString_ = "MidiInCore::openVirtualPort: error creating virtual OS-X MIDI destination.";
error( RtMidiError::DRIVER_ERROR, errorString_ ); error( RtMidiError::DRIVER_ERROR, errorString_ );
@@ -730,6 +1031,22 @@ void MidiInCore :: closePort( void )
connected_ = false; connected_ = false;
} }
void MidiInCore :: setClientName ( const std::string& )
{
errorString_ = "MidiInCore::setClientName: this function is not implemented for the MACOSX_CORE API!";
error( RtMidiError::WARNING, errorString_ );
}
void MidiInCore :: setPortName ( const std::string& )
{
errorString_ = "MidiInCore::setPortName: this function is not implemented for the MACOSX_CORE API!";
error( RtMidiError::WARNING, errorString_ );
}
unsigned int MidiInCore :: getPortCount() unsigned int MidiInCore :: getPortCount()
{ {
CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false );
@@ -798,6 +1115,7 @@ CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal )
// prepend the device name to the entity name // prepend the device name to the entity name
if ( CFStringGetLength( result ) > 0 ) if ( CFStringGetLength( result ) > 0 )
CFStringInsert( result, 0, CFSTR(" ") ); CFStringInsert( result, 0, CFSTR(" ") );
CFStringInsert( result, 0, str ); CFStringInsert( result, 0, str );
} }
CFRelease( str ); CFRelease( str );
@@ -844,7 +1162,8 @@ static CFStringRef ConnectedEndpointName( MIDIEndpointRef endpoint )
if ( str != NULL ) { if ( str != NULL ) {
if ( anyStrings ) if ( anyStrings )
CFStringAppend( result, CFSTR(", ") ); CFStringAppend( result, CFSTR(", ") );
else anyStrings = true; else
anyStrings = true;
CFStringAppend( result, str ); CFStringAppend( result, str );
CFRelease( str ); CFRelease( str );
} }
@@ -891,15 +1210,16 @@ std::string MidiInCore :: getPortName( unsigned int portNumber )
// Class Definitions: MidiOutCore // Class Definitions: MidiOutCore
//*********************************************************************// //*********************************************************************//
MidiOutCore :: MidiOutCore( const std::string &clientName ) : MidiOutApi() MidiOutCore :: MidiOutCore( const std::string &clientName )
: MidiOutApi()
{ {
initialize( clientName ); MidiOutCore::initialize( clientName );
} }
MidiOutCore :: ~MidiOutCore( void ) MidiOutCore :: ~MidiOutCore( void )
{ {
// Close a connection if it exists. // Close a connection if it exists.
closePort(); MidiOutCore::closePort();
// Cleanup. // Cleanup.
CoreMidiData *data = static_cast<CoreMidiData *> (apiData_); CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
@@ -987,9 +1307,7 @@ void MidiOutCore :: openPort( unsigned int portNumber, const std::string &portNa
MIDIPortRef port; MIDIPortRef port;
CoreMidiData *data = static_cast<CoreMidiData *> (apiData_); CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ); CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII );
OSStatus result = MIDIOutputPortCreate( data->client, OSStatus result = MIDIOutputPortCreate( data->client, portNameRef, &port );
portNameRef,
&port );
CFRelease( portNameRef ); CFRelease( portNameRef );
if ( result != noErr ) { if ( result != noErr ) {
MIDIClientDispose( data->client ); MIDIClientDispose( data->client );
@@ -1031,6 +1349,22 @@ void MidiOutCore :: closePort( void )
connected_ = false; connected_ = false;
} }
void MidiOutCore :: setClientName ( const std::string& )
{
errorString_ = "MidiOutCore::setClientName: this function is not implemented for the MACOSX_CORE API!";
error( RtMidiError::WARNING, errorString_ );
}
void MidiOutCore :: setPortName ( const std::string& )
{
errorString_ = "MidiOutCore::setPortName: this function is not implemented for the MACOSX_CORE API!";
error( RtMidiError::WARNING, errorString_ );
}
void MidiOutCore :: openVirtualPort( const std::string &portName ) void MidiOutCore :: openVirtualPort( const std::string &portName )
{ {
CoreMidiData *data = static_cast<CoreMidiData *> (apiData_); CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
@@ -1043,9 +1377,10 @@ void MidiOutCore :: openVirtualPort( const std::string &portName )
// Create a virtual MIDI output source. // Create a virtual MIDI output source.
MIDIEndpointRef endpoint; MIDIEndpointRef endpoint;
OSStatus result = MIDISourceCreate( data->client, CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII );
CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), OSStatus result = MIDISourceCreate( data->client, portNameRef, &endpoint );
&endpoint ); CFRelease( portNameRef );
if ( result != noErr ) { if ( result != noErr ) {
errorString_ = "MidiOutCore::initialize: error creating OS-X virtual MIDI source."; errorString_ = "MidiOutCore::initialize: error creating OS-X virtual MIDI source.";
error( RtMidiError::DRIVER_ERROR, errorString_ ); error( RtMidiError::DRIVER_ERROR, errorString_ );
@@ -1284,6 +1619,8 @@ static void *alsaMidiHandler( void *ptr )
break; break;
} }
} }
doDecode = true;
break;
default: default:
doDecode = true; doDecode = true;
@@ -1320,21 +1657,25 @@ static void *alsaMidiHandler( void *ptr )
// https://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html // https://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html
// Perform the carry for the later subtraction by updating y. // Perform the carry for the later subtraction by updating y.
// Temp var y is timespec because computation requires signed types,
// while snd_seq_real_time_t has unsigned types.
snd_seq_real_time_t &x( ev->time.time ); snd_seq_real_time_t &x( ev->time.time );
snd_seq_real_time_t &y(apiData->lastTime); struct timespec y;
y.tv_nsec = apiData->lastTime.tv_nsec;
y.tv_sec = apiData->lastTime.tv_sec;
if ( x.tv_nsec < y.tv_nsec ) { if ( x.tv_nsec < y.tv_nsec ) {
int nsec = (y.tv_nsec - x.tv_nsec) / 1000000000 + 1; int nsec = (y.tv_nsec - (int)x.tv_nsec) / 1000000000 + 1;
y.tv_nsec -= 1000000000 * nsec; y.tv_nsec -= 1000000000 * nsec;
y.tv_sec += nsec; y.tv_sec += nsec;
} }
if ( x.tv_nsec - y.tv_nsec > 1000000000 ) { if ( x.tv_nsec - y.tv_nsec > 1000000000 ) {
int nsec = (x.tv_nsec - y.tv_nsec) / 1000000000; int nsec = ((int)x.tv_nsec - y.tv_nsec) / 1000000000;
y.tv_nsec += 1000000000 * nsec; y.tv_nsec += 1000000000 * nsec;
y.tv_sec -= nsec; y.tv_sec -= nsec;
} }
// Compute the time difference. // Compute the time difference.
time = x.tv_sec - y.tv_sec + (x.tv_nsec - y.tv_nsec)*1e-9; time = (int)x.tv_sec - y.tv_sec + ((int)x.tv_nsec - y.tv_nsec)*1e-9;
apiData->lastTime = ev->time.time; apiData->lastTime = ev->time.time;
@@ -1372,15 +1713,16 @@ static void *alsaMidiHandler( void *ptr )
return 0; return 0;
} }
MidiInAlsa :: MidiInAlsa( const std::string &clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) MidiInAlsa :: MidiInAlsa( const std::string &clientName, unsigned int queueSizeLimit )
: MidiInApi( queueSizeLimit )
{ {
initialize( clientName ); MidiInAlsa::initialize( clientName );
} }
MidiInAlsa :: ~MidiInAlsa() MidiInAlsa :: ~MidiInAlsa()
{ {
// Close a connection if it exists. // Close a connection if it exists.
closePort(); MidiInAlsa::closePort();
// Shutdown the input thread. // Shutdown the input thread.
AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_); AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
@@ -1719,6 +2061,24 @@ void MidiInAlsa :: closePort( void )
} }
} }
void MidiInAlsa :: setClientName( const std::string &clientName )
{
AlsaMidiData *data = static_cast<AlsaMidiData *> ( apiData_ );
snd_seq_set_client_name( data->seq, clientName.c_str() );
}
void MidiInAlsa :: setPortName( const std::string &portName )
{
AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
snd_seq_port_info_t *pinfo;
snd_seq_port_info_alloca( &pinfo );
snd_seq_get_port_info( data->seq, data->vport, pinfo );
snd_seq_port_info_set_name( pinfo, portName.c_str() );
snd_seq_set_port_info( data->seq, data->vport, pinfo );
}
//*********************************************************************// //*********************************************************************//
// API: LINUX ALSA // API: LINUX ALSA
// Class Definitions: MidiOutAlsa // Class Definitions: MidiOutAlsa
@@ -1726,13 +2086,13 @@ void MidiInAlsa :: closePort( void )
MidiOutAlsa :: MidiOutAlsa( const std::string &clientName ) : MidiOutApi() MidiOutAlsa :: MidiOutAlsa( const std::string &clientName ) : MidiOutApi()
{ {
initialize( clientName ); MidiOutAlsa::initialize( clientName );
} }
MidiOutAlsa :: ~MidiOutAlsa() MidiOutAlsa :: ~MidiOutAlsa()
{ {
// Close a connection if it exists. // Close a connection if it exists.
closePort(); MidiOutAlsa::closePort();
// Cleanup. // Cleanup.
AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_); AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
@@ -1898,6 +2258,24 @@ void MidiOutAlsa :: closePort( void )
} }
} }
void MidiOutAlsa :: setClientName( const std::string &clientName )
{
AlsaMidiData *data = static_cast<AlsaMidiData *> ( apiData_ );
snd_seq_set_client_name( data->seq, clientName.c_str() );
}
void MidiOutAlsa :: setPortName( const std::string &portName )
{
AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
snd_seq_port_info_t *pinfo;
snd_seq_port_info_alloca( &pinfo );
snd_seq_get_port_info( data->seq, data->vport, pinfo );
snd_seq_port_info_set_name( pinfo, portName.c_str() );
snd_seq_set_port_info( data->seq, data->vport, pinfo );
}
void MidiOutAlsa :: openVirtualPort( const std::string &portName ) void MidiOutAlsa :: openVirtualPort( const std::string &portName )
{ {
AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_); AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
@@ -2045,7 +2423,6 @@ static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/,
data->firstMessage = false; data->firstMessage = false;
} }
else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001; else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001;
apiData->lastTime = timestamp;
if ( inputStatus == MIM_DATA ) { // Channel or system message if ( inputStatus == MIM_DATA ) { // Channel or system message
@@ -2106,6 +2483,9 @@ static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/,
else return; else return;
} }
// Save the time of the last non-filtered message
apiData->lastTime = timestamp;
if ( data->usingCallback ) { if ( data->usingCallback ) {
RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;
callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData ); callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData );
@@ -2120,15 +2500,16 @@ static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/,
apiData->message.bytes.clear(); apiData->message.bytes.clear();
} }
MidiInWinMM :: MidiInWinMM( const std::string &clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) MidiInWinMM :: MidiInWinMM( const std::string &clientName, unsigned int queueSizeLimit )
: MidiInApi( queueSizeLimit )
{ {
initialize( clientName ); MidiInWinMM::initialize( clientName );
} }
MidiInWinMM :: ~MidiInWinMM() MidiInWinMM :: ~MidiInWinMM()
{ {
// Close a connection if it exists. // Close a connection if it exists.
closePort(); MidiInWinMM::closePort();
WinMidiData *data = static_cast<WinMidiData *> (apiData_); WinMidiData *data = static_cast<WinMidiData *> (apiData_);
DeleteCriticalSection( &(data->_mutex) ); DeleteCriticalSection( &(data->_mutex) );
@@ -2269,6 +2650,22 @@ void MidiInWinMM :: closePort( void )
} }
} }
void MidiInWinMM :: setClientName ( const std::string& )
{
errorString_ = "MidiInWinMM::setClientName: this function is not implemented for the WINDOWS_MM API!";
error( RtMidiError::WARNING, errorString_ );
}
void MidiInWinMM :: setPortName ( const std::string& )
{
errorString_ = "MidiInWinMM::setPortName: this function is not implemented for the WINDOWS_MM API!";
error( RtMidiError::WARNING, errorString_ );
}
unsigned int MidiInWinMM :: getPortCount() unsigned int MidiInWinMM :: getPortCount()
{ {
return midiInGetNumDevs(); return midiInGetNumDevs();
@@ -2293,7 +2690,7 @@ std::string MidiInWinMM :: getPortName( unsigned int portNumber )
// Next lines added to add the portNumber to the name so that // Next lines added to add the portNumber to the name so that
// the device's names are sure to be listed with individual names // the device's names are sure to be listed with individual names
// even when they have the same brand name // even when they have the same brand name
#ifdef RTMIDI_ENSURE_UNIQUE_PORTNAMES #ifndef RTMIDI_DO_NOT_ENSURE_UNIQUE_PORTNAMES
std::ostringstream os; std::ostringstream os;
os << " "; os << " ";
os << portNumber; os << portNumber;
@@ -2310,13 +2707,13 @@ std::string MidiInWinMM :: getPortName( unsigned int portNumber )
MidiOutWinMM :: MidiOutWinMM( const std::string &clientName ) : MidiOutApi() MidiOutWinMM :: MidiOutWinMM( const std::string &clientName ) : MidiOutApi()
{ {
initialize( clientName ); MidiOutWinMM::initialize( clientName );
} }
MidiOutWinMM :: ~MidiOutWinMM() MidiOutWinMM :: ~MidiOutWinMM()
{ {
// Close a connection if it exists. // Close a connection if it exists.
closePort(); MidiOutWinMM::closePort();
// Cleanup. // Cleanup.
WinMidiData *data = static_cast<WinMidiData *> (apiData_); WinMidiData *data = static_cast<WinMidiData *> (apiData_);
@@ -2363,7 +2760,7 @@ std::string MidiOutWinMM :: getPortName( unsigned int portNumber )
// the device's names are sure to be listed with individual names // the device's names are sure to be listed with individual names
// even when they have the same brand name // even when they have the same brand name
std::ostringstream os; std::ostringstream os;
#ifdef RTMIDI_ENSURE_UNIQUE_PORTNAMES #ifndef RTMIDI_DO_NOT_ENSURE_UNIQUE_PORTNAMES
os << " "; os << " ";
os << portNumber; os << portNumber;
stringName += os.str(); stringName += os.str();
@@ -2421,6 +2818,22 @@ void MidiOutWinMM :: closePort( void )
} }
} }
void MidiOutWinMM :: setClientName ( const std::string& )
{
errorString_ = "MidiOutWinMM::setClientName: this function is not implemented for the WINDOWS_MM API!";
error( RtMidiError::WARNING, errorString_ );
}
void MidiOutWinMM :: setPortName ( const std::string& )
{
errorString_ = "MidiOutWinMM::setPortName: this function is not implemented for the WINDOWS_MM API!";
error( RtMidiError::WARNING, errorString_ );
}
void MidiOutWinMM :: openVirtualPort( const std::string &/*portName*/ ) void MidiOutWinMM :: openVirtualPort( const std::string &/*portName*/ )
{ {
// This function cannot be implemented for the Windows MM MIDI API. // This function cannot be implemented for the Windows MM MIDI API.
@@ -2556,29 +2969,64 @@ static int jackProcessIn( jack_nframes_t nframes, void *arg )
// Is port created? // Is port created?
if ( jData->port == NULL ) return 0; if ( jData->port == NULL ) return 0;
void *buff = jack_port_get_buffer( jData->port, nframes ); void *buff = jack_port_get_buffer( jData->port, nframes );
bool& continueSysex = rtData->continueSysex;
unsigned char& ignoreFlags = rtData->ignoreFlags;
// We have midi events in buffer // We have midi events in buffer
int evCount = jack_midi_get_event_count( buff ); int evCount = jack_midi_get_event_count( buff );
for (int j = 0; j < evCount; j++) { for (int j = 0; j < evCount; j++) {
MidiInApi::MidiMessage message; MidiInApi::MidiMessage& message = rtData->message;
message.bytes.clear();
jack_midi_event_get( &event, buff, j ); jack_midi_event_get( &event, buff, j );
for ( unsigned int i = 0; i < event.size; i++ )
message.bytes.push_back( event.buffer[i] );
// Compute the delta time. // Compute the delta time.
time = jack_get_time(); time = jack_get_time();
if ( rtData->firstMessage == true ) if ( rtData->firstMessage == true ) {
message.timeStamp = 0.0;
rtData->firstMessage = false; rtData->firstMessage = false;
else } else
message.timeStamp = ( time - jData->lastTime ) * 0.000001; message.timeStamp = ( time - jData->lastTime ) * 0.000001;
jData->lastTime = time; jData->lastTime = time;
if ( !rtData->continueSysex ) { if ( !continueSysex )
message.bytes.clear();
if ( !( ( continueSysex || event.buffer[0] == 0xF0 ) && ( ignoreFlags & 0x01 ) ) ) {
// Unless this is a (possibly continued) SysEx message and we're ignoring SysEx,
// copy the event buffer into the MIDI message struct.
for ( unsigned int i = 0; i < event.size; i++ )
message.bytes.push_back( event.buffer[i] );
}
switch ( event.buffer[0] ) {
case 0xF0:
// Start of a SysEx message
continueSysex = event.buffer[event.size - 1] != 0xF7;
if ( ignoreFlags & 0x01 ) continue;
break;
case 0xF1:
case 0xF8:
// MIDI Time Code or Timing Clock message
if ( ignoreFlags & 0x02 ) continue;
break;
case 0xFE:
// Active Sensing message
if ( ignoreFlags & 0x04 ) continue;
break;
default:
if ( continueSysex ) {
// Continuation of a SysEx message
continueSysex = event.buffer[event.size - 1] != 0xF7;
if ( ignoreFlags & 0x01 ) continue;
}
// All other MIDI messages
}
if ( !continueSysex ) {
// If not a continuation of a SysEx message,
// invoke the user callback function or queue the message.
if ( rtData->usingCallback ) { if ( rtData->usingCallback ) {
RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) rtData->userCallback; RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) rtData->userCallback;
callback( message.timeStamp, &message.bytes, rtData->userData ); callback( message.timeStamp, &message.bytes, rtData->userData );
@@ -2594,9 +3042,10 @@ static int jackProcessIn( jack_nframes_t nframes, void *arg )
return 0; return 0;
} }
MidiInJack :: MidiInJack( const std::string &clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) MidiInJack :: MidiInJack( const std::string &clientName, unsigned int queueSizeLimit )
: MidiInApi( queueSizeLimit )
{ {
initialize( clientName ); MidiInJack::initialize( clientName );
} }
void MidiInJack :: initialize( const std::string& clientName ) void MidiInJack :: initialize( const std::string& clientName )
@@ -2632,7 +3081,7 @@ void MidiInJack :: connect()
MidiInJack :: ~MidiInJack() MidiInJack :: ~MidiInJack()
{ {
JackMidiData *data = static_cast<JackMidiData *> (apiData_); JackMidiData *data = static_cast<JackMidiData *> (apiData_);
closePort(); MidiInJack::closePort();
if ( data->client ) if ( data->client )
jack_client_close( data->client ); jack_client_close( data->client );
@@ -2659,6 +3108,8 @@ void MidiInJack :: openPort( unsigned int portNumber, const std::string &portNam
// Connecting to the output // Connecting to the output
std::string name = getPortName( portNumber ); std::string name = getPortName( portNumber );
jack_connect( data->client, name.c_str(), jack_port_name( data->port ) ); jack_connect( data->client, name.c_str(), jack_port_name( data->port ) );
connected_ = true;
} }
void MidiInJack :: openVirtualPort( const std::string &portName ) void MidiInJack :: openVirtualPort( const std::string &portName )
@@ -2714,7 +3165,9 @@ std::string MidiInJack :: getPortName( unsigned int portNumber )
return retStr; return retStr;
} }
if ( ports[portNumber] == NULL ) { unsigned int i;
for ( i=0; i<portNumber && ports[i]; i++ ) {}
if ( i < portNumber || !ports[portNumber] ) {
std::ostringstream ost; std::ostringstream ost;
ost << "MidiInJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; ost << "MidiInJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";
errorString_ = ost.str(); errorString_ = ost.str();
@@ -2722,7 +3175,7 @@ std::string MidiInJack :: getPortName( unsigned int portNumber )
} }
else retStr.assign( ports[portNumber] ); else retStr.assign( ports[portNumber] );
free( ports ); jack_free( ports );
return retStr; return retStr;
} }
@@ -2733,6 +3186,26 @@ void MidiInJack :: closePort()
if ( data->port == NULL ) return; if ( data->port == NULL ) return;
jack_port_unregister( data->client, data->port ); jack_port_unregister( data->client, data->port );
data->port = NULL; data->port = NULL;
connected_ = false;
}
void MidiInJack:: setClientName( const std::string& )
{
errorString_ = "MidiInJack::setClientName: this function is not implemented for the UNIX_JACK API!";
error( RtMidiError::WARNING, errorString_ );
}
void MidiInJack :: setPortName( const std::string &portName )
{
JackMidiData *data = static_cast<JackMidiData *> (apiData_);
#ifdef JACK_HAS_PORT_RENAME
jack_port_rename( data->client, data->port, portName.c_str() );
#else
jack_port_set_name( data->port, portName.c_str() );
#endif
} }
//*********************************************************************// //*********************************************************************//
@@ -2770,7 +3243,7 @@ static int jackProcessOut( jack_nframes_t nframes, void *arg )
MidiOutJack :: MidiOutJack( const std::string &clientName ) : MidiOutApi() MidiOutJack :: MidiOutJack( const std::string &clientName ) : MidiOutApi()
{ {
initialize( clientName ); MidiOutJack::initialize( clientName );
} }
void MidiOutJack :: initialize( const std::string& clientName ) void MidiOutJack :: initialize( const std::string& clientName )
@@ -2813,7 +3286,7 @@ void MidiOutJack :: connect()
MidiOutJack :: ~MidiOutJack() MidiOutJack :: ~MidiOutJack()
{ {
JackMidiData *data = static_cast<JackMidiData *> (apiData_); JackMidiData *data = static_cast<JackMidiData *> (apiData_);
closePort(); MidiOutJack::closePort();
// Cleanup // Cleanup
jack_ringbuffer_free( data->buffSize ); jack_ringbuffer_free( data->buffSize );
@@ -2850,6 +3323,8 @@ void MidiOutJack :: openPort( unsigned int portNumber, const std::string &portNa
// Connecting to the output // Connecting to the output
std::string name = getPortName( portNumber ); std::string name = getPortName( portNumber );
jack_connect( data->client, jack_port_name( data->port ), name.c_str() ); jack_connect( data->client, jack_port_name( data->port ), name.c_str() );
connected_ = true;
} }
void MidiOutJack :: openVirtualPort( const std::string &portName ) void MidiOutJack :: openVirtualPort( const std::string &portName )
@@ -2926,8 +3401,7 @@ void MidiOutJack :: closePort()
#ifdef HAVE_SEMAPHORE #ifdef HAVE_SEMAPHORE
struct timespec ts; struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) != -1) if ( clock_gettime( CLOCK_REALTIME, &ts ) != -1 ) {
{
ts.tv_sec += 1; // wait max one second ts.tv_sec += 1; // wait max one second
sem_post( &data->sem_needpost ); sem_post( &data->sem_needpost );
sem_timedwait( &data->sem_cleanup, &ts ); sem_timedwait( &data->sem_cleanup, &ts );
@@ -2936,6 +3410,26 @@ void MidiOutJack :: closePort()
jack_port_unregister( data->client, data->port ); jack_port_unregister( data->client, data->port );
data->port = NULL; data->port = NULL;
connected_ = false;
}
void MidiOutJack:: setClientName( const std::string& )
{
errorString_ = "MidiOutJack::setClientName: this function is not implemented for the UNIX_JACK API!";
error( RtMidiError::WARNING, errorString_ );
}
void MidiOutJack :: setPortName( const std::string &portName )
{
JackMidiData *data = static_cast<JackMidiData *> (apiData_);
#ifdef JACK_HAS_PORT_RENAME
jack_port_rename( data->client, data->port, portName.c_str() );
#else
jack_port_set_name( data->port, portName.c_str() );
#endif
} }
void MidiOutJack :: sendMessage( const unsigned char *message, size_t size ) void MidiOutJack :: sendMessage( const unsigned char *message, size_t size )
@@ -2944,8 +3438,7 @@ void MidiOutJack :: sendMessage( const unsigned char *message, size_t size )
JackMidiData *data = static_cast<JackMidiData *> (apiData_); JackMidiData *data = static_cast<JackMidiData *> (apiData_);
// Write full message to buffer // Write full message to buffer
jack_ringbuffer_write( data->buffMessage, ( const char * ) message, jack_ringbuffer_write( data->buffMessage, ( const char * ) message, nBytes );
nBytes );
jack_ringbuffer_write( data->buffSize, ( char * ) &nBytes, sizeof( nBytes ) ); jack_ringbuffer_write( data->buffSize, ( char * ) &nBytes, sizeof( nBytes ) );
} }