mirror of
https://github.com/thestk/stk
synced 2026-04-19 14:06:55 +00:00
Updated RtAudio/RtMidi for new release, plus additional documentation updates.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# 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_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)
|
||||
|
||||
@@ -2,7 +2,7 @@ The Synthesis ToolKit in C++ (STK)
|
||||
|
||||
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)
|
||||
- various documentation updates
|
||||
- new Recorder (flute a la Verge) class (thanks to Mathias Bredholt)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
and OSS), Macintosh OS X (CoreAudio and Jack), and Windows
|
||||
(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: realtime audio i/o C++ classes
|
||||
@@ -45,7 +46,21 @@
|
||||
#ifndef __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 <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
|
||||
when opening the stream (default = NULL).
|
||||
|
||||
\return
|
||||
To continue normal stream operation, the RtAudioCallback function
|
||||
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
|
||||
@@ -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:
|
||||
//! Defined RtAudioError types.
|
||||
@@ -260,7 +276,7 @@ typedef void (*RtAudioErrorCallback)( RtAudioError::Type type, const std::string
|
||||
|
||||
class RtApi;
|
||||
|
||||
class RtAudio
|
||||
class RTAUDIO_DLL_PUBLIC RtAudio
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -275,7 +291,8 @@ class RtAudio
|
||||
WINDOWS_WASAPI, /*!< The Microsoft WASAPI API. */
|
||||
WINDOWS_ASIO, /*!< The Steinberg Audio Stream I/O 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.
|
||||
@@ -387,6 +404,29 @@ class RtAudio
|
||||
*/
|
||||
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 constructor performs minor initialization tasks. An exception
|
||||
@@ -583,6 +623,7 @@ class RtAudio
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uintptr_t ThreadHandle;
|
||||
typedef CRITICAL_SECTION StreamMutex;
|
||||
@@ -651,7 +692,6 @@ class S24 {
|
||||
return *this;
|
||||
}
|
||||
|
||||
S24( const S24& v ) { *this = v; }
|
||||
S24( const double& d ) { *this = (int) d; }
|
||||
S24( const float& f ) { *this = (int) f; }
|
||||
S24( const signed short& s ) { *this = (int) s; }
|
||||
@@ -671,7 +711,7 @@ class S24 {
|
||||
|
||||
#include <sstream>
|
||||
|
||||
class RtApi
|
||||
class RTAUDIO_DLL_PUBLIC RtApi
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -864,7 +904,6 @@ public:
|
||||
void startStream( void );
|
||||
void stopStream( void );
|
||||
void abortStream( void );
|
||||
long getStreamLatency( void );
|
||||
|
||||
// This function is intended for internal use only. It must be
|
||||
// public because it is called by the internal callback handler,
|
||||
@@ -900,7 +939,6 @@ public:
|
||||
void startStream( void );
|
||||
void stopStream( void );
|
||||
void abortStream( void );
|
||||
long getStreamLatency( void );
|
||||
|
||||
// This function is intended for internal use only. It must be
|
||||
// public because it is called by the internal callback handler,
|
||||
@@ -935,7 +973,6 @@ public:
|
||||
void startStream( void );
|
||||
void stopStream( void );
|
||||
void abortStream( void );
|
||||
long getStreamLatency( void );
|
||||
|
||||
// This function is intended for internal use only. It must be
|
||||
// public because it is called by the internal callback handler,
|
||||
@@ -973,7 +1010,6 @@ public:
|
||||
void startStream( void );
|
||||
void stopStream( void );
|
||||
void abortStream( void );
|
||||
long getStreamLatency( void );
|
||||
|
||||
// This function is intended for internal use only. It must be
|
||||
// public because it is called by the internal callback handler,
|
||||
@@ -1003,7 +1039,7 @@ class RtApiWasapi : public RtApi
|
||||
{
|
||||
public:
|
||||
RtApiWasapi();
|
||||
~RtApiWasapi();
|
||||
virtual ~RtApiWasapi();
|
||||
|
||||
RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_WASAPI; }
|
||||
unsigned int getDeviceCount( void );
|
||||
|
||||
295
include/RtMidi.h
295
include/RtMidi.h
@@ -5,7 +5,8 @@
|
||||
This class implements some common functionality for the realtime
|
||||
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
|
||||
Copyright (c) 2003-2019 Gary P. Scavone
|
||||
@@ -43,7 +44,21 @@
|
||||
#ifndef 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 <iostream>
|
||||
@@ -60,7 +75,7 @@
|
||||
*/
|
||||
/************************************************************************/
|
||||
|
||||
class RtMidiError : public std::exception
|
||||
class RTMIDI_DLL_PUBLIC RtMidiError : public std::exception
|
||||
{
|
||||
public:
|
||||
//! Defined RtMidiError types.
|
||||
@@ -79,7 +94,8 @@ class RtMidiError : public std::exception
|
||||
};
|
||||
|
||||
//! 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.
|
||||
virtual ~RtMidiError( void ) throw() {}
|
||||
@@ -113,10 +129,9 @@ typedef void (*RtMidiErrorCallback)( RtMidiError::Type type, const std::string &
|
||||
|
||||
class MidiApi;
|
||||
|
||||
class RtMidi
|
||||
class RTMIDI_DLL_PUBLIC RtMidi
|
||||
{
|
||||
public:
|
||||
|
||||
//! MIDI API specifier arguments.
|
||||
enum Api {
|
||||
UNSPECIFIED, /*!< Search for a working compiled API. */
|
||||
@@ -124,7 +139,8 @@ class RtMidi
|
||||
LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */
|
||||
UNIX_JACK, /*!< The JACK Low-Latency MIDI Server 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.
|
||||
@@ -138,6 +154,29 @@ class RtMidi
|
||||
*/
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
/*!
|
||||
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;
|
||||
|
||||
protected:
|
||||
|
||||
RtMidi();
|
||||
virtual ~RtMidi();
|
||||
|
||||
MidiApi *rtapi_;
|
||||
};
|
||||
|
||||
@@ -188,8 +228,6 @@ class RtMidi
|
||||
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
|
||||
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:
|
||||
|
||||
@@ -335,7 +373,6 @@ class RtMidiIn : public RtMidi
|
||||
|
||||
protected:
|
||||
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
|
||||
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.
|
||||
|
||||
by Gary P. Scavone, 2003-2019.
|
||||
*/
|
||||
/**********************************************************************/
|
||||
|
||||
class RtMidiOut : public RtMidi
|
||||
class RTMIDI_DLL_PUBLIC RtMidiOut : public RtMidi
|
||||
{
|
||||
public:
|
||||
|
||||
//! Default constructor that allows an optional client name.
|
||||
/*!
|
||||
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:
|
||||
|
||||
@@ -468,6 +502,8 @@ class MidiApi
|
||||
virtual void openPort( unsigned int portNumber, const std::string &portName ) = 0;
|
||||
virtual void openVirtualPort( const std::string &portName ) = 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 std::string getPortName( unsigned int portNumber ) = 0;
|
||||
@@ -489,7 +525,7 @@ protected:
|
||||
void *errorCallbackUserData_;
|
||||
};
|
||||
|
||||
class MidiInApi : public MidiApi
|
||||
class RTMIDI_DLL_PUBLIC MidiInApi : public MidiApi
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -524,8 +560,7 @@ class MidiInApi : public MidiApi
|
||||
: front(0), back(0), ringSize(0), ring(0) {}
|
||||
bool push( const MidiMessage& );
|
||||
bool pop( std::vector<unsigned char>*, double* );
|
||||
unsigned int size(unsigned int *back=0,
|
||||
unsigned int *front=0);
|
||||
unsigned int size( unsigned int *back=0, unsigned int *front=0 );
|
||||
};
|
||||
|
||||
// The RtMidiInData structure is used to pass private class data to
|
||||
@@ -544,16 +579,15 @@ class MidiInApi : public MidiApi
|
||||
|
||||
// Default constructor.
|
||||
RtMidiInData()
|
||||
: ignoreFlags(7), doInput(false), firstMessage(true),
|
||||
apiData(0), usingCallback(false), userCallback(0), userData(0),
|
||||
continueSysex(false) {}
|
||||
: ignoreFlags(7), doInput(false), firstMessage(true), apiData(0), usingCallback(false),
|
||||
userCallback(0), userData(0), continueSysex(false) {}
|
||||
};
|
||||
|
||||
protected:
|
||||
RtMidiInData inputData_;
|
||||
};
|
||||
|
||||
class MidiOutApi : public MidiApi
|
||||
class RTMIDI_DLL_PUBLIC MidiOutApi : public MidiApi
|
||||
{
|
||||
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 :: closePort( void ) { rtapi_->closePort(); }
|
||||
inline bool RtMidiIn :: isPortOpen() const { return rtapi_->isPortOpen(); }
|
||||
inline void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) { ((MidiInApi *)rtapi_)->setCallback( callback, userData ); }
|
||||
inline void RtMidiIn :: cancelCallback( void ) { ((MidiInApi *)rtapi_)->cancelCallback(); }
|
||||
inline void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) { static_cast<MidiInApi *>(rtapi_)->setCallback( callback, userData ); }
|
||||
inline void RtMidiIn :: cancelCallback( void ) { static_cast<MidiInApi *>(rtapi_)->cancelCallback(); }
|
||||
inline unsigned int RtMidiIn :: getPortCount( void ) { return rtapi_->getPortCount(); }
|
||||
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 double RtMidiIn :: getMessage( std::vector<unsigned char> *message ) { return ((MidiInApi *)rtapi_)->getMessage( message ); }
|
||||
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 static_cast<MidiInApi *>(rtapi_)->getMessage( message ); }
|
||||
inline void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); }
|
||||
|
||||
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 unsigned int RtMidiOut :: getPortCount( void ) { return rtapi_->getPortCount(); }
|
||||
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 unsigned char *message, size_t size ) { ((MidiOutApi *)rtapi_)->sendMessage( 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 ) { static_cast<MidiOutApi *>(rtapi_)->sendMessage( message, size ); }
|
||||
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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# 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 pitch 64.0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
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:
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
Stanford, bearing the names of Karplus and/or
|
||||
Strong.
|
||||
|
||||
by Perry R. Cook and Gary P. Scavone, 1995--2017.
|
||||
by Perry R. Cook and Gary P. Scavone, 1995--2019.
|
||||
*/
|
||||
/***************************************************/
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace stk {
|
||||
Stanford, bearing the names of Karplus and/or
|
||||
Strong.
|
||||
|
||||
by Perry R. Cook and Gary P. Scavone, 1995--2017.
|
||||
by Perry R. Cook and Gary P. Scavone, 1995--2019.
|
||||
*/
|
||||
/***************************************************/
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
sample rates. You can specify the maximum polyphony (maximum
|
||||
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.
|
||||
*/
|
||||
/***************************************************/
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace stk {
|
||||
sample rates. You can specify the maximum polyphony (maximum
|
||||
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.
|
||||
*/
|
||||
/***************************************************/
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
sample rates. You can specify the maximum polyphony (maximum
|
||||
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.
|
||||
*/
|
||||
/***************************************************/
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace stk {
|
||||
sample rates. You can specify the maximum polyphony (maximum
|
||||
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.
|
||||
*/
|
||||
/***************************************************/
|
||||
|
||||
|
||||
985
src/RtAudio.cpp
985
src/RtAudio.cpp
File diff suppressed because it is too large
Load Diff
637
src/RtMidi.cpp
637
src/RtMidi.cpp
@@ -5,7 +5,8 @@
|
||||
This class implements some common functionality for the realtime
|
||||
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
|
||||
Copyright (c) 2003-2019 Gary P. Scavone
|
||||
@@ -47,8 +48,227 @@
|
||||
#endif
|
||||
|
||||
// Default for Windows is to add an identifier to the port names; this
|
||||
// flag can be undefined to disable this behaviour.
|
||||
#define RTMIDI_ENSURE_UNIQUE_PORTNAMES
|
||||
// flag can be defined (e.g. in your project file) to disable this behaviour.
|
||||
//#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
|
||||
@@ -70,29 +290,92 @@ std::string RtMidi :: getVersion( void ) throw()
|
||||
return std::string( RTMIDI_VERSION );
|
||||
}
|
||||
|
||||
void RtMidi :: getCompiledApi( std::vector<RtMidi::Api> &apis ) throw()
|
||||
{
|
||||
apis.clear();
|
||||
// Define API names and display names.
|
||||
// Must be in same order as API enum.
|
||||
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 constructor.
|
||||
extern "C" const RtMidi::Api rtmidi_compiled_apis[] = {
|
||||
#if defined(__MACOSX_CORE__)
|
||||
apis.push_back( MACOSX_CORE );
|
||||
RtMidi::MACOSX_CORE,
|
||||
#endif
|
||||
#if defined(__LINUX_ALSA__)
|
||||
apis.push_back( LINUX_ALSA );
|
||||
RtMidi::LINUX_ALSA,
|
||||
#endif
|
||||
#if defined(__UNIX_JACK__)
|
||||
apis.push_back( UNIX_JACK );
|
||||
RtMidi::UNIX_JACK,
|
||||
#endif
|
||||
#if defined(__WINDOWS_MM__)
|
||||
apis.push_back( WINDOWS_MM );
|
||||
RtMidi::WINDOWS_MM,
|
||||
#endif
|
||||
#if defined(__RTMIDI_DUMMY__)
|
||||
apis.push_back( RTMIDI_DUMMY );
|
||||
RtMidi::RTMIDI_DUMMY,
|
||||
#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
|
||||
//*********************************************************************//
|
||||
@@ -124,7 +407,7 @@ void RtMidiIn :: openMidiApi( RtMidi::Api api, const std::string &clientName, un
|
||||
#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()
|
||||
{
|
||||
if ( api != UNSPECIFIED ) {
|
||||
@@ -192,7 +475,7 @@ void RtMidiOut :: openMidiApi( RtMidi::Api api, const std::string &clientName )
|
||||
#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 ) {
|
||||
// Attempt to open the specified API.
|
||||
@@ -479,10 +762,12 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void *
|
||||
// function.
|
||||
|
||||
nBytes = packet->length;
|
||||
if ( nBytes == 0 ) continue;
|
||||
if ( nBytes == 0 ) {
|
||||
packet = MIDIPacketNext( packet );
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate time stamp.
|
||||
|
||||
if ( data->firstMessage ) {
|
||||
message.timeStamp = 0.0;
|
||||
data->firstMessage = false;
|
||||
@@ -497,11 +782,10 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void *
|
||||
if ( !continueSysex )
|
||||
message.timeStamp = time * 0.000000001;
|
||||
}
|
||||
apiData->lastTime = packet->timeStamp;
|
||||
if ( apiData->lastTime == 0 ) { // this happens when receiving asynchronous sysex messages
|
||||
apiData->lastTime = AudioGetCurrentHostTime();
|
||||
}
|
||||
//std::cout << "TimeStamp = " << packet->timeStamp << std::endl;
|
||||
|
||||
// Track whether any non-filtered messages were found in this
|
||||
// packet for timestamp calculation
|
||||
bool foundNonFiltered = false;
|
||||
|
||||
iByte = 0;
|
||||
if ( continueSysex ) {
|
||||
@@ -570,6 +854,7 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void *
|
||||
|
||||
// Copy the MIDI data to our vector.
|
||||
if ( size ) {
|
||||
foundNonFiltered = true;
|
||||
message.bytes.assign( &packet->data[iByte], &packet->data[iByte+size] );
|
||||
if ( !continueSysex ) {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
// Close a connection if it exists.
|
||||
closePort();
|
||||
MidiInCore::closePort();
|
||||
|
||||
// Cleanup.
|
||||
CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
|
||||
@@ -658,9 +953,12 @@ void MidiInCore :: openPort( unsigned int portNumber, const std::string &portNam
|
||||
|
||||
MIDIPortRef port;
|
||||
CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
|
||||
CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII );
|
||||
OSStatus result = MIDIInputPortCreate( data->client,
|
||||
CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ),
|
||||
portNameRef,
|
||||
midiInputCallback, (void *)&inputData_, &port );
|
||||
CFRelease( portNameRef );
|
||||
|
||||
if ( result != noErr ) {
|
||||
MIDIClientDispose( data->client );
|
||||
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.
|
||||
MIDIEndpointRef endpoint;
|
||||
CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII );
|
||||
OSStatus result = MIDIDestinationCreate( data->client,
|
||||
CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ),
|
||||
portNameRef,
|
||||
midiInputCallback, (void *)&inputData_, &endpoint );
|
||||
CFRelease( portNameRef );
|
||||
|
||||
if ( result != noErr ) {
|
||||
errorString_ = "MidiInCore::openVirtualPort: error creating virtual OS-X MIDI destination.";
|
||||
error( RtMidiError::DRIVER_ERROR, errorString_ );
|
||||
@@ -730,6 +1031,22 @@ void MidiInCore :: closePort( void )
|
||||
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()
|
||||
{
|
||||
CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false );
|
||||
@@ -798,6 +1115,7 @@ CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal )
|
||||
// prepend the device name to the entity name
|
||||
if ( CFStringGetLength( result ) > 0 )
|
||||
CFStringInsert( result, 0, CFSTR(" ") );
|
||||
|
||||
CFStringInsert( result, 0, str );
|
||||
}
|
||||
CFRelease( str );
|
||||
@@ -844,7 +1162,8 @@ static CFStringRef ConnectedEndpointName( MIDIEndpointRef endpoint )
|
||||
if ( str != NULL ) {
|
||||
if ( anyStrings )
|
||||
CFStringAppend( result, CFSTR(", ") );
|
||||
else anyStrings = true;
|
||||
else
|
||||
anyStrings = true;
|
||||
CFStringAppend( result, str );
|
||||
CFRelease( str );
|
||||
}
|
||||
@@ -891,15 +1210,16 @@ std::string MidiInCore :: getPortName( unsigned int portNumber )
|
||||
// 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 )
|
||||
{
|
||||
// Close a connection if it exists.
|
||||
closePort();
|
||||
MidiOutCore::closePort();
|
||||
|
||||
// Cleanup.
|
||||
CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
|
||||
@@ -987,9 +1307,7 @@ void MidiOutCore :: openPort( unsigned int portNumber, const std::string &portNa
|
||||
MIDIPortRef port;
|
||||
CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
|
||||
CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII );
|
||||
OSStatus result = MIDIOutputPortCreate( data->client,
|
||||
portNameRef,
|
||||
&port );
|
||||
OSStatus result = MIDIOutputPortCreate( data->client, portNameRef, &port );
|
||||
CFRelease( portNameRef );
|
||||
if ( result != noErr ) {
|
||||
MIDIClientDispose( data->client );
|
||||
@@ -1031,6 +1349,22 @@ void MidiOutCore :: closePort( void )
|
||||
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 )
|
||||
{
|
||||
CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
|
||||
@@ -1043,9 +1377,10 @@ void MidiOutCore :: openVirtualPort( const std::string &portName )
|
||||
|
||||
// Create a virtual MIDI output source.
|
||||
MIDIEndpointRef endpoint;
|
||||
OSStatus result = MIDISourceCreate( data->client,
|
||||
CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ),
|
||||
&endpoint );
|
||||
CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII );
|
||||
OSStatus result = MIDISourceCreate( data->client, portNameRef, &endpoint );
|
||||
CFRelease( portNameRef );
|
||||
|
||||
if ( result != noErr ) {
|
||||
errorString_ = "MidiOutCore::initialize: error creating OS-X virtual MIDI source.";
|
||||
error( RtMidiError::DRIVER_ERROR, errorString_ );
|
||||
@@ -1284,6 +1619,8 @@ static void *alsaMidiHandler( void *ptr )
|
||||
break;
|
||||
}
|
||||
}
|
||||
doDecode = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
doDecode = true;
|
||||
@@ -1320,21 +1657,25 @@ static void *alsaMidiHandler( void *ptr )
|
||||
// https://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html
|
||||
|
||||
// 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 &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 ) {
|
||||
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_sec += nsec;
|
||||
}
|
||||
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_sec -= nsec;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
@@ -1372,15 +1713,16 @@ static void *alsaMidiHandler( void *ptr )
|
||||
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()
|
||||
{
|
||||
// Close a connection if it exists.
|
||||
closePort();
|
||||
MidiInAlsa::closePort();
|
||||
|
||||
// Shutdown the input thread.
|
||||
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
|
||||
// Class Definitions: MidiOutAlsa
|
||||
@@ -1726,13 +2086,13 @@ void MidiInAlsa :: closePort( void )
|
||||
|
||||
MidiOutAlsa :: MidiOutAlsa( const std::string &clientName ) : MidiOutApi()
|
||||
{
|
||||
initialize( clientName );
|
||||
MidiOutAlsa::initialize( clientName );
|
||||
}
|
||||
|
||||
MidiOutAlsa :: ~MidiOutAlsa()
|
||||
{
|
||||
// Close a connection if it exists.
|
||||
closePort();
|
||||
MidiOutAlsa::closePort();
|
||||
|
||||
// Cleanup.
|
||||
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 )
|
||||
{
|
||||
AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);
|
||||
@@ -2045,7 +2423,6 @@ static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/,
|
||||
data->firstMessage = false;
|
||||
}
|
||||
else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001;
|
||||
apiData->lastTime = timestamp;
|
||||
|
||||
if ( inputStatus == MIM_DATA ) { // Channel or system message
|
||||
|
||||
@@ -2106,6 +2483,9 @@ static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/,
|
||||
else return;
|
||||
}
|
||||
|
||||
// Save the time of the last non-filtered message
|
||||
apiData->lastTime = timestamp;
|
||||
|
||||
if ( data->usingCallback ) {
|
||||
RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;
|
||||
callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData );
|
||||
@@ -2120,15 +2500,16 @@ static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/,
|
||||
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()
|
||||
{
|
||||
// Close a connection if it exists.
|
||||
closePort();
|
||||
MidiInWinMM::closePort();
|
||||
|
||||
WinMidiData *data = static_cast<WinMidiData *> (apiData_);
|
||||
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()
|
||||
{
|
||||
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
|
||||
// the device's names are sure to be listed with individual names
|
||||
// even when they have the same brand name
|
||||
#ifdef RTMIDI_ENSURE_UNIQUE_PORTNAMES
|
||||
#ifndef RTMIDI_DO_NOT_ENSURE_UNIQUE_PORTNAMES
|
||||
std::ostringstream os;
|
||||
os << " ";
|
||||
os << portNumber;
|
||||
@@ -2310,13 +2707,13 @@ std::string MidiInWinMM :: getPortName( unsigned int portNumber )
|
||||
|
||||
MidiOutWinMM :: MidiOutWinMM( const std::string &clientName ) : MidiOutApi()
|
||||
{
|
||||
initialize( clientName );
|
||||
MidiOutWinMM::initialize( clientName );
|
||||
}
|
||||
|
||||
MidiOutWinMM :: ~MidiOutWinMM()
|
||||
{
|
||||
// Close a connection if it exists.
|
||||
closePort();
|
||||
MidiOutWinMM::closePort();
|
||||
|
||||
// Cleanup.
|
||||
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
|
||||
// even when they have the same brand name
|
||||
std::ostringstream os;
|
||||
#ifdef RTMIDI_ENSURE_UNIQUE_PORTNAMES
|
||||
#ifndef RTMIDI_DO_NOT_ENSURE_UNIQUE_PORTNAMES
|
||||
os << " ";
|
||||
os << portNumber;
|
||||
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*/ )
|
||||
{
|
||||
// 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?
|
||||
if ( jData->port == NULL ) return 0;
|
||||
|
||||
void *buff = jack_port_get_buffer( jData->port, nframes );
|
||||
bool& continueSysex = rtData->continueSysex;
|
||||
unsigned char& ignoreFlags = rtData->ignoreFlags;
|
||||
|
||||
// We have midi events in buffer
|
||||
int evCount = jack_midi_get_event_count( buff );
|
||||
for (int j = 0; j < evCount; j++) {
|
||||
MidiInApi::MidiMessage message;
|
||||
message.bytes.clear();
|
||||
|
||||
MidiInApi::MidiMessage& message = rtData->message;
|
||||
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.
|
||||
time = jack_get_time();
|
||||
if ( rtData->firstMessage == true )
|
||||
if ( rtData->firstMessage == true ) {
|
||||
message.timeStamp = 0.0;
|
||||
rtData->firstMessage = false;
|
||||
else
|
||||
} else
|
||||
message.timeStamp = ( time - jData->lastTime ) * 0.000001;
|
||||
|
||||
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 ) {
|
||||
RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) rtData->userCallback;
|
||||
callback( message.timeStamp, &message.bytes, rtData->userData );
|
||||
@@ -2594,9 +3042,10 @@ static int jackProcessIn( jack_nframes_t nframes, void *arg )
|
||||
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 )
|
||||
@@ -2632,7 +3081,7 @@ void MidiInJack :: connect()
|
||||
MidiInJack :: ~MidiInJack()
|
||||
{
|
||||
JackMidiData *data = static_cast<JackMidiData *> (apiData_);
|
||||
closePort();
|
||||
MidiInJack::closePort();
|
||||
|
||||
if ( 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
|
||||
std::string name = getPortName( portNumber );
|
||||
jack_connect( data->client, name.c_str(), jack_port_name( data->port ) );
|
||||
|
||||
connected_ = true;
|
||||
}
|
||||
|
||||
void MidiInJack :: openVirtualPort( const std::string &portName )
|
||||
@@ -2714,7 +3165,9 @@ std::string MidiInJack :: getPortName( unsigned int portNumber )
|
||||
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;
|
||||
ost << "MidiInJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";
|
||||
errorString_ = ost.str();
|
||||
@@ -2722,7 +3175,7 @@ std::string MidiInJack :: getPortName( unsigned int portNumber )
|
||||
}
|
||||
else retStr.assign( ports[portNumber] );
|
||||
|
||||
free( ports );
|
||||
jack_free( ports );
|
||||
return retStr;
|
||||
}
|
||||
|
||||
@@ -2733,6 +3186,26 @@ void MidiInJack :: closePort()
|
||||
if ( data->port == NULL ) return;
|
||||
jack_port_unregister( data->client, data->port );
|
||||
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()
|
||||
{
|
||||
initialize( clientName );
|
||||
MidiOutJack::initialize( clientName );
|
||||
}
|
||||
|
||||
void MidiOutJack :: initialize( const std::string& clientName )
|
||||
@@ -2813,7 +3286,7 @@ void MidiOutJack :: connect()
|
||||
MidiOutJack :: ~MidiOutJack()
|
||||
{
|
||||
JackMidiData *data = static_cast<JackMidiData *> (apiData_);
|
||||
closePort();
|
||||
MidiOutJack::closePort();
|
||||
|
||||
// Cleanup
|
||||
jack_ringbuffer_free( data->buffSize );
|
||||
@@ -2850,6 +3323,8 @@ void MidiOutJack :: openPort( unsigned int portNumber, const std::string &portNa
|
||||
// Connecting to the output
|
||||
std::string name = getPortName( portNumber );
|
||||
jack_connect( data->client, jack_port_name( data->port ), name.c_str() );
|
||||
|
||||
connected_ = true;
|
||||
}
|
||||
|
||||
void MidiOutJack :: openVirtualPort( const std::string &portName )
|
||||
@@ -2926,8 +3401,7 @@ void MidiOutJack :: closePort()
|
||||
|
||||
#ifdef HAVE_SEMAPHORE
|
||||
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
|
||||
sem_post( &data->sem_needpost );
|
||||
sem_timedwait( &data->sem_cleanup, &ts );
|
||||
@@ -2936,6 +3410,26 @@ void MidiOutJack :: closePort()
|
||||
|
||||
jack_port_unregister( data->client, data->port );
|
||||
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 )
|
||||
@@ -2944,8 +3438,7 @@ void MidiOutJack :: sendMessage( const unsigned char *message, size_t size )
|
||||
JackMidiData *data = static_cast<JackMidiData *> (apiData_);
|
||||
|
||||
// Write full message to buffer
|
||||
jack_ringbuffer_write( data->buffMessage, ( const char * ) message,
|
||||
nBytes );
|
||||
jack_ringbuffer_write( data->buffMessage, ( const char * ) message, nBytes );
|
||||
jack_ringbuffer_write( data->buffSize, ( char * ) &nBytes, sizeof( nBytes ) );
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user