From e8c88bc60b6223679fcc0a9a05094a7d809b5e1b Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 26 Mar 2014 20:30:35 +0100 Subject: [PATCH 001/210] Partially define an API for reliable port selection. --- RtMidi.h | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index 9a878884..2fb96263 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -129,6 +129,27 @@ class RtMidi //! A static function to determine the current RtMidi version. static std::string getVersion( void ) throw(); + //! Define a port Id type. + typedef void * PortIdType; + + //! A port descriptor type. + struct PortDescriptor { + std::string Name; /*!< The Name of the port */ + std::string Path; /*!< API dependent path that allows to uniquely identify the port */ + PortIdType id; /*!< API dependent id of the port */ + void * api; /*!< API to be called when the port shall be opened */ + } + + //! Define a port Id type. + typedef void * PortIdType; + + //! A port descriptor type. + struct PortDescriptor { + std::string Name; /*!< The Name of the port */ + std::string Path; /*!< API dependent path that allows to uniquely identify the port */ + PortIdType id; /*!< API dependent id of the port */ + void * api; /*!< API to be called when the port shall be opened */ + } //! A static function to determine the available compiled MIDI APIs. /*! @@ -141,9 +162,18 @@ class RtMidi //! Pure virtual openPort() function. virtual void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi" ) ) = 0; + //! Pure virtual openPort() function. + virtual void openPort( const PortIdType portId, const std::string portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual openPort() function. + virtual void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi" ) ) = 0; + //! Pure virtual openVirtualPort() function. virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0; + //! Pure virtual getPortList() function. + virtual std::list getPortList(); + //! Pure virtual getPortCount() function. virtual unsigned int getPortCount() = 0; @@ -246,6 +276,20 @@ class RtMidiIn : public RtMidi */ void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi Input" ) ); + //! Open a MIDI input connection given as string representation of the API dependent port id. + /*! + \param portId An API dependent port id must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + virtual void openPort( const PortIdType portId, const std::string portName = std::string( "RtMidi" ) ) = 0; + + //! Open a MIDI input connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + virtual void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi" ) ) = 0; + //! Create a virtual input port, with optional name, to allow software connections (OS X, JACK and ALSA only). /*! This function creates a virtual MIDI input port to which other @@ -255,9 +299,16 @@ class RtMidiIn : public RtMidi \param portName An optional name for the application port that is used to connect to portId can be specified. + */ void openVirtualPort( const std::string portName = std::string( "RtMidi Input" ) ); + //! Return a list of all available ports of the current API. + /*! + \return This function returns a list of port descriptors. + */ + virtual std::list getPortList(); + //! Set a callback function to be invoked for incoming MIDI messages. /*! The callback function will be called whenever an incoming MIDI @@ -475,8 +526,8 @@ class MidiInApi : public MidiApi // A MIDI structure used internally by the class to store incoming // messages. Each message represents one and only one MIDI message. - struct MidiMessage { - std::vector bytes; + struct MidiMessage { + std::vector bytes; double timeStamp; // Default constructor. From ac862631a3dc3ae7b8665d1d1a54093f3ed08c38 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Thu, 27 Mar 2014 08:47:44 +0100 Subject: [PATCH 002/210] Mark RtMidi.h to be C++. This helps certain editors to select the correct mode that usually interpet .h files as C headers. --- RtMidi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RtMidi.h b/RtMidi.h index 2fb96263..6f3af2f2 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -1,4 +1,4 @@ -/**********************************************************************/ +/********************* -*- C++ -*- ****************************************/ /*! \class RtMidi \brief An abstract base class for realtime MIDI input/output. From a7281d2ac5141addc0d389569eab330f26fe4f0e Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Thu, 27 Mar 2014 19:35:28 +0100 Subject: [PATCH 003/210] Merge port Id type into PortDescriptor and go further with cascading the API. --- RtMidi.h | 145 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 120 insertions(+), 25 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index 6f3af2f2..929bd1c6 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -112,6 +112,8 @@ class RtMidiError : public std::exception typedef void (*RtMidiErrorCallback)( RtMidiError::Type type, const std::string &errorText ); class MidiApi; +class RtMidiIn; +class RtMidiOut; class RtMidi { @@ -129,16 +131,91 @@ class RtMidi //! A static function to determine the current RtMidi version. static std::string getVersion( void ) throw(); - //! Define a port Id type. - typedef void * PortIdType; //! A port descriptor type. + /*! This will be used with scoped pointers to store system dependent + * data for identifying the port. + */ struct PortDescriptor { - std::string Name; /*!< The Name of the port */ - std::string Path; /*!< API dependent path that allows to uniquely identify the port */ - PortIdType id; /*!< API dependent id of the port */ - void * api; /*!< API to be called when the port shall be opened */ - } + //! Flags for formatting a string description of the port. + /*! These flags just mark the requirements that the string + should fulfil. An API may return the same string for + different requirements e.g. the same short and long + name. */ + enum NamingType { + SHORT_NAME =0, /*!< A short human readable name + depending on the API + e.g. “Ensoniq AudioPCI” */ + LONG_NAME, /*!< A complete human readable + name depending on the API + e.g. "Ensoniq AudioPCI: ES1371" */ + SESSION_PATH, /*!< A unique description that can + be used to identify the port + during runtime. It may be a + cryptic string. */ + STORAGE_PATH, /*!< A unique description that is + optimised for storage in + configuration files. This is a + more textual representation that + is more robust to small changes in + the surrounding environment than + \ref SESSION_PATH */ + UNIQUE_NAME = 0x10, /*!< Make all names uniqe. This + is usually done by adding + numbers to the end of the + string */ + INCLUDE_API = 0x20 /*!< Add a string describing the + API at the beginning of the + string. */ + }; + + //! Flags describing the capabilities of a given port. + enum PortCapabilities { + INPUT = 1, /*!< Ports that can be read from. */ + OUTPUT = 2, /*!< Ports that can be written to. */ + INOUTPUT = 3 /*!< Ports that allow reading and writing (INPUT | OUTPUT) */ + }; + + //! Default constructor. + /*! + * Derived classes should have a constructor. + */ + PortIdType() {}; + + //! Get the MIDI api for the current port. + /*! This is the only information RtMidi needs to know: Which + * API should handle this object. + * + * \return API that can handle this object. + */ + virtual MidiApi * getAPI() = 0; + + //! A virtual destructor + /*! As we might have to destruct the object from the application code + * each port id must have a virtual destructor. + */ + virtual ~PortIdType() = 0; + + //! Return the port name + /*! + * \param flags A description of the requirements of the returned name. + * \return A name that is formatted according to \ref flags. + * \sa NamingTypes + */ + virtual std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) = 0; + + //! Get capabilities + /*! \return a capabilities flag describing the capabilities of the port. + * \sa PortCapabilities + */ + virtual int getCapabilities(); + }; + + //! A list of port descriptors. + /*! Port descriptors are stored as shared pointers. This avoids + unnecessary duplication of the data structure and handles automatic + deletion if all references have been removed. */ + typedef std::list > PortList; //! Define a port Id type. typedef void * PortIdType; @@ -162,9 +239,6 @@ class RtMidi //! Pure virtual openPort() function. virtual void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi" ) ) = 0; - //! Pure virtual openPort() function. - virtual void openPort( const PortIdType portId, const std::string portName = std::string( "RtMidi" ) ) = 0; - //! Pure virtual openPort() function. virtual void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi" ) ) = 0; @@ -172,7 +246,7 @@ class RtMidi virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0; //! Pure virtual getPortList() function. - virtual std::list getPortList(); + virtual std::list getPortList(int capabilities = PortDescriptor:: INOUTPUT) = 0; //! Pure virtual getPortCount() function. virtual unsigned int getPortCount() = 0; @@ -186,6 +260,9 @@ class RtMidi //! Returns true if a port is open and false if not. virtual bool isPortOpen( void ) const = 0; + //! Returns a port descirptor if the port is open + virtual std::scoped_ptr getDescriptor() = 0; + //! Set an error callback function to be invoked when an error has occured. /*! The callback function will be called whenever an error has occured. It is best @@ -276,13 +353,6 @@ class RtMidiIn : public RtMidi */ void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi Input" ) ); - //! Open a MIDI input connection given as string representation of the API dependent port id. - /*! - \param portId An API dependent port id must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - */ - virtual void openPort( const PortIdType portId, const std::string portName = std::string( "RtMidi" ) ) = 0; - //! Open a MIDI input connection given by a port descriptor. /*! \param port A port descriptor of the port must be specified. @@ -305,9 +375,12 @@ class RtMidiIn : public RtMidi //! Return a list of all available ports of the current API. /*! + \param capabilities an opitonnal parameter that describes which + device types are returned. \return This function returns a list of port descriptors. + \note An API is not required to return all output ports from RtMidiIn. */ - virtual std::list getPortList(); + virtual std::list getPortList(int capabilities = PortDescriptor:: INPUT); //! Set a callback function to be invoked for incoming MIDI messages. /*! @@ -335,6 +408,9 @@ class RtMidiIn : public RtMidi //! Returns true if a port is open and false if not. virtual bool isPortOpen() const; + //! Returns a port descirptor if the port is open + virtual std::scoped_ptr getDescriptor() = 0; + //! Return the number of available MIDI input ports. /*! \return This function returns the number of MIDI ports of the selected API. @@ -417,7 +493,7 @@ class RtMidiOut : public RtMidi //! Returns the MIDI API specifier for the current instance of RtMidiOut. RtMidi::Api getCurrentApi( void ) throw(); - //! Open a MIDI output connection. + //! Open a MIDI output connection given by an enumeration number. /*! An optional port number greater than 0 can be specified. Otherwise, the default or first port found is opened. An @@ -426,11 +502,12 @@ class RtMidiOut : public RtMidi */ void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi Output" ) ); - //! Close an open MIDI connection (if one exists). - void closePort( void ); - - //! Returns true if a port is open and false if not. - virtual bool isPortOpen() const; + //! Open a MIDI output connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + virtual void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi Output" ) ) = 0; //! Create a virtual output port, with optional name, to allow software connections (OS X, JACK and ALSA only). /*! @@ -443,6 +520,24 @@ class RtMidiOut : public RtMidi */ void openVirtualPort( const std::string portName = std::string( "RtMidi Output" ) ); + //! Close an open MIDI connection (if one exists). + void closePort( void ); + + //! Returns true if a port is open and false if not. + virtual bool isPortOpen() const; + + //! Returns a port descirptor if the port is open + virtual std::scoped_ptr getDescriptor() = 0; + + //! Return a list of all available ports of the current API. + /*! + \param capabilities an opitonnal parameter that describes which + device types are returned. + \return This function returns a list of port descriptors. + \note An API is not required to return all input ports from RtMidiOut. + */ + virtual std::list getPortList(int capabilities = PortDescriptor::OUTPUT); + //! Return the number of available MIDI output ports. unsigned int getPortCount( void ); From 3abc0346a636273d592a1295f1101e661ad17bfe Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 28 Mar 2014 09:16:42 +0100 Subject: [PATCH 004/210] Complete the API part of the new PortDescriptor based API This includes also some reorganisation that moves the common global/local API out of RtMIDI and the backend api. --- RtMidi.h | 534 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 336 insertions(+), 198 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index 929bd1c6..d7093367 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -49,6 +49,8 @@ #include #include #include +#include +#include /************************************************************************/ /*! \class RtMidiError @@ -80,7 +82,7 @@ class RtMidiError : public std::exception //! The constructor. RtMidiError( const std::string& message, Type type = RtMidiError::UNSPECIFIED ) throw() : message_(message), type_(type) {} - + //! The destructor. virtual ~RtMidiError( void ) throw() {} @@ -111,11 +113,241 @@ class RtMidiError : public std::exception */ typedef void (*RtMidiErrorCallback)( RtMidiError::Type type, const std::string &errorText ); -class MidiApi; -class RtMidiIn; -class RtMidiOut; +class MidiApi { + //! A port descriptor type. + /*! This will be used with scoped pointers to store system dependent + * data for identifying the port. + */ + struct PortDescriptor { + //! Flags for formatting a string description of the port. + /*! These flags just mark the requirements that the string + should fulfil. An API may return the same string for + different requirements e.g. the same short and long + name. */ + enum NamingType { + SHORT_NAME =0, /*!< A short human readable name + depending on the API + e.g. “Ensoniq AudioPCI” */ + LONG_NAME, /*!< A complete human readable + name depending on the API + e.g. "Ensoniq AudioPCI: ES1371" */ + SESSION_PATH, /*!< A unique description that can + be used to identify the port + during runtime. It may be a + cryptic string. */ + STORAGE_PATH, /*!< A unique description that is + optimised for storage in + configuration files. This is a + more textual representation that + is more robust to small changes in + the surrounding environment than + \ref SESSION_PATH */ + UNIQUE_NAME = 0x10, /*!< Make all names uniqe. This + is usually done by adding + numbers to the end of the + string */ + INCLUDE_API = 0x20 /*!< Add a string describing the + API at the beginning of the + string. */ + }; + + //! Flags describing the capabilities of a given port. + enum PortCapabilities { + INPUT = 1, /*!< Ports that can be read from. */ + OUTPUT = 2, /*!< Ports that can be written to. */ + INOUTPUT = 3 /*!< Ports that allow reading and writing (INPUT | OUTPUT) */ + }; + + +#if __cplusplus < 201103L + class Pointer { + protected: + struct countPointer { + int count; + PortDescriptor * descriptor; + }; + public: + Pointer(PortDescriptor * p):ptr(new countPointer) { + ptr->count = 1; + ptr->descriptor = p; + } + Pointer(Pointer & other): + ptr(other.ptr) { + ptr->count++; + } + + ~Pointer() { + if (!ptr) return; + if (!ptr->descriptor) { + delete ptr; + return; + } + if (!(--ptr->count)) { + delete ptr->descriptor; + delete ptr; + } + } + + PortDescriptor * operator -> () { + if (!ptr) return 0; + // this should throw an exception + + return ptr->descriptor; + } + protected: + countPointer * ptr; + }; +#else + typedef shared_ptr Pointer; +#endif + + + //! Default constructor. + /*! + * Derived classes should have a constructor. + */ + PortDescriptor() {}; + + //! A virtual destructor + /*! As we might have to destruct the object from the application code + * each port id must have a virtual destructor. + */ + virtual ~PortDescriptor() = 0; + + //! Get the MIDI api for the current port. + /*! This is the only information RtMidi needs to know: Which + * API should handle this object. + * + * \return API that can handle this object. + */ + virtual MidiApi * getAPI() = 0; + + //! Return the port name + /*! + * \param flags A description of the requirements of the returned name. + * \return A name that is formatted according to \ref flags. + * \sa NamingTypes + */ + virtual std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) = 0; + + //! Get capabilities + /*! \return a capabilities flag describing the capabilities of the port. + * \sa PortCapabilities + */ + virtual int getCapabilities(); + }; + + //! A list of port descriptors. + /*! Port descriptors are stored as shared pointers. This avoids + unnecessary duplication of the data structure and handles automatic + deletion if all references have been removed. */ + typedef std::list PortList; + + //! Pure virtal function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + */ + virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. + + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. + */ + virtual void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + virtual void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual function to return a port descirptor if the port is open + virtual PortDescriptor::Pointer getDescriptor() = 0; + + //! Pure virtual function to return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that describes which + device types are returned. + + \return This function returns a list of port descriptors. + + \note An input API may but need not necessarily report + output devices which cannot be used as input if + \ref PortDescriptor::OUTPUT is passed as \ref capabilities parameter. + */ + virtual MidiApi::PortList getPortList(int capabilities = PortDescriptor:: INOUTPUT) = 0; + + //! Pure virtual to return the number of available MIDI ports of the current API. + /*! + \return This function returns the number of MIDI ports of + the selected API. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortName + */ + virtual unsigned int getPortCount() = 0; + + //! Pure virtual function to return a string identifier for the specified MIDI port number. + /*! + \param portNumber Number of the device to be referred to. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortCount() + */ + std::string getPortName( unsigned int portNumber = 0 ); + + //! Pure virtual function to close an open MIDI connection (if one exists). + virtual void closePort( void ) = 0; + + // ! A basic error reporting function for RtMidi classes. + // static void error( RtMidiError::Type type, std::string &errorString ); + + //! Pure virtual function to return whether a port is open or not. + /*! \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). + */ + virtual bool isPortOpen( void ) const = 0; + + //! Pure virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL ) = 0; +} + +/**********************************************************************/ +/*! \class RtMidi + \brief A global class that implements basic backend API handling. + + This class enhances \ref MidiApi by some functionality to handle + backend API objects. It serves as base class for the public RtMidi + API. -class RtMidi + by Gary P. Scavone, 2003-2014. +*/ +/**********************************************************************/ +class RtMidi : public MidiApi { public: @@ -132,102 +364,6 @@ class RtMidi //! A static function to determine the current RtMidi version. static std::string getVersion( void ) throw(); - //! A port descriptor type. - /*! This will be used with scoped pointers to store system dependent - * data for identifying the port. - */ - struct PortDescriptor { - //! Flags for formatting a string description of the port. - /*! These flags just mark the requirements that the string - should fulfil. An API may return the same string for - different requirements e.g. the same short and long - name. */ - enum NamingType { - SHORT_NAME =0, /*!< A short human readable name - depending on the API - e.g. “Ensoniq AudioPCI” */ - LONG_NAME, /*!< A complete human readable - name depending on the API - e.g. "Ensoniq AudioPCI: ES1371" */ - SESSION_PATH, /*!< A unique description that can - be used to identify the port - during runtime. It may be a - cryptic string. */ - STORAGE_PATH, /*!< A unique description that is - optimised for storage in - configuration files. This is a - more textual representation that - is more robust to small changes in - the surrounding environment than - \ref SESSION_PATH */ - UNIQUE_NAME = 0x10, /*!< Make all names uniqe. This - is usually done by adding - numbers to the end of the - string */ - INCLUDE_API = 0x20 /*!< Add a string describing the - API at the beginning of the - string. */ - }; - - //! Flags describing the capabilities of a given port. - enum PortCapabilities { - INPUT = 1, /*!< Ports that can be read from. */ - OUTPUT = 2, /*!< Ports that can be written to. */ - INOUTPUT = 3 /*!< Ports that allow reading and writing (INPUT | OUTPUT) */ - }; - - //! Default constructor. - /*! - * Derived classes should have a constructor. - */ - PortIdType() {}; - - //! Get the MIDI api for the current port. - /*! This is the only information RtMidi needs to know: Which - * API should handle this object. - * - * \return API that can handle this object. - */ - virtual MidiApi * getAPI() = 0; - - //! A virtual destructor - /*! As we might have to destruct the object from the application code - * each port id must have a virtual destructor. - */ - virtual ~PortIdType() = 0; - - //! Return the port name - /*! - * \param flags A description of the requirements of the returned name. - * \return A name that is formatted according to \ref flags. - * \sa NamingTypes - */ - virtual std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) = 0; - - //! Get capabilities - /*! \return a capabilities flag describing the capabilities of the port. - * \sa PortCapabilities - */ - virtual int getCapabilities(); - }; - - //! A list of port descriptors. - /*! Port descriptors are stored as shared pointers. This avoids - unnecessary duplication of the data structure and handles automatic - deletion if all references have been removed. */ - typedef std::list > PortList; - - //! Define a port Id type. - typedef void * PortIdType; - - //! A port descriptor type. - struct PortDescriptor { - std::string Name; /*!< The Name of the port */ - std::string Path; /*!< API dependent path that allows to uniquely identify the port */ - PortIdType id; /*!< API dependent id of the port */ - void * api; /*!< API to be called when the port shall be opened */ - } - //! A static function to determine the available compiled MIDI APIs. /*! The values returned in the std::vector can be compared against @@ -236,40 +372,6 @@ class RtMidi */ static void getCompiledApi( std::vector &apis ) throw(); - //! Pure virtual openPort() function. - virtual void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi" ) ) = 0; - - //! Pure virtual openPort() function. - virtual void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi" ) ) = 0; - - //! Pure virtual openVirtualPort() function. - virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0; - - //! Pure virtual getPortList() function. - virtual std::list getPortList(int capabilities = PortDescriptor:: INOUTPUT) = 0; - - //! Pure virtual getPortCount() function. - virtual unsigned int getPortCount() = 0; - - //! Pure virtual getPortName() function. - virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; - - //! Pure virtual closePort() function. - virtual void closePort( void ) = 0; - - //! Returns true if a port is open and false if not. - virtual bool isPortOpen( void ) const = 0; - - //! Returns a port descirptor if the port is open - virtual std::scoped_ptr getDescriptor() = 0; - - //! Set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. - */ - virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL ) = 0; - protected: RtMidi(); @@ -345,6 +447,18 @@ class RtMidiIn : public RtMidi //! Returns the MIDI API specifier for the current instance of RtMidiIn. RtMidi::Api getCurrentApi( void ) throw(); + //! Create a virtual input port, with optional name, to allow software connections (OS X, JACK and ALSA only). + /*! + This function creates a virtual MIDI input port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + */ + void openVirtualPort( const std::string portName = std::string( "RtMidi Input" ) ); + //! Open a MIDI input connection given by enumeration number. /*! \param portNumber An optional port number greater than 0 can be specified. @@ -358,29 +472,38 @@ class RtMidiIn : public RtMidi \param port A port descriptor of the port must be specified. \param portName An optional name for the applicaction port that is used to connect to portId can be specified. */ - virtual void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi" ) ) = 0; + void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi" ) ) = 0; - //! Create a virtual input port, with optional name, to allow software connections (OS X, JACK and ALSA only). - /*! - This function creates a virtual MIDI input port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, any JACK, - and Linux ALSA APIs (the function returns an error for the other APIs). + //! Returns a port descirptor if the port is open + virtual MidiApi::PortDescriptor::Pointer getDescriptor() = 0; - \param portName An optional name for the application port that is - used to connect to portId can be specified. + //! Return a list of all available input ports of the current API. + /*! + \param capabilities an optional parameter that describes which + device types are returned. + \return This function returns a list of port descriptors. + \note An Output API is not required to return all output ports from RtMidiIn. + */ + virtual MidiApi::PortList getPortList(int capabilities = PortDescriptor:: INPUT); + //! Return the number of available MIDI input ports. + /*! + \return This function returns the number of midi ports of the selected API. */ - void openVirtualPort( const std::string portName = std::string( "RtMidi Input" ) ); + unsigned int getPortCount(); - //! Return a list of all available ports of the current API. + //! Return a string identifier for the specified MIDI input port number. /*! - \param capabilities an opitonnal parameter that describes which - device types are returned. - \return This function returns a list of port descriptors. - \note An API is not required to return all output ports from RtMidiIn. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. */ - virtual std::list getPortList(int capabilities = PortDescriptor:: INPUT); + std::string getPortName( unsigned int portNumber = 0 ); + + //! Close an open MIDI connection (if one exists). + void closePort( void ); + + //! Returns true if a port is open and false if not. + virtual bool isPortOpen() const; //! Set a callback function to be invoked for incoming MIDI messages. /*! @@ -402,28 +525,6 @@ class RtMidiIn : public RtMidi */ void cancelCallback(); - //! Close an open MIDI connection (if one exists). - void closePort( void ); - - //! Returns true if a port is open and false if not. - virtual bool isPortOpen() const; - - //! Returns a port descirptor if the port is open - virtual std::scoped_ptr getDescriptor() = 0; - - //! Return the number of available MIDI input ports. - /*! - \return This function returns the number of MIDI ports of the selected API. - */ - unsigned int getPortCount(); - - //! Return a string identifier for the specified MIDI input port number. - /*! - \return The name of the port with the given Id is returned. - \retval An empty string is returned if an invalid port specifier is provided. - */ - std::string getPortName( unsigned int portNumber = 0 ); - //! Specify whether certain MIDI message types should be queued or ignored during input. /*! By default, MIDI timing and active sensing messages are ignored @@ -493,6 +594,17 @@ class RtMidiOut : public RtMidi //! Returns the MIDI API specifier for the current instance of RtMidiOut. RtMidi::Api getCurrentApi( void ) throw(); + //! Create a virtual output port, with optional name, to allow software connections (OS X and ALSA only). + /*! + This function creates a virtual MIDI output port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X and Linux ALSA + APIs (the function does nothing with the other APIs). An + exception is thrown if an error occurs while attempting to create + the virtual port. + */ + void openVirtualPort( const std::string portName = std::string( "RtMidi Output" ) ); + //! Open a MIDI output connection given by an enumeration number. /*! An optional port number greater than 0 can be specified. @@ -509,16 +621,11 @@ class RtMidiOut : public RtMidi */ virtual void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi Output" ) ) = 0; - //! Create a virtual output port, with optional name, to allow software connections (OS X, JACK and ALSA only). - /*! - This function creates a virtual MIDI output port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, Linux ALSA - and JACK APIs (the function does nothing with the other APIs). - An exception is thrown if an error occurs while attempting to - create the virtual port. - */ - void openVirtualPort( const std::string portName = std::string( "RtMidi Output" ) ); + //! Returns a port descirptor if the port is open + /*! \return Port descriptor of the currently open port + * \retval 0 iff the port s not open + */ + virtual MidiApi::PortDescriptor::Pointer getDescriptor() = 0; //! Close an open MIDI connection (if one exists). void closePort( void ); @@ -526,9 +633,6 @@ class RtMidiOut : public RtMidi //! Returns true if a port is open and false if not. virtual bool isPortOpen() const; - //! Returns a port descirptor if the port is open - virtual std::scoped_ptr getDescriptor() = 0; - //! Return a list of all available ports of the current API. /*! \param capabilities an opitonnal parameter that describes which @@ -536,14 +640,15 @@ class RtMidiOut : public RtMidi \return This function returns a list of port descriptors. \note An API is not required to return all input ports from RtMidiOut. */ - virtual std::list getPortList(int capabilities = PortDescriptor::OUTPUT); + virtual MidiApi::PortList getPortList(int capabilities = PortDescriptor::OUTPUT); //! Return the number of available MIDI output ports. unsigned int getPortCount( void ); //! Return a string identifier for the specified MIDI port type and number. /*! - An empty string is returned if an invalid port specifier is provided. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. */ std::string getPortName( unsigned int portNumber = 0 ); @@ -579,21 +684,17 @@ class RtMidiOut : public RtMidi // // **************************************************************** // -class MidiApi +class MidiBackendApi: public MidiApi { public: MidiApi(); virtual ~MidiApi(); - virtual RtMidi::Api getCurrentApi( void ) = 0; - 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 unsigned int getPortCount( void ) = 0; virtual std::string getPortName( unsigned int portNumber ) = 0; - inline bool isPortOpen() const { return connected_; } + bool isPortOpen() const { return connected_; } void setErrorCallback( RtMidiErrorCallback errorCallback ); //! A basic error reporting function for RtMidi classes. @@ -608,7 +709,7 @@ class MidiApi RtMidiErrorCallback errorCallback_; }; -class MidiInApi : public MidiApi +class MidiInApi : public MidiBackendApi { public: @@ -667,7 +768,7 @@ class MidiInApi : public MidiApi RtMidiInData inputData_; }; -class MidiOutApi : public MidiApi +class MidiOutApi : public MidiBackendApi { public: @@ -725,6 +826,9 @@ class MidiInCore: public MidiInApi RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; }; void openPort( unsigned int portNumber, const std::string portName ); void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + MidiApi::PortDescriptor::Pointer getDescriptor(); + MidiApi::PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -741,6 +845,9 @@ class MidiOutCore: public MidiOutApi RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; }; void openPort( unsigned int portNumber, const std::string portName ); void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + MidiApi::PortDescriptor::Pointer getDescriptor(); + MidiApi::PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -762,6 +869,9 @@ class MidiInJack: public MidiInApi RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; }; void openPort( unsigned int portNumber, const std::string portName ); void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + MidiApi::PortDescriptor::Pointer getDescriptor(); + MidiApi::PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -781,6 +891,9 @@ class MidiOutJack: public MidiOutApi RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; }; void openPort( unsigned int portNumber, const std::string portName ); void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + MidiApi::PortDescriptor::Pointer getDescriptor(); + MidiApi::PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -805,6 +918,9 @@ class MidiInAlsa: public MidiInApi RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; }; void openPort( unsigned int portNumber, const std::string portName ); void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + MidiApi::PortDescriptor::Pointer getDescriptor(); + MidiApi::PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -821,6 +937,9 @@ class MidiOutAlsa: public MidiOutApi RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; }; void openPort( unsigned int portNumber, const std::string portName ); void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + MidiApi::PortDescriptor::Pointer getDescriptor(); + MidiApi::PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -842,6 +961,9 @@ class MidiInWinMM: public MidiInApi RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; }; void openPort( unsigned int portNumber, const std::string portName ); void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + MidiApi::PortDescriptor::Pointer getDescriptor(); + MidiApi::PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -858,6 +980,9 @@ class MidiOutWinMM: public MidiOutApi RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; }; void openPort( unsigned int portNumber, const std::string portName ); void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + MidiApi::PortDescriptor::Pointer getDescriptor(); + MidiApi::PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -874,10 +999,17 @@ class MidiOutWinMM: public MidiOutApi 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_ ); } + 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 openPort( const PortDescriptor & port, const std::string portName) {} + MidiApi::PortDescriptor::Pointer getDescriptor() { return 0; } + MidiApi::PortList getPortList(int capabilities) { return MidiApi::PortList(); } void closePort( void ) {} unsigned int getPortCount( void ) { return 0; } std::string getPortName( unsigned int portNumber ) { return ""; } @@ -889,10 +1021,16 @@ class MidiInDummy: public MidiInApi class MidiOutDummy: public MidiOutApi { public: - MidiOutDummy( const std::string /*clientName*/ ) { errorString_ = "MidiOutDummy: This class provides no functionality."; error( RtMidiError::WARNING, errorString_ ); } + 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 openPort( const PortDescriptor & port, const std::string portName) {} + MidiApi::PortDescriptor::Pointer getDescriptor() { return 0; } + MidiApi::PortList getPortList(int capabilities) { return MidiApi::PortList(); } void closePort( void ) {} unsigned int getPortCount( void ) { return 0; } std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } From 1a7451dc0e6e298929ff1eb1118cc80af4fc7af9 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 29 Mar 2014 09:58:12 +0100 Subject: [PATCH 005/210] Revert renaming MidiApi into MidiBackendApi and rename the other MidiApi. The new MidiApi is now called CommonMidiApi. This avoids some compilation errors. --- RtMidi.h | 72 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index d7093367..7abc03f6 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -113,7 +113,8 @@ class RtMidiError : public std::exception */ typedef void (*RtMidiErrorCallback)( RtMidiError::Type type, const std::string &errorText ); -class MidiApi { +class CommonMidiApi { +public: //! A port descriptor type. /*! This will be used with scoped pointers to store system dependent * data for identifying the port. @@ -220,7 +221,7 @@ class MidiApi { * * \return API that can handle this object. */ - virtual MidiApi * getAPI() = 0; + virtual CommonMidiApi * getAPI() = 0; //! Return the port name /*! @@ -287,7 +288,7 @@ class MidiApi { output devices which cannot be used as input if \ref PortDescriptor::OUTPUT is passed as \ref capabilities parameter. */ - virtual MidiApi::PortList getPortList(int capabilities = PortDescriptor:: INOUTPUT) = 0; + virtual CommonMidiApi::PortList getPortList(int capabilities = PortDescriptor:: INOUTPUT) = 0; //! Pure virtual to return the number of available MIDI ports of the current API. /*! @@ -340,14 +341,15 @@ class MidiApi { /*! \class RtMidi \brief A global class that implements basic backend API handling. - This class enhances \ref MidiApi by some functionality to handle + This class enhances \ref CommonMidiApi by some functionality to handle backend API objects. It serves as base class for the public RtMidi API. by Gary P. Scavone, 2003-2014. */ /**********************************************************************/ -class RtMidi : public MidiApi +class MidiApi; +class RtMidi : public CommonMidiApi { public: @@ -373,11 +375,11 @@ class RtMidi : public MidiApi static void getCompiledApi( std::vector &apis ) throw(); protected: + MidiApi *rtapi_; RtMidi(); virtual ~RtMidi(); - MidiApi *rtapi_; }; /**********************************************************************/ @@ -475,7 +477,7 @@ class RtMidiIn : public RtMidi void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi" ) ) = 0; //! Returns a port descirptor if the port is open - virtual MidiApi::PortDescriptor::Pointer getDescriptor() = 0; + virtual CommonMidiApi::PortDescriptor::Pointer getDescriptor(); //! Return a list of all available input ports of the current API. /*! @@ -484,7 +486,7 @@ class RtMidiIn : public RtMidi \return This function returns a list of port descriptors. \note An Output API is not required to return all output ports from RtMidiIn. */ - virtual MidiApi::PortList getPortList(int capabilities = PortDescriptor:: INPUT); + virtual CommonMidiApi::PortList getPortList(int capabilities = PortDescriptor:: INPUT); //! Return the number of available MIDI input ports. /*! @@ -625,7 +627,7 @@ class RtMidiOut : public RtMidi /*! \return Port descriptor of the currently open port * \retval 0 iff the port s not open */ - virtual MidiApi::PortDescriptor::Pointer getDescriptor() = 0; + virtual CommonMidiApi::PortDescriptor::Pointer getDescriptor(); //! Close an open MIDI connection (if one exists). void closePort( void ); @@ -640,7 +642,7 @@ class RtMidiOut : public RtMidi \return This function returns a list of port descriptors. \note An API is not required to return all input ports from RtMidiOut. */ - virtual MidiApi::PortList getPortList(int capabilities = PortDescriptor::OUTPUT); + virtual CommonMidiApi::PortList getPortList(int capabilities = PortDescriptor::OUTPUT); //! Return the number of available MIDI output ports. unsigned int getPortCount( void ); @@ -684,7 +686,7 @@ class RtMidiOut : public RtMidi // // **************************************************************** // -class MidiBackendApi: public MidiApi +class MidiApi: public CommonMidiApi { public: @@ -709,7 +711,7 @@ class MidiBackendApi: public MidiApi RtMidiErrorCallback errorCallback_; }; -class MidiInApi : public MidiBackendApi +class MidiInApi : public MidiApi { public: @@ -768,7 +770,7 @@ class MidiInApi : public MidiBackendApi RtMidiInData inputData_; }; -class MidiOutApi : public MidiBackendApi +class MidiOutApi : public MidiApi { public: @@ -827,8 +829,8 @@ class MidiInCore: public MidiInApi void openPort( unsigned int portNumber, const std::string portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string portName); - MidiApi::PortDescriptor::Pointer getDescriptor(); - MidiApi::PortList getPortList(int capabilities); + CommonMidiApi::PortDescriptor::Pointer getDescriptor(); + CommonMidiApi::PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -846,8 +848,8 @@ class MidiOutCore: public MidiOutApi void openPort( unsigned int portNumber, const std::string portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string portName); - MidiApi::PortDescriptor::Pointer getDescriptor(); - MidiApi::PortList getPortList(int capabilities); + CommonMidiApi::PortDescriptor::Pointer getDescriptor(); + CommonMidiApi::PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -870,8 +872,8 @@ class MidiInJack: public MidiInApi void openPort( unsigned int portNumber, const std::string portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string portName); - MidiApi::PortDescriptor::Pointer getDescriptor(); - MidiApi::PortList getPortList(int capabilities); + CommonMidiApi::PortDescriptor::Pointer getDescriptor(); + CommonMidiApi::PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -892,8 +894,8 @@ class MidiOutJack: public MidiOutApi void openPort( unsigned int portNumber, const std::string portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string portName); - MidiApi::PortDescriptor::Pointer getDescriptor(); - MidiApi::PortList getPortList(int capabilities); + CommonMidiApi::PortDescriptor::Pointer getDescriptor(); + CommonMidiApi::PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -915,12 +917,12 @@ class MidiInAlsa: public MidiInApi public: MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit ); ~MidiInAlsa( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; }; + RtMidi::Api getCurrentApi( void ) throw() { return RtMidi::LINUX_ALSA; }; void openPort( unsigned int portNumber, const std::string portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string portName); - MidiApi::PortDescriptor::Pointer getDescriptor(); - MidiApi::PortList getPortList(int capabilities); + CommonMidiApi::PortDescriptor::Pointer getDescriptor(); + CommonMidiApi::PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -934,12 +936,12 @@ class MidiOutAlsa: public MidiOutApi public: MidiOutAlsa( const std::string clientName ); ~MidiOutAlsa( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; }; + RtMidi::Api getCurrentApi( void ) throw() { return RtMidi::LINUX_ALSA; }; void openPort( unsigned int portNumber, const std::string portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string portName); - MidiApi::PortDescriptor::Pointer getDescriptor(); - MidiApi::PortList getPortList(int capabilities); + CommonMidiApi::PortDescriptor::Pointer getDescriptor(); + CommonMidiApi::PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -962,8 +964,8 @@ class MidiInWinMM: public MidiInApi void openPort( unsigned int portNumber, const std::string portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string portName); - MidiApi::PortDescriptor::Pointer getDescriptor(); - MidiApi::PortList getPortList(int capabilities); + CommonMidiApi::PortDescriptor::Pointer getDescriptor(); + CommonMidiApi::PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -981,8 +983,8 @@ class MidiOutWinMM: public MidiOutApi void openPort( unsigned int portNumber, const std::string portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string portName); - MidiApi::PortDescriptor::Pointer getDescriptor(); - MidiApi::PortList getPortList(int capabilities); + CommonMidiApi::PortDescriptor::Pointer getDescriptor(); + CommonMidiApi::PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -1008,8 +1010,8 @@ class MidiInDummy: public MidiInApi void openPort( unsigned int /*portNumber*/, const std::string /*portName*/ ) {} void openVirtualPort( const std::string /*portName*/ ) {} void openPort( const PortDescriptor & port, const std::string portName) {} - MidiApi::PortDescriptor::Pointer getDescriptor() { return 0; } - MidiApi::PortList getPortList(int capabilities) { return MidiApi::PortList(); } + CommonMidiApi::PortDescriptor::Pointer getDescriptor() { return 0; } + CommonMidiApi::PortList getPortList(int capabilities) { return CommonMidiApi::PortList(); } void closePort( void ) {} unsigned int getPortCount( void ) { return 0; } std::string getPortName( unsigned int portNumber ) { return ""; } @@ -1029,8 +1031,8 @@ class MidiOutDummy: public MidiOutApi void openPort( unsigned int /*portNumber*/, const std::string /*portName*/ ) {} void openVirtualPort( const std::string /*portName*/ ) {} void openPort( const PortDescriptor & port, const std::string portName) {} - MidiApi::PortDescriptor::Pointer getDescriptor() { return 0; } - MidiApi::PortList getPortList(int capabilities) { return MidiApi::PortList(); } + CommonMidiApi::PortDescriptor::Pointer getDescriptor() { return 0; } + CommonMidiApi::PortList getPortList(int capabilities) { return CommonMidiApi::PortList(); } void closePort( void ) {} unsigned int getPortCount( void ) { return 0; } std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } From 93acc7db7ab8e1784f3fd4397f7a8c4e75b6f87a Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 29 Mar 2014 09:59:24 +0100 Subject: [PATCH 006/210] Fix some compiler errros. --- RtMidi.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index 7abc03f6..0560f27b 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -172,7 +172,7 @@ class CommonMidiApi { ptr->count = 1; ptr->descriptor = p; } - Pointer(Pointer & other): + Pointer(const Pointer & other): ptr(other.ptr) { ptr->count++; } @@ -335,7 +335,7 @@ class CommonMidiApi { to set the error callback function before opening a port. */ virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL ) = 0; -} +}; /**********************************************************************/ /*! \class RtMidi @@ -474,7 +474,7 @@ class RtMidiIn : public RtMidi \param port A port descriptor of the port must be specified. \param portName An optional name for the applicaction port that is used to connect to portId can be specified. */ - void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi" ) ) = 0; + void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi" ) ); //! Returns a port descirptor if the port is open virtual CommonMidiApi::PortDescriptor::Pointer getDescriptor(); @@ -621,7 +621,7 @@ class RtMidiOut : public RtMidi \param port A port descriptor of the port must be specified. \param portName An optional name for the applicaction port that is used to connect to portId can be specified. */ - virtual void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi Output" ) ) = 0; + virtual void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi Output" ) ); //! Returns a port descirptor if the port is open /*! \return Port descriptor of the currently open port From e9047af39b978ccee0c890c0410aa5533d585afb Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 29 Mar 2014 10:01:34 +0100 Subject: [PATCH 007/210] Add missing inline functions and reformat existing ones. This should be better readable. --- RtMidi.h | 131 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 111 insertions(+), 20 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index 0560f27b..db16b870 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -699,6 +699,10 @@ class MidiApi: public CommonMidiApi bool isPortOpen() const { return connected_; } void setErrorCallback( RtMidiErrorCallback errorCallback ); + + //! Returns the MIDI API specifier for the current instance of RtMidiIn. + virtual RtMidi::Api getCurrentApi( void ) throw(); + //! A basic error reporting function for RtMidi classes. void error( RtMidiError::Type type, std::string errorString ); @@ -785,28 +789,115 @@ class MidiOutApi : public MidiApi // // **************************************************************** // -inline RtMidi::Api RtMidiIn :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); } -inline void RtMidiIn :: openPort( unsigned int portNumber, const std::string portName ) { rtapi_->openPort( portNumber, portName ); } -inline void RtMidiIn :: openVirtualPort( const std::string portName ) { rtapi_->openVirtualPort( portName ); } +inline RtMidi::Api RtMidiIn :: getCurrentApi( void ) throw() +{ + return rtapi_->getCurrentApi(); +} +inline void RtMidiIn :: openVirtualPort( const std::string portName ) +{ + rtapi_->openVirtualPort( portName ); +} +inline void RtMidiIn :: openPort( unsigned int portNumber, + const std::string portName ) +{ + rtapi_->openPort( portNumber, portName ); +} +inline void RtMidiIn :: openPort( const CommonMidiApi::PortDescriptor & port, + const std::string portName) +{ + rtapi_->openPort(port,portName); +} +inline CommonMidiApi::PortDescriptor::Pointer RtMidiIn :: getDescriptor() +{ + return rtapi_->getDescriptor(); +} +inline CommonMidiApi::PortList RtMidiIn :: getPortList(int capabilities) +{ + return rtapi_->getPortList(capabilities); +} +inline unsigned int RtMidiIn :: getPortCount( void ) +{ + return rtapi_->getPortCount(); +} +inline std::string RtMidiIn :: getPortName( unsigned int portNumber ) +{ + return rtapi_->getPortName( portNumber ); +} 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 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 *message ) { return ((MidiInApi *)rtapi_)->getMessage( message ); } -inline void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback ) { rtapi_->setErrorCallback(errorCallback); } - -inline RtMidi::Api RtMidiOut :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); } -inline void RtMidiOut :: openPort( unsigned int portNumber, const std::string portName ) { rtapi_->openPort( portNumber, portName ); } -inline void RtMidiOut :: openVirtualPort( const std::string portName ) { rtapi_->openVirtualPort( portName ); } -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( std::vector *message ) { ((MidiOutApi *)rtapi_)->sendMessage( message ); } -inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback ) { rtapi_->setErrorCallback(errorCallback); } +inline void RtMidiIn :: setCallback( RtMidiCallback callback, + void *userData ) +{ + ((MidiInApi *)rtapi_)->setCallback( callback, userData ); +} +inline void RtMidiIn :: cancelCallback( void ) +{ + ((MidiInApi *)rtapi_)->cancelCallback(); +} +inline void RtMidiIn :: ignoreTypes( bool midiSysex, + bool midiTime, + bool midiSense ) +{ + ((MidiInApi *)rtapi_)->ignoreTypes( midiSysex, midiTime, midiSense ); +} +inline double RtMidiIn :: getMessage( std::vector *message ) +{ + return ((MidiInApi *)rtapi_)->getMessage( message ); +} +inline void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback ) +{ + rtapi_->setErrorCallback(errorCallback); +} + +inline RtMidi::Api RtMidiOut :: getCurrentApi( void ) throw() +{ + return rtapi_->getCurrentApi(); +} +inline void RtMidiOut :: openPort( unsigned int portNumber, const std::string portName ) +{ + rtapi_->openPort( portNumber, portName ); +} +inline void RtMidiOut :: openVirtualPort( const std::string portName ) +{ + rtapi_->openVirtualPort( portName ); +} +inline void RtMidiOut :: openPort( const CommonMidiApi::PortDescriptor & port, + const std::string portName) +{ + rtapi_->openPort(port,portName); +} +inline CommonMidiApi::PortDescriptor::Pointer RtMidiOut :: getDescriptor() +{ + return rtapi_->getDescriptor(); +} +inline CommonMidiApi::PortList RtMidiOut :: getPortList(int capabilities) +{ + return rtapi_->getPortList(capabilities); +} +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( std::vector *message ) +{ + ((MidiOutApi *)rtapi_)->sendMessage( message ); +} +inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback ) +{ + rtapi_->setErrorCallback(errorCallback); +} // **************************************************************** // // From 1f6d76ef836d3648c360a0d0805cc1315d90a834 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 30 Mar 2014 16:13:04 +0200 Subject: [PATCH 008/210] Namespace based API and get rid of virtual inline functions for RtMidi(In|Out). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch includes more than it was intended to. The changes include: • provide a namespace rtmidi to simplify class names • Make all functions of Midi(In|Out)? non-virtual. Virtual inline functions have several pitfalls. • provide Dummies for the new ALSA api. • provide workaround for the major API breaks. • use references for passing certain pointer arguments and deprecate the pointer versions of these functions. --- RtMidi.cpp | 5171 ++++++++++++++++++++++++++-------------------------- RtMidi.h | 1961 ++++++++++---------- 2 files changed, 3601 insertions(+), 3531 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 07e23168..16cf8267 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1,2839 +1,2902 @@ /**********************************************************************/ -/*! \class RtMidi - \brief An abstract base class for realtime MIDI input/output. - - 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: realtime MIDI i/o C++ classes - Copyright (c) 2003-2014 Gary P. Scavone - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - Any person wishing to distribute modifications to the Software is - asked to send the modifications to the original developer so that - they can be incorporated into the canonical version. This is, - however, not a binding provision of this license. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/*! \class Midi + \brief An abstract base class for realtime MIDI input/output. + + This class implements some common functionality for the realtime + MIDI input/output subclasses MidiIn and MidiOut. + + Midi WWW site: http://music.mcgill.ca/~gary/rtmidi/ + + Midi: realtime MIDI i/o C++ classes + Copyright (c) 2003-2014 Gary P. Scavone + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + Any person wishing to distribute modifications to the Software is + asked to send the modifications to the original developer so that + they can be incorporated into the canonical version. This is, + however, not a binding provision of this license. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**********************************************************************/ #include "RtMidi.h" #include -//*********************************************************************// -// RtMidi Definitions -//*********************************************************************// - -RtMidi :: RtMidi() - : rtapi_(0) -{ -} - -RtMidi :: ~RtMidi() -{ - if ( rtapi_ ) - delete rtapi_; - rtapi_ = 0; -} - -std::string RtMidi :: getVersion( void ) throw() -{ - return std::string( RTMIDI_VERSION ); -} +namespace rtmidi { + //*********************************************************************// + // Midi Definitions + //*********************************************************************// + std::string Midi :: getVersion( void ) throw() + { + return std::string( RTMIDI_VERSION ); + } -void RtMidi :: getCompiledApi( std::vector &apis ) throw() -{ - apis.clear(); + void Midi :: getCompiledApi( std::vector &apis ) throw() + { + apis.clear(); - // The order here will control the order of RtMidi's API search in - // the constructor. + // The order here will control the order of RtMidi's API search in + // the constructor. #if defined(__MACOSX_CORE__) - apis.push_back( MACOSX_CORE ); + apis.push_back( rtmidi::MACOSX_CORE ); #endif #if defined(__LINUX_ALSA__) - apis.push_back( LINUX_ALSA ); + apis.push_back( rtmidi::LINUX_ALSA ); #endif #if defined(__UNIX_JACK__) - apis.push_back( UNIX_JACK ); + apis.push_back( rtmidi::UNIX_JACK ); #endif #if defined(__WINDOWS_MM__) - apis.push_back( WINDOWS_MM ); + apis.push_back( rtmidi::WINDOWS_MM ); #endif #if defined(__RTMIDI_DUMMY__) - apis.push_back( RTMIDI_DUMMY ); + apis.push_back( rtmidi::RTMIDI_DUMMY ); #endif -} + } + + void Midi :: error( Error::Type type, std::string errorString ) + { +#if 0 + if ( errorCallback_ ) { + static bool firstErrorOccured = false; -//*********************************************************************// -// RtMidiIn Definitions -//*********************************************************************// + if ( firstErrorOccured ) + return; -void RtMidiIn :: openMidiApi( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit ) -{ - if ( rtapi_ ) - delete rtapi_; - rtapi_ = 0; + firstErrorOccured = true; + const std::string errorMessage = errorString; + + errorCallback_( type, errorMessage ); + firstErrorOccured = false; + return; + } +#endif + + if ( type == Error::WARNING ) { + std::cerr << '\n' << errorString << "\n\n"; + } + else if ( type == Error::DEBUG_WARNING ) { +#if defined(__RTMIDI_DEBUG__) + std::cerr << '\n' << errorString << "\n\n"; +#endif + } + else { + std::cerr << '\n' << errorString << "\n\n"; + throw Error( errorString, type ); + } + } + + + + + //*********************************************************************// + // MidiIn Definitions + //*********************************************************************// + + void MidiIn :: openMidiApi( ApiType api, const std::string clientName, unsigned int queueSizeLimit ) + { + if ( rtapi_ ) + delete rtapi_; + rtapi_ = 0; #if defined(__UNIX_JACK__) - if ( api == UNIX_JACK ) - rtapi_ = new MidiInJack( clientName, queueSizeLimit ); + if ( api == rtmidi::UNIX_JACK ) + rtapi_ = new MidiInJack( clientName, queueSizeLimit ); #endif #if defined(__LINUX_ALSA__) - if ( api == LINUX_ALSA ) - rtapi_ = new MidiInAlsa( clientName, queueSizeLimit ); + if ( api == rtmidi::LINUX_ALSA ) + rtapi_ = new MidiInAlsa( clientName, queueSizeLimit ); #endif #if defined(__WINDOWS_MM__) - if ( api == WINDOWS_MM ) - rtapi_ = new MidiInWinMM( clientName, queueSizeLimit ); + if ( api == rtmidi::WINDOWS_MM ) + rtapi_ = new MidiInWinMM( clientName, queueSizeLimit ); #endif #if defined(__MACOSX_CORE__) - if ( api == MACOSX_CORE ) - rtapi_ = new MidiInCore( clientName, queueSizeLimit ); + if ( api == rtmidi::MACOSX_CORE ) + rtapi_ = new MidiInCore( clientName, queueSizeLimit ); #endif #if defined(__RTMIDI_DUMMY__) - if ( api == RTMIDI_DUMMY ) - rtapi_ = new MidiInDummy( clientName, queueSizeLimit ); + if ( api == rtmidi::RTMIDI_DUMMY ) + rtapi_ = new MidiInDummy( clientName, queueSizeLimit ); #endif -} + } -RtMidiIn :: RtMidiIn( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit ) - : RtMidi() -{ - if ( api != UNSPECIFIED ) { - // Attempt to open the specified API. - openMidiApi( api, clientName, queueSizeLimit ); - if ( rtapi_ ) return; - - // No compiled support for specified API value. Issue a warning - // and continue as if no API was specified. - std::cerr << "\nRtMidiIn: no compiled support for specified API argument!\n\n" << std::endl; - } - - // Iterate through the compiled APIs and return as soon as we find - // one with at least one port or we reach the end of the list. - std::vector< RtMidi::Api > apis; - getCompiledApi( apis ); - for ( unsigned int i=0; igetPortCount() ) break; - } - - if ( rtapi_ ) return; - - // It should not be possible to get here because the preprocessor - // definition __RTMIDI_DUMMY__ is automatically defined if no - // API-specific definitions are passed to the compiler. But just in - // case something weird happens, we'll throw an error. - std::string errorText = "RtMidiIn: no compiled API support found ... critical error!!"; - throw( RtMidiError( errorText, RtMidiError::UNSPECIFIED ) ); -} + MidiIn :: MidiIn( ApiType api, const std::string clientName, unsigned int queueSizeLimit ) + : Midi() + { + if ( api != rtmidi::UNSPECIFIED ) { + // Attempt to open the specified API. + openMidiApi( api, clientName, queueSizeLimit ); + if ( rtapi_ ) return; + + // No compiled support for specified API value. Issue a warning + // and continue as if no API was specified. + std::cerr << "\nMidiIn: no compiled support for specified API argument!\n\n" << std::endl; + } + + // Iterate through the compiled APIs and return as soon as we find + // one with at least one port or we reach the end of the list. + std::vector< ApiType > apis; + getCompiledApi( apis ); + for ( unsigned int i=0; igetPortCount() ) break; + } + + if ( rtapi_ ) return; + + // It should not be possible to get here because the preprocessor + // definition __RTMIDI_DUMMY__ is automatically defined if no + // API-specific definitions are passed to the compiler. But just in + // case something weird happens, we'll throw an error. + std::string errorText = "MidiIn: no compiled API support found ... critical error!!"; + throw( Error( errorText, Error::UNSPECIFIED ) ); + } -RtMidiIn :: ~RtMidiIn() throw() -{ -} + MidiIn :: ~MidiIn() throw() + { + } -//*********************************************************************// -// RtMidiOut Definitions -//*********************************************************************// + //*********************************************************************// + // MidiOut Definitions + //*********************************************************************// -void RtMidiOut :: openMidiApi( RtMidi::Api api, const std::string clientName ) -{ - if ( rtapi_ ) - delete rtapi_; - rtapi_ = 0; + void MidiOut :: openMidiApi( ApiType api, const std::string clientName ) + { + if ( rtapi_ ) + delete rtapi_; + rtapi_ = 0; #if defined(__UNIX_JACK__) - if ( api == UNIX_JACK ) - rtapi_ = new MidiOutJack( clientName ); + if ( api == rtmidi::UNIX_JACK ) + rtapi_ = new MidiOutJack( clientName ); #endif #if defined(__LINUX_ALSA__) - if ( api == LINUX_ALSA ) - rtapi_ = new MidiOutAlsa( clientName ); + if ( api == rtmidi::LINUX_ALSA ) + rtapi_ = new MidiOutAlsa( clientName ); #endif #if defined(__WINDOWS_MM__) - if ( api == WINDOWS_MM ) - rtapi_ = new MidiOutWinMM( clientName ); + if ( api == rtmidi::WINDOWS_MM ) + rtapi_ = new MidiOutWinMM( clientName ); #endif #if defined(__MACOSX_CORE__) - if ( api == MACOSX_CORE ) - rtapi_ = new MidiOutCore( clientName ); + if ( api == rtmidi::MACOSX_CORE ) + rtapi_ = new MidiOutCore( clientName ); #endif #if defined(__RTMIDI_DUMMY__) - if ( api == RTMIDI_DUMMY ) - rtapi_ = new MidiOutDummy( clientName ); + if ( api == rtmidi::RTMIDI_DUMMY ) + rtapi_ = new MidiOutDummy( clientName ); #endif -} + } -RtMidiOut :: RtMidiOut( RtMidi::Api api, const std::string clientName ) -{ - if ( api != UNSPECIFIED ) { - // Attempt to open the specified API. - openMidiApi( api, clientName ); - if ( rtapi_ ) return; - - // No compiled support for specified API value. Issue a warning - // and continue as if no API was specified. - std::cerr << "\nRtMidiOut: no compiled support for specified API argument!\n\n" << std::endl; - } - - // Iterate through the compiled APIs and return as soon as we find - // one with at least one port or we reach the end of the list. - std::vector< RtMidi::Api > apis; - getCompiledApi( apis ); - for ( unsigned int i=0; igetPortCount() ) break; - } - - if ( rtapi_ ) return; - - // It should not be possible to get here because the preprocessor - // definition __RTMIDI_DUMMY__ is automatically defined if no - // API-specific definitions are passed to the compiler. But just in - // case something weird happens, we'll thrown an error. - std::string errorText = "RtMidiOut: no compiled API support found ... critical error!!"; - throw( RtMidiError( errorText, RtMidiError::UNSPECIFIED ) ); -} + MidiOut :: MidiOut( ApiType api, const std::string clientName ) + { + if ( api != rtmidi::UNSPECIFIED ) { + // Attempt to open the specified API. + openMidiApi( api, clientName ); + if ( rtapi_ ) return; + + // No compiled support for specified API value. Issue a warning + // and continue as if no API was specified. + std::cerr << "\nMidiOut: no compiled support for specified API argument!\n\n" << std::endl; + } + + // Iterate through the compiled APIs and return as soon as we find + // one with at least one port or we reach the end of the list. + std::vector< ApiType > apis; + getCompiledApi( apis ); + for ( unsigned int i=0; igetPortCount() ) break; + } + + if ( rtapi_ ) return; + + // It should not be possible to get here because the preprocessor + // definition __RTMIDI_DUMMY__ is automatically defined if no + // API-specific definitions are passed to the compiler. But just in + // case something weird happens, we'll thrown an error. + std::string errorText = "MidiOut: no compiled API support found ... critical error!!"; + throw( Error( errorText, Error::UNSPECIFIED ) ); + } -RtMidiOut :: ~RtMidiOut() throw() -{ -} + MidiOut :: ~MidiOut() throw() + { + } -//*********************************************************************// -// Common MidiApi Definitions -//*********************************************************************// + //*********************************************************************// + // Common MidiApi Definitions + //*********************************************************************// -MidiApi :: MidiApi( void ) - : apiData_( 0 ), connected_( false ), errorCallback_(0) -{ -} + MidiApi :: MidiApi( void ) + : apiData_( 0 ), connected_( false ), errorCallback_(0) + { + } -MidiApi :: ~MidiApi( void ) -{ -} + MidiApi :: ~MidiApi( void ) + { + } -void MidiApi :: setErrorCallback( RtMidiErrorCallback errorCallback ) -{ - errorCallback_ = errorCallback; -} + void MidiApi :: setErrorCallback( ErrorCallback errorCallback ) + { + errorCallback_ = errorCallback; + } -void MidiApi :: error( RtMidiError::Type type, std::string errorString ) -{ - if ( errorCallback_ ) { - static bool firstErrorOccured = false; + void MidiApi :: error( Error::Type type, std::string errorString ) + { + if ( errorCallback_ ) { + static bool firstErrorOccured = false; - if ( firstErrorOccured ) - return; + if ( firstErrorOccured ) + return; - firstErrorOccured = true; - const std::string errorMessage = errorString; + firstErrorOccured = true; + const std::string errorMessage = errorString; - errorCallback_( type, errorMessage ); - firstErrorOccured = false; - return; - } + errorCallback_( type, errorMessage ); + firstErrorOccured = false; + return; + } - if ( type == RtMidiError::WARNING ) { - std::cerr << '\n' << errorString << "\n\n"; - } - else if ( type == RtMidiError::DEBUG_WARNING ) { + if ( type == Error::WARNING ) { + std::cerr << '\n' << errorString << "\n\n"; + } + else if ( type == Error::DEBUG_WARNING ) { #if defined(__RTMIDI_DEBUG__) - std::cerr << '\n' << errorString << "\n\n"; + std::cerr << '\n' << errorString << "\n\n"; #endif - } - else { - std::cerr << '\n' << errorString << "\n\n"; - throw RtMidiError( errorString, type ); - } -} + } + else { + std::cerr << '\n' << errorString << "\n\n"; + throw Error( errorString, type ); + } + } -//*********************************************************************// -// Common MidiInApi Definitions -//*********************************************************************// - -MidiInApi :: MidiInApi( unsigned int queueSizeLimit ) - : MidiApi() -{ - // Allocate the MIDI queue. - inputData_.queue.ringSize = queueSizeLimit; - if ( inputData_.queue.ringSize > 0 ) - inputData_.queue.ring = new MidiMessage[ inputData_.queue.ringSize ]; -} + //*********************************************************************// + // Common MidiInApi Definitions + //*********************************************************************// + + MidiInApi :: MidiInApi( unsigned int queueSizeLimit ) + : MidiApi() + { + // Allocate the MIDI queue. + inputData_.queue.ringSize = queueSizeLimit; + if ( inputData_.queue.ringSize > 0 ) + inputData_.queue.ring = new MidiMessage[ inputData_.queue.ringSize ]; + } -MidiInApi :: ~MidiInApi( void ) -{ - // Delete the MIDI queue. - if ( inputData_.queue.ringSize > 0 ) delete [] inputData_.queue.ring; -} + MidiInApi :: ~MidiInApi( void ) + { + // Delete the MIDI queue. + if ( inputData_.queue.ringSize > 0 ) delete [] inputData_.queue.ring; + } -void MidiInApi :: setCallback( RtMidiIn::RtMidiCallback callback, void *userData ) -{ - if ( inputData_.usingCallback ) { - errorString_ = "MidiInApi::setCallback: a callback function is already set!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - if ( !callback ) { - errorString_ = "RtMidiIn::setCallback: callback function value is invalid!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - inputData_.userCallback = callback; - inputData_.userData = userData; - inputData_.usingCallback = true; -} + void MidiInApi :: setCallback( MidiCallback callback, void *userData ) + { + if ( inputData_.usingCallback ) { + errorString_ = "MidiInApi::setCallback: a callback function is already set!"; + error( Error::WARNING, errorString_ ); + return; + } + + if ( !callback ) { + errorString_ = "MidiIn::setCallback: callback function value is invalid!"; + error( Error::WARNING, errorString_ ); + return; + } + + inputData_.userCallback = callback; + inputData_.userData = userData; + inputData_.usingCallback = true; + } -void MidiInApi :: cancelCallback() -{ - if ( !inputData_.usingCallback ) { - errorString_ = "RtMidiIn::cancelCallback: no callback function was set!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - inputData_.userCallback = 0; - inputData_.userData = 0; - inputData_.usingCallback = false; -} + void MidiInApi :: cancelCallback() + { + if ( !inputData_.usingCallback ) { + errorString_ = "MidiIn::cancelCallback: no callback function was set!"; + error( Error::WARNING, errorString_ ); + return; + } + + inputData_.userCallback = 0; + inputData_.userData = 0; + inputData_.usingCallback = false; + } -void MidiInApi :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) -{ - inputData_.ignoreFlags = 0; - if ( midiSysex ) inputData_.ignoreFlags = 0x01; - if ( midiTime ) inputData_.ignoreFlags |= 0x02; - if ( midiSense ) inputData_.ignoreFlags |= 0x04; -} + void MidiInApi :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) + { + inputData_.ignoreFlags = 0; + if ( midiSysex ) inputData_.ignoreFlags = 0x01; + if ( midiTime ) inputData_.ignoreFlags |= 0x02; + if ( midiSense ) inputData_.ignoreFlags |= 0x04; + } -double MidiInApi :: getMessage( std::vector *message ) -{ - message->clear(); + double MidiInApi :: getMessage( std::vector &message ) + { + message.clear(); - if ( inputData_.usingCallback ) { - errorString_ = "RtMidiIn::getNextMessage: a user callback is currently set for this port."; - error( RtMidiError::WARNING, errorString_ ); - return 0.0; - } + if ( inputData_.usingCallback ) { + errorString_ = "MidiIn::getMessage: a user callback is currently set for this port."; + error( Error::WARNING, errorString_ ); + return 0.0; + } - if ( inputData_.queue.size == 0 ) return 0.0; + if ( inputData_.queue.size == 0 ) return 0.0; - // Copy queued message to the vector pointer argument and then "pop" it. - std::vector *bytes = &(inputData_.queue.ring[inputData_.queue.front].bytes); - message->assign( bytes->begin(), bytes->end() ); - double deltaTime = inputData_.queue.ring[inputData_.queue.front].timeStamp; - inputData_.queue.size--; - inputData_.queue.front++; - if ( inputData_.queue.front == inputData_.queue.ringSize ) - inputData_.queue.front = 0; + // Copy queued message to the vector pointer argument and then "pop" it. + std::vector *bytes = &(inputData_.queue.ring[inputData_.queue.front].bytes); + message.assign( bytes->begin(), bytes->end() ); + double deltaTime = inputData_.queue.ring[inputData_.queue.front].timeStamp; + inputData_.queue.size--; + inputData_.queue.front++; + if ( inputData_.queue.front == inputData_.queue.ringSize ) + inputData_.queue.front = 0; - return deltaTime; -} + return deltaTime; + } -//*********************************************************************// -// Common MidiOutApi Definitions -//*********************************************************************// + //*********************************************************************// + // Common MidiOutApi Definitions + //*********************************************************************// -MidiOutApi :: MidiOutApi( void ) - : MidiApi() -{ -} + MidiOutApi :: MidiOutApi( void ) + : MidiApi() + { + } -MidiOutApi :: ~MidiOutApi( void ) -{ -} + MidiOutApi :: ~MidiOutApi( void ) + { + } -// *************************************************** // -// -// OS/API-specific methods. -// -// *************************************************** // + // *************************************************** // + // + // OS/API-specific methods. + // + // *************************************************** // +} #if defined(__MACOSX_CORE__) -// The CoreMIDI API is based on the use of a callback function for -// MIDI input. We convert the system specific time stamps to delta -// time values. + // The CoreMIDI API is based on the use of a callback function for + // MIDI input. We convert the system specific time stamps to delta + // time values. -// OS-X CoreMIDI header files. + // OS-X CoreMIDI header files. #include #include #include -// A structure to hold variables related to the CoreMIDI API -// implementation. -struct CoreMidiData { - MIDIClientRef client; - MIDIPortRef port; - MIDIEndpointRef endpoint; - MIDIEndpointRef destinationId; - unsigned long long lastTime; - MIDISysexSendRequest sysexreq; -}; - -//*********************************************************************// -// API: OS-X -// Class Definitions: MidiInCore -//*********************************************************************// - -static void midiInputCallback( const MIDIPacketList *list, void *procRef, void */*srcRef*/ ) -{ - MidiInApi::RtMidiInData *data = static_cast (procRef); - CoreMidiData *apiData = static_cast (data->apiData); - - unsigned char status; - unsigned short nBytes, iByte, size; - unsigned long long time; - - bool& continueSysex = data->continueSysex; - MidiInApi::MidiMessage& message = data->message; - - const MIDIPacket *packet = &list->packet[0]; - for ( unsigned int i=0; inumPackets; ++i ) { - - // My interpretation of the CoreMIDI documentation: all message - // types, except sysex, are complete within a packet and there may - // be several of them in a single packet. Sysex messages can be - // broken across multiple packets and PacketLists but are bundled - // alone within each packet (these packets do not contain other - // message types). If sysex messages are split across multiple - // MIDIPacketLists, they must be handled by multiple calls to this - // function. - - nBytes = packet->length; - if ( nBytes == 0 ) continue; - - // Calculate time stamp. - - if ( data->firstMessage ) { - message.timeStamp = 0.0; - data->firstMessage = false; - } - else { - time = packet->timeStamp; - if ( time == 0 ) { // this happens when receiving asynchronous sysex messages - time = AudioGetCurrentHostTime(); - } - time -= apiData->lastTime; - time = AudioConvertHostTimeToNanos( time ); - 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; - - iByte = 0; - if ( continueSysex ) { - // We have a continuing, segmented sysex message. - if ( !( data->ignoreFlags & 0x01 ) ) { - // If we're not ignoring sysex messages, copy the entire packet. - for ( unsigned int j=0; jdata[j] ); - } - continueSysex = packet->data[nBytes-1] != 0xF7; - - if ( !( data->ignoreFlags & 0x01 ) && !continueSysex ) { - // If not a continuing sysex message, invoke the user callback function or queue the message. - if ( data->usingCallback ) { - RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; - callback( message.timeStamp, &message.bytes, data->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else - std::cerr << "\nMidiInCore: message queue limit reached!!\n\n"; - } - message.bytes.clear(); - } - } - else { - while ( iByte < nBytes ) { - size = 0; - // We are expecting that the next byte in the packet is a status byte. - status = packet->data[iByte]; - if ( !(status & 0x80) ) break; - // Determine the number of bytes in the MIDI message. - if ( status < 0xC0 ) size = 3; - else if ( status < 0xE0 ) size = 2; - else if ( status < 0xF0 ) size = 3; - else if ( status == 0xF0 ) { - // A MIDI sysex - if ( data->ignoreFlags & 0x01 ) { - size = 0; - iByte = nBytes; - } - else size = nBytes - iByte; - continueSysex = packet->data[nBytes-1] != 0xF7; - } - else if ( status == 0xF1 ) { - // A MIDI time code message - if ( data->ignoreFlags & 0x02 ) { - size = 0; - iByte += 2; - } - else size = 2; - } - else if ( status == 0xF2 ) size = 3; - else if ( status == 0xF3 ) size = 2; - else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) { - // A MIDI timing tick message and we're ignoring it. - size = 0; - iByte += 1; - } - else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) { - // A MIDI active sensing message and we're ignoring it. - size = 0; - iByte += 1; - } - else size = 1; - - // Copy the MIDI data to our vector. - if ( size ) { - 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. - if ( data->usingCallback ) { - RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; - callback( message.timeStamp, &message.bytes, data->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else - std::cerr << "\nMidiInCore: message queue limit reached!!\n\n"; - } - message.bytes.clear(); - } - iByte += size; - } - } - } - packet = MIDIPacketNext(packet); - } -} -MidiInCore :: MidiInCore( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) -{ - initialize( clientName ); -} +namespace rtmidi { + // A structure to hold variables related to the CoreMIDI API + // implementation. + struct CoreMidiData { + MIDIClientRef client; + MIDIPortRef port; + MIDIEndpointRef endpoint; + MIDIEndpointRef destinationId; + unsigned long long lastTime; + MIDISysexSendRequest sysexreq; + }; + + //*********************************************************************// + // API: OS-X + // Class Definitions: MidiInCore + //*********************************************************************// + + static void midiInputCallback( const MIDIPacketList *list, void *procRef, void */*srcRef*/ ) + { + MidiInApi::MidiInData *data = static_cast (procRef); + CoreMidiData *apiData = static_cast (data->apiData); + + unsigned char status; + unsigned short nBytes, iByte, size; + unsigned long long time; + + bool& continueSysex = data->continueSysex; + MidiInApi::MidiMessage& message = data->message; + + const MIDIPacket *packet = &list->packet[0]; + for ( unsigned int i=0; inumPackets; ++i ) { + + // My interpretation of the CoreMIDI documentation: all message + // types, except sysex, are complete within a packet and there may + // be several of them in a single packet. Sysex messages can be + // broken across multiple packets and PacketLists but are bundled + // alone within each packet (these packets do not contain other + // message types). If sysex messages are split across multiple + // MIDIPacketLists, they must be handled by multiple calls to this + // function. + + nBytes = packet->length; + if ( nBytes == 0 ) continue; + + // Calculate time stamp. + + if ( data->firstMessage ) { + message.timeStamp = 0.0; + data->firstMessage = false; + } + else { + time = packet->timeStamp; + if ( time == 0 ) { // this happens when receiving asynchronous sysex messages + time = AudioGetCurrentHostTime(); + } + time -= apiData->lastTime; + time = AudioConvertHostTimeToNanos( time ); + 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; + + iByte = 0; + if ( continueSysex ) { + // We have a continuing, segmented sysex message. + if ( !( data->ignoreFlags & 0x01 ) ) { + // If we're not ignoring sysex messages, copy the entire packet. + for ( unsigned int j=0; jdata[j] ); + } + continueSysex = packet->data[nBytes-1] != 0xF7; + + if ( !( data->ignoreFlags & 0x01 ) ) { + if ( !continueSysex ) { + // If not a continuing sysex message, invoke the user callback function or queue the message. + if ( data->usingCallback ) { + MidiCallback callback = (MidiCallback) data->userCallback; + callback( message.timeStamp, &message.bytes, data->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else + std::cerr << "\nMidiInCore: message queue limit reached!!\n\n"; + } + message.bytes.clear(); + } + } + } + else { + while ( iByte < nBytes ) { + size = 0; + // We are expecting that the next byte in the packet is a status byte. + status = packet->data[iByte]; + if ( !(status & 0x80) ) break; + // Determine the number of bytes in the MIDI message. + if ( status < 0xC0 ) size = 3; + else if ( status < 0xE0 ) size = 2; + else if ( status < 0xF0 ) size = 3; + else if ( status == 0xF0 ) { + // A MIDI sysex + if ( data->ignoreFlags & 0x01 ) { + size = 0; + iByte = nBytes; + } + else size = nBytes - iByte; + continueSysex = packet->data[nBytes-1] != 0xF7; + } + else if ( status == 0xF1 ) { + // A MIDI time code message + if ( data->ignoreFlags & 0x02 ) { + size = 0; + iByte += 2; + } + else size = 2; + } + else if ( status == 0xF2 ) size = 3; + else if ( status == 0xF3 ) size = 2; + else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) { + // A MIDI timing tick message and we're ignoring it. + size = 0; + iByte += 1; + } + else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) { + // A MIDI active sensing message and we're ignoring it. + size = 0; + iByte += 1; + } + else size = 1; + + // Copy the MIDI data to our vector. + if ( size ) { + 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. + if ( data->usingCallback ) { + MidiCallback callback = (MidiCallback) data->userCallback; + callback( message.timeStamp, &message.bytes, data->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else + std::cerr << "\nMidiInCore: message queue limit reached!!\n\n"; + } + message.bytes.clear(); + } + iByte += size; + } + } + } + packet = MIDIPacketNext(packet); + } + } -MidiInCore :: ~MidiInCore( void ) -{ - // Close a connection if it exists. - closePort(); + MidiInCore :: MidiInCore( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) + { + initialize( clientName ); + } - // Cleanup. - CoreMidiData *data = static_cast (apiData_); - MIDIClientDispose( data->client ); - if ( data->endpoint ) MIDIEndpointDispose( data->endpoint ); - delete data; -} + MidiInCore :: ~MidiInCore( void ) + { + // Close a connection if it exists. + closePort(); -void MidiInCore :: initialize( const std::string& clientName ) -{ - // Set up our client. - MIDIClientRef client; - OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client ); - if ( result != noErr ) { - errorString_ = "MidiInCore::initialize: error creating OS-X MIDI client object."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Save our api-specific connection information. - CoreMidiData *data = (CoreMidiData *) new CoreMidiData; - data->client = client; - data->endpoint = 0; - apiData_ = (void *) data; - inputData_.apiData = (void *) data; -} + // Cleanup. + CoreMidiData *data = static_cast (apiData_); + MIDIClientDispose( data->client ); + if ( data->endpoint ) MIDIEndpointDispose( data->endpoint ); + delete data; + } -void MidiInCore :: openPort( unsigned int portNumber, const std::string portName ) -{ - if ( connected_ ) { - errorString_ = "MidiInCore::openPort: a valid connection already exists!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - unsigned int nSrc = MIDIGetNumberOfSources(); - if (nSrc < 1) { - errorString_ = "MidiInCore::openPort: no MIDI input sources found!"; - error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); - return; - } - - if ( portNumber >= nSrc ) { - std::ostringstream ost; - ost << "MidiInCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::INVALID_PARAMETER, errorString_ ); - return; - } - - MIDIPortRef port; - CoreMidiData *data = static_cast (apiData_); - OSStatus result = MIDIInputPortCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), - midiInputCallback, (void *)&inputData_, &port ); - if ( result != noErr ) { - MIDIClientDispose( data->client ); - errorString_ = "MidiInCore::openPort: error creating OS-X MIDI input port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Get the desired input source identifier. - MIDIEndpointRef endpoint = MIDIGetSource( portNumber ); - if ( endpoint == 0 ) { - MIDIPortDispose( port ); - MIDIClientDispose( data->client ); - errorString_ = "MidiInCore::openPort: error getting MIDI input source reference."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Make the connection. - result = MIDIPortConnectSource( port, endpoint, NULL ); - if ( result != noErr ) { - MIDIPortDispose( port ); - MIDIClientDispose( data->client ); - errorString_ = "MidiInCore::openPort: error connecting OS-X MIDI input port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Save our api-specific port information. - data->port = port; - - connected_ = true; -} + void MidiInCore :: initialize( const std::string& clientName ) + { + // Set up our client. + MIDIClientRef client; + OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client ); + if ( result != noErr ) { + errorString_ = "MidiInCore::initialize: error creating OS-X MIDI client object."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Save our api-specific connection information. + CoreMidiData *data = (CoreMidiData *) new CoreMidiData; + data->client = client; + data->endpoint = 0; + apiData_ = (void *) data; + inputData_.apiData = (void *) data; + } -void MidiInCore :: openVirtualPort( const std::string portName ) -{ - CoreMidiData *data = static_cast (apiData_); - - // Create a virtual MIDI input destination. - MIDIEndpointRef endpoint; - OSStatus result = MIDIDestinationCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), - midiInputCallback, (void *)&inputData_, &endpoint ); - if ( result != noErr ) { - errorString_ = "MidiInCore::openVirtualPort: error creating virtual OS-X MIDI destination."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Save our api-specific connection information. - data->endpoint = endpoint; -} + void MidiInCore :: openPort( unsigned int portNumber, const std::string portName ) + { + if ( connected_ ) { + errorString_ = "MidiInCore::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + unsigned int nSrc = MIDIGetNumberOfSources(); + if (nSrc < 1) { + errorString_ = "MidiInCore::openPort: no MIDI input sources found!"; + error( Error::NO_DEVICES_FOUND, errorString_ ); + return; + } + + if ( portNumber >= nSrc ) { + std::ostringstream ost; + ost << "MidiInCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::INVALID_PARAMETER, errorString_ ); + return; + } + + MIDIPortRef port; + CoreMidiData *data = static_cast (apiData_); + OSStatus result = MIDIInputPortCreate( data->client, + CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), + midiInputCallback, (void *)&inputData_, &port ); + if ( result != noErr ) { + MIDIClientDispose( data->client ); + errorString_ = "MidiInCore::openPort: error creating OS-X MIDI input port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Get the desired input source identifier. + MIDIEndpointRef endpoint = MIDIGetSource( portNumber ); + if ( endpoint == 0 ) { + MIDIPortDispose( port ); + MIDIClientDispose( data->client ); + errorString_ = "MidiInCore::openPort: error getting MIDI input source reference."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Make the connection. + result = MIDIPortConnectSource( port, endpoint, NULL ); + if ( result != noErr ) { + MIDIPortDispose( port ); + MIDIClientDispose( data->client ); + errorString_ = "MidiInCore::openPort: error connecting OS-X MIDI input port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Save our api-specific port information. + data->port = port; + + connected_ = true; + } -void MidiInCore :: closePort( void ) -{ - if ( connected_ ) { - CoreMidiData *data = static_cast (apiData_); - MIDIPortDispose( data->port ); - connected_ = false; - } -} + void MidiInCore :: openVirtualPort( const std::string portName ) + { + CoreMidiData *data = static_cast (apiData_); + + // Create a virtual MIDI input destination. + MIDIEndpointRef endpoint; + OSStatus result = MIDIDestinationCreate( data->client, + CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), + midiInputCallback, (void *)&inputData_, &endpoint ); + if ( result != noErr ) { + errorString_ = "MidiInCore::openVirtualPort: error creating virtual OS-X MIDI destination."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Save our api-specific connection information. + data->endpoint = endpoint; + } -unsigned int MidiInCore :: getPortCount() -{ - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - return MIDIGetNumberOfSources(); -} + void MidiInCore :: closePort( void ) + { + if ( connected_ ) { + CoreMidiData *data = static_cast (apiData_); + MIDIPortDispose( data->port ); + connected_ = false; + } + } -// This function was submitted by Douglas Casey Tucker and apparently -// derived largely from PortMidi. -CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal ) -{ - CFMutableStringRef result = CFStringCreateMutable( NULL, 0 ); - CFStringRef str; - - // Begin with the endpoint's name. - str = NULL; - MIDIObjectGetStringProperty( endpoint, kMIDIPropertyName, &str ); - if ( str != NULL ) { - CFStringAppend( result, str ); - CFRelease( str ); - } - - MIDIEntityRef entity = 0; - MIDIEndpointGetEntity( endpoint, &entity ); - if ( entity == 0 ) - // probably virtual - return result; - - if ( CFStringGetLength( result ) == 0 ) { - // endpoint name has zero length -- try the entity - str = NULL; - MIDIObjectGetStringProperty( entity, kMIDIPropertyName, &str ); - if ( str != NULL ) { - CFStringAppend( result, str ); - CFRelease( str ); - } - } - // now consider the device's name - MIDIDeviceRef device = 0; - MIDIEntityGetDevice( entity, &device ); - if ( device == 0 ) - return result; - - str = NULL; - MIDIObjectGetStringProperty( device, kMIDIPropertyName, &str ); - if ( CFStringGetLength( result ) == 0 ) { - CFRelease( result ); - return str; - } - if ( str != NULL ) { - // if an external device has only one entity, throw away - // the endpoint name and just use the device name - if ( isExternal && MIDIDeviceGetNumberOfEntities( device ) < 2 ) { - CFRelease( result ); - return str; - } else { - if ( CFStringGetLength( str ) == 0 ) { - CFRelease( str ); - return result; - } - // does the entity name already start with the device name? - // (some drivers do this though they shouldn't) - // if so, do not prepend - if ( CFStringCompareWithOptions( result, /* endpoint name */ - str /* device name */, - CFRangeMake(0, CFStringGetLength( str ) ), 0 ) != kCFCompareEqualTo ) { - // prepend the device name to the entity name - if ( CFStringGetLength( result ) > 0 ) - CFStringInsert( result, 0, CFSTR(" ") ); - CFStringInsert( result, 0, str ); - } - CFRelease( str ); - } - } - return result; -} + unsigned int MidiInCore :: getPortCount() + { + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + return MIDIGetNumberOfSources(); + } -// This function was submitted by Douglas Casey Tucker and apparently -// derived largely from PortMidi. -static CFStringRef ConnectedEndpointName( MIDIEndpointRef endpoint ) -{ - CFMutableStringRef result = CFStringCreateMutable( NULL, 0 ); - CFStringRef str; - OSStatus err; - int i; - - // Does the endpoint have connections? - CFDataRef connections = NULL; - int nConnected = 0; - bool anyStrings = false; - err = MIDIObjectGetDataProperty( endpoint, kMIDIPropertyConnectionUniqueID, &connections ); - if ( connections != NULL ) { - // It has connections, follow them - // Concatenate the names of all connected devices - nConnected = CFDataGetLength( connections ) / sizeof(MIDIUniqueID); - if ( nConnected ) { - const SInt32 *pid = (const SInt32 *)(CFDataGetBytePtr(connections)); - for ( i=0; i 0 ) + CFStringInsert( result, 0, CFSTR(" ") ); + CFStringInsert( result, 0, str ); + } + CFRelease( str ); + } + } + return result; + } -std::string MidiInCore :: getPortName( unsigned int portNumber ) -{ - CFStringRef nameRef; - MIDIEndpointRef portRef; - char name[128]; - - std::string stringName; - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - if ( portNumber >= MIDIGetNumberOfSources() ) { - std::ostringstream ost; - ost << "MidiInCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return stringName; - } - - portRef = MIDIGetSource( portNumber ); - nameRef = ConnectedEndpointName(portRef); - CFStringGetCString( nameRef, name, sizeof(name), CFStringGetSystemEncoding()); - CFRelease( nameRef ); - - return stringName = name; -} + // This function was submitted by Douglas Casey Tucker and apparently + // derived largely from PortMidi. + static CFStringRef ConnectedEndpointName( MIDIEndpointRef endpoint ) + { + CFMutableStringRef result = CFStringCreateMutable( NULL, 0 ); + CFStringRef str; + OSStatus err; + int i; + + // Does the endpoint have connections? + CFDataRef connections = NULL; + int nConnected = 0; + bool anyStrings = false; + err = MIDIObjectGetDataProperty( endpoint, kMIDIPropertyConnectionUniqueID, &connections ); + if ( connections != NULL ) { + // It has connections, follow them + // Concatenate the names of all connected devices + nConnected = CFDataGetLength( connections ) / sizeof(MIDIUniqueID); + if ( nConnected ) { + const SInt32 *pid = (const SInt32 *)(CFDataGetBytePtr(connections)); + for ( i=0; i= MIDIGetNumberOfSources() ) { + std::ostringstream ost; + ost << "MidiInCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::WARNING, errorString_ ); + return stringName; + } + + portRef = MIDIGetSource( portNumber ); + nameRef = ConnectedEndpointName(portRef); + CFStringGetCString( nameRef, name, sizeof(name), CFStringGetSystemEncoding()); + CFRelease( nameRef ); + + return stringName = name; + } -MidiOutCore :: MidiOutCore( const std::string clientName ) : MidiOutApi() -{ - initialize( clientName ); -} + //*********************************************************************// + // API: OS-X + // Class Definitions: MidiOutCore + //*********************************************************************// -MidiOutCore :: ~MidiOutCore( void ) -{ - // Close a connection if it exists. - closePort(); + MidiOutCore :: MidiOutCore( const std::string clientName ) : MidiOutApi() + { + initialize( clientName ); + } - // Cleanup. - CoreMidiData *data = static_cast (apiData_); - MIDIClientDispose( data->client ); - if ( data->endpoint ) MIDIEndpointDispose( data->endpoint ); - delete data; -} + MidiOutCore :: ~MidiOutCore( void ) + { + // Close a connection if it exists. + closePort(); -void MidiOutCore :: initialize( const std::string& clientName ) -{ - // Set up our client. - MIDIClientRef client; - OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client ); - if ( result != noErr ) { - errorString_ = "MidiOutCore::initialize: error creating OS-X MIDI client object."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Save our api-specific connection information. - CoreMidiData *data = (CoreMidiData *) new CoreMidiData; - data->client = client; - data->endpoint = 0; - apiData_ = (void *) data; -} + // Cleanup. + CoreMidiData *data = static_cast (apiData_); + MIDIClientDispose( data->client ); + if ( data->endpoint ) MIDIEndpointDispose( data->endpoint ); + delete data; + } -unsigned int MidiOutCore :: getPortCount() -{ - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - return MIDIGetNumberOfDestinations(); -} + void MidiOutCore :: initialize( const std::string& clientName ) + { + // Set up our client. + MIDIClientRef client; + OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client ); + if ( result != noErr ) { + errorString_ = "MidiOutCore::initialize: error creating OS-X MIDI client object."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Save our api-specific connection information. + CoreMidiData *data = (CoreMidiData *) new CoreMidiData; + data->client = client; + data->endpoint = 0; + apiData_ = (void *) data; + } + + unsigned int MidiOutCore :: getPortCount() + { + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + return MIDIGetNumberOfDestinations(); + } -std::string MidiOutCore :: getPortName( unsigned int portNumber ) -{ - CFStringRef nameRef; - MIDIEndpointRef portRef; - char name[128]; - - std::string stringName; - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - if ( portNumber >= MIDIGetNumberOfDestinations() ) { - std::ostringstream ost; - ost << "MidiOutCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return stringName; - } - - portRef = MIDIGetDestination( portNumber ); - nameRef = ConnectedEndpointName(portRef); - CFStringGetCString( nameRef, name, sizeof(name), CFStringGetSystemEncoding()); - CFRelease( nameRef ); + std::string MidiOutCore :: getPortName( unsigned int portNumber ) + { + CFStringRef nameRef; + MIDIEndpointRef portRef; + char name[128]; + + std::string stringName; + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + if ( portNumber >= MIDIGetNumberOfDestinations() ) { + std::ostringstream ost; + ost << "MidiOutCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::WARNING, errorString_ ); + return stringName; + } + + portRef = MIDIGetDestination( portNumber ); + nameRef = ConnectedEndpointName(portRef); + CFStringGetCString( nameRef, name, sizeof(name), CFStringGetSystemEncoding()); + CFRelease( nameRef ); - return stringName = name; -} + return stringName = name; + } -void MidiOutCore :: openPort( unsigned int portNumber, const std::string portName ) -{ - if ( connected_ ) { - errorString_ = "MidiOutCore::openPort: a valid connection already exists!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - unsigned int nDest = MIDIGetNumberOfDestinations(); - if (nDest < 1) { - errorString_ = "MidiOutCore::openPort: no MIDI output destinations found!"; - error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); - return; - } - - if ( portNumber >= nDest ) { - std::ostringstream ost; - ost << "MidiOutCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::INVALID_PARAMETER, errorString_ ); - return; - } - - MIDIPortRef port; - CoreMidiData *data = static_cast (apiData_); - OSStatus result = MIDIOutputPortCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), - &port ); - if ( result != noErr ) { - MIDIClientDispose( data->client ); - errorString_ = "MidiOutCore::openPort: error creating OS-X MIDI output port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Get the desired output port identifier. - MIDIEndpointRef destination = MIDIGetDestination( portNumber ); - if ( destination == 0 ) { - MIDIPortDispose( port ); - MIDIClientDispose( data->client ); - errorString_ = "MidiOutCore::openPort: error getting MIDI output destination reference."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Save our api-specific connection information. - data->port = port; - data->destinationId = destination; - connected_ = true; -} + void MidiOutCore :: openPort( unsigned int portNumber, const std::string portName ) + { + if ( connected_ ) { + errorString_ = "MidiOutCore::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + unsigned int nDest = MIDIGetNumberOfDestinations(); + if (nDest < 1) { + errorString_ = "MidiOutCore::openPort: no MIDI output destinations found!"; + error( Error::NO_DEVICES_FOUND, errorString_ ); + return; + } + + if ( portNumber >= nDest ) { + std::ostringstream ost; + ost << "MidiOutCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::INVALID_PARAMETER, errorString_ ); + return; + } + + MIDIPortRef port; + CoreMidiData *data = static_cast (apiData_); + OSStatus result = MIDIOutputPortCreate( data->client, + CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), + &port ); + if ( result != noErr ) { + MIDIClientDispose( data->client ); + errorString_ = "MidiOutCore::openPort: error creating OS-X MIDI output port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Get the desired output port identifier. + MIDIEndpointRef destination = MIDIGetDestination( portNumber ); + if ( destination == 0 ) { + MIDIPortDispose( port ); + MIDIClientDispose( data->client ); + errorString_ = "MidiOutCore::openPort: error getting MIDI output destination reference."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Save our api-specific connection information. + data->port = port; + data->destinationId = destination; + connected_ = true; + } -void MidiOutCore :: closePort( void ) -{ - if ( connected_ ) { - CoreMidiData *data = static_cast (apiData_); - MIDIPortDispose( data->port ); - connected_ = false; - } -} + void MidiOutCore :: closePort( void ) + { + if ( connected_ ) { + CoreMidiData *data = static_cast (apiData_); + MIDIPortDispose( data->port ); + connected_ = false; + } + } -void MidiOutCore :: openVirtualPort( std::string portName ) -{ - CoreMidiData *data = static_cast (apiData_); - - if ( data->endpoint ) { - errorString_ = "MidiOutCore::openVirtualPort: a virtual output port already exists!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - // Create a virtual MIDI output source. - MIDIEndpointRef endpoint; - OSStatus result = MIDISourceCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), - &endpoint ); - if ( result != noErr ) { - errorString_ = "MidiOutCore::initialize: error creating OS-X virtual MIDI source."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Save our api-specific connection information. - data->endpoint = endpoint; -} + void MidiOutCore :: openVirtualPort( std::string portName ) + { + CoreMidiData *data = static_cast (apiData_); + + if ( data->endpoint ) { + errorString_ = "MidiOutCore::openVirtualPort: a virtual output port already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + + // Create a virtual MIDI output source. + MIDIEndpointRef endpoint; + OSStatus result = MIDISourceCreate( data->client, + CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), + &endpoint ); + if ( result != noErr ) { + errorString_ = "MidiOutCore::initialize: error creating OS-X virtual MIDI source."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Save our api-specific connection information. + data->endpoint = endpoint; + } -// Not necessary if we don't treat sysex messages any differently than -// normal messages ... see below. -//static void sysexCompletionProc( MIDISysexSendRequest *sreq ) -//{ -// free( sreq ); -//} - -void MidiOutCore :: sendMessage( std::vector *message ) -{ - // We use the MIDISendSysex() function to asynchronously send sysex - // messages. Otherwise, we use a single CoreMidi MIDIPacket. - unsigned int nBytes = message->size(); - if ( nBytes == 0 ) { - errorString_ = "MidiOutCore::sendMessage: no data in message argument!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - // unsigned int packetBytes, bytesLeft = nBytes; - // unsigned int messageIndex = 0; - MIDITimeStamp timeStamp = AudioGetCurrentHostTime(); - CoreMidiData *data = static_cast (apiData_); - OSStatus result; - - /* - // I don't think this code is necessary. We can send sysex - // messages through the normal mechanism. In addition, this avoids - // the problem of virtual ports not receiving sysex messages. - - if ( message->at(0) == 0xF0 ) { - - // Apple's fantastic API requires us to free the allocated data in - // the completion callback but trashes the pointer and size before - // we get a chance to free it!! This is a somewhat ugly hack - // submitted by ptarabbia that puts the sysex buffer data right at - // the end of the MIDISysexSendRequest structure. This solution - // does not require that we wait for a previous sysex buffer to be - // sent before sending a new one, which was the old way we did it. - MIDISysexSendRequest *newRequest = (MIDISysexSendRequest *) malloc(sizeof(struct MIDISysexSendRequest) + nBytes); - char * sysexBuffer = ((char *) newRequest) + sizeof(struct MIDISysexSendRequest); - - // Copy data to buffer. - for ( unsigned int i=0; iat(i); - - newRequest->destination = data->destinationId; - newRequest->data = (Byte *)sysexBuffer; - newRequest->bytesToSend = nBytes; - newRequest->complete = 0; - newRequest->completionProc = sysexCompletionProc; - newRequest->completionRefCon = newRequest; - - result = MIDISendSysex(newRequest); - if ( result != noErr ) { - free( newRequest ); - errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; - error( RtMidiError::WARNING, errorString_ ); - return; - } - return; - } - else if ( nBytes > 3 ) { - errorString_ = "MidiOutCore::sendMessage: message format problem ... not sysex but > 3 bytes?"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - */ - - MIDIPacketList packetList; - MIDIPacket *packet = MIDIPacketListInit( &packetList ); - packet = MIDIPacketListAdd( &packetList, sizeof(packetList), packet, timeStamp, nBytes, (const Byte *) &message->at( 0 ) ); - if ( !packet ) { - errorString_ = "MidiOutCore::sendMessage: could not allocate packet list"; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Send to any destinations that may have connected to us. - if ( data->endpoint ) { - result = MIDIReceived( data->endpoint, &packetList ); - if ( result != noErr ) { - errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; - error( RtMidiError::WARNING, errorString_ ); - } - } - - // And send to an explicit destination port if we're connected. - if ( connected_ ) { - result = MIDISend( data->port, data->destinationId, &packetList ); - if ( result != noErr ) { - errorString_ = "MidiOutCore::sendMessage: error sending MIDI message to port."; - error( RtMidiError::WARNING, errorString_ ); - } - } + // Not necessary if we don't treat sysex messages any differently than + // normal messages ... see below. + //static void sysexCompletionProc( MIDISysexSendRequest *sreq ) + //{ + // free( sreq ); + //} + + void MidiOutCore :: sendMessage( std::vector *message ) + { + // We use the MIDISendSysex() function to asynchronously send sysex + // messages. Otherwise, we use a single CoreMidi MIDIPacket. + unsigned int nBytes = message->size(); + if ( nBytes == 0 ) { + errorString_ = "MidiOutCore::sendMessage: no data in message argument!"; + error( Error::WARNING, errorString_ ); + return; + } + + // unsigned int packetBytes, bytesLeft = nBytes; + // unsigned int messageIndex = 0; + MIDITimeStamp timeStamp = AudioGetCurrentHostTime(); + CoreMidiData *data = static_cast (apiData_); + OSStatus result; + + /* + // I don't think this code is necessary. We can send sysex + // messages through the normal mechanism. In addition, this avoids + // the problem of virtual ports not receiving sysex messages. + + if ( message->at(0) == 0xF0 ) { + + // Apple's fantastic API requires us to free the allocated data in + // the completion callback but trashes the pointer and size before + // we get a chance to free it!! This is a somewhat ugly hack + // submitted by ptarabbia that puts the sysex buffer data right at + // the end of the MIDISysexSendRequest structure. This solution + // does not require that we wait for a previous sysex buffer to be + // sent before sending a new one, which was the old way we did it. + MIDISysexSendRequest *newRequest = (MIDISysexSendRequest *) malloc(sizeof(struct MIDISysexSendRequest) + nBytes); + char * sysexBuffer = ((char *) newRequest) + sizeof(struct MIDISysexSendRequest); + + // Copy data to buffer. + for ( unsigned int i=0; iat(i); + + newRequest->destination = data->destinationId; + newRequest->data = (Byte *)sysexBuffer; + newRequest->bytesToSend = nBytes; + newRequest->complete = 0; + newRequest->completionProc = sysexCompletionProc; + newRequest->completionRefCon = newRequest; + + result = MIDISendSysex(newRequest); + if ( result != noErr ) { + free( newRequest ); + errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; + error( Error::WARNING, errorString_ ); + return; + } + return; + } + else if ( nBytes > 3 ) { + errorString_ = "MidiOutCore::sendMessage: message format problem ... not sysex but > 3 bytes?"; + error( Error::WARNING, errorString_ ); + return; + } + */ + + MIDIPacketList packetList; + MIDIPacket *packet = MIDIPacketListInit( &packetList ); + packet = MIDIPacketListAdd( &packetList, sizeof(packetList), packet, timeStamp, nBytes, (const Byte *) &message->at( 0 ) ); + if ( !packet ) { + errorString_ = "MidiOutCore::sendMessage: could not allocate packet list"; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Send to any destinations that may have connected to us. + if ( data->endpoint ) { + result = MIDIReceived( data->endpoint, &packetList ); + if ( result != noErr ) { + errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; + error( Error::WARNING, errorString_ ); + } + } + + // And send to an explicit destination port if we're connected. + if ( connected_ ) { + result = MIDISend( data->port, data->destinationId, &packetList ); + if ( result != noErr ) { + errorString_ = "MidiOutCore::sendMessage: error sending MIDI message to port."; + error( Error::WARNING, errorString_ ); + } + } + } } - #endif // __MACOSX_CORE__ -//*********************************************************************// -// API: LINUX ALSA SEQUENCER -//*********************************************************************// + //*********************************************************************// + // API: LINUX ALSA SEQUENCER + //*********************************************************************// -// API information found at: -// - http://www.alsa-project.org/documentation.php#Library + // API information found at: + // - http://www.alsa-project.org/documentation.php#Library #if defined(__LINUX_ALSA__) -// The ALSA Sequencer API is based on the use of a callback function for -// MIDI input. -// -// Thanks to Pedro Lopez-Cabanillas for help with the ALSA sequencer -// time stamps and other assorted fixes!!! + // The ALSA Sequencer API is based on the use of a callback function for + // MIDI input. + // + // Thanks to Pedro Lopez-Cabanillas for help with the ALSA sequencer + // time stamps and other assorted fixes!!! -// If you don't need timestamping for incoming MIDI events, define the -// preprocessor definition AVOID_TIMESTAMPING to save resources -// associated with the ALSA sequencer queues. + // If you don't need timestamping for incoming MIDI events, define the + // preprocessor definition AVOID_TIMESTAMPING to save resources + // associated with the ALSA sequencer queues. #include #include -// ALSA header file. + // ALSA header file. #include -// A structure to hold variables related to the ALSA API -// implementation. -struct AlsaMidiData { - snd_seq_t *seq; - unsigned int portNum; - int vport; - snd_seq_port_subscribe_t *subscription; - snd_midi_event_t *coder; - unsigned int bufferSize; - unsigned char *buffer; - pthread_t thread; - pthread_t dummy_thread_id; - unsigned long long lastTime; - int queue_id; // an input queue is needed to get timestamped events - int trigger_fds[2]; -}; +namespace rtmidi { + // A structure to hold variables related to the ALSA API + // implementation. + struct AlsaMidiData { + snd_seq_t *seq; + unsigned int portNum; + int vport; + snd_seq_port_subscribe_t *subscription; + snd_midi_event_t *coder; + unsigned int bufferSize; + unsigned char *buffer; + pthread_t thread; + pthread_t dummy_thread_id; + unsigned long long lastTime; + int queue_id; // an input queue is needed to get timestamped events + int trigger_fds[2]; + }; #define PORT_TYPE( pinfo, bits ) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits)) -//*********************************************************************// -// API: LINUX ALSA -// Class Definitions: MidiInAlsa -//*********************************************************************// - -static void *alsaMidiHandler( void *ptr ) -{ - MidiInApi::RtMidiInData *data = static_cast (ptr); - AlsaMidiData *apiData = static_cast (data->apiData); - - long nBytes; - unsigned long long time, lastTime; - bool continueSysex = false; - bool doDecode = false; - MidiInApi::MidiMessage message; - int poll_fd_count; - struct pollfd *poll_fds; - - snd_seq_event_t *ev; - int result; - apiData->bufferSize = 32; - result = snd_midi_event_new( 0, &apiData->coder ); - if ( result < 0 ) { - data->doInput = false; - std::cerr << "\nMidiInAlsa::alsaMidiHandler: error initializing MIDI event parser!\n\n"; - return 0; - } - unsigned char *buffer = (unsigned char *) malloc( apiData->bufferSize ); - if ( buffer == NULL ) { - data->doInput = false; - snd_midi_event_free( apiData->coder ); - apiData->coder = 0; - std::cerr << "\nMidiInAlsa::alsaMidiHandler: error initializing buffer memory!\n\n"; - return 0; - } - snd_midi_event_init( apiData->coder ); - snd_midi_event_no_status( apiData->coder, 1 ); // suppress running status messages - - poll_fd_count = snd_seq_poll_descriptors_count( apiData->seq, POLLIN ) + 1; - poll_fds = (struct pollfd*)alloca( poll_fd_count * sizeof( struct pollfd )); - snd_seq_poll_descriptors( apiData->seq, poll_fds + 1, poll_fd_count - 1, POLLIN ); - poll_fds[0].fd = apiData->trigger_fds[0]; - poll_fds[0].events = POLLIN; - - while ( data->doInput ) { - - if ( snd_seq_event_input_pending( apiData->seq, 1 ) == 0 ) { - // No data pending - if ( poll( poll_fds, poll_fd_count, -1) >= 0 ) { - if ( poll_fds[0].revents & POLLIN ) { - bool dummy; - int res = read( poll_fds[0].fd, &dummy, sizeof(dummy) ); - (void) res; - } - } - continue; - } - - // If here, there should be data. - result = snd_seq_event_input( apiData->seq, &ev ); - if ( result == -ENOSPC ) { - std::cerr << "\nMidiInAlsa::alsaMidiHandler: MIDI input buffer overrun!\n\n"; - continue; - } - else if ( result <= 0 ) { - std::cerr << "\nMidiInAlsa::alsaMidiHandler: unknown MIDI input error!\n"; - perror("System reports"); - continue; - } - - // This is a bit weird, but we now have to decode an ALSA MIDI - // event (back) into MIDI bytes. We'll ignore non-MIDI types. - if ( !continueSysex ) message.bytes.clear(); - - doDecode = false; - switch ( ev->type ) { - - case SND_SEQ_EVENT_PORT_SUBSCRIBED: + //*********************************************************************// + // API: LINUX ALSA + // Class Definitions: MidiInAlsa + //*********************************************************************// + + static void *alsaMidiHandler( void *ptr ) + { + MidiInApi::MidiInData *data = static_cast (ptr); + AlsaMidiData *apiData = static_cast (data->apiData); + + long nBytes; + unsigned long long time, lastTime; + bool continueSysex = false; + bool doDecode = false; + MidiInApi::MidiMessage message; + int poll_fd_count; + struct pollfd *poll_fds; + + snd_seq_event_t *ev; + int result; + apiData->bufferSize = 32; + result = snd_midi_event_new( 0, &apiData->coder ); + if ( result < 0 ) { + data->doInput = false; + std::cerr << "\nMidiInAlsa::alsaMidiHandler: error initializing MIDI event parser!\n\n"; + return 0; + } + unsigned char *buffer = (unsigned char *) malloc( apiData->bufferSize ); + if ( buffer == NULL ) { + data->doInput = false; + snd_midi_event_free( apiData->coder ); + apiData->coder = 0; + std::cerr << "\nMidiInAlsa::alsaMidiHandler: error initializing buffer memory!\n\n"; + return 0; + } + snd_midi_event_init( apiData->coder ); + snd_midi_event_no_status( apiData->coder, 1 ); // suppress running status messages + + poll_fd_count = snd_seq_poll_descriptors_count( apiData->seq, POLLIN ) + 1; + poll_fds = (struct pollfd*)alloca( poll_fd_count * sizeof( struct pollfd )); + snd_seq_poll_descriptors( apiData->seq, poll_fds + 1, poll_fd_count - 1, POLLIN ); + poll_fds[0].fd = apiData->trigger_fds[0]; + poll_fds[0].events = POLLIN; + + while ( data->doInput ) { + + if ( snd_seq_event_input_pending( apiData->seq, 1 ) == 0 ) { + // No data pending + if ( poll( poll_fds, poll_fd_count, -1) >= 0 ) { + if ( poll_fds[0].revents & POLLIN ) { + bool dummy; + int res = read( poll_fds[0].fd, &dummy, sizeof(dummy) ); + (void) res; + } + } + continue; + } + + // If here, there should be data. + result = snd_seq_event_input( apiData->seq, &ev ); + if ( result == -ENOSPC ) { + std::cerr << "\nMidiInAlsa::alsaMidiHandler: MIDI input buffer overrun!\n\n"; + continue; + } + else if ( result <= 0 ) { + std::cerr << "\nMidiInAlsa::alsaMidiHandler: unknown MIDI input error!\n"; + perror("System reports"); + continue; + } + + // This is a bit weird, but we now have to decode an ALSA MIDI + // event (back) into MIDI bytes. We'll ignore non-MIDI types. + if ( !continueSysex ) message.bytes.clear(); + + doDecode = false; + switch ( ev->type ) { + + case SND_SEQ_EVENT_PORT_SUBSCRIBED: #if defined(__RTMIDI_DEBUG__) - std::cout << "MidiInAlsa::alsaMidiHandler: port connection made!\n"; + std::cout << "MidiInAlsa::alsaMidiHandler: port connection made!\n"; #endif - break; + break; - case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: + case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: #if defined(__RTMIDI_DEBUG__) - std::cerr << "MidiInAlsa::alsaMidiHandler: port connection has closed!\n"; - std::cout << "sender = " << (int) ev->data.connect.sender.client << ":" - << (int) ev->data.connect.sender.port - << ", dest = " << (int) ev->data.connect.dest.client << ":" - << (int) ev->data.connect.dest.port - << std::endl; + std::cerr << "MidiInAlsa::alsaMidiHandler: port connection has closed!\n"; + std::cout << "sender = " << (int) ev->data.connect.sender.client << ":" + << (int) ev->data.connect.sender.port + << ", dest = " << (int) ev->data.connect.dest.client << ":" + << (int) ev->data.connect.dest.port + << std::endl; #endif - break; - - case SND_SEQ_EVENT_QFRAME: // MIDI time code - if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true; - break; - - case SND_SEQ_EVENT_TICK: // 0xF9 ... MIDI timing tick - if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true; - break; - - case SND_SEQ_EVENT_CLOCK: // 0xF8 ... MIDI timing (clock) tick - if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true; - break; - - case SND_SEQ_EVENT_SENSING: // Active sensing - if ( !( data->ignoreFlags & 0x04 ) ) doDecode = true; - break; - - case SND_SEQ_EVENT_SYSEX: - if ( (data->ignoreFlags & 0x01) ) break; - if ( ev->data.ext.len > apiData->bufferSize ) { - apiData->bufferSize = ev->data.ext.len; - free( buffer ); - buffer = (unsigned char *) malloc( apiData->bufferSize ); - if ( buffer == NULL ) { - data->doInput = false; - std::cerr << "\nMidiInAlsa::alsaMidiHandler: error resizing buffer memory!\n\n"; - break; - } - } - - default: - doDecode = true; - } - - if ( doDecode ) { - - nBytes = snd_midi_event_decode( apiData->coder, buffer, apiData->bufferSize, ev ); - if ( nBytes > 0 ) { - // The ALSA sequencer has a maximum buffer size for MIDI sysex - // events of 256 bytes. If a device sends sysex messages larger - // than this, they are segmented into 256 byte chunks. So, - // we'll watch for this and concatenate sysex chunks into a - // single sysex message if necessary. - if ( !continueSysex ) - message.bytes.assign( buffer, &buffer[nBytes] ); - else - message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] ); - - continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) ); - if ( !continueSysex ) { - - // Calculate the time stamp: - message.timeStamp = 0.0; - - // Method 1: Use the system time. - //(void)gettimeofday(&tv, (struct timezone *)NULL); - //time = (tv.tv_sec * 1000000) + tv.tv_usec; - - // Method 2: Use the ALSA sequencer event time data. - // (thanks to Pedro Lopez-Cabanillas!). - time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 ); - lastTime = time; - time -= apiData->lastTime; - apiData->lastTime = lastTime; - if ( data->firstMessage == true ) - data->firstMessage = false; - else - message.timeStamp = time * 0.000001; - } - else { + break; + + case SND_SEQ_EVENT_QFRAME: // MIDI time code + if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true; + break; + + case SND_SEQ_EVENT_TICK: // 0xF9 ... MIDI timing tick + if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true; + break; + + case SND_SEQ_EVENT_CLOCK: // 0xF8 ... MIDI timing (clock) tick + if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true; + break; + + case SND_SEQ_EVENT_SENSING: // Active sensing + if ( !( data->ignoreFlags & 0x04 ) ) doDecode = true; + break; + + case SND_SEQ_EVENT_SYSEX: + if ( (data->ignoreFlags & 0x01) ) break; + if ( ev->data.ext.len > apiData->bufferSize ) { + apiData->bufferSize = ev->data.ext.len; + free( buffer ); + buffer = (unsigned char *) malloc( apiData->bufferSize ); + if ( buffer == NULL ) { + data->doInput = false; + std::cerr << "\nMidiInAlsa::alsaMidiHandler: error resizing buffer memory!\n\n"; + break; + } + } + + default: + doDecode = true; + } + + if ( doDecode ) { + + nBytes = snd_midi_event_decode( apiData->coder, buffer, apiData->bufferSize, ev ); + if ( nBytes > 0 ) { + // The ALSA sequencer has a maximum buffer size for MIDI sysex + // events of 256 bytes. If a device sends sysex messages larger + // than this, they are segmented into 256 byte chunks. So, + // we'll watch for this and concatenate sysex chunks into a + // single sysex message if necessary. + if ( !continueSysex ) + message.bytes.assign( buffer, &buffer[nBytes] ); + else + message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] ); + + continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) ); + if ( !continueSysex ) { + + // Calculate the time stamp: + message.timeStamp = 0.0; + + // Method 1: Use the system time. + //(void)gettimeofday(&tv, (struct timezone *)NULL); + //time = (tv.tv_sec * 1000000) + tv.tv_usec; + + // Method 2: Use the ALSA sequencer event time data. + // (thanks to Pedro Lopez-Cabanillas!). + time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 ); + lastTime = time; + time -= apiData->lastTime; + apiData->lastTime = lastTime; + if ( data->firstMessage == true ) + data->firstMessage = false; + else + message.timeStamp = time * 0.000001; + } + else { #if defined(__RTMIDI_DEBUG__) - std::cerr << "\nMidiInAlsa::alsaMidiHandler: event parsing error or not a MIDI event!\n\n"; + std::cerr << "\nMidiInAlsa::alsaMidiHandler: event parsing error or not a MIDI event!\n\n"; #endif - } - } - } - - snd_seq_free_event( ev ); - if ( message.bytes.size() == 0 || continueSysex ) continue; - - if ( data->usingCallback ) { - RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; - callback( message.timeStamp, &message.bytes, data->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else - std::cerr << "\nMidiInAlsa: message queue limit reached!!\n\n"; - } - } - - if ( buffer ) free( buffer ); - snd_midi_event_free( apiData->coder ); - apiData->coder = 0; - apiData->thread = apiData->dummy_thread_id; - return 0; -} + } + } + } + + snd_seq_free_event( ev ); + if ( message.bytes.size() == 0 || continueSysex ) continue; + + if ( data->usingCallback ) { + MidiCallback callback = (MidiCallback) data->userCallback; + callback( message.timeStamp, &message.bytes, data->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else + std::cerr << "\nMidiInAlsa: message queue limit reached!!\n\n"; + } + } + + if ( buffer ) free( buffer ); + snd_midi_event_free( apiData->coder ); + apiData->coder = 0; + apiData->thread = apiData->dummy_thread_id; + return 0; + } -MidiInAlsa :: MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) -{ - initialize( clientName ); -} + MidiInAlsa :: MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) + { + initialize( clientName ); + } -MidiInAlsa :: ~MidiInAlsa() -{ - // Close a connection if it exists. - closePort(); - - // Shutdown the input thread. - AlsaMidiData *data = static_cast (apiData_); - if ( inputData_.doInput ) { - inputData_.doInput = false; - int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput) ); - (void) res; - if ( !pthread_equal(data->thread, data->dummy_thread_id) ) - pthread_join( data->thread, NULL ); - } - - // Cleanup. - close ( data->trigger_fds[0] ); - close ( data->trigger_fds[1] ); - if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport ); + MidiInAlsa :: ~MidiInAlsa() + { + // Close a connection if it exists. + closePort(); + + // Shutdown the input thread. + AlsaMidiData *data = static_cast (apiData_); + if ( inputData_.doInput ) { + inputData_.doInput = false; + int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput) ); + (void) res; + if ( !pthread_equal(data->thread, data->dummy_thread_id) ) + pthread_join( data->thread, NULL ); + } + + // Cleanup. + close ( data->trigger_fds[0] ); + close ( data->trigger_fds[1] ); + if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport ); #ifndef AVOID_TIMESTAMPING - snd_seq_free_queue( data->seq, data->queue_id ); + snd_seq_free_queue( data->seq, data->queue_id ); #endif - snd_seq_close( data->seq ); - delete data; -} + snd_seq_close( data->seq ); + delete data; + } -void MidiInAlsa :: initialize( const std::string& clientName ) -{ - // Set up the ALSA sequencer client. - snd_seq_t *seq; - int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); - if ( result < 0 ) { - errorString_ = "MidiInAlsa::initialize: error creating ALSA sequencer client object."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Set client name. - snd_seq_set_client_name( seq, clientName.c_str() ); - - // Save our api-specific connection information. - AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; - data->seq = seq; - data->portNum = -1; - data->vport = -1; - data->subscription = 0; - data->dummy_thread_id = pthread_self(); - data->thread = data->dummy_thread_id; - data->trigger_fds[0] = -1; - data->trigger_fds[1] = -1; - apiData_ = (void *) data; - inputData_.apiData = (void *) data; - - if ( pipe(data->trigger_fds) == -1 ) { - errorString_ = "MidiInAlsa::initialize: error creating pipe objects."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Create the input queue + void MidiInAlsa :: initialize( const std::string& clientName ) + { + // Set up the ALSA sequencer client. + snd_seq_t *seq; + int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); + if ( result < 0 ) { + errorString_ = "MidiInAlsa::initialize: error creating ALSA sequencer client object."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Set client name. + snd_seq_set_client_name( seq, clientName.c_str() ); + + // Save our api-specific connection information. + AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; + data->seq = seq; + data->portNum = -1; + data->vport = -1; + data->subscription = 0; + data->dummy_thread_id = pthread_self(); + data->thread = data->dummy_thread_id; + data->trigger_fds[0] = -1; + data->trigger_fds[1] = -1; + apiData_ = (void *) data; + inputData_.apiData = (void *) data; + + if ( pipe(data->trigger_fds) == -1 ) { + errorString_ = "MidiInAlsa::initialize: error creating pipe objects."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Create the input queue #ifndef AVOID_TIMESTAMPING - data->queue_id = snd_seq_alloc_named_queue(seq, "RtMidi Queue"); - // Set arbitrary tempo (mm=100) and resolution (240) - snd_seq_queue_tempo_t *qtempo; - snd_seq_queue_tempo_alloca(&qtempo); - snd_seq_queue_tempo_set_tempo(qtempo, 600000); - snd_seq_queue_tempo_set_ppq(qtempo, 240); - snd_seq_set_queue_tempo(data->seq, data->queue_id, qtempo); - snd_seq_drain_output(data->seq); + data->queue_id = snd_seq_alloc_named_queue(seq, "Midi Queue"); + // Set arbitrary tempo (mm=100) and resolution (240) + snd_seq_queue_tempo_t *qtempo; + snd_seq_queue_tempo_alloca(&qtempo); + snd_seq_queue_tempo_set_tempo(qtempo, 600000); + snd_seq_queue_tempo_set_ppq(qtempo, 240); + snd_seq_set_queue_tempo(data->seq, data->queue_id, qtempo); + snd_seq_drain_output(data->seq); #endif -} + } -// This function is used to count or get the pinfo structure for a given port number. -unsigned int portInfo( snd_seq_t *seq, snd_seq_port_info_t *pinfo, unsigned int type, int portNumber ) -{ - snd_seq_client_info_t *cinfo; - int client; - int count = 0; - snd_seq_client_info_alloca( &cinfo ); - - snd_seq_client_info_set_client( cinfo, -1 ); - while ( snd_seq_query_next_client( seq, cinfo ) >= 0 ) { - client = snd_seq_client_info_get_client( cinfo ); - if ( client == 0 ) continue; - // Reset query info - snd_seq_port_info_set_client( pinfo, client ); - snd_seq_port_info_set_port( pinfo, -1 ); - while ( snd_seq_query_next_port( seq, pinfo ) >= 0 ) { - unsigned int atyp = snd_seq_port_info_get_type( pinfo ); - if ( ( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) == 0 ) continue; - unsigned int caps = snd_seq_port_info_get_capability( pinfo ); - if ( ( caps & type ) != type ) continue; - if ( count == portNumber ) return 1; - ++count; - } - } - - // If a negative portNumber was used, return the port count. - if ( portNumber < 0 ) return count; - return 0; -} + // This function is used to count or get the pinfo structure for a given port number. + unsigned int portInfo( snd_seq_t *seq, snd_seq_port_info_t *pinfo, unsigned int type, int portNumber ) + { + snd_seq_client_info_t *cinfo; + int client; + int count = 0; + snd_seq_client_info_alloca( &cinfo ); + + snd_seq_client_info_set_client( cinfo, -1 ); + while ( snd_seq_query_next_client( seq, cinfo ) >= 0 ) { + client = snd_seq_client_info_get_client( cinfo ); + if ( client == 0 ) continue; + // Reset query info + snd_seq_port_info_set_client( pinfo, client ); + snd_seq_port_info_set_port( pinfo, -1 ); + while ( snd_seq_query_next_port( seq, pinfo ) >= 0 ) { + unsigned int atyp = snd_seq_port_info_get_type( pinfo ); + if ( ( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) == 0 ) continue; + unsigned int caps = snd_seq_port_info_get_capability( pinfo ); + if ( ( caps & type ) != type ) continue; + if ( count == portNumber ) return 1; + ++count; + } + } + + // If a negative portNumber was used, return the port count. + if ( portNumber < 0 ) return count; + return 0; + } -unsigned int MidiInAlsa :: getPortCount() -{ - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); + unsigned int MidiInAlsa :: getPortCount() + { + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); - AlsaMidiData *data = static_cast (apiData_); - return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, -1 ); -} + AlsaMidiData *data = static_cast (apiData_); + return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, -1 ); + } -std::string MidiInAlsa :: getPortName( unsigned int portNumber ) -{ - snd_seq_client_info_t *cinfo; - snd_seq_port_info_t *pinfo; - snd_seq_client_info_alloca( &cinfo ); - snd_seq_port_info_alloca( &pinfo ); - - std::string stringName; - AlsaMidiData *data = static_cast (apiData_); - if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) ) { - int cnum = snd_seq_port_info_get_client( pinfo ); - snd_seq_get_any_client_info( data->seq, cnum, cinfo ); - std::ostringstream os; - os << snd_seq_client_info_get_name( cinfo ); - os << " "; // These lines added to make sure devices are listed - os << snd_seq_port_info_get_client( pinfo ); // with full portnames added to ensure individual device names - os << ":"; - os << snd_seq_port_info_get_port( pinfo ); - stringName = os.str(); - return stringName; - } - - // If we get here, we didn't find a match. - errorString_ = "MidiInAlsa::getPortName: error looking for port name!"; - error( RtMidiError::WARNING, errorString_ ); - return stringName; -} + std::string MidiInAlsa :: getPortName( unsigned int portNumber ) + { + snd_seq_client_info_t *cinfo; + snd_seq_port_info_t *pinfo; + snd_seq_client_info_alloca( &cinfo ); + snd_seq_port_info_alloca( &pinfo ); + + std::string stringName; + AlsaMidiData *data = static_cast (apiData_); + if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) ) { + int cnum = snd_seq_port_info_get_client( pinfo ); + snd_seq_get_any_client_info( data->seq, cnum, cinfo ); + std::ostringstream os; + os << snd_seq_client_info_get_name( cinfo ); + os << " "; // These lines added to make sure devices are listed + os << snd_seq_port_info_get_client( pinfo ); // with full portnames added to ensure individual device names + os << ":"; + os << snd_seq_port_info_get_port( pinfo ); + stringName = os.str(); + return stringName; + } + + // If we get here, we didn't find a match. + errorString_ = "MidiInAlsa::getPortName: error looking for port name!"; + error( Error::WARNING, errorString_ ); + return stringName; + } -void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName ) -{ - if ( connected_ ) { - errorString_ = "MidiInAlsa::openPort: a valid connection already exists!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - unsigned int nSrc = this->getPortCount(); - if ( nSrc < 1 ) { - errorString_ = "MidiInAlsa::openPort: no MIDI input sources found!"; - error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); - return; - } - - snd_seq_port_info_t *src_pinfo; - snd_seq_port_info_alloca( &src_pinfo ); - AlsaMidiData *data = static_cast (apiData_); - if ( portInfo( data->seq, src_pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) == 0 ) { - std::ostringstream ost; - ost << "MidiInAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::INVALID_PARAMETER, errorString_ ); - return; - } - - snd_seq_addr_t sender, receiver; - sender.client = snd_seq_port_info_get_client( src_pinfo ); - sender.port = snd_seq_port_info_get_port( src_pinfo ); - - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); - if ( data->vport < 0 ) { - snd_seq_port_info_set_client( pinfo, 0 ); - snd_seq_port_info_set_port( pinfo, 0 ); - snd_seq_port_info_set_capability( pinfo, - SND_SEQ_PORT_CAP_WRITE | - SND_SEQ_PORT_CAP_SUBS_WRITE ); - snd_seq_port_info_set_type( pinfo, - SND_SEQ_PORT_TYPE_MIDI_GENERIC | - SND_SEQ_PORT_TYPE_APPLICATION ); - snd_seq_port_info_set_midi_channels(pinfo, 16); + void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName ) + { + if ( connected_ ) { + errorString_ = "MidiInAlsa::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + + unsigned int nSrc = this->getPortCount(); + if ( nSrc < 1 ) { + errorString_ = "MidiInAlsa::openPort: no MIDI input sources found!"; + error( Error::NO_DEVICES_FOUND, errorString_ ); + return; + } + + snd_seq_port_info_t *src_pinfo; + snd_seq_port_info_alloca( &src_pinfo ); + AlsaMidiData *data = static_cast (apiData_); + if ( portInfo( data->seq, src_pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) == 0 ) { + std::ostringstream ost; + ost << "MidiInAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::INVALID_PARAMETER, errorString_ ); + return; + } + + snd_seq_addr_t sender, receiver; + sender.client = snd_seq_port_info_get_client( src_pinfo ); + sender.port = snd_seq_port_info_get_port( src_pinfo ); + + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + if ( data->vport < 0 ) { + snd_seq_port_info_set_client( pinfo, 0 ); + snd_seq_port_info_set_port( pinfo, 0 ); + snd_seq_port_info_set_capability( pinfo, + SND_SEQ_PORT_CAP_WRITE | + SND_SEQ_PORT_CAP_SUBS_WRITE ); + snd_seq_port_info_set_type( pinfo, + SND_SEQ_PORT_TYPE_MIDI_GENERIC | + SND_SEQ_PORT_TYPE_APPLICATION ); + snd_seq_port_info_set_midi_channels(pinfo, 16); #ifndef AVOID_TIMESTAMPING - snd_seq_port_info_set_timestamping(pinfo, 1); - snd_seq_port_info_set_timestamp_real(pinfo, 1); - snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id); + snd_seq_port_info_set_timestamping(pinfo, 1); + snd_seq_port_info_set_timestamp_real(pinfo, 1); + snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id); #endif - snd_seq_port_info_set_name(pinfo, portName.c_str() ); - data->vport = snd_seq_create_port(data->seq, pinfo); + snd_seq_port_info_set_name(pinfo, portName.c_str() ); + int createok = snd_seq_create_port(data->seq, pinfo); - if ( data->vport < 0 ) { - errorString_ = "MidiInAlsa::openPort: ALSA error creating input port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - data->vport = snd_seq_port_info_get_port(pinfo); - } - - receiver.client = snd_seq_port_info_get_client( pinfo ); - receiver.port = data->vport; - - if ( !data->subscription ) { - // Make subscription - if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { - errorString_ = "MidiInAlsa::openPort: ALSA error allocation port subscription."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - snd_seq_port_subscribe_set_sender(data->subscription, &sender); - snd_seq_port_subscribe_set_dest(data->subscription, &receiver); - if ( snd_seq_subscribe_port(data->seq, data->subscription) ) { - snd_seq_port_subscribe_free( data->subscription ); - data->subscription = 0; - errorString_ = "MidiInAlsa::openPort: ALSA error making port connection."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - } - - if ( inputData_.doInput == false ) { - // Start the input queue + if ( createok < 0 ) { + errorString_ = "MidiInAlsa::openPort: ALSA error creating input port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + data->vport = snd_seq_port_info_get_port(pinfo); + } + + receiver.client = snd_seq_port_info_get_client( pinfo ); + receiver.port = data->vport; + + if ( !data->subscription ) { + // Make subscription + if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { + errorString_ = "MidiInAlsa::openPort: ALSA error allocation port subscription."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + snd_seq_port_subscribe_set_sender(data->subscription, &sender); + snd_seq_port_subscribe_set_dest(data->subscription, &receiver); + if ( snd_seq_subscribe_port(data->seq, data->subscription) ) { + snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; + errorString_ = "MidiInAlsa::openPort: ALSA error making port connection."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + } + + if ( inputData_.doInput == false ) { + // Start the input queue #ifndef AVOID_TIMESTAMPING - snd_seq_start_queue( data->seq, data->queue_id, NULL ); - snd_seq_drain_output( data->seq ); + snd_seq_start_queue( data->seq, data->queue_id, NULL ); + snd_seq_drain_output( data->seq ); #endif - // Start our MIDI input thread. - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - pthread_attr_setschedpolicy(&attr, SCHED_OTHER); - - inputData_.doInput = true; - int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_); - pthread_attr_destroy(&attr); - if ( err ) { - snd_seq_unsubscribe_port( data->seq, data->subscription ); - snd_seq_port_subscribe_free( data->subscription ); - data->subscription = 0; - inputData_.doInput = false; - errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!"; - error( RtMidiError::THREAD_ERROR, errorString_ ); - return; - } - } - - connected_ = true; -} + // Start our MIDI input thread. + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + pthread_attr_setschedpolicy(&attr, SCHED_OTHER); + + inputData_.doInput = true; + int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_); + pthread_attr_destroy(&attr); + if ( err ) { + snd_seq_unsubscribe_port( data->seq, data->subscription ); + snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; + inputData_.doInput = false; + errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!"; + error( Error::THREAD_ERROR, errorString_ ); + return; + } + } + + connected_ = true; + } + + void MidiInAlsa :: openPort( const PortDescriptor & port, + const std::string portName = std::string( "RtMidi" ) ) + { + abort(); + } + + Pointer MidiInAlsa :: getDescriptor() + { + abort(); + } + PortList MidiInAlsa :: getPortList(int capabilities) + { + abort(); + } + + -void MidiInAlsa :: openVirtualPort( std::string portName ) -{ - AlsaMidiData *data = static_cast (apiData_); - if ( data->vport < 0 ) { - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); - snd_seq_port_info_set_capability( pinfo, - SND_SEQ_PORT_CAP_WRITE | - SND_SEQ_PORT_CAP_SUBS_WRITE ); - snd_seq_port_info_set_type( pinfo, - SND_SEQ_PORT_TYPE_MIDI_GENERIC | - SND_SEQ_PORT_TYPE_APPLICATION ); - snd_seq_port_info_set_midi_channels(pinfo, 16); + void MidiInAlsa :: openVirtualPort( std::string portName ) + { + AlsaMidiData *data = static_cast (apiData_); + if ( data->vport < 0 ) { + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + snd_seq_port_info_set_capability( pinfo, + SND_SEQ_PORT_CAP_WRITE | + SND_SEQ_PORT_CAP_SUBS_WRITE ); + snd_seq_port_info_set_type( pinfo, + SND_SEQ_PORT_TYPE_MIDI_GENERIC | + SND_SEQ_PORT_TYPE_APPLICATION ); + snd_seq_port_info_set_midi_channels(pinfo, 16); #ifndef AVOID_TIMESTAMPING - snd_seq_port_info_set_timestamping(pinfo, 1); - snd_seq_port_info_set_timestamp_real(pinfo, 1); - snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id); + snd_seq_port_info_set_timestamping(pinfo, 1); + snd_seq_port_info_set_timestamp_real(pinfo, 1); + snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id); #endif - snd_seq_port_info_set_name(pinfo, portName.c_str()); - data->vport = snd_seq_create_port(data->seq, pinfo); - - if ( data->vport < 0 ) { - errorString_ = "MidiInAlsa::openVirtualPort: ALSA error creating virtual port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - data->vport = snd_seq_port_info_get_port(pinfo); - } - - if ( inputData_.doInput == false ) { - // Wait for old thread to stop, if still running - if ( !pthread_equal(data->thread, data->dummy_thread_id) ) - pthread_join( data->thread, NULL ); - - // Start the input queue + snd_seq_port_info_set_name(pinfo, portName.c_str()); + int createok = snd_seq_create_port(data->seq, pinfo); + + if ( createok < 0 ) { + errorString_ = "MidiInAlsa::openVirtualPort: ALSA error creating virtual port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + data->vport = snd_seq_port_info_get_port(pinfo); + } + + if ( inputData_.doInput == false ) { + // Wait for old thread to stop, if still running + if ( !pthread_equal(data->thread, data->dummy_thread_id) ) + pthread_join( data->thread, NULL ); + + // Start the input queue #ifndef AVOID_TIMESTAMPING - snd_seq_start_queue( data->seq, data->queue_id, NULL ); - snd_seq_drain_output( data->seq ); + snd_seq_start_queue( data->seq, data->queue_id, NULL ); + snd_seq_drain_output( data->seq ); #endif - // Start our MIDI input thread. - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - pthread_attr_setschedpolicy(&attr, SCHED_OTHER); - - inputData_.doInput = true; - int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_); - pthread_attr_destroy(&attr); - if ( err ) { - if ( data->subscription ) { - snd_seq_unsubscribe_port( data->seq, data->subscription ); - snd_seq_port_subscribe_free( data->subscription ); - data->subscription = 0; - } - inputData_.doInput = false; - errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!"; - error( RtMidiError::THREAD_ERROR, errorString_ ); - return; - } - } -} + // Start our MIDI input thread. + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + pthread_attr_setschedpolicy(&attr, SCHED_OTHER); + + inputData_.doInput = true; + int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_); + pthread_attr_destroy(&attr); + if ( err ) { + if ( data->subscription ) { + snd_seq_unsubscribe_port( data->seq, data->subscription ); + snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; + } + inputData_.doInput = false; + errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!"; + error( Error::THREAD_ERROR, errorString_ ); + return; + } + } + } -void MidiInAlsa :: closePort( void ) -{ - AlsaMidiData *data = static_cast (apiData_); - - if ( connected_ ) { - if ( data->subscription ) { - snd_seq_unsubscribe_port( data->seq, data->subscription ); - snd_seq_port_subscribe_free( data->subscription ); - data->subscription = 0; - } - // Stop the input queue + void MidiInAlsa :: closePort( void ) + { + AlsaMidiData *data = static_cast (apiData_); + + if ( connected_ ) { + if ( data->subscription ) { + snd_seq_unsubscribe_port( data->seq, data->subscription ); + snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; + } + // Stop the input queue #ifndef AVOID_TIMESTAMPING - snd_seq_stop_queue( data->seq, data->queue_id, NULL ); - snd_seq_drain_output( data->seq ); + snd_seq_stop_queue( data->seq, data->queue_id, NULL ); + snd_seq_drain_output( data->seq ); #endif - connected_ = false; - } - - // Stop thread to avoid triggering the callback, while the port is intended to be closed - if ( inputData_.doInput ) { - inputData_.doInput = false; - int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput) ); - (void) res; - if ( !pthread_equal(data->thread, data->dummy_thread_id) ) - pthread_join( data->thread, NULL ); - } -} + connected_ = false; + } + + // Stop thread to avoid triggering the callback, while the port is intended to be closed + if ( inputData_.doInput ) { + inputData_.doInput = false; + int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput) ); + (void) res; + if ( !pthread_equal(data->thread, data->dummy_thread_id) ) + pthread_join( data->thread, NULL ); + } + } -//*********************************************************************// -// API: LINUX ALSA -// Class Definitions: MidiOutAlsa -//*********************************************************************// + //*********************************************************************// + // API: LINUX ALSA + // Class Definitions: MidiOutAlsa + //*********************************************************************// -MidiOutAlsa :: MidiOutAlsa( const std::string clientName ) : MidiOutApi() -{ - initialize( clientName ); -} + MidiOutAlsa :: MidiOutAlsa( const std::string clientName ) : MidiOutApi() + { + initialize( clientName ); + } -MidiOutAlsa :: ~MidiOutAlsa() -{ - // Close a connection if it exists. - closePort(); - - // Cleanup. - AlsaMidiData *data = static_cast (apiData_); - if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport ); - if ( data->coder ) snd_midi_event_free( data->coder ); - if ( data->buffer ) free( data->buffer ); - snd_seq_close( data->seq ); - delete data; -} + MidiOutAlsa :: ~MidiOutAlsa() + { + // Close a connection if it exists. + closePort(); + + // Cleanup. + AlsaMidiData *data = static_cast (apiData_); + if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport ); + if ( data->coder ) snd_midi_event_free( data->coder ); + if ( data->buffer ) free( data->buffer ); + snd_seq_close( data->seq ); + delete data; + } -void MidiOutAlsa :: initialize( const std::string& clientName ) -{ - // Set up the ALSA sequencer client. - snd_seq_t *seq; - int result1 = snd_seq_open( &seq, "default", SND_SEQ_OPEN_OUTPUT, SND_SEQ_NONBLOCK ); - if ( result1 < 0 ) { - errorString_ = "MidiOutAlsa::initialize: error creating ALSA sequencer client object."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Set client name. - snd_seq_set_client_name( seq, clientName.c_str() ); - - // Save our api-specific connection information. - AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; - data->seq = seq; - data->portNum = -1; - data->vport = -1; - data->bufferSize = 32; - data->coder = 0; - data->buffer = 0; - int result = snd_midi_event_new( data->bufferSize, &data->coder ); - if ( result < 0 ) { - delete data; - errorString_ = "MidiOutAlsa::initialize: error initializing MIDI event parser!\n\n"; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - data->buffer = (unsigned char *) malloc( data->bufferSize ); - if ( data->buffer == NULL ) { - delete data; - errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n"; - error( RtMidiError::MEMORY_ERROR, errorString_ ); - return; - } - snd_midi_event_init( data->coder ); - apiData_ = (void *) data; -} + void MidiOutAlsa :: initialize( const std::string& clientName ) + { + // Set up the ALSA sequencer client. + snd_seq_t *seq; + int result1 = snd_seq_open( &seq, "default", SND_SEQ_OPEN_OUTPUT, SND_SEQ_NONBLOCK ); + if ( result1 < 0 ) { + errorString_ = "MidiOutAlsa::initialize: error creating ALSA sequencer client object."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Set client name. + snd_seq_set_client_name( seq, clientName.c_str() ); + + // Save our api-specific connection information. + AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; + data->seq = seq; + data->portNum = -1; + data->vport = -1; + data->bufferSize = 32; + data->coder = 0; + data->buffer = 0; + int result = snd_midi_event_new( data->bufferSize, &data->coder ); + if ( result < 0 ) { + delete data; + errorString_ = "MidiOutAlsa::initialize: error initializing MIDI event parser!\n\n"; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + data->buffer = (unsigned char *) malloc( data->bufferSize ); + if ( data->buffer == NULL ) { + delete data; + errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n"; + error( Error::MEMORY_ERROR, errorString_ ); + return; + } + snd_midi_event_init( data->coder ); + apiData_ = (void *) data; + } -unsigned int MidiOutAlsa :: getPortCount() -{ - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); + unsigned int MidiOutAlsa :: getPortCount() + { + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); - AlsaMidiData *data = static_cast (apiData_); - return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, -1 ); -} + AlsaMidiData *data = static_cast (apiData_); + return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, -1 ); + } -std::string MidiOutAlsa :: getPortName( unsigned int portNumber ) -{ - snd_seq_client_info_t *cinfo; - snd_seq_port_info_t *pinfo; - snd_seq_client_info_alloca( &cinfo ); - snd_seq_port_info_alloca( &pinfo ); - - std::string stringName; - AlsaMidiData *data = static_cast (apiData_); - if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) ) { - int cnum = snd_seq_port_info_get_client(pinfo); - snd_seq_get_any_client_info( data->seq, cnum, cinfo ); - std::ostringstream os; - os << snd_seq_client_info_get_name(cinfo); - os << " "; // These lines added to make sure devices are listed - os << snd_seq_port_info_get_client( pinfo ); // with full portnames added to ensure individual device names - os << ":"; - os << snd_seq_port_info_get_port(pinfo); - stringName = os.str(); - return stringName; - } - - // If we get here, we didn't find a match. - errorString_ = "MidiOutAlsa::getPortName: error looking for port name!"; - error( RtMidiError::WARNING, errorString_ ); - return stringName; -} + std::string MidiOutAlsa :: getPortName( unsigned int portNumber ) + { + snd_seq_client_info_t *cinfo; + snd_seq_port_info_t *pinfo; + snd_seq_client_info_alloca( &cinfo ); + snd_seq_port_info_alloca( &pinfo ); + + std::string stringName; + AlsaMidiData *data = static_cast (apiData_); + if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) ) { + int cnum = snd_seq_port_info_get_client(pinfo); + snd_seq_get_any_client_info( data->seq, cnum, cinfo ); + std::ostringstream os; + os << snd_seq_client_info_get_name(cinfo); + os << " "; // These lines added to make sure devices are listed + os << snd_seq_port_info_get_client( pinfo ); // with full portnames added to ensure individual device names + os << ":"; + os << snd_seq_port_info_get_port(pinfo); + stringName = os.str(); + return stringName; + } + + // If we get here, we didn't find a match. + errorString_ = "MidiOutAlsa::getPortName: error looking for port name!"; + error( Error::WARNING, errorString_ ); + return stringName; + } -void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string portName ) -{ - if ( connected_ ) { - errorString_ = "MidiOutAlsa::openPort: a valid connection already exists!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - unsigned int nSrc = this->getPortCount(); - if (nSrc < 1) { - errorString_ = "MidiOutAlsa::openPort: no MIDI output sources found!"; - error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); - return; - } - - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); - AlsaMidiData *data = static_cast (apiData_); - if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) == 0 ) { - std::ostringstream ost; - ost << "MidiOutAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::INVALID_PARAMETER, errorString_ ); - return; - } - - snd_seq_addr_t sender, receiver; - receiver.client = snd_seq_port_info_get_client( pinfo ); - receiver.port = snd_seq_port_info_get_port( pinfo ); - sender.client = snd_seq_client_id( data->seq ); - - if ( data->vport < 0 ) { - data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(), - SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, - SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); - if ( data->vport < 0 ) { - errorString_ = "MidiOutAlsa::openPort: ALSA error creating output port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - } - - sender.port = data->vport; - - // Make subscription - if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { - snd_seq_port_subscribe_free( data->subscription ); - errorString_ = "MidiOutAlsa::openPort: error allocating port subscription."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - snd_seq_port_subscribe_set_sender(data->subscription, &sender); - snd_seq_port_subscribe_set_dest(data->subscription, &receiver); - snd_seq_port_subscribe_set_time_update(data->subscription, 1); - snd_seq_port_subscribe_set_time_real(data->subscription, 1); - if ( snd_seq_subscribe_port(data->seq, data->subscription) ) { - snd_seq_port_subscribe_free( data->subscription ); - errorString_ = "MidiOutAlsa::openPort: ALSA error making port connection."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - connected_ = true; -} + void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string portName ) + { + if ( connected_ ) { + errorString_ = "MidiOutAlsa::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + + unsigned int nSrc = this->getPortCount(); + if (nSrc < 1) { + errorString_ = "MidiOutAlsa::openPort: no MIDI output sources found!"; + error( Error::NO_DEVICES_FOUND, errorString_ ); + return; + } + + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + AlsaMidiData *data = static_cast (apiData_); + if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) == 0 ) { + std::ostringstream ost; + ost << "MidiOutAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::INVALID_PARAMETER, errorString_ ); + return; + } + + snd_seq_addr_t sender, receiver; + receiver.client = snd_seq_port_info_get_client( pinfo ); + receiver.port = snd_seq_port_info_get_port( pinfo ); + sender.client = snd_seq_client_id( data->seq ); + + if ( data->vport < 0 ) { + data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(), + SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, + SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); + if ( data->vport < 0 ) { + errorString_ = "MidiOutAlsa::openPort: ALSA error creating output port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + } + + sender.port = data->vport; + + // Make subscription + if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { + snd_seq_port_subscribe_free( data->subscription ); + errorString_ = "MidiOutAlsa::openPort: error allocating port subscription."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + snd_seq_port_subscribe_set_sender(data->subscription, &sender); + snd_seq_port_subscribe_set_dest(data->subscription, &receiver); + snd_seq_port_subscribe_set_time_update(data->subscription, 1); + snd_seq_port_subscribe_set_time_real(data->subscription, 1); + if ( snd_seq_subscribe_port(data->seq, data->subscription) ) { + snd_seq_port_subscribe_free( data->subscription ); + errorString_ = "MidiOutAlsa::openPort: ALSA error making port connection."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + connected_ = true; + } -void MidiOutAlsa :: closePort( void ) -{ - if ( connected_ ) { - AlsaMidiData *data = static_cast (apiData_); - snd_seq_unsubscribe_port( data->seq, data->subscription ); - snd_seq_port_subscribe_free( data->subscription ); - connected_ = false; - } -} + void MidiOutAlsa :: closePort( void ) + { + if ( connected_ ) { + AlsaMidiData *data = static_cast (apiData_); + snd_seq_unsubscribe_port( data->seq, data->subscription ); + snd_seq_port_subscribe_free( data->subscription ); + connected_ = false; + } + } -void MidiOutAlsa :: openVirtualPort( std::string portName ) -{ - AlsaMidiData *data = static_cast (apiData_); - if ( data->vport < 0 ) { - data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(), - SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, - SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); - - if ( data->vport < 0 ) { - errorString_ = "MidiOutAlsa::openVirtualPort: ALSA error creating virtual port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - } - } -} + void MidiOutAlsa :: openVirtualPort( std::string portName ) + { + AlsaMidiData *data = static_cast (apiData_); + if ( data->vport < 0 ) { + data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(), + SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, + SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); + + if ( data->vport < 0 ) { + errorString_ = "MidiOutAlsa::openVirtualPort: ALSA error creating virtual port."; + error( Error::DRIVER_ERROR, errorString_ ); + } + } + } -void MidiOutAlsa :: sendMessage( std::vector *message ) -{ - int result; - AlsaMidiData *data = static_cast (apiData_); - unsigned int nBytes = message->size(); - if ( nBytes > data->bufferSize ) { - data->bufferSize = nBytes; - result = snd_midi_event_resize_buffer ( data->coder, nBytes); - if ( result != 0 ) { - errorString_ = "MidiOutAlsa::sendMessage: ALSA error resizing MIDI event buffer."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - free (data->buffer); - data->buffer = (unsigned char *) malloc( data->bufferSize ); - if ( data->buffer == NULL ) { - errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n"; - error( RtMidiError::MEMORY_ERROR, errorString_ ); - return; - } - } - - snd_seq_event_t ev; - snd_seq_ev_clear(&ev); - snd_seq_ev_set_source(&ev, data->vport); - snd_seq_ev_set_subs(&ev); - snd_seq_ev_set_direct(&ev); - for ( unsigned int i=0; ibuffer[i] = message->at(i); - result = snd_midi_event_encode( data->coder, data->buffer, (long)nBytes, &ev ); - if ( result < (int)nBytes ) { - errorString_ = "MidiOutAlsa::sendMessage: event parsing error!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - // Send the event. - result = snd_seq_event_output(data->seq, &ev); - if ( result < 0 ) { - errorString_ = "MidiOutAlsa::sendMessage: error sending MIDI message to port."; - error( RtMidiError::WARNING, errorString_ ); - return; - } - snd_seq_drain_output(data->seq); -} + void MidiOutAlsa :: sendMessage( std::vector &message ) + { + int result; + AlsaMidiData *data = static_cast (apiData_); + unsigned int nBytes = message.size(); + if ( nBytes > data->bufferSize ) { + data->bufferSize = nBytes; + result = snd_midi_event_resize_buffer ( data->coder, nBytes); + if ( result != 0 ) { + errorString_ = "MidiOutAlsa::sendMessage: ALSA error resizing MIDI event buffer."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + free (data->buffer); + data->buffer = (unsigned char *) malloc( data->bufferSize ); + if ( data->buffer == NULL ) { + errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n"; + error( Error::MEMORY_ERROR, errorString_ ); + return; + } + } + + snd_seq_event_t ev; + snd_seq_ev_clear(&ev); + snd_seq_ev_set_source(&ev, data->vport); + snd_seq_ev_set_subs(&ev); + snd_seq_ev_set_direct(&ev); + for ( unsigned int i=0; ibuffer[i] = message.at(i); + result = snd_midi_event_encode( data->coder, data->buffer, (long)nBytes, &ev ); + if ( result < (int)nBytes ) { + errorString_ = "MidiOutAlsa::sendMessage: event parsing error!"; + error( Error::WARNING, errorString_ ); + return; + } + + // Send the event. + result = snd_seq_event_output(data->seq, &ev); + if ( result < 0 ) { + errorString_ = "MidiOutAlsa::sendMessage: error sending MIDI message to port."; + error( Error::WARNING, errorString_ ); + return; + } + snd_seq_drain_output(data->seq); + } + void MidiOutAlsa :: openPort( const PortDescriptor & port, + const std::string portName) + { + abort(); + } + Pointer MidiOutAlsa :: getDescriptor() + { + abort(); + } + PortList MidiOutAlsa :: getPortList(int capabilities) + { + abort(); + } +} #endif // __LINUX_ALSA__ -//*********************************************************************// -// API: Windows Multimedia Library (MM) -//*********************************************************************// + //*********************************************************************// + // API: Windows Multimedia Library (MM) + //*********************************************************************// -// API information deciphered from: -// - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_midi_reference.asp + // API information deciphered from: + // - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_midi_reference.asp -// Thanks to Jean-Baptiste Berruchon for the sysex code. + // Thanks to Jean-Baptiste Berruchon for the sysex code. #if defined(__WINDOWS_MM__) -// The Windows MM API is based on the use of a callback function for -// MIDI input. We convert the system specific time stamps to delta -// time values. + // The Windows MM API is based on the use of a callback function for + // MIDI input. We convert the system specific time stamps to delta + // time values. -// Windows MM MIDI header files. + // Windows MM MIDI header files. #include #include #define RT_SYSEX_BUFFER_SIZE 1024 #define RT_SYSEX_BUFFER_COUNT 4 +namespace rtmidi{ + // A structure to hold variables related to the CoreMIDI API + // implementation. + struct WinMidiData { + HMIDIIN inHandle; // Handle to Midi Input Device + HMIDIOUT outHandle; // Handle to Midi Output Device + DWORD lastTime; + MidiInApi::MidiMessage message; + LPMIDIHDR sysexBuffer[RT_SYSEX_BUFFER_COUNT]; + CRITICAL_SECTION _mutex; // [Patrice] see https://groups.google.com/forum/#!topic/mididev/6OUjHutMpEo + }; + + //*********************************************************************// + // API: Windows MM + // Class Definitions: MidiInWinMM + //*********************************************************************// + + static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, + UINT inputStatus, + DWORD_PTR instancePtr, + DWORD_PTR midiMessage, + DWORD timestamp ) + { + if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA && inputStatus != MIM_LONGERROR ) return; + + //MidiInApi::MidiInData *data = static_cast (instancePtr); + MidiInApi::MidiInData *data = (MidiInApi::MidiInData *)instancePtr; + WinMidiData *apiData = static_cast (data->apiData); + + // Calculate time stamp. + if ( data->firstMessage == true ) { + apiData->message.timeStamp = 0.0; + data->firstMessage = false; + } + else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001; + apiData->lastTime = timestamp; + + if ( inputStatus == MIM_DATA ) { // Channel or system message + + // Make sure the first byte is a status byte. + unsigned char status = (unsigned char) (midiMessage & 0x000000FF); + if ( !(status & 0x80) ) return; + + // Determine the number of bytes in the MIDI message. + unsigned short nBytes = 1; + if ( status < 0xC0 ) nBytes = 3; + else if ( status < 0xE0 ) nBytes = 2; + else if ( status < 0xF0 ) nBytes = 3; + else if ( status == 0xF1 ) { + if ( data->ignoreFlags & 0x02 ) return; + else nBytes = 2; + } + else if ( status == 0xF2 ) nBytes = 3; + else if ( status == 0xF3 ) nBytes = 2; + else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) { + // A MIDI timing tick message and we're ignoring it. + return; + } + else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { + // A MIDI active sensing message and we're ignoring it. + return; + } + + // Copy bytes to our MIDI message. + unsigned char *ptr = (unsigned char *) &midiMessage; + for ( int i=0; imessage.bytes.push_back( *ptr++ ); + } + else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) + MIDIHDR *sysex = ( MIDIHDR *) midiMessage; + if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { + // Sysex message and we're not ignoring it + for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) + apiData->message.bytes.push_back( sysex->lpData[i] ); + } + + // The WinMM API requires that the sysex buffer be requeued after + // input of each sysex message. Even if we are ignoring sysex + // messages, we still need to requeue the buffer in case the user + // decides to not ignore sysex messages in the future. However, + // it seems that WinMM calls this function with an empty sysex + // buffer when an application closes and in this case, we should + // avoid requeueing it, else the computer suddenly reboots after + // one or two minutes. + if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { + //if ( sysex->dwBytesRecorded > 0 ) { + EnterCriticalSection( &(apiData->_mutex) ); + MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); + LeaveCriticalSection( &(apiData->_mutex) ); + if ( result != MMSYSERR_NOERROR ) + std::cerr << "\nMidiIn::midiInputCallback: error sending sysex to Midi device!!\n\n"; + + if ( data->ignoreFlags & 0x01 ) return; + } + else return; + } + + if ( data->usingCallback ) { + MidiCallback callback = (MidiCallback) data->userCallback; + callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = apiData->message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else + std::cerr << "\nMidiIn: message queue limit reached!!\n\n"; + } + + // Clear the vector for the next input message. + apiData->message.bytes.clear(); + } -// A structure to hold variables related to the CoreMIDI API -// implementation. -struct WinMidiData { - HMIDIIN inHandle; // Handle to Midi Input Device - HMIDIOUT outHandle; // Handle to Midi Output Device - DWORD lastTime; - MidiInApi::MidiMessage message; - LPMIDIHDR sysexBuffer[RT_SYSEX_BUFFER_COUNT]; - CRITICAL_SECTION _mutex; // [Patrice] see https://groups.google.com/forum/#!topic/mididev/6OUjHutMpEo -}; - -//*********************************************************************// -// API: Windows MM -// Class Definitions: MidiInWinMM -//*********************************************************************// - -static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, - UINT inputStatus, - DWORD_PTR instancePtr, - DWORD_PTR midiMessage, - DWORD timestamp ) -{ - if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA && inputStatus != MIM_LONGERROR ) return; - - //MidiInApi::RtMidiInData *data = static_cast (instancePtr); - MidiInApi::RtMidiInData *data = (MidiInApi::RtMidiInData *)instancePtr; - WinMidiData *apiData = static_cast (data->apiData); - - // Calculate time stamp. - if ( data->firstMessage == true ) { - apiData->message.timeStamp = 0.0; - data->firstMessage = false; - } - else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001; - apiData->lastTime = timestamp; - - if ( inputStatus == MIM_DATA ) { // Channel or system message - - // Make sure the first byte is a status byte. - unsigned char status = (unsigned char) (midiMessage & 0x000000FF); - if ( !(status & 0x80) ) return; - - // Determine the number of bytes in the MIDI message. - unsigned short nBytes = 1; - if ( status < 0xC0 ) nBytes = 3; - else if ( status < 0xE0 ) nBytes = 2; - else if ( status < 0xF0 ) nBytes = 3; - else if ( status == 0xF1 ) { - if ( data->ignoreFlags & 0x02 ) return; - else nBytes = 2; - } - else if ( status == 0xF2 ) nBytes = 3; - else if ( status == 0xF3 ) nBytes = 2; - else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) { - // A MIDI timing tick message and we're ignoring it. - return; - } - else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { - // A MIDI active sensing message and we're ignoring it. - return; - } - - // Copy bytes to our MIDI message. - unsigned char *ptr = (unsigned char *) &midiMessage; - for ( int i=0; imessage.bytes.push_back( *ptr++ ); - } - else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) - MIDIHDR *sysex = ( MIDIHDR *) midiMessage; - if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { - // Sysex message and we're not ignoring it - for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) - apiData->message.bytes.push_back( sysex->lpData[i] ); - } - - // The WinMM API requires that the sysex buffer be requeued after - // input of each sysex message. Even if we are ignoring sysex - // messages, we still need to requeue the buffer in case the user - // decides to not ignore sysex messages in the future. However, - // it seems that WinMM calls this function with an empty sysex - // buffer when an application closes and in this case, we should - // avoid requeueing it, else the computer suddenly reboots after - // one or two minutes. - if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { - //if ( sysex->dwBytesRecorded > 0 ) { - EnterCriticalSection( &(apiData->_mutex) ); - MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); - LeaveCriticalSection( &(apiData->_mutex) ); - if ( result != MMSYSERR_NOERROR ) - std::cerr << "\nRtMidiIn::midiInputCallback: error sending sysex to Midi device!!\n\n"; - - if ( data->ignoreFlags & 0x01 ) return; - } - else return; - } - - if ( data->usingCallback ) { - RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; - callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = apiData->message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else - std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n"; - } - - // Clear the vector for the next input message. - apiData->message.bytes.clear(); -} - -MidiInWinMM :: MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) -{ - initialize( clientName ); -} + MidiInWinMM :: MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) + { + initialize( clientName ); + } -MidiInWinMM :: ~MidiInWinMM() -{ - // Close a connection if it exists. - closePort(); + MidiInWinMM :: ~MidiInWinMM() + { + // Close a connection if it exists. + closePort(); - WinMidiData *data = static_cast (apiData_); - DeleteCriticalSection( &(data->_mutex) ); + WinMidiData *data = static_cast (apiData_); + DeleteCriticalSection( &(data->_mutex) ); - // Cleanup. - delete data; -} + // Cleanup. + delete data; + } -void MidiInWinMM :: initialize( const std::string& /*clientName*/ ) -{ - // We'll issue a warning here if no devices are available but not - // throw an error since the user can plugin something later. - unsigned int nDevices = midiInGetNumDevs(); - if ( nDevices == 0 ) { - errorString_ = "MidiInWinMM::initialize: no MIDI input devices currently available."; - error( RtMidiError::WARNING, errorString_ ); - } - - // Save our api-specific connection information. - WinMidiData *data = (WinMidiData *) new WinMidiData; - apiData_ = (void *) data; - inputData_.apiData = (void *) data; - data->message.bytes.clear(); // needs to be empty for first input message - - if ( !InitializeCriticalSectionAndSpinCount(&(data->_mutex), 0x00000400) ) { - errorString_ = "MidiInWinMM::initialize: InitializeCriticalSectionAndSpinCount failed."; - error( RtMidiError::WARNING, errorString_ ); - } -} + void MidiInWinMM :: initialize( const std::string& /*clientName*/ ) + { + // We'll issue a warning here if no devices are available but not + // throw an error since the user can plugin something later. + unsigned int nDevices = midiInGetNumDevs(); + if ( nDevices == 0 ) { + errorString_ = "MidiInWinMM::initialize: no MIDI input devices currently available."; + error( Error::WARNING, errorString_ ); + } + + // Save our api-specific connection information. + WinMidiData *data = (WinMidiData *) new WinMidiData; + apiData_ = (void *) data; + inputData_.apiData = (void *) data; + data->message.bytes.clear(); // needs to be empty for first input message + + if ( !InitializeCriticalSectionAndSpinCount(&(data->_mutex), 0x00000400) ) { + errorString_ = "MidiInWinMM::initialize: InitializeCriticalSectionAndSpinCount failed."; + error( Error::WARNING, errorString_ ); + } + } -void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) -{ - if ( connected_ ) { - errorString_ = "MidiInWinMM::openPort: a valid connection already exists!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - unsigned int nDevices = midiInGetNumDevs(); - if (nDevices == 0) { - errorString_ = "MidiInWinMM::openPort: no MIDI input sources found!"; - error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); - return; - } - - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiInWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::INVALID_PARAMETER, errorString_ ); - return; - } - - WinMidiData *data = static_cast (apiData_); - MMRESULT result = midiInOpen( &data->inHandle, - portNumber, - (DWORD_PTR)&midiInputCallback, - (DWORD_PTR)&inputData_, - CALLBACK_FUNCTION ); - if ( result != MMSYSERR_NOERROR ) { - errorString_ = "MidiInWinMM::openPort: error creating Windows MM MIDI input port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Allocate and init the sysex buffers. - for ( int i=0; isysexBuffer[i] = (MIDIHDR*) new char[ sizeof(MIDIHDR) ]; - data->sysexBuffer[i]->lpData = new char[ RT_SYSEX_BUFFER_SIZE ]; - data->sysexBuffer[i]->dwBufferLength = RT_SYSEX_BUFFER_SIZE; - data->sysexBuffer[i]->dwUser = i; // We use the dwUser parameter as buffer indicator - data->sysexBuffer[i]->dwFlags = 0; - - result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (PrepareHeader)."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Register the buffer. - result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (AddBuffer)."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - } - - result = midiInStart( data->inHandle ); - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - connected_ = true; -} + void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) + { + if ( connected_ ) { + errorString_ = "MidiInWinMM::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + + unsigned int nDevices = midiInGetNumDevs(); + if (nDevices == 0) { + errorString_ = "MidiInWinMM::openPort: no MIDI input sources found!"; + error( Error::NO_DEVICES_FOUND, errorString_ ); + return; + } + + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiInWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::INVALID_PARAMETER, errorString_ ); + return; + } + + WinMidiData *data = static_cast (apiData_); + MMRESULT result = midiInOpen( &data->inHandle, + portNumber, + (DWORD_PTR)&midiInputCallback, + (DWORD_PTR)&inputData_, + CALLBACK_FUNCTION ); + if ( result != MMSYSERR_NOERROR ) { + errorString_ = "MidiInWinMM::openPort: error creating Windows MM MIDI input port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Allocate and init the sysex buffers. + for ( int i=0; isysexBuffer[i] = (MIDIHDR*) new char[ sizeof(MIDIHDR) ]; + data->sysexBuffer[i]->lpData = new char[ RT_SYSEX_BUFFER_SIZE ]; + data->sysexBuffer[i]->dwBufferLength = RT_SYSEX_BUFFER_SIZE; + data->sysexBuffer[i]->dwUser = i; // We use the dwUser parameter as buffer indicator + data->sysexBuffer[i]->dwFlags = 0; + + result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (PrepareHeader)."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Register the buffer. + result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (AddBuffer)."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + } + + result = midiInStart( data->inHandle ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + connected_ = true; + } -void MidiInWinMM :: openVirtualPort( std::string /*portName*/ ) -{ - // This function cannot be implemented for the Windows MM MIDI API. - errorString_ = "MidiInWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; - error( RtMidiError::WARNING, errorString_ ); -} + void MidiInWinMM :: openVirtualPort( std::string /*portName*/ ) + { + // This function cannot be implemented for the Windows MM MIDI API. + errorString_ = "MidiInWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; + error( Error::WARNING, errorString_ ); + } -void MidiInWinMM :: closePort( void ) -{ - if ( connected_ ) { - WinMidiData *data = static_cast (apiData_); - EnterCriticalSection( &(data->_mutex) ); - midiInReset( data->inHandle ); - midiInStop( data->inHandle ); - - for ( int i=0; iinHandle, data->sysexBuffer[i], sizeof(MIDIHDR)); - delete [] data->sysexBuffer[i]->lpData; - delete [] data->sysexBuffer[i]; - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader)."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - } - - midiInClose( data->inHandle ); - connected_ = false; - LeaveCriticalSection( &(data->_mutex) ); - } -} + void MidiInWinMM :: closePort( void ) + { + if ( connected_ ) { + WinMidiData *data = static_cast (apiData_); + EnterCriticalSection( &(data->_mutex) ); + midiInReset( data->inHandle ); + midiInStop( data->inHandle ); + + for ( int i=0; iinHandle, data->sysexBuffer[i], sizeof(MIDIHDR)); + delete [] data->sysexBuffer[i]->lpData; + delete [] data->sysexBuffer[i]; + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + errorString_ = "MidiInWinMM::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader)."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + } + + midiInClose( data->inHandle ); + connected_ = false; + LeaveCriticalSection( &(data->_mutex) ); + } + } -unsigned int MidiInWinMM :: getPortCount() -{ - return midiInGetNumDevs(); -} + unsigned int MidiInWinMM :: getPortCount() + { + return midiInGetNumDevs(); + } -std::string MidiInWinMM :: getPortName( unsigned int portNumber ) -{ - std::string stringName; - unsigned int nDevices = midiInGetNumDevs(); - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiInWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return stringName; - } - - MIDIINCAPS deviceCaps; - midiInGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIINCAPS)); + std::string MidiInWinMM :: getPortName( unsigned int portNumber ) + { + std::string stringName; + unsigned int nDevices = midiInGetNumDevs(); + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiInWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::WARNING, errorString_ ); + return stringName; + } + + MIDIINCAPS deviceCaps; + midiInGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIINCAPS)); #if defined( UNICODE ) || defined( _UNICODE ) - int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; - stringName.assign( length, 0 ); - length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); + int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; + stringName.assign( length, 0 ); + length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); #else - stringName = std::string( deviceCaps.szPname ); + stringName = std::string( deviceCaps.szPname ); #endif - // 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 - std::ostringstream os; - os << " "; - os << portNumber; - stringName += os.str(); + // 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 + std::ostringstream os; + os << " "; + os << portNumber; + stringName += os.str(); - return stringName; -} + return stringName; + } -//*********************************************************************// -// API: Windows MM -// Class Definitions: MidiOutWinMM -//*********************************************************************// + //*********************************************************************// + // API: Windows MM + // Class Definitions: MidiOutWinMM + //*********************************************************************// -MidiOutWinMM :: MidiOutWinMM( const std::string clientName ) : MidiOutApi() -{ - initialize( clientName ); -} + MidiOutWinMM :: MidiOutWinMM( const std::string clientName ) : MidiOutApi() + { + initialize( clientName ); + } -MidiOutWinMM :: ~MidiOutWinMM() -{ - // Close a connection if it exists. - closePort(); + MidiOutWinMM :: ~MidiOutWinMM() + { + // Close a connection if it exists. + closePort(); - // Cleanup. - WinMidiData *data = static_cast (apiData_); - delete data; -} + // Cleanup. + WinMidiData *data = static_cast (apiData_); + delete data; + } -void MidiOutWinMM :: initialize( const std::string& /*clientName*/ ) -{ - // We'll issue a warning here if no devices are available but not - // throw an error since the user can plug something in later. - unsigned int nDevices = midiOutGetNumDevs(); - if ( nDevices == 0 ) { - errorString_ = "MidiOutWinMM::initialize: no MIDI output devices currently available."; - error( RtMidiError::WARNING, errorString_ ); - } - - // Save our api-specific connection information. - WinMidiData *data = (WinMidiData *) new WinMidiData; - apiData_ = (void *) data; -} + void MidiOutWinMM :: initialize( const std::string& /*clientName*/ ) + { + // We'll issue a warning here if no devices are available but not + // throw an error since the user can plug something in later. + unsigned int nDevices = midiOutGetNumDevs(); + if ( nDevices == 0 ) { + errorString_ = "MidiOutWinMM::initialize: no MIDI output devices currently available."; + error( Error::WARNING, errorString_ ); + } + + // Save our api-specific connection information. + WinMidiData *data = (WinMidiData *) new WinMidiData; + apiData_ = (void *) data; + } -unsigned int MidiOutWinMM :: getPortCount() -{ - return midiOutGetNumDevs(); -} + unsigned int MidiOutWinMM :: getPortCount() + { + return midiOutGetNumDevs(); + } -std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) -{ - std::string stringName; - unsigned int nDevices = midiOutGetNumDevs(); - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiOutWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return stringName; - } - - MIDIOUTCAPS deviceCaps; - midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS)); + std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) + { + std::string stringName; + unsigned int nDevices = midiOutGetNumDevs(); + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiOutWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::WARNING, errorString_ ); + return stringName; + } + + MIDIOUTCAPS deviceCaps; + midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS)); #if defined( UNICODE ) || defined( _UNICODE ) - int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; - stringName.assign( length, 0 ); - length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); + int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; + stringName.assign( length, 0 ); + length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); #else - stringName = std::string( deviceCaps.szPname ); + stringName = std::string( deviceCaps.szPname ); #endif - return stringName; -} + return stringName; + } -void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) -{ - if ( connected_ ) { - errorString_ = "MidiOutWinMM::openPort: a valid connection already exists!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - unsigned int nDevices = midiOutGetNumDevs(); - if (nDevices < 1) { - errorString_ = "MidiOutWinMM::openPort: no MIDI output destinations found!"; - error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); - return; - } - - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiOutWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::INVALID_PARAMETER, errorString_ ); - return; - } - - WinMidiData *data = static_cast (apiData_); - MMRESULT result = midiOutOpen( &data->outHandle, - portNumber, - (DWORD)NULL, - (DWORD)NULL, - CALLBACK_NULL ); - if ( result != MMSYSERR_NOERROR ) { - errorString_ = "MidiOutWinMM::openPort: error creating Windows MM MIDI output port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - connected_ = true; -} + void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) + { + if ( connected_ ) { + errorString_ = "MidiOutWinMM::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + + unsigned int nDevices = midiOutGetNumDevs(); + if (nDevices < 1) { + errorString_ = "MidiOutWinMM::openPort: no MIDI output destinations found!"; + error( Error::NO_DEVICES_FOUND, errorString_ ); + return; + } + + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiOutWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::INVALID_PARAMETER, errorString_ ); + return; + } + + WinMidiData *data = static_cast (apiData_); + MMRESULT result = midiOutOpen( &data->outHandle, + portNumber, + (DWORD)NULL, + (DWORD)NULL, + CALLBACK_NULL ); + if ( result != MMSYSERR_NOERROR ) { + errorString_ = "MidiOutWinMM::openPort: error creating Windows MM MIDI output port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + connected_ = true; + } -void MidiOutWinMM :: closePort( void ) -{ - if ( connected_ ) { - WinMidiData *data = static_cast (apiData_); - midiOutReset( data->outHandle ); - midiOutClose( data->outHandle ); - connected_ = false; - } -} + void MidiOutWinMM :: closePort( void ) + { + if ( connected_ ) { + WinMidiData *data = static_cast (apiData_); + midiOutReset( data->outHandle ); + midiOutClose( data->outHandle ); + connected_ = false; + } + } -void MidiOutWinMM :: openVirtualPort( std::string /*portName*/ ) -{ - // This function cannot be implemented for the Windows MM MIDI API. - errorString_ = "MidiOutWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; - error( RtMidiError::WARNING, errorString_ ); -} + void MidiOutWinMM :: openVirtualPort( std::string /*portName*/ ) + { + // This function cannot be implemented for the Windows MM MIDI API. + errorString_ = "MidiOutWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; + error( Error::WARNING, errorString_ ); + } -void MidiOutWinMM :: sendMessage( std::vector *message ) -{ - if ( !connected_ ) return; - - unsigned int nBytes = static_cast(message->size()); - if ( nBytes == 0 ) { - errorString_ = "MidiOutWinMM::sendMessage: message argument is empty!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - MMRESULT result; - WinMidiData *data = static_cast (apiData_); - if ( message->at(0) == 0xF0 ) { // Sysex message - - // Allocate buffer for sysex data. - char *buffer = (char *) malloc( nBytes ); - if ( buffer == NULL ) { - errorString_ = "MidiOutWinMM::sendMessage: error allocating sysex message memory!"; - error( RtMidiError::MEMORY_ERROR, errorString_ ); - return; - } - - // Copy data to buffer. - for ( unsigned int i=0; iat(i); - - // Create and prepare MIDIHDR structure. - MIDIHDR sysex; - sysex.lpData = (LPSTR) buffer; - sysex.dwBufferLength = nBytes; - sysex.dwFlags = 0; - result = midiOutPrepareHeader( data->outHandle, &sysex, sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - free( buffer ); - errorString_ = "MidiOutWinMM::sendMessage: error preparing sysex header."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Send the message. - result = midiOutLongMsg( data->outHandle, &sysex, sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - free( buffer ); - errorString_ = "MidiOutWinMM::sendMessage: error sending sysex message."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Unprepare the buffer and MIDIHDR. - while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof (MIDIHDR) ) ) Sleep( 1 ); - free( buffer ); - } - else { // Channel or system message. - - // Make sure the message size isn't too big. - if ( nBytes > 3 ) { - errorString_ = "MidiOutWinMM::sendMessage: message size is greater than 3 bytes (and not sysex)!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - // Pack MIDI bytes into double word. - DWORD packet; - unsigned char *ptr = (unsigned char *) &packet; - for ( unsigned int i=0; iat(i); - ++ptr; - } - - // Send the message immediately. - result = midiOutShortMsg( data->outHandle, packet ); - if ( result != MMSYSERR_NOERROR ) { - errorString_ = "MidiOutWinMM::sendMessage: error sending MIDI message."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - } - } + void MidiOutWinMM :: sendMessage( std::vector *message ) + { + if ( !connected_ ) return; + + unsigned int nBytes = static_cast(message->size()); + if ( nBytes == 0 ) { + errorString_ = "MidiOutWinMM::sendMessage: message argument is empty!"; + error( Error::WARNING, errorString_ ); + return; + } + + MMRESULT result; + WinMidiData *data = static_cast (apiData_); + if ( message->at(0) == 0xF0 ) { // Sysex message + + // Allocate buffer for sysex data. + char *buffer = (char *) malloc( nBytes ); + if ( buffer == NULL ) { + errorString_ = "MidiOutWinMM::sendMessage: error allocating sysex message memory!"; + error( Error::MEMORY_ERROR, errorString_ ); + return; + } + + // Copy data to buffer. + for ( unsigned int i=0; iat(i); + + // Create and prepare MIDIHDR structure. + MIDIHDR sysex; + sysex.lpData = (LPSTR) buffer; + sysex.dwBufferLength = nBytes; + sysex.dwFlags = 0; + result = midiOutPrepareHeader( data->outHandle, &sysex, sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + free( buffer ); + errorString_ = "MidiOutWinMM::sendMessage: error preparing sysex header."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Send the message. + result = midiOutLongMsg( data->outHandle, &sysex, sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + free( buffer ); + errorString_ = "MidiOutWinMM::sendMessage: error sending sysex message."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Unprepare the buffer and MIDIHDR. + while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof (MIDIHDR) ) ) Sleep( 1 ); + free( buffer ); + } + else { // Channel or system message. + + // Make sure the message size isn't too big. + if ( nBytes > 3 ) { + errorString_ = "MidiOutWinMM::sendMessage: message size is greater than 3 bytes (and not sysex)!"; + error( Error::WARNING, errorString_ ); + return; + } + + // Pack MIDI bytes into double word. + DWORD packet; + unsigned char *ptr = (unsigned char *) &packet; + for ( unsigned int i=0; iat(i); + ++ptr; + } + + // Send the message immediately. + result = midiOutShortMsg( data->outHandle, packet ); + if ( result != MMSYSERR_NOERROR ) { + errorString_ = "MidiOutWinMM::sendMessage: error sending MIDI message."; + error( Error::DRIVER_ERROR, errorString_ ); + } + } + } } - #endif // __WINDOWS_MM__ -//*********************************************************************// -// API: UNIX JACK -// -// Written primarily by Alexander Svetalkin, with updates for delta -// time by Gary Scavone, April 2011. -// -// *********************************************************************// + //*********************************************************************// + // API: UNIX JACK + // + // Written primarily by Alexander Svetalkin, with updates for delta + // time by Gary Scavone, April 2011. + // + // *********************************************************************// #if defined(__UNIX_JACK__) -// JACK header files + // JACK header files #include #include #include #define JACK_RINGBUFFER_SIZE 16384 // Default size for ringbuffer -struct JackMidiData { - jack_client_t *client; - jack_port_t *port; - jack_ringbuffer_t *buffSize; - jack_ringbuffer_t *buffMessage; - jack_time_t lastTime; - MidiInApi :: RtMidiInData *rtMidiIn; - }; - -//*********************************************************************// -// API: JACK -// Class Definitions: MidiInJack -//*********************************************************************// - -static int jackProcessIn( jack_nframes_t nframes, void *arg ) -{ - JackMidiData *jData = (JackMidiData *) arg; - MidiInApi :: RtMidiInData *rtData = jData->rtMidiIn; - jack_midi_event_t event; - jack_time_t time; - - // Is port created? - if ( jData->port == NULL ) return 0; - void *buff = jack_port_get_buffer( jData->port, nframes ); - - // 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(); - - 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 ) - rtData->firstMessage = false; - else - message.timeStamp = ( time - jData->lastTime ) * 0.000001; - - jData->lastTime = time; - - if ( !rtData->continueSysex ) { - if ( rtData->usingCallback ) { - RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) rtData->userCallback; - callback( message.timeStamp, &message.bytes, rtData->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( rtData->queue.size < rtData->queue.ringSize ) { - rtData->queue.ring[rtData->queue.back++] = message; - if ( rtData->queue.back == rtData->queue.ringSize ) - rtData->queue.back = 0; - rtData->queue.size++; - } - else - std::cerr << "\nMidiInJack: message queue limit reached!!\n\n"; - } - } - } - - return 0; -} +namespace rtmidi { + + struct JackMidiData { + jack_client_t *client; + jack_port_t *port; + jack_ringbuffer_t *buffSize; + jack_ringbuffer_t *buffMessage; + jack_time_t lastTime; + MidiInApi :: MidiInData *rtMidiIn; + }; + + //*********************************************************************// + // API: JACK + // Class Definitions: MidiInJack + //*********************************************************************// + + static int jackProcessIn( jack_nframes_t nframes, void *arg ) + { + JackMidiData *jData = (JackMidiData *) arg; + MidiInApi :: MidiInData *rtData = jData->rtMidiIn; + jack_midi_event_t event; + jack_time_t time; + + // Is port created? + if ( jData->port == NULL ) return 0; + void *buff = jack_port_get_buffer( jData->port, nframes ); + + // 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(); + + 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 ) + rtData->firstMessage = false; + else + message.timeStamp = ( time - jData->lastTime ) * 0.000001; + + jData->lastTime = time; + + if ( !rtData->continueSysex ) { + if ( rtData->usingCallback ) { + MidiCallback callback = (MidiCallback) rtData->userCallback; + callback( message.timeStamp, &message.bytes, rtData->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( rtData->queue.size < rtData->queue.ringSize ) { + rtData->queue.ring[rtData->queue.back++] = message; + if ( rtData->queue.back == rtData->queue.ringSize ) + rtData->queue.back = 0; + rtData->queue.size++; + } + else + std::cerr << "\nMidiInJack: message queue limit reached!!\n\n"; + } + } + } + + return 0; + } -MidiInJack :: MidiInJack( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) -{ - initialize( clientName ); -} + MidiInJack :: MidiInJack( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) + { + initialize( clientName ); + } -void MidiInJack :: initialize( const std::string& clientName ) -{ - JackMidiData *data = new JackMidiData; - apiData_ = (void *) data; + void MidiInJack :: initialize( const std::string& clientName ) + { + JackMidiData *data = new JackMidiData; + apiData_ = (void *) data; - data->rtMidiIn = &inputData_; - data->port = NULL; - data->client = NULL; - this->clientName = clientName; + data->rtMidiIn = &inputData_; + data->port = NULL; + data->client = NULL; + this->clientName = clientName; - connect(); -} + connect(); + } -void MidiInJack :: connect() -{ - JackMidiData *data = static_cast (apiData_); - if ( data->client ) - return; - - // Initialize JACK client - if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { - errorString_ = "MidiInJack::initialize: JACK server not running?"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - jack_set_process_callback( data->client, jackProcessIn, data ); - jack_activate( data->client ); -} + void MidiInJack :: connect() + { + JackMidiData *data = static_cast (apiData_); + if ( data->client ) + return; + + // Initialize JACK client + if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { + errorString_ = "MidiInJack::initialize: JACK server not running?"; + error( Error::WARNING, errorString_ ); + return; + } + + jack_set_process_callback( data->client, jackProcessIn, data ); + jack_activate( data->client ); + } -MidiInJack :: ~MidiInJack() -{ - JackMidiData *data = static_cast (apiData_); - closePort(); + MidiInJack :: ~MidiInJack() + { + JackMidiData *data = static_cast (apiData_); + closePort(); - if ( data->client ) - jack_client_close( data->client ); - delete data; -} + if ( data->client ) + jack_client_close( data->client ); + delete data; + } -void MidiInJack :: openPort( unsigned int portNumber, const std::string portName ) -{ - JackMidiData *data = static_cast (apiData_); + void MidiInJack :: openPort( unsigned int portNumber, const std::string portName ) + { + JackMidiData *data = static_cast (apiData_); - connect(); + connect(); - // Creating new port - if ( data->port == NULL) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); + // Creating new port + if ( data->port == NULL) + data->port = jack_port_register( data->client, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); - if ( data->port == NULL) { - errorString_ = "MidiInJack::openPort: JACK error creating port"; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } + if ( data->port == NULL) { + errorString_ = "MidiInJack::openPort: JACK error creating port"; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } - // Connecting to the output - std::string name = getPortName( portNumber ); - jack_connect( data->client, name.c_str(), jack_port_name( data->port ) ); -} + // Connecting to the output + std::string name = getPortName( portNumber ); + jack_connect( data->client, name.c_str(), jack_port_name( data->port ) ); + } -void MidiInJack :: openVirtualPort( const std::string portName ) -{ - JackMidiData *data = static_cast (apiData_); + void MidiInJack :: openVirtualPort( const std::string portName ) + { + JackMidiData *data = static_cast (apiData_); - connect(); - if ( data->port == NULL ) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); + connect(); + if ( data->port == NULL ) + data->port = jack_port_register( data->client, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); - if ( data->port == NULL ) { - errorString_ = "MidiInJack::openVirtualPort: JACK error creating virtual port"; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - } -} + if ( data->port == NULL ) { + errorString_ = "MidiInJack::openVirtualPort: JACK error creating virtual port"; + error( Error::DRIVER_ERROR, errorString_ ); + } + } -unsigned int MidiInJack :: getPortCount() -{ - int count = 0; - JackMidiData *data = static_cast (apiData_); - connect(); - if ( !data->client ) - return 0; + unsigned int MidiInJack :: getPortCount() + { + int count = 0; + JackMidiData *data = static_cast (apiData_); + connect(); + if ( !data->client ) + return 0; - // List of available ports - const char **ports = jack_get_ports( data->client, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); + // List of available ports + const char **ports = jack_get_ports( data->client, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); - if ( ports == NULL ) return 0; - while ( ports[count] != NULL ) - count++; + if ( ports == NULL ) return 0; + while ( ports[count] != NULL ) + count++; - free( ports ); + free( ports ); - return count; -} + return count; + } -std::string MidiInJack :: getPortName( unsigned int portNumber ) -{ - JackMidiData *data = static_cast (apiData_); - std::string retStr(""); - - connect(); - - // List of available ports - const char **ports = jack_get_ports( data->client, NULL, - JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); - - // Check port validity - if ( ports == NULL ) { - errorString_ = "MidiInJack::getPortName: no ports available!"; - error( RtMidiError::WARNING, errorString_ ); - return retStr; - } - - if ( ports[portNumber] == NULL ) { - std::ostringstream ost; - ost << "MidiInJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - } - else retStr.assign( ports[portNumber] ); - - free( ports ); - return retStr; -} + std::string MidiInJack :: getPortName( unsigned int portNumber ) + { + JackMidiData *data = static_cast (apiData_); + std::string retStr(""); + + connect(); + + // List of available ports + const char **ports = jack_get_ports( data->client, NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); + + // Check port validity + if ( ports == NULL ) { + errorString_ = "MidiInJack::getPortName: no ports available!"; + error( Error::WARNING, errorString_ ); + return retStr; + } + + if ( ports[portNumber] == NULL ) { + std::ostringstream ost; + ost << "MidiInJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::WARNING, errorString_ ); + } + else retStr.assign( ports[portNumber] ); + + free( ports ); + return retStr; + } -void MidiInJack :: closePort() -{ - JackMidiData *data = static_cast (apiData_); + void MidiInJack :: closePort() + { + JackMidiData *data = static_cast (apiData_); - if ( data->port == NULL ) return; - jack_port_unregister( data->client, data->port ); - data->port = NULL; -} + if ( data->port == NULL ) return; + jack_port_unregister( data->client, data->port ); + data->port = NULL; + } -//*********************************************************************// -// API: JACK -// Class Definitions: MidiOutJack -//*********************************************************************// + //*********************************************************************// + // API: JACK + // Class Definitions: MidiOutJack + //*********************************************************************// -// Jack process callback -static int jackProcessOut( jack_nframes_t nframes, void *arg ) -{ - JackMidiData *data = (JackMidiData *) arg; - jack_midi_data_t *midiData; - int space; + // Jack process callback + static int jackProcessOut( jack_nframes_t nframes, void *arg ) + { + JackMidiData *data = (JackMidiData *) arg; + jack_midi_data_t *midiData; + int space; - // Is port created? - if ( data->port == NULL ) return 0; + // Is port created? + if ( data->port == NULL ) return 0; - void *buff = jack_port_get_buffer( data->port, nframes ); - jack_midi_clear_buffer( buff ); + void *buff = jack_port_get_buffer( data->port, nframes ); + jack_midi_clear_buffer( buff ); - while ( jack_ringbuffer_read_space( data->buffSize ) > 0 ) { - jack_ringbuffer_read( data->buffSize, (char *) &space, (size_t) sizeof(space) ); - midiData = jack_midi_event_reserve( buff, 0, space ); + while ( jack_ringbuffer_read_space( data->buffSize ) > 0 ) { + jack_ringbuffer_read( data->buffSize, (char *) &space, (size_t) sizeof(space) ); + midiData = jack_midi_event_reserve( buff, 0, space ); - jack_ringbuffer_read( data->buffMessage, (char *) midiData, (size_t) space ); - } + jack_ringbuffer_read( data->buffMessage, (char *) midiData, (size_t) space ); + } - return 0; -} + return 0; + } -MidiOutJack :: MidiOutJack( const std::string clientName ) : MidiOutApi() -{ - initialize( clientName ); -} + MidiOutJack :: MidiOutJack( const std::string clientName ) : MidiOutApi() + { + initialize( clientName ); + } -void MidiOutJack :: initialize( const std::string& clientName ) -{ - JackMidiData *data = new JackMidiData; - apiData_ = (void *) data; + void MidiOutJack :: initialize( const std::string& clientName ) + { + JackMidiData *data = new JackMidiData; + apiData_ = (void *) data; - data->port = NULL; - data->client = NULL; - this->clientName = clientName; + data->port = NULL; + data->client = NULL; + this->clientName = clientName; - connect(); -} + connect(); + } -void MidiOutJack :: connect() -{ - JackMidiData *data = static_cast (apiData_); - if ( data->client ) - return; - - // Initialize JACK client - if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { - errorString_ = "MidiOutJack::initialize: JACK server not running?"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - jack_set_process_callback( data->client, jackProcessOut, data ); - data->buffSize = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); - data->buffMessage = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); - jack_activate( data->client ); -} + void MidiOutJack :: connect() + { + JackMidiData *data = static_cast (apiData_); + if ( data->client ) + return; + + // Initialize JACK client + if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { + errorString_ = "MidiOutJack::initialize: JACK server not running?"; + error( Error::WARNING, errorString_ ); + return; + } + + jack_set_process_callback( data->client, jackProcessOut, data ); + data->buffSize = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); + data->buffMessage = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); + jack_activate( data->client ); + } -MidiOutJack :: ~MidiOutJack() -{ - JackMidiData *data = static_cast (apiData_); - closePort(); + MidiOutJack :: ~MidiOutJack() + { + JackMidiData *data = static_cast (apiData_); + closePort(); - if ( data->client ) { - // Cleanup - jack_client_close( data->client ); - jack_ringbuffer_free( data->buffSize ); - jack_ringbuffer_free( data->buffMessage ); - } + if ( data->client ) { + // Cleanup + jack_client_close( data->client ); + jack_ringbuffer_free( data->buffSize ); + jack_ringbuffer_free( data->buffMessage ); + } - delete data; -} + delete data; + } -void MidiOutJack :: openPort( unsigned int portNumber, const std::string portName ) -{ - JackMidiData *data = static_cast (apiData_); + void MidiOutJack :: openPort( unsigned int portNumber, const std::string portName ) + { + JackMidiData *data = static_cast (apiData_); - connect(); + connect(); - // Creating new port - if ( data->port == NULL ) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); + // Creating new port + if ( data->port == NULL ) + data->port = jack_port_register( data->client, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); - if ( data->port == NULL ) { - errorString_ = "MidiOutJack::openPort: JACK error creating port"; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } + if ( data->port == NULL ) { + errorString_ = "MidiOutJack::openPort: JACK error creating port"; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } - // Connecting to the output - std::string name = getPortName( portNumber ); - jack_connect( data->client, jack_port_name( data->port ), name.c_str() ); -} + // Connecting to the output + std::string name = getPortName( portNumber ); + jack_connect( data->client, jack_port_name( data->port ), name.c_str() ); + } -void MidiOutJack :: openVirtualPort( const std::string portName ) -{ - JackMidiData *data = static_cast (apiData_); + void MidiOutJack :: openVirtualPort( const std::string portName ) + { + JackMidiData *data = static_cast (apiData_); - connect(); - if ( data->port == NULL ) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); + connect(); + if ( data->port == NULL ) + data->port = jack_port_register( data->client, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); - if ( data->port == NULL ) { - errorString_ = "MidiOutJack::openVirtualPort: JACK error creating virtual port"; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - } -} + if ( data->port == NULL ) { + errorString_ = "MidiOutJack::openVirtualPort: JACK error creating virtual port"; + error( Error::DRIVER_ERROR, errorString_ ); + } + } -unsigned int MidiOutJack :: getPortCount() -{ - int count = 0; - JackMidiData *data = static_cast (apiData_); - connect(); - if ( !data->client ) - return 0; + unsigned int MidiOutJack :: getPortCount() + { + int count = 0; + JackMidiData *data = static_cast (apiData_); + connect(); + if ( !data->client ) + return 0; - // List of available ports - const char **ports = jack_get_ports( data->client, NULL, - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); + // List of available ports + const char **ports = jack_get_ports( data->client, NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); - if ( ports == NULL ) return 0; - while ( ports[count] != NULL ) - count++; + if ( ports == NULL ) return 0; + while ( ports[count] != NULL ) + count++; - free( ports ); + free( ports ); - return count; -} + return count; + } -std::string MidiOutJack :: getPortName( unsigned int portNumber ) -{ - JackMidiData *data = static_cast (apiData_); - std::string retStr(""); - - connect(); - - // List of available ports - const char **ports = jack_get_ports( data->client, NULL, - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); - - // Check port validity - if ( ports == NULL) { - errorString_ = "MidiOutJack::getPortName: no ports available!"; - error( RtMidiError::WARNING, errorString_ ); - return retStr; - } - - if ( ports[portNumber] == NULL) { - std::ostringstream ost; - ost << "MidiOutJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - } - else retStr.assign( ports[portNumber] ); - - free( ports ); - return retStr; -} + std::string MidiOutJack :: getPortName( unsigned int portNumber ) + { + JackMidiData *data = static_cast (apiData_); + std::string retStr(""); + + connect(); + + // List of available ports + const char **ports = jack_get_ports( data->client, NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); + + // Check port validity + if ( ports == NULL) { + errorString_ = "MidiOutJack::getPortName: no ports available!"; + error( Error::WARNING, errorString_ ); + return retStr; + } + + if ( ports[portNumber] == NULL) { + std::ostringstream ost; + ost << "MidiOutJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::WARNING, errorString_ ); + } + else retStr.assign( ports[portNumber] ); + + free( ports ); + return retStr; + } -void MidiOutJack :: closePort() -{ - JackMidiData *data = static_cast (apiData_); + void MidiOutJack :: closePort() + { + JackMidiData *data = static_cast (apiData_); - if ( data->port == NULL ) return; - jack_port_unregister( data->client, data->port ); - data->port = NULL; -} + if ( data->port == NULL ) return; + jack_port_unregister( data->client, data->port ); + data->port = NULL; + } -void MidiOutJack :: sendMessage( std::vector *message ) -{ - int nBytes = message->size(); - JackMidiData *data = static_cast (apiData_); + void MidiOutJack :: sendMessage( std::vector *message ) + { + int nBytes = message->size(); + JackMidiData *data = static_cast (apiData_); - // Write full message to buffer - jack_ringbuffer_write( data->buffMessage, ( const char * ) &( *message )[0], - message->size() ); - jack_ringbuffer_write( data->buffSize, ( char * ) &nBytes, sizeof( nBytes ) ); + // Write full message to buffer + jack_ringbuffer_write( data->buffMessage, ( const char * ) &( *message )[0], + message->size() ); + jack_ringbuffer_write( data->buffSize, ( char * ) &nBytes, sizeof( nBytes ) ); + } } - #endif // __UNIX_JACK__ + diff --git a/RtMidi.h b/RtMidi.h index db16b870..43aa353e 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -1,49 +1,58 @@ /********************* -*- C++ -*- ****************************************/ /*! \class RtMidi - \brief An abstract base class for realtime MIDI input/output. - - 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: realtime MIDI i/o C++ classes - Copyright (c) 2003-2014 Gary P. Scavone - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - Any person wishing to distribute modifications to the Software is - asked to send the modifications to the original developer so that - they can be incorporated into the canonical version. This is, - however, not a binding provision of this license. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + \brief An abstract base class for realtime MIDI input/output. + + 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: realtime MIDI i/o C++ classes + Copyright (c) 2003-2014 Gary P. Scavone + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + Any person wishing to distribute modifications to the Software is + asked to send the modifications to the original developer so that + they can be incorporated into the canonical version. This is, + however, not a binding provision of this license. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**********************************************************************/ /*! \file RtMidi.h - */ +*/ #ifndef RTMIDI_H #define RTMIDI_H -#define RTMIDI_VERSION "2.1.0" +#define RTMIDI_VERSION "3.0.0alpha" + +#ifdef __GNUC__ +#define RTMIDI_DEPRECATED(func) func __attribute__ ((deprecated)) +#elif defined(_MSC_VER) +#define RTMIDI_DEPRECATED(func) __declspec(deprecated) func +#else +#pragma message("WARNING: You need to implement DEPRECATED for this compiler") +#define RTMIDI_DEPRECATED(func) func +#endif #include #include @@ -52,73 +61,142 @@ #include #include -/************************************************************************/ -/*! \class RtMidiError - \brief Exception handling class for RtMidi. +namespace rtmidi { + + //! MIDI API specifier arguments. + enum ApiType { + UNSPECIFIED, /*!< Search for a working compiled API. */ + MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ + LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ + UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ + WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ + WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ + RTMIDI_DUMMY /*!< A compilable but non-functional API. */ + }; - The RtMidiError class is quite simple but it does allow errors to be - "caught" by RtMidiError::Type. See the RtMidi documentation to know - which methods can throw an RtMidiError. -*/ -/************************************************************************/ - -class RtMidiError : public std::exception -{ - public: - //! Defined RtMidiError types. - enum Type { - WARNING, /*!< A non-critical error. */ - DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ - UNSPECIFIED, /*!< The default, unspecified error type. */ - NO_DEVICES_FOUND, /*!< No devices found on system. */ - INVALID_DEVICE, /*!< An invalid device ID was specified. */ - MEMORY_ERROR, /*!< An error occured during memory allocation. */ - INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ - INVALID_USE, /*!< The function was called incorrectly. */ - DRIVER_ERROR, /*!< A system driver error occured. */ - SYSTEM_ERROR, /*!< A system error occured. */ - THREAD_ERROR /*!< A thread error occured. */ - }; - - //! The constructor. - RtMidiError( const std::string& message, Type type = RtMidiError::UNSPECIFIED ) throw() : message_(message), type_(type) {} - - //! The destructor. - virtual ~RtMidiError( void ) throw() {} - - //! Prints thrown error message to stderr. - virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } - - //! Returns the thrown error message type. - virtual const Type& getType(void) const throw() { return type_; } - - //! Returns the thrown error message string. - virtual const std::string& getMessage(void) const throw() { return message_; } - - //! Returns the thrown error message as a c-style string. - virtual const char* what( void ) const throw() { return message_.c_str(); } - - protected: - std::string message_; - Type type_; -}; - -//! RtMidi error callback function prototype. -/*! - \param type Type of error. - \param errorText Error description. - - Note that class behaviour is undefined after a critical error (not - a warning) is reported. - */ -typedef void (*RtMidiErrorCallback)( RtMidiError::Type type, const std::string &errorText ); - -class CommonMidiApi { -public: - //! A port descriptor type. - /*! This will be used with scoped pointers to store system dependent - * data for identifying the port. + //! User callback function type definition. + /*! + \param timeStamp timestamp indicating when the event has been received + \param message a pointer to the binary MIDI message + \param userData a pointer that can be set using setUserdata + \sa MidiIn + \sa MidiInApi */ + typedef void (*MidiCallback)( double timeStamp, std::vector *message, void *userData); + + /************************************************************************/ + /*! \class Error + \brief Exception handling class for RtMidi. + + The Error class is quite simple but it does allow errors to be + "caught" by Error::Type. See the RtMidi documentation to know + which methods can throw an Error. + */ + /************************************************************************/ + + class Error : public std::exception + { + public: + //! Defined Error types. + enum Type { + WARNING, /*!< A non-critical error. */ + DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ + UNSPECIFIED, /*!< The default, unspecified error type. */ + NO_DEVICES_FOUND, /*!< No devices found on system. */ + INVALID_DEVICE, /*!< An invalid device ID was specified. */ + MEMORY_ERROR, /*!< An error occured during memory allocation. */ + INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ + INVALID_USE, /*!< The function was called incorrectly. */ + DRIVER_ERROR, /*!< A system driver error occured. */ + SYSTEM_ERROR, /*!< A system error occured. */ + THREAD_ERROR /*!< A thread error occured. */ + }; + + //! The constructor. + Error( const std::string& message, Type type = Error::UNSPECIFIED ) throw() : message_(message), type_(type) {} + + //! The destructor. + virtual ~Error( void ) throw() {} + + //! Prints thrown error message to stderr. + virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } + + //! Returns the thrown error message type. + virtual const Type& getType(void) const throw() { return type_; } + + //! Returns the thrown error message string. + virtual const std::string& getMessage(void) const throw() { return message_; } + + //! Returns the thrown error message as a c-style string. + virtual const char* what( void ) const throw() { return message_.c_str(); } + + protected: + std::string message_; + Type type_; + }; + + //! RtMidi error callback function prototype. + /*! + \param type Type of error. + \param errorText Error description. + + Note that class behaviour is undefined after a critical error (not + a warning) is reported. + */ + typedef void (*ErrorCallback)( Error::Type type, const std::string &errorText ); + + + +#if __cplusplus < 201103L + class PortDescriptor; + + template + class Pointer { + public: + typedef T datatype; + protected: + struct countPointer { + int count; + datatype * descriptor; + }; + public: + Pointer(datatype * p):ptr(new countPointer) { + ptr->count = 1; + ptr->descriptor = p; + } + Pointer(const Pointer & other): + ptr(other.ptr) { + ptr->count++; + } + + ~Pointer() { + if (!ptr) return; + if (!ptr->descriptor) { + delete ptr; + return; + } + if (!(--ptr->count)) { + delete ptr->descriptor; + delete ptr; + } + } + + datatype * operator -> () { + if (!ptr) return 0; + // this should throw an exception + + return ptr->descriptor; + } + protected: + countPointer * ptr; + }; +#else + template + typedef shared_ptr Pointer; +#endif + + class MidiApi; + struct PortDescriptor { //! Flags for formatting a string description of the port. /*! These flags just mark the requirements that the string @@ -159,50 +237,6 @@ class CommonMidiApi { INOUTPUT = 3 /*!< Ports that allow reading and writing (INPUT | OUTPUT) */ }; - -#if __cplusplus < 201103L - class Pointer { - protected: - struct countPointer { - int count; - PortDescriptor * descriptor; - }; - public: - Pointer(PortDescriptor * p):ptr(new countPointer) { - ptr->count = 1; - ptr->descriptor = p; - } - Pointer(const Pointer & other): - ptr(other.ptr) { - ptr->count++; - } - - ~Pointer() { - if (!ptr) return; - if (!ptr->descriptor) { - delete ptr; - return; - } - if (!(--ptr->count)) { - delete ptr->descriptor; - delete ptr; - } - } - - PortDescriptor * operator -> () { - if (!ptr) return 0; - // this should throw an exception - - return ptr->descriptor; - } - protected: - countPointer * ptr; - }; -#else - typedef shared_ptr Pointer; -#endif - - //! Default constructor. /*! * Derived classes should have a constructor. @@ -221,7 +255,7 @@ class CommonMidiApi { * * \return API that can handle this object. */ - virtual CommonMidiApi * getAPI() = 0; + virtual MidiApi * getAPI() = 0; //! Return the port name /*! @@ -242,668 +276,635 @@ class CommonMidiApi { /*! Port descriptors are stored as shared pointers. This avoids unnecessary duplication of the data structure and handles automatic deletion if all references have been removed. */ - typedef std::list PortList; + typedef std::list > PortList; - //! Pure virtal function to create a virtual port, with optional name. - /*! - This function creates a virtual MIDI port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, any JACK, - and Linux ALSA APIs (the function returns an error for the other APIs). - \param portName An optional name for the applicaction port that is - used to connect to portId can be specified. - */ - virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0; - //! Pure virtual function to open a MIDI connection given by enumeration number. - /*! \param portNumber An optional port number greater than 0 - can be specified. Otherwise, the default or first port - found is opened. + // **************************************************************** // + // + // MidiInApi / MidiOutApi class declarations. + // + // Subclasses of MidiInApi and MidiOutApi contain all API- and + // OS-specific code necessary to fully implement the RtMidi API. + // + // Note that MidiInApi and MidiOutApi are abstract base classes and + // cannot be explicitly instantiated. MidiIn and MidiOut will + // create instances of a MidiInApi or MidiOutApi subclass. + // + // **************************************************************** // - \param portName An optional name for the applicaction port - that will be generated to connect to portId can be - specified. - */ - virtual void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi" ) ) = 0; + class MidiApi + { + public: - //! Pure virtual function to open a MIDI connection given by a port descriptor. - /*! - \param port A port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - */ - virtual void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi" ) ) = 0; + MidiApi(); + virtual ~MidiApi(); - //! Pure virtual function to return a port descirptor if the port is open - virtual PortDescriptor::Pointer getDescriptor() = 0; + //! Pure virtal function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + */ + virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. + + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. + */ + virtual void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + virtual void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi" ) ) = 0; - //! Pure virtual function to return a list of all available ports of the current API. - /*! - \param capabilities an optional parameter that describes which - device types are returned. + //! Pure virtual function to return a port descirptor if the port is open + virtual Pointer getDescriptor() = 0; - \return This function returns a list of port descriptors. + //! Pure virtual function to return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that describes which + device types are returned. - \note An input API may but need not necessarily report - output devices which cannot be used as input if - \ref PortDescriptor::OUTPUT is passed as \ref capabilities parameter. - */ - virtual CommonMidiApi::PortList getPortList(int capabilities = PortDescriptor:: INOUTPUT) = 0; + \return This function returns a list of port descriptors. - //! Pure virtual to return the number of available MIDI ports of the current API. - /*! - \return This function returns the number of MIDI ports of - the selected API. + \note An input API may but need not necessarily report + output devices which cannot be used as input if + \ref PortDescriptor::OUTPUT is passed as \ref capabilities parameter. + */ + virtual PortList getPortList(int capabilities = PortDescriptor:: INOUTPUT) = 0; - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. + //! Pure virtual to return the number of available MIDI ports of the current API. + /*! + \return This function returns the number of MIDI ports of + the selected API. - \sa getPortName - */ - virtual unsigned int getPortCount() = 0; + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. - //! Pure virtual function to return a string identifier for the specified MIDI port number. - /*! - \param portNumber Number of the device to be referred to. - \return The name of the port with the given Id is returned. - \retval An empty string is returned if an invalid port specifier is provided. + \sa getPortName + */ + virtual unsigned int getPortCount() = 0; + + //! Pure virtual function to return a string identifier for the specified MIDI port number. + /*! + \param portNumber Number of the device to be referred to. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortCount() + */ + virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; + + //! Pure virtual function to close an open MIDI connection (if one exists). + virtual void closePort( void ) = 0; + + // ! A basic error reporting function for RtMidi classes. + // static void error( Error::Type type, std::string &errorString ); + + //! Pure virtual function to return whether a port is open or not. + /*! \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). + */ + bool isPortOpen() const { return connected_; } + + //! Pure virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + virtual void setErrorCallback( ErrorCallback errorCallback = NULL ); + + + //! Returns the MIDI API specifier for the current instance of RtMidiIn. + virtual ApiType getCurrentApi( void ) throw() = 0; + + //! A basic error reporting function for RtMidi classes. + void error( Error::Type type, std::string errorString ); - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. + protected: + virtual void initialize( const std::string& clientName ) = 0; - \sa getPortCount() + void *apiData_; + bool connected_; + std::string errorString_; + ErrorCallback errorCallback_; + }; + + class MidiInApi : public MidiApi + { + public: + + MidiInApi( unsigned int queueSizeLimit ); + virtual ~MidiInApi( void ); + void setCallback( MidiCallback callback, void *userData ); + void cancelCallback( void ); + virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); + RTMIDI_DEPRECATED(double getMessage( std::vector *message )) + { + if (!message) { + errorString_ = "MidiInApi::getMessage: passed NULL pointer"; + error( Error::WARNING, errorString_ ); + } + return getMessage(*message); + } + double getMessage( std::vector &message ); + + // A MIDI structure used internally by the class to store incoming + // messages. Each message represents one and only one MIDI message. + struct MidiMessage { + std::vector bytes; + double timeStamp; + + // Default constructor. + MidiMessage() + :bytes(0), timeStamp(0.0) {} + }; + + struct MidiQueue { + unsigned int front; + unsigned int back; + unsigned int size; + unsigned int ringSize; + MidiMessage *ring; + + // Default constructor. + MidiQueue() + :front(0), back(0), size(0), ringSize(0) {} + }; + + // The RtMidiInData structure is used to pass private class data to + // the MIDI input handling function or thread. + struct MidiInData { + MidiQueue queue; + MidiMessage message; + unsigned char ignoreFlags; + bool doInput; + bool firstMessage; + void *apiData; + bool usingCallback; + MidiCallback userCallback; + void *userData; + bool continueSysex; + + // Default constructor. + MidiInData() + : ignoreFlags(7), doInput(false), firstMessage(true), + apiData(0), usingCallback(false), userCallback(0), userData(0), + continueSysex(false) {} + }; + + protected: + MidiInData inputData_; + }; + + class MidiOutApi : public MidiApi + { + public: + + MidiOutApi( void ); + virtual ~MidiOutApi( void ); + RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) + { + if (!message) { + errorString_ = "MidiOutApi::sendMessage: no data in message argument!"; + error( Error::WARNING, errorString_ ); + } + sendMessage(*message); + } + virtual void sendMessage( std::vector &message ) = 0; + }; + + + /*! \class Midi + \brief A global class that implements basic backend API handling. + + This class enhances \ref MidiApi by some functionality to handle + backend API objects. It serves as base class for the public RtMidi + API. + + by Gary P. Scavone, 2003-2014. */ - std::string getPortName( unsigned int portNumber = 0 ); + /**********************************************************************/ + class Midi { + public: + typedef rtmidi::ApiType Api; + //! defined for compatibility + enum Api2 { + UNSPECIFIED = rtmidi::UNSPECIFIED, + MACOSX_CORE = rtmidi::MACOSX_CORE, + LINUX_ALSA = rtmidi::LINUX_ALSA, + UNIX_JACK = rtmidi::UNIX_JACK, + WINDOWS_MM = rtmidi::WINDOWS_MM, + WINDOWS_KS = rtmidi::WINDOWS_KS, + RTMIDI_DUMMY = rtmidi::RTMIDI_DUMMY + }; + - //! Pure virtual function to close an open MIDI connection (if one exists). - virtual void closePort( void ) = 0; + //! A static function to determine the current RtMidi version. + static std::string getVersion( void ) throw(); - // ! A basic error reporting function for RtMidi classes. - // static void error( RtMidiError::Type type, std::string &errorString ); + //! A static function to determine the available compiled MIDI APIs. + /*! + The values returned in the std::vector can be compared against + the enumerated list values. Note that there can be more than one + API compiled for certain operating systems. + */ + static void getCompiledApi( std::vector &apis ) throw(); + + //! Returns the MIDI API specifier for the current instance of RtMidiIn. + ApiType getCurrentApi( void ) throw() + { + if (rtapi_) return rtapi_->getCurrentApi(); + else return rtmidi::UNSPECIFIED; + } + + //! Function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + */ + void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) + { + if (rtapi_) rtapi_->openVirtualPort(portName); + } + + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. + + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. + */ + void openPort( unsigned int portNumber = 0, + const std::string portName = std::string( "RtMidi" ) ) + { + if (rtapi_) rtapi_->openPort(portNumber,portName); + } + + //! Pure virtual function to open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + void openPort( const PortDescriptor & port, + const std::string portName = std::string( "RtMidi" ) ) + { + if (rtapi_) rtapi_->openPort(port,portName); + } + + //! Pure virtual function to return a port descirptor if the port is open + Pointer getDescriptor() + { + if (rtapi_) return rtapi_->getDescriptor(); + return 0; + } + + //! Pure virtual function to return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that describes which + device types are returned. + + \return This function returns a list of port descriptors. + + \note An input API may but need not necessarily report + output devices which cannot be used as input if + \ref PortDescriptor::OUTPUT is passed as \ref capabilities parameter. + */ + PortList getPortList(int capabilities = PortDescriptor:: INOUTPUT) + { + if (rtapi_) return rtapi_->getPortList(capabilities); + return PortList(); + } + + //! Pure virtual to return the number of available MIDI ports of the current API. + /*! + \return This function returns the number of MIDI ports of + the selected API. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortName + */ + unsigned int getPortCount() + { + if (rtapi_) return rtapi_->getPortCount(); + return 0; + } + + //! Pure virtual function to return a string identifier for the specified MIDI port number. + /*! + \param portNumber Number of the device to be referred to. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortCount() + */ + std::string getPortName( unsigned int portNumber = 0 ) + { + if (rtapi_) return rtapi_->getPortName(portNumber); + return ""; + } + + //! Close an open MIDI connection (if one exists). + void closePort( void ) + { + if (rtapi_) rtapi_->closePort(); + } + + // ! A basic error reporting function for RtMidi classes. + // static void error( Error::Type type, std::string &errorString ); + + //! Pure virtual function to return whether a port is open or not. + /*! \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). + */ + bool isPortOpen( void ) const + { + if (rtapi_) return rtapi_->isPortOpen(); + return false; + } + + //! Pure virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + void setErrorCallback( ErrorCallback errorCallback = NULL ) + { + if (rtapi_) rtapi_->setErrorCallback(errorCallback); + } + + //! A basic error reporting function for RtMidi classes. + void error( Error::Type type, std::string errorString ); + protected: + MidiApi *rtapi_; + + Midi():rtapi_(0) {} + ~Midi() + { + if (rtapi_) { + delete rtapi_; + rtapi_ = 0; + } + } + }; - //! Pure virtual function to return whether a port is open or not. - /*! \retval true if a port is open and - \retval false if the port is not open (e.g. not opend or closed). + /**********************************************************************/ + /*! \class MidiIn + \brief A realtime MIDI input class. + + This class provides a common, platform-independent API for + realtime MIDI input. It allows access to a single MIDI input + port. Incoming MIDI messages are either saved to a queue for + retrieval using the getMessage() function or immediately passed to + a user-specified callback function. Create multiple instances of + this class to connect to more than one MIDI device at the same + time. With the OS-X and Linux ALSA 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-2014. */ - virtual bool isPortOpen( void ) const = 0; + /**********************************************************************/ + + // **************************************************************** // + // + // MidiIn and MidiOut class declarations. + // + // MidiIn / MidiOut are "controllers" used to select an available + // MIDI input or output interface. They present common APIs for the + // user to call but all functionality is implemented by the classes + // MidiInApi, MidiOutApi and their subclasses. MidiIn and MidiOut + // each create an instance of a MidiInApi or MidiOutApi subclass based + // on the user's API choice. If no choice is made, they attempt to + // make a "logical" API selection. + // + // **************************************************************** // + + class MidiIn : public Midi + { + public: + + + //! Default constructor that allows an optional api, client name and queue size. + /*! + An exception will be thrown if a MIDI system initialization + error occurs. The queue size defines the maximum number of + messages that can be held in the MIDI queue (when not using a + callback function). If the queue size limit is reached, + incoming messages will be ignored. + + If no API argument is specified and multiple API support has been + compiled, the default order of use is JACK, ALSA (Linux) and CORE, + JACK (OS-X). + + \param api An optional API id can be specified. + \param clientName An optional Client name can be specified. This + will be used to group the ports that are created + by the application. + \param queueSizeLimit An optional size of the MIDI input queue can be specified. + */ + MidiIn( ApiType api=rtmidi::UNSPECIFIED, + const std::string clientName = std::string( "RtMidi Input Client"), + unsigned int queueSizeLimit = 100 ); + + //! If a MIDI connection is still open, it will be closed by the destructor. + ~MidiIn ( void ) throw(); + + + //! Set a callback function to be invoked for incoming MIDI messages. + /*! + The callback function will be called whenever an incoming MIDI + message is received. While not absolutely necessary, it is best + to set the callback function before opening a MIDI port to avoid + leaving some messages in the queue. + + \param callback A callback function must be given. + \param userData Opitionally, a pointer to additional data can be + passed to the callback function whenever it is called. + */ + void setCallback( MidiCallback callback, void *userData = 0 ) + { + if (rtapi_) + static_cast(rtapi_)->setCallback(callback,userData); + } + + //! Cancel use of the current callback function (if one exists). + /*! + Subsequent incoming MIDI messages will be written to the queue + and can be retrieved with the \e getMessage function. + */ + void cancelCallback() + { + if (rtapi_) + static_cast(rtapi_)->cancelCallback(); + } + + //! Specify whether certain MIDI message types should be queued or ignored during input. + /*! + By default, MIDI timing and active sensing messages are ignored + during message input because of their relative high data rates. + MIDI sysex messages are ignored by default as well. Variable + values of "true" imply that the respective message type will be + ignored. + */ + void ignoreTypes( bool midiSysex = true, + bool midiTime = true, + bool midiSense = true ) + { + if (rtapi_) + static_cast(rtapi_)->ignoreTypes(midiSysex, midiTime, midiSense); + } + + //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. + /*! + This function returns immediately whether a new message is + available or not. A valid message is indicated by a non-zero + vector size. An exception is thrown if an error occurs during + message retrieval or an input connection was not previously + established. + */ + double getMessage( std::vector &message ) + { + if (rtapi_) + return static_cast(rtapi_)->getMessage(message); + std::string errorString_ = "MidiIn::getMessage: No valid API found."; + error( Error::WARNING, errorString_ ); + return 0.0; + } + + //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. + /*! + This function returns immediately whether a new message is + available or not. A valid message is indicated by a non-zero + vector size. An exception is thrown if an error occurs during + message retrieval or an input connection was not previously + established. + + \deprecated + */ + RTMIDI_DEPRECATED(double getMessage( std::vector *message )) + { + if (!message) { + error( Error::WARNING, + "MidiIn::getMessage: passed NULL pointer"); + } + if (rtapi_) + return static_cast(rtapi_)->getMessage(*message); + error( Error::WARNING, + "MidiIn::getMessage: No valid API found."); + return 0.0; + } - //! Pure virtual function to set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. + protected: + void openMidiApi( ApiType api, const std::string clientName, unsigned int queueSizeLimit ); + + }; + + /**********************************************************************/ + /*! \class MidiOut + \brief A realtime MIDI output class. + + This class provides a common, platform-independent API for MIDI + output. It allows one to probe available MIDI output ports, to + connect to one such port, and to send MIDI bytes immediately over + the connection. Create multiple instances of this class to + connect to more than one MIDI device at the same time. With the + OS-X and Linux ALSA MIDI APIs, it is also possible to open a + virtual port to which other MIDI software clients can connect. + + by Gary P. Scavone, 2003-2014. */ - virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL ) = 0; -}; + /**********************************************************************/ -/**********************************************************************/ -/*! \class RtMidi - \brief A global class that implements basic backend API handling. + class MidiOut : public Midi + { + public: - This class enhances \ref CommonMidiApi by some functionality to handle - backend API objects. It serves as base class for the public RtMidi - API. + //! Default constructor that allows an optional client name. + /*! + An exception will be thrown if a MIDI system initialization error occurs. - by Gary P. Scavone, 2003-2014. -*/ -/**********************************************************************/ -class MidiApi; -class RtMidi : public CommonMidiApi -{ - public: - - //! MIDI API specifier arguments. - enum Api { - UNSPECIFIED, /*!< Search for a working compiled API. */ - MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ - 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. */ - }; - - //! A static function to determine the current RtMidi version. - static std::string getVersion( void ) throw(); - - //! A static function to determine the available compiled MIDI APIs. - /*! - The values returned in the std::vector can be compared against - the enumerated list values. Note that there can be more than one - API compiled for certain operating systems. - */ - static void getCompiledApi( std::vector &apis ) throw(); - - protected: - MidiApi *rtapi_; - - RtMidi(); - virtual ~RtMidi(); - -}; + If no API argument is specified and multiple API support has been + compiled, the default order of use is JACK, ALSA (Linux) and CORE, + JACK (OS-X). + */ + MidiOut( ApiType api=rtmidi::UNSPECIFIED, + const std::string clientName = std::string( "RtMidi Output Client") ); -/**********************************************************************/ -/*! \class RtMidiIn - \brief A realtime MIDI input class. - - This class provides a common, platform-independent API for - realtime MIDI input. It allows access to a single MIDI input - port. Incoming MIDI messages are either saved to a queue for - retrieval using the getMessage() function or immediately passed to - a user-specified callback function. Create multiple instances of - this class to 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 input port to which other MIDI software - clients can connect. - - by Gary P. Scavone, 2003-2014. -*/ -/**********************************************************************/ + //! The destructor closes any open MIDI connections. + ~MidiOut( void ) throw(); -// **************************************************************** // -// -// RtMidiIn and RtMidiOut class declarations. -// -// RtMidiIn / RtMidiOut are "controllers" used to select an available -// MIDI input or output interface. They present common APIs for the -// user to call but all functionality is implemented by the classes -// MidiInApi, MidiOutApi and their subclasses. RtMidiIn and RtMidiOut -// each create an instance of a MidiInApi or MidiOutApi subclass based -// on the user's API choice. If no choice is made, they attempt to -// make a "logical" API selection. -// -// **************************************************************** // - -class RtMidiIn : public RtMidi -{ - public: - - //! User callback function type definition. - typedef void (*RtMidiCallback)( double timeStamp, std::vector *message, void *userData); - - //! Default constructor that allows an optional api, client name and queue size. - /*! - An exception will be thrown if a MIDI system initialization - error occurs. The queue size defines the maximum number of - messages that can be held in the MIDI queue (when not using a - callback function). If the queue size limit is reached, - incoming messages will be ignored. - - If no API argument is specified and multiple API support has been - compiled, the default order of use is ALSA, JACK (Linux) and CORE, - JACK (OS-X). - - \param api An optional API id can be specified. - \param clientName An optional client name can be specified. This - will be used to group the ports that are created - by the application. - \param queueSizeLimit An optional size of the MIDI input queue can be specified. - */ - RtMidiIn( RtMidi::Api api=UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Input Client"), - unsigned int queueSizeLimit = 100 ); - - //! If a MIDI connection is still open, it will be closed by the destructor. - ~RtMidiIn ( void ) throw(); - - //! Returns the MIDI API specifier for the current instance of RtMidiIn. - RtMidi::Api getCurrentApi( void ) throw(); - - //! Create a virtual input port, with optional name, to allow software connections (OS X, JACK and ALSA only). - /*! - This function creates a virtual MIDI input port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, any JACK, - and Linux ALSA APIs (the function returns an error for the other APIs). - - \param portName An optional name for the applicaction port that is - used to connect to portId can be specified. - */ - void openVirtualPort( const std::string portName = std::string( "RtMidi Input" ) ); - - //! Open a MIDI input connection given by enumeration number. - /*! - \param portNumber An optional port number greater than 0 can be specified. - Otherwise, the default or first port found is opened. - \param portName An optional name for the application port that is used to connect to portId can be specified. - */ - void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi Input" ) ); - - //! Open a MIDI input connection given by a port descriptor. - /*! - \param port A port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - */ - void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi" ) ); - - //! Returns a port descirptor if the port is open - virtual CommonMidiApi::PortDescriptor::Pointer getDescriptor(); - - //! Return a list of all available input ports of the current API. - /*! - \param capabilities an optional parameter that describes which - device types are returned. - \return This function returns a list of port descriptors. - \note An Output API is not required to return all output ports from RtMidiIn. - */ - virtual CommonMidiApi::PortList getPortList(int capabilities = PortDescriptor:: INPUT); - - //! Return the number of available MIDI input ports. - /*! - \return This function returns the number of midi ports of the selected API. - */ - unsigned int getPortCount(); - - //! Return a string identifier for the specified MIDI input port number. - /*! - \return The name of the port with the given Id is returned. - \retval An empty string is returned if an invalid port specifier is provided. - */ - std::string getPortName( unsigned int portNumber = 0 ); - - //! Close an open MIDI connection (if one exists). - void closePort( void ); - - //! Returns true if a port is open and false if not. - virtual bool isPortOpen() const; - - //! Set a callback function to be invoked for incoming MIDI messages. - /*! - The callback function will be called whenever an incoming MIDI - message is received. While not absolutely necessary, it is best - to set the callback function before opening a MIDI port to avoid - leaving some messages in the queue. - - \param callback A callback function must be given. - \param userData Optionally, a pointer to additional data can be - passed to the callback function whenever it is called. - */ - void setCallback( RtMidiCallback callback, void *userData = 0 ); - - //! Cancel use of the current callback function (if one exists). - /*! - Subsequent incoming MIDI messages will be written to the queue - and can be retrieved with the \e getMessage function. - */ - void cancelCallback(); - - //! Specify whether certain MIDI message types should be queued or ignored during input. - /*! - By default, MIDI timing and active sensing messages are ignored - during message input because of their relative high data rates. - MIDI sysex messages are ignored by default as well. Variable - values of "true" imply that the respective message type will be - ignored. - */ - void ignoreTypes( bool midiSysex = true, bool midiTime = true, bool midiSense = true ); - - //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. - /*! - This function returns immediately whether a new message is - available or not. A valid message is indicated by a non-zero - vector size. An exception is thrown if an error occurs during - message retrieval or an input connection was not previously - established. - */ - double getMessage( std::vector *message ); - - //! Set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. - */ - virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL ); - - protected: - void openMidiApi( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit ); - -}; + //! Immediately send a single message out an open MIDI output port. + /*! + An exception is thrown if an error occurs during output or an + output connection was not previously established. + + \deprecated + */ + RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) + { + if (!message) { + error( Error::WARNING, + "MidiOutApi::sendMessage: no data in message argument!"); + } + if (rtapi_) + static_cast(rtapi_)->sendMessage(*message); + error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); + } -/**********************************************************************/ -/*! \class RtMidiOut - \brief A realtime MIDI output class. - - This class provides a common, platform-independent API for MIDI - output. It allows one to probe available MIDI output ports, to - connect to one such port, and to send MIDI bytes immediately over - the connection. Create multiple instances of this class to - 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-2014. -*/ -/**********************************************************************/ -class RtMidiOut : public RtMidi -{ - public: - - //! Default constructor that allows an optional client name. - /*! - An exception will be thrown if a MIDI system initialization error occurs. - - If no API argument is specified and multiple API support has been - compiled, the default order of use is ALSA, JACK (Linux) and CORE, - JACK (OS-X). - */ - RtMidiOut( RtMidi::Api api=UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Output Client") ); - - //! The destructor closes any open MIDI connections. - ~RtMidiOut( void ) throw(); - - //! Returns the MIDI API specifier for the current instance of RtMidiOut. - RtMidi::Api getCurrentApi( void ) throw(); - - //! Create a virtual output port, with optional name, to allow software connections (OS X and ALSA only). - /*! - This function creates a virtual MIDI output port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X and Linux ALSA - APIs (the function does nothing with the other APIs). An - exception is thrown if an error occurs while attempting to create - the virtual port. - */ - void openVirtualPort( const std::string portName = std::string( "RtMidi Output" ) ); - - //! Open a MIDI output connection given by an enumeration number. - /*! - An optional port number greater than 0 can be specified. - Otherwise, the default or first port found is opened. An - exception is thrown if an error occurs while attempting to make - the port connection. - */ - void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi Output" ) ); - - //! Open a MIDI output connection given by a port descriptor. - /*! - \param port A port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - */ - virtual void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi Output" ) ); - - //! Returns a port descirptor if the port is open - /*! \return Port descriptor of the currently open port - * \retval 0 iff the port s not open - */ - virtual CommonMidiApi::PortDescriptor::Pointer getDescriptor(); - - //! Close an open MIDI connection (if one exists). - void closePort( void ); - - //! Returns true if a port is open and false if not. - virtual bool isPortOpen() const; - - //! Return a list of all available ports of the current API. - /*! - \param capabilities an opitonnal parameter that describes which - device types are returned. - \return This function returns a list of port descriptors. - \note An API is not required to return all input ports from RtMidiOut. - */ - virtual CommonMidiApi::PortList getPortList(int capabilities = PortDescriptor::OUTPUT); - - //! Return the number of available MIDI output ports. - unsigned int getPortCount( void ); - - //! Return a string identifier for the specified MIDI port type and number. - /*! - \return The name of the port with the given Id is returned. - \retval An empty string is returned if an invalid port specifier is provided. - */ - std::string getPortName( unsigned int portNumber = 0 ); - - //! Immediately send a single message out an open MIDI output port. - /*! - An exception is thrown if an error occurs during output or an - output connection was not previously established. - */ - void sendMessage( std::vector *message ); - - //! Set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. - */ - virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL ); - - protected: - void openMidiApi( RtMidi::Api api, const std::string clientName ); -}; - - -// **************************************************************** // -// -// MidiInApi / MidiOutApi class declarations. -// -// Subclasses of MidiInApi and MidiOutApi contain all API- and -// OS-specific code necessary to fully implement the RtMidi API. -// -// Note that MidiInApi and MidiOutApi are abstract base classes and -// cannot be explicitly instantiated. RtMidiIn and RtMidiOut will -// create instances of a MidiInApi or MidiOutApi subclass. -// -// **************************************************************** // - -class MidiApi: public CommonMidiApi -{ - public: - - MidiApi(); - virtual ~MidiApi(); - - virtual unsigned int getPortCount( void ) = 0; - virtual std::string getPortName( unsigned int portNumber ) = 0; - - bool isPortOpen() const { return connected_; } - void setErrorCallback( RtMidiErrorCallback errorCallback ); - - - //! Returns the MIDI API specifier for the current instance of RtMidiIn. - virtual RtMidi::Api getCurrentApi( void ) throw(); - - //! A basic error reporting function for RtMidi classes. - void error( RtMidiError::Type type, std::string errorString ); - -protected: - virtual void initialize( const std::string& clientName ) = 0; - - void *apiData_; - bool connected_; - std::string errorString_; - RtMidiErrorCallback errorCallback_; -}; - -class MidiInApi : public MidiApi -{ - public: - - MidiInApi( unsigned int queueSizeLimit ); - virtual ~MidiInApi( void ); - void setCallback( RtMidiIn::RtMidiCallback callback, void *userData ); - void cancelCallback( void ); - virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); - double getMessage( std::vector *message ); - - // A MIDI structure used internally by the class to store incoming - // messages. Each message represents one and only one MIDI message. - struct MidiMessage { - std::vector bytes; - double timeStamp; - - // Default constructor. - MidiMessage() - :bytes(0), timeStamp(0.0) {} - }; - - struct MidiQueue { - unsigned int front; - unsigned int back; - unsigned int size; - unsigned int ringSize; - MidiMessage *ring; - - // Default constructor. - MidiQueue() - :front(0), back(0), size(0), ringSize(0) {} - }; - - // The RtMidiInData structure is used to pass private class data to - // the MIDI input handling function or thread. - struct RtMidiInData { - MidiQueue queue; - MidiMessage message; - unsigned char ignoreFlags; - bool doInput; - bool firstMessage; - void *apiData; - bool usingCallback; - RtMidiIn::RtMidiCallback userCallback; - void *userData; - bool continueSysex; - - // Default constructor. - RtMidiInData() - : ignoreFlags(7), doInput(false), firstMessage(true), - apiData(0), usingCallback(false), userCallback(0), userData(0), - continueSysex(false) {} - }; - - protected: - RtMidiInData inputData_; -}; - -class MidiOutApi : public MidiApi -{ - public: - - MidiOutApi( void ); - virtual ~MidiOutApi( void ); - virtual void sendMessage( std::vector *message ) = 0; -}; - -// **************************************************************** // -// -// Inline RtMidiIn and RtMidiOut definitions. -// -// **************************************************************** // - -inline RtMidi::Api RtMidiIn :: getCurrentApi( void ) throw() -{ - return rtapi_->getCurrentApi(); -} -inline void RtMidiIn :: openVirtualPort( const std::string portName ) -{ - rtapi_->openVirtualPort( portName ); -} -inline void RtMidiIn :: openPort( unsigned int portNumber, - const std::string portName ) -{ - rtapi_->openPort( portNumber, portName ); -} -inline void RtMidiIn :: openPort( const CommonMidiApi::PortDescriptor & port, - const std::string portName) -{ - rtapi_->openPort(port,portName); -} -inline CommonMidiApi::PortDescriptor::Pointer RtMidiIn :: getDescriptor() -{ - return rtapi_->getDescriptor(); -} -inline CommonMidiApi::PortList RtMidiIn :: getPortList(int capabilities) -{ - return rtapi_->getPortList(capabilities); -} -inline unsigned int RtMidiIn :: getPortCount( void ) -{ - return rtapi_->getPortCount(); -} -inline std::string RtMidiIn :: getPortName( unsigned int portNumber ) -{ - return rtapi_->getPortName( portNumber ); -} -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 :: ignoreTypes( bool midiSysex, - bool midiTime, - bool midiSense ) -{ - ((MidiInApi *)rtapi_)->ignoreTypes( midiSysex, midiTime, midiSense ); -} -inline double RtMidiIn :: getMessage( std::vector *message ) -{ - return ((MidiInApi *)rtapi_)->getMessage( message ); -} -inline void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback ) -{ - rtapi_->setErrorCallback(errorCallback); -} + //! Immediately send a single message out an open MIDI output port. + /*! + An exception is thrown if an error occurs during output or an + output connection was not previously established. + */ + void sendMessage( std::vector &message ) { + if (rtapi_) + static_cast(rtapi_)->sendMessage(message); + error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); + } + protected: + void openMidiApi( ApiType api, const std::string clientName ); + }; -inline RtMidi::Api RtMidiOut :: getCurrentApi( void ) throw() -{ - return rtapi_->getCurrentApi(); -} -inline void RtMidiOut :: openPort( unsigned int portNumber, const std::string portName ) -{ - rtapi_->openPort( portNumber, portName ); -} -inline void RtMidiOut :: openVirtualPort( const std::string portName ) -{ - rtapi_->openVirtualPort( portName ); -} -inline void RtMidiOut :: openPort( const CommonMidiApi::PortDescriptor & port, - const std::string portName) -{ - rtapi_->openPort(port,portName); -} -inline CommonMidiApi::PortDescriptor::Pointer RtMidiOut :: getDescriptor() -{ - return rtapi_->getDescriptor(); -} -inline CommonMidiApi::PortList RtMidiOut :: getPortList(int capabilities) -{ - return rtapi_->getPortList(capabilities); -} -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( std::vector *message ) -{ - ((MidiOutApi *)rtapi_)->sendMessage( message ); -} -inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback ) -{ - rtapi_->setErrorCallback(errorCallback); -} -// **************************************************************** // -// -// MidiInApi and MidiOutApi subclass prototypes. -// -// **************************************************************** // + // **************************************************************** // + // + // MidiInApi and MidiOutApi subclass prototypes. + // + // **************************************************************** // #if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__) #define __RTMIDI_DUMMY__ @@ -911,228 +912,234 @@ inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback ) #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 openPort( const PortDescriptor & port, const std::string portName); - CommonMidiApi::PortDescriptor::Pointer getDescriptor(); - CommonMidiApi::PortList getPortList(int capabilities); - 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 openPort( const PortDescriptor & port, const std::string portName); - CommonMidiApi::PortDescriptor::Pointer getDescriptor(); - CommonMidiApi::PortList getPortList(int capabilities); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector *message ); - - protected: - void initialize( const std::string& clientName ); -}; + class MidiInCore: public MidiInApi + { + public: + MidiInCore( const std::string clientName, unsigned int queueSizeLimit ); + ~MidiInCore( void ); + ApiType getCurrentApi( void ) { return MACOSX_CORE; }; + void openPort( unsigned int portNumber, const std::string portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + 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 ); + ApiType getCurrentApi( void ) { return MACOSX_CORE; }; + void openPort( unsigned int portNumber, const std::string portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + void closePort( void ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( std::vector &message ); + + 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 openPort( const PortDescriptor & port, const std::string portName); - CommonMidiApi::PortDescriptor::Pointer getDescriptor(); - CommonMidiApi::PortList getPortList(int capabilities); - 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 openPort( const PortDescriptor & port, const std::string portName); - CommonMidiApi::PortDescriptor::Pointer getDescriptor(); - CommonMidiApi::PortList getPortList(int capabilities); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector *message ); - - protected: - std::string clientName; - - void connect( void ); - void initialize( const std::string& clientName ); -}; + class MidiInJack: public MidiInApi + { + public: + MidiInJack( const std::string clientName, unsigned int queueSizeLimit ); + ~MidiInJack( void ); + ApiType getCurrentApi( void ) { return UNIX_JACK; }; + void openPort( unsigned int portNumber, const std::string portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + 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 ); + ApiType getCurrentApi( void ) { return UNIX_JACK; }; + void openPort( unsigned int portNumber, const std::string portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + void closePort( void ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( std::vector &message ); + + 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 ) throw() { return RtMidi::LINUX_ALSA; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - CommonMidiApi::PortDescriptor::Pointer getDescriptor(); - CommonMidiApi::PortList getPortList(int capabilities); - 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 ) throw() { return RtMidi::LINUX_ALSA; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - CommonMidiApi::PortDescriptor::Pointer getDescriptor(); - CommonMidiApi::PortList getPortList(int capabilities); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector *message ); - - protected: - void initialize( const std::string& clientName ); -}; + class MidiInAlsa: public MidiInApi + { + public: + MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit ); + ~MidiInAlsa( void ); + ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; + void openPort( unsigned int portNumber, const std::string portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + 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 ); + ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; + void openPort( unsigned int portNumber, const std::string portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + void closePort( void ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( std::vector &message ); + + 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 openPort( const PortDescriptor & port, const std::string portName); - CommonMidiApi::PortDescriptor::Pointer getDescriptor(); - CommonMidiApi::PortList getPortList(int capabilities); - 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 openPort( const PortDescriptor & port, const std::string portName); - CommonMidiApi::PortDescriptor::Pointer getDescriptor(); - CommonMidiApi::PortList getPortList(int capabilities); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector *message ); - - protected: - void initialize( const std::string& clientName ); -}; + class MidiInWinMM: public MidiInApi + { + public: + MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ); + ~MidiInWinMM( void ); + ApiType getCurrentApi( void ) { return WINDOWS_MM; }; + void openPort( unsigned int portNumber, const std::string portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + 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 ); + ApiType getCurrentApi( void ) { return WINDOWS_MM; }; + void openPort( unsigned int portNumber, const std::string portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + void closePort( void ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( std::vector &message ); + + 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 openPort( const PortDescriptor & port, const std::string portName) {} - CommonMidiApi::PortDescriptor::Pointer getDescriptor() { return 0; } - CommonMidiApi::PortList getPortList(int capabilities) { return CommonMidiApi::PortList(); } - 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 openPort( const PortDescriptor & port, const std::string portName) {} - CommonMidiApi::PortDescriptor::Pointer getDescriptor() { return 0; } - CommonMidiApi::PortList getPortList(int capabilities) { return CommonMidiApi::PortList(); } - void closePort( void ) {} - unsigned int getPortCount( void ) { return 0; } - std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } - void sendMessage( std::vector * /*message*/ ) {} - - protected: - void initialize( const std::string& /*clientName*/ ) {} -}; + class MidiInDummy: public MidiInApi + { + public: + MidiInDummy( const std::string /*clientName*/, unsigned int queueSizeLimit ) + : MidiInApi( queueSizeLimit ) { + errorString_ = "MidiInDummy: This class provides no functionality."; + error( Error::WARNING, errorString_ ); + } + ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } + void openPort( unsigned int /*portNumber*/, const std::string /*portName*/ ) {} + void openVirtualPort( const std::string /*portName*/ ) {} + void openPort( const PortDescriptor & port, const std::string portName) {} + Pointer getDescriptor() { return 0; } + PortList getPortList(int capabilities) { return PortList(); } + 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( Error::WARNING, errorString_ ); + } + ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } + void openPort( unsigned int /*portNumber*/, const std::string /*portName*/ ) {} + void openVirtualPort( const std::string /*portName*/ ) {} + void openPort( const PortDescriptor & port, const std::string portName) {} + Pointer getDescriptor() { return 0; } + PortList getPortList(int capabilities) { return PortList(); } + void closePort( void ) {} + unsigned int getPortCount( void ) { return 0; } + std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } + void sendMessage( std::vector & /*message*/ ) {} + + protected: + void initialize( const std::string& /*clientName*/ ) {} + }; #endif +} + +typedef rtmidi::Midi RtMidi; +typedef rtmidi::MidiIn RtMidiIn; +typedef rtmidi::MidiOut RtMidiOut; +typedef rtmidi::Error RtMidiError; #endif From 7adbc8e0b848af2567ea6ecb901e646c51612abf Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 8 Aug 2018 09:37:57 +0200 Subject: [PATCH 009/210] Fix indentation with emacs --- .dir-locals.el | 8 + RtMidi.cpp | 5284 ++++++++++++++++++++++++------------------------ RtMidi.h | 2078 +++++++++---------- 3 files changed, 3690 insertions(+), 3680 deletions(-) create mode 100644 .dir-locals.el diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 00000000..3c3abd62 --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1,8 @@ +;;; Directory Local Variables +;;; For more information see (info "(emacs) Directory Variables") + +((c++-mode + (c-basic-offset . 2)) + (c-mode + (c-basic-offset . 2))) + diff --git a/RtMidi.cpp b/RtMidi.cpp index 16cf8267..356ce6d4 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -39,2864 +39,2864 @@ #include "RtMidi.h" #include -namespace rtmidi { - //*********************************************************************// - // Midi Definitions - //*********************************************************************// - std::string Midi :: getVersion( void ) throw() - { - return std::string( RTMIDI_VERSION ); - } +NAMSPACE_RTMIDI_START +//*********************************************************************// +// Midi Definitions +//*********************************************************************// +std::string Midi :: getVersion( void ) throw() +{ + return std::string( RTMIDI_VERSION ); +} - void Midi :: getCompiledApi( std::vector &apis ) throw() - { - apis.clear(); +void Midi :: getCompiledApi( std::vector &apis ) throw() +{ + apis.clear(); - // The order here will control the order of RtMidi's API search in - // the constructor. + // The order here will control the order of RtMidi's API search in + // the constructor. #if defined(__MACOSX_CORE__) - apis.push_back( rtmidi::MACOSX_CORE ); + apis.push_back( rtmidi::MACOSX_CORE ); #endif #if defined(__LINUX_ALSA__) - apis.push_back( rtmidi::LINUX_ALSA ); + apis.push_back( rtmidi::LINUX_ALSA ); #endif #if defined(__UNIX_JACK__) - apis.push_back( rtmidi::UNIX_JACK ); + apis.push_back( rtmidi::UNIX_JACK ); #endif #if defined(__WINDOWS_MM__) - apis.push_back( rtmidi::WINDOWS_MM ); + apis.push_back( rtmidi::WINDOWS_MM ); #endif #if defined(__RTMIDI_DUMMY__) - apis.push_back( rtmidi::RTMIDI_DUMMY ); + apis.push_back( rtmidi::RTMIDI_DUMMY ); #endif - } +} - void Midi :: error( Error::Type type, std::string errorString ) - { +void Midi :: error( Error::Type type, std::string errorString ) +{ #if 0 - if ( errorCallback_ ) { - static bool firstErrorOccured = false; + if ( errorCallback_ ) { + static bool firstErrorOccured = false; - if ( firstErrorOccured ) - return; + if ( firstErrorOccured ) + return; - firstErrorOccured = true; - const std::string errorMessage = errorString; + firstErrorOccured = true; + const std::string errorMessage = errorString; - errorCallback_( type, errorMessage ); - firstErrorOccured = false; - return; - } + errorCallback_( type, errorMessage ); + firstErrorOccured = false; + return; + } #endif - if ( type == Error::WARNING ) { - std::cerr << '\n' << errorString << "\n\n"; - } - else if ( type == Error::DEBUG_WARNING ) { + if ( type == Error::WARNING ) { + std::cerr << '\n' << errorString << "\n\n"; + } + else if ( type == Error::DEBUG_WARNING ) { #if defined(__RTMIDI_DEBUG__) - std::cerr << '\n' << errorString << "\n\n"; + std::cerr << '\n' << errorString << "\n\n"; #endif - } - else { - std::cerr << '\n' << errorString << "\n\n"; - throw Error( errorString, type ); - } - } + } + else { + std::cerr << '\n' << errorString << "\n\n"; + throw Error( errorString, type ); + } +} - //*********************************************************************// - // MidiIn Definitions - //*********************************************************************// +//*********************************************************************// +// MidiIn Definitions +//*********************************************************************// - void MidiIn :: openMidiApi( ApiType api, const std::string clientName, unsigned int queueSizeLimit ) - { - if ( rtapi_ ) - delete rtapi_; - rtapi_ = 0; +void MidiIn :: openMidiApi( ApiType api, const std::string clientName, unsigned int queueSizeLimit ) +{ + if ( rtapi_ ) + delete rtapi_; + rtapi_ = 0; #if defined(__UNIX_JACK__) - if ( api == rtmidi::UNIX_JACK ) - rtapi_ = new MidiInJack( clientName, queueSizeLimit ); + if ( api == rtmidi::UNIX_JACK ) + rtapi_ = new MidiInJack( clientName, queueSizeLimit ); #endif #if defined(__LINUX_ALSA__) - if ( api == rtmidi::LINUX_ALSA ) - rtapi_ = new MidiInAlsa( clientName, queueSizeLimit ); + if ( api == rtmidi::LINUX_ALSA ) + rtapi_ = new MidiInAlsa( clientName, queueSizeLimit ); #endif #if defined(__WINDOWS_MM__) - if ( api == rtmidi::WINDOWS_MM ) - rtapi_ = new MidiInWinMM( clientName, queueSizeLimit ); + if ( api == rtmidi::WINDOWS_MM ) + rtapi_ = new MidiInWinMM( clientName, queueSizeLimit ); #endif #if defined(__MACOSX_CORE__) - if ( api == rtmidi::MACOSX_CORE ) - rtapi_ = new MidiInCore( clientName, queueSizeLimit ); + if ( api == rtmidi::MACOSX_CORE ) + rtapi_ = new MidiInCore( clientName, queueSizeLimit ); #endif #if defined(__RTMIDI_DUMMY__) - if ( api == rtmidi::RTMIDI_DUMMY ) - rtapi_ = new MidiInDummy( clientName, queueSizeLimit ); + if ( api == rtmidi::RTMIDI_DUMMY ) + rtapi_ = new MidiInDummy( clientName, queueSizeLimit ); #endif - } +} - MidiIn :: MidiIn( ApiType api, const std::string clientName, unsigned int queueSizeLimit ) - : Midi() - { - if ( api != rtmidi::UNSPECIFIED ) { - // Attempt to open the specified API. - openMidiApi( api, clientName, queueSizeLimit ); - if ( rtapi_ ) return; - - // No compiled support for specified API value. Issue a warning - // and continue as if no API was specified. - std::cerr << "\nMidiIn: no compiled support for specified API argument!\n\n" << std::endl; - } - - // Iterate through the compiled APIs and return as soon as we find - // one with at least one port or we reach the end of the list. - std::vector< ApiType > apis; - getCompiledApi( apis ); - for ( unsigned int i=0; igetPortCount() ) break; - } - - if ( rtapi_ ) return; - - // It should not be possible to get here because the preprocessor - // definition __RTMIDI_DUMMY__ is automatically defined if no - // API-specific definitions are passed to the compiler. But just in - // case something weird happens, we'll throw an error. - std::string errorText = "MidiIn: no compiled API support found ... critical error!!"; - throw( Error( errorText, Error::UNSPECIFIED ) ); - } +MidiIn :: MidiIn( ApiType api, const std::string clientName, unsigned int queueSizeLimit ) + : Midi() +{ + if ( api != rtmidi::UNSPECIFIED ) { + // Attempt to open the specified API. + openMidiApi( api, clientName, queueSizeLimit ); + if ( rtapi_ ) return; + + // No compiled support for specified API value. Issue a warning + // and continue as if no API was specified. + std::cerr << "\nMidiIn: no compiled support for specified API argument!\n\n" << std::endl; + } + + // Iterate through the compiled APIs and return as soon as we find + // one with at least one port or we reach the end of the list. + std::vector< ApiType > apis; + getCompiledApi( apis ); + for ( unsigned int i=0; igetPortCount() ) break; + } + + if ( rtapi_ ) return; + + // It should not be possible to get here because the preprocessor + // definition __RTMIDI_DUMMY__ is automatically defined if no + // API-specific definitions are passed to the compiler. But just in + // case something weird happens, we'll throw an error. + std::string errorText = "MidiIn: no compiled API support found ... critical error!!"; + throw( Error( errorText, Error::UNSPECIFIED ) ); +} - MidiIn :: ~MidiIn() throw() - { - } +MidiIn :: ~MidiIn() throw() +{ +} - //*********************************************************************// - // MidiOut Definitions - //*********************************************************************// +//*********************************************************************// +// MidiOut Definitions +//*********************************************************************// - void MidiOut :: openMidiApi( ApiType api, const std::string clientName ) - { - if ( rtapi_ ) - delete rtapi_; - rtapi_ = 0; +void MidiOut :: openMidiApi( ApiType api, const std::string clientName ) +{ + if ( rtapi_ ) + delete rtapi_; + rtapi_ = 0; #if defined(__UNIX_JACK__) - if ( api == rtmidi::UNIX_JACK ) - rtapi_ = new MidiOutJack( clientName ); + if ( api == rtmidi::UNIX_JACK ) + rtapi_ = new MidiOutJack( clientName ); #endif #if defined(__LINUX_ALSA__) - if ( api == rtmidi::LINUX_ALSA ) - rtapi_ = new MidiOutAlsa( clientName ); + if ( api == rtmidi::LINUX_ALSA ) + rtapi_ = new MidiOutAlsa( clientName ); #endif #if defined(__WINDOWS_MM__) - if ( api == rtmidi::WINDOWS_MM ) - rtapi_ = new MidiOutWinMM( clientName ); + if ( api == rtmidi::WINDOWS_MM ) + rtapi_ = new MidiOutWinMM( clientName ); #endif #if defined(__MACOSX_CORE__) - if ( api == rtmidi::MACOSX_CORE ) - rtapi_ = new MidiOutCore( clientName ); + if ( api == rtmidi::MACOSX_CORE ) + rtapi_ = new MidiOutCore( clientName ); #endif #if defined(__RTMIDI_DUMMY__) - if ( api == rtmidi::RTMIDI_DUMMY ) - rtapi_ = new MidiOutDummy( clientName ); + if ( api == rtmidi::RTMIDI_DUMMY ) + rtapi_ = new MidiOutDummy( clientName ); #endif - } +} - MidiOut :: MidiOut( ApiType api, const std::string clientName ) - { - if ( api != rtmidi::UNSPECIFIED ) { - // Attempt to open the specified API. - openMidiApi( api, clientName ); - if ( rtapi_ ) return; - - // No compiled support for specified API value. Issue a warning - // and continue as if no API was specified. - std::cerr << "\nMidiOut: no compiled support for specified API argument!\n\n" << std::endl; - } - - // Iterate through the compiled APIs and return as soon as we find - // one with at least one port or we reach the end of the list. - std::vector< ApiType > apis; - getCompiledApi( apis ); - for ( unsigned int i=0; igetPortCount() ) break; - } - - if ( rtapi_ ) return; - - // It should not be possible to get here because the preprocessor - // definition __RTMIDI_DUMMY__ is automatically defined if no - // API-specific definitions are passed to the compiler. But just in - // case something weird happens, we'll thrown an error. - std::string errorText = "MidiOut: no compiled API support found ... critical error!!"; - throw( Error( errorText, Error::UNSPECIFIED ) ); - } +MidiOut :: MidiOut( ApiType api, const std::string clientName ) +{ + if ( api != rtmidi::UNSPECIFIED ) { + // Attempt to open the specified API. + openMidiApi( api, clientName ); + if ( rtapi_ ) return; + + // No compiled support for specified API value. Issue a warning + // and continue as if no API was specified. + std::cerr << "\nMidiOut: no compiled support for specified API argument!\n\n" << std::endl; + } + + // Iterate through the compiled APIs and return as soon as we find + // one with at least one port or we reach the end of the list. + std::vector< ApiType > apis; + getCompiledApi( apis ); + for ( unsigned int i=0; igetPortCount() ) break; + } + + if ( rtapi_ ) return; + + // It should not be possible to get here because the preprocessor + // definition __RTMIDI_DUMMY__ is automatically defined if no + // API-specific definitions are passed to the compiler. But just in + // case something weird happens, we'll thrown an error. + std::string errorText = "MidiOut: no compiled API support found ... critical error!!"; + throw( Error( errorText, Error::UNSPECIFIED ) ); +} - MidiOut :: ~MidiOut() throw() - { - } +MidiOut :: ~MidiOut() throw() +{ +} - //*********************************************************************// - // Common MidiApi Definitions - //*********************************************************************// +//*********************************************************************// +// Common MidiApi Definitions +//*********************************************************************// - MidiApi :: MidiApi( void ) - : apiData_( 0 ), connected_( false ), errorCallback_(0) - { - } +MidiApi :: MidiApi( void ) + : apiData_( 0 ), connected_( false ), errorCallback_(0) +{ +} - MidiApi :: ~MidiApi( void ) - { - } +MidiApi :: ~MidiApi( void ) +{ +} - void MidiApi :: setErrorCallback( ErrorCallback errorCallback ) - { - errorCallback_ = errorCallback; - } +void MidiApi :: setErrorCallback( ErrorCallback errorCallback ) +{ + errorCallback_ = errorCallback; +} - void MidiApi :: error( Error::Type type, std::string errorString ) - { - if ( errorCallback_ ) { - static bool firstErrorOccured = false; +void MidiApi :: error( Error::Type type, std::string errorString ) +{ + if ( errorCallback_ ) { + static bool firstErrorOccured = false; - if ( firstErrorOccured ) - return; + if ( firstErrorOccured ) + return; - firstErrorOccured = true; - const std::string errorMessage = errorString; + firstErrorOccured = true; + const std::string errorMessage = errorString; - errorCallback_( type, errorMessage ); - firstErrorOccured = false; - return; - } + errorCallback_( type, errorMessage ); + firstErrorOccured = false; + return; + } - if ( type == Error::WARNING ) { - std::cerr << '\n' << errorString << "\n\n"; - } - else if ( type == Error::DEBUG_WARNING ) { + if ( type == Error::WARNING ) { + std::cerr << '\n' << errorString << "\n\n"; + } + else if ( type == Error::DEBUG_WARNING ) { #if defined(__RTMIDI_DEBUG__) - std::cerr << '\n' << errorString << "\n\n"; + std::cerr << '\n' << errorString << "\n\n"; #endif - } - else { - std::cerr << '\n' << errorString << "\n\n"; - throw Error( errorString, type ); - } - } + } + else { + std::cerr << '\n' << errorString << "\n\n"; + throw Error( errorString, type ); + } +} - //*********************************************************************// - // Common MidiInApi Definitions - //*********************************************************************// - - MidiInApi :: MidiInApi( unsigned int queueSizeLimit ) - : MidiApi() - { - // Allocate the MIDI queue. - inputData_.queue.ringSize = queueSizeLimit; - if ( inputData_.queue.ringSize > 0 ) - inputData_.queue.ring = new MidiMessage[ inputData_.queue.ringSize ]; - } +//*********************************************************************// +// Common MidiInApi Definitions +//*********************************************************************// + +MidiInApi :: MidiInApi( unsigned int queueSizeLimit ) + : MidiApi() +{ + // Allocate the MIDI queue. + inputData_.queue.ringSize = queueSizeLimit; + if ( inputData_.queue.ringSize > 0 ) + inputData_.queue.ring = new MidiMessage[ inputData_.queue.ringSize ]; +} - MidiInApi :: ~MidiInApi( void ) - { - // Delete the MIDI queue. - if ( inputData_.queue.ringSize > 0 ) delete [] inputData_.queue.ring; - } +MidiInApi :: ~MidiInApi( void ) +{ + // Delete the MIDI queue. + if ( inputData_.queue.ringSize > 0 ) delete [] inputData_.queue.ring; +} - void MidiInApi :: setCallback( MidiCallback callback, void *userData ) - { - if ( inputData_.usingCallback ) { - errorString_ = "MidiInApi::setCallback: a callback function is already set!"; - error( Error::WARNING, errorString_ ); - return; - } - - if ( !callback ) { - errorString_ = "MidiIn::setCallback: callback function value is invalid!"; - error( Error::WARNING, errorString_ ); - return; - } - - inputData_.userCallback = callback; - inputData_.userData = userData; - inputData_.usingCallback = true; - } +void MidiInApi :: setCallback( MidiCallback callback, void *userData ) +{ + if ( inputData_.usingCallback ) { + errorString_ = "MidiInApi::setCallback: a callback function is already set!"; + error( Error::WARNING, errorString_ ); + return; + } + + if ( !callback ) { + errorString_ = "MidiIn::setCallback: callback function value is invalid!"; + error( Error::WARNING, errorString_ ); + return; + } + + inputData_.userCallback = callback; + inputData_.userData = userData; + inputData_.usingCallback = true; +} - void MidiInApi :: cancelCallback() - { - if ( !inputData_.usingCallback ) { - errorString_ = "MidiIn::cancelCallback: no callback function was set!"; - error( Error::WARNING, errorString_ ); - return; - } - - inputData_.userCallback = 0; - inputData_.userData = 0; - inputData_.usingCallback = false; - } +void MidiInApi :: cancelCallback() +{ + if ( !inputData_.usingCallback ) { + errorString_ = "MidiIn::cancelCallback: no callback function was set!"; + error( Error::WARNING, errorString_ ); + return; + } + + inputData_.userCallback = 0; + inputData_.userData = 0; + inputData_.usingCallback = false; +} - void MidiInApi :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) - { - inputData_.ignoreFlags = 0; - if ( midiSysex ) inputData_.ignoreFlags = 0x01; - if ( midiTime ) inputData_.ignoreFlags |= 0x02; - if ( midiSense ) inputData_.ignoreFlags |= 0x04; - } +void MidiInApi :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) +{ + inputData_.ignoreFlags = 0; + if ( midiSysex ) inputData_.ignoreFlags = 0x01; + if ( midiTime ) inputData_.ignoreFlags |= 0x02; + if ( midiSense ) inputData_.ignoreFlags |= 0x04; +} - double MidiInApi :: getMessage( std::vector &message ) - { - message.clear(); +double MidiInApi :: getMessage( std::vector &message ) +{ + message.clear(); - if ( inputData_.usingCallback ) { - errorString_ = "MidiIn::getMessage: a user callback is currently set for this port."; - error( Error::WARNING, errorString_ ); - return 0.0; - } + if ( inputData_.usingCallback ) { + errorString_ = "MidiIn::getMessage: a user callback is currently set for this port."; + error( Error::WARNING, errorString_ ); + return 0.0; + } - if ( inputData_.queue.size == 0 ) return 0.0; + if ( inputData_.queue.size == 0 ) return 0.0; - // Copy queued message to the vector pointer argument and then "pop" it. - std::vector *bytes = &(inputData_.queue.ring[inputData_.queue.front].bytes); - message.assign( bytes->begin(), bytes->end() ); - double deltaTime = inputData_.queue.ring[inputData_.queue.front].timeStamp; - inputData_.queue.size--; - inputData_.queue.front++; - if ( inputData_.queue.front == inputData_.queue.ringSize ) - inputData_.queue.front = 0; + // Copy queued message to the vector pointer argument and then "pop" it. + std::vector *bytes = &(inputData_.queue.ring[inputData_.queue.front].bytes); + message.assign( bytes->begin(), bytes->end() ); + double deltaTime = inputData_.queue.ring[inputData_.queue.front].timeStamp; + inputData_.queue.size--; + inputData_.queue.front++; + if ( inputData_.queue.front == inputData_.queue.ringSize ) + inputData_.queue.front = 0; - return deltaTime; - } + return deltaTime; +} - //*********************************************************************// - // Common MidiOutApi Definitions - //*********************************************************************// +//*********************************************************************// +// Common MidiOutApi Definitions +//*********************************************************************// - MidiOutApi :: MidiOutApi( void ) - : MidiApi() - { - } +MidiOutApi :: MidiOutApi( void ) + : MidiApi() +{ +} - MidiOutApi :: ~MidiOutApi( void ) - { - } +MidiOutApi :: ~MidiOutApi( void ) +{ +} - // *************************************************** // - // - // OS/API-specific methods. - // - // *************************************************** // +// *************************************************** // +// +// OS/API-specific methods. +// +// *************************************************** // -} +NAMSPACE_RTMIDI_END #if defined(__MACOSX_CORE__) - // The CoreMIDI API is based on the use of a callback function for - // MIDI input. We convert the system specific time stamps to delta - // time values. +// The CoreMIDI API is based on the use of a callback function for +// MIDI input. We convert the system specific time stamps to delta +// time values. - // OS-X CoreMIDI header files. +// OS-X CoreMIDI header files. #include #include #include -namespace rtmidi { - // A structure to hold variables related to the CoreMIDI API - // implementation. - struct CoreMidiData { - MIDIClientRef client; - MIDIPortRef port; - MIDIEndpointRef endpoint; - MIDIEndpointRef destinationId; - unsigned long long lastTime; - MIDISysexSendRequest sysexreq; - }; - - //*********************************************************************// - // API: OS-X - // Class Definitions: MidiInCore - //*********************************************************************// - - static void midiInputCallback( const MIDIPacketList *list, void *procRef, void */*srcRef*/ ) - { - MidiInApi::MidiInData *data = static_cast (procRef); - CoreMidiData *apiData = static_cast (data->apiData); - - unsigned char status; - unsigned short nBytes, iByte, size; - unsigned long long time; - - bool& continueSysex = data->continueSysex; - MidiInApi::MidiMessage& message = data->message; - - const MIDIPacket *packet = &list->packet[0]; - for ( unsigned int i=0; inumPackets; ++i ) { - - // My interpretation of the CoreMIDI documentation: all message - // types, except sysex, are complete within a packet and there may - // be several of them in a single packet. Sysex messages can be - // broken across multiple packets and PacketLists but are bundled - // alone within each packet (these packets do not contain other - // message types). If sysex messages are split across multiple - // MIDIPacketLists, they must be handled by multiple calls to this - // function. - - nBytes = packet->length; - if ( nBytes == 0 ) continue; - - // Calculate time stamp. - - if ( data->firstMessage ) { - message.timeStamp = 0.0; - data->firstMessage = false; - } - else { - time = packet->timeStamp; - if ( time == 0 ) { // this happens when receiving asynchronous sysex messages - time = AudioGetCurrentHostTime(); - } - time -= apiData->lastTime; - time = AudioConvertHostTimeToNanos( time ); - 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; - - iByte = 0; - if ( continueSysex ) { - // We have a continuing, segmented sysex message. - if ( !( data->ignoreFlags & 0x01 ) ) { - // If we're not ignoring sysex messages, copy the entire packet. - for ( unsigned int j=0; jdata[j] ); - } - continueSysex = packet->data[nBytes-1] != 0xF7; - - if ( !( data->ignoreFlags & 0x01 ) ) { - if ( !continueSysex ) { - // If not a continuing sysex message, invoke the user callback function or queue the message. - if ( data->usingCallback ) { - MidiCallback callback = (MidiCallback) data->userCallback; - callback( message.timeStamp, &message.bytes, data->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else - std::cerr << "\nMidiInCore: message queue limit reached!!\n\n"; - } - message.bytes.clear(); - } - } - } - else { - while ( iByte < nBytes ) { - size = 0; - // We are expecting that the next byte in the packet is a status byte. - status = packet->data[iByte]; - if ( !(status & 0x80) ) break; - // Determine the number of bytes in the MIDI message. - if ( status < 0xC0 ) size = 3; - else if ( status < 0xE0 ) size = 2; - else if ( status < 0xF0 ) size = 3; - else if ( status == 0xF0 ) { - // A MIDI sysex - if ( data->ignoreFlags & 0x01 ) { - size = 0; - iByte = nBytes; - } - else size = nBytes - iByte; - continueSysex = packet->data[nBytes-1] != 0xF7; - } - else if ( status == 0xF1 ) { - // A MIDI time code message - if ( data->ignoreFlags & 0x02 ) { - size = 0; - iByte += 2; - } - else size = 2; - } - else if ( status == 0xF2 ) size = 3; - else if ( status == 0xF3 ) size = 2; - else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) { - // A MIDI timing tick message and we're ignoring it. - size = 0; - iByte += 1; - } - else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) { - // A MIDI active sensing message and we're ignoring it. - size = 0; - iByte += 1; - } - else size = 1; - - // Copy the MIDI data to our vector. - if ( size ) { - 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. - if ( data->usingCallback ) { - MidiCallback callback = (MidiCallback) data->userCallback; - callback( message.timeStamp, &message.bytes, data->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else - std::cerr << "\nMidiInCore: message queue limit reached!!\n\n"; - } - message.bytes.clear(); - } - iByte += size; - } - } - } - packet = MIDIPacketNext(packet); - } - } +NAMSPACE_RTMIDI_START +// A structure to hold variables related to the CoreMIDI API +// implementation. +struct CoreMidiData { + MIDIClientRef client; + MIDIPortRef port; + MIDIEndpointRef endpoint; + MIDIEndpointRef destinationId; + unsigned long long lastTime; + MIDISysexSendRequest sysexreq; +}; + +//*********************************************************************// +// API: OS-X +// Class Definitions: MidiInCore +//*********************************************************************// + +static void midiInputCallback( const MIDIPacketList *list, void *procRef, void */*srcRef*/ ) +{ + MidiInApi::MidiInData *data = static_cast (procRef); + CoreMidiData *apiData = static_cast (data->apiData); + + unsigned char status; + unsigned short nBytes, iByte, size; + unsigned long long time; + + bool& continueSysex = data->continueSysex; + MidiInApi::MidiMessage& message = data->message; + + const MIDIPacket *packet = &list->packet[0]; + for ( unsigned int i=0; inumPackets; ++i ) { + + // My interpretation of the CoreMIDI documentation: all message + // types, except sysex, are complete within a packet and there may + // be several of them in a single packet. Sysex messages can be + // broken across multiple packets and PacketLists but are bundled + // alone within each packet (these packets do not contain other + // message types). If sysex messages are split across multiple + // MIDIPacketLists, they must be handled by multiple calls to this + // function. + + nBytes = packet->length; + if ( nBytes == 0 ) continue; + + // Calculate time stamp. + + if ( data->firstMessage ) { + message.timeStamp = 0.0; + data->firstMessage = false; + } + else { + time = packet->timeStamp; + if ( time == 0 ) { // this happens when receiving asynchronous sysex messages + time = AudioGetCurrentHostTime(); + } + time -= apiData->lastTime; + time = AudioConvertHostTimeToNanos( time ); + 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; + + iByte = 0; + if ( continueSysex ) { + // We have a continuing, segmented sysex message. + if ( !( data->ignoreFlags & 0x01 ) ) { + // If we're not ignoring sysex messages, copy the entire packet. + for ( unsigned int j=0; jdata[j] ); + } + continueSysex = packet->data[nBytes-1] != 0xF7; + + if ( !( data->ignoreFlags & 0x01 ) ) { + if ( !continueSysex ) { + // If not a continuing sysex message, invoke the user callback function or queue the message. + if ( data->usingCallback ) { + MidiCallback callback = (MidiCallback) data->userCallback; + callback( message.timeStamp, &message.bytes, data->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else + std::cerr << "\nMidiInCore: message queue limit reached!!\n\n"; + } + message.bytes.clear(); + } + } + } + else { + while ( iByte < nBytes ) { + size = 0; + // We are expecting that the next byte in the packet is a status byte. + status = packet->data[iByte]; + if ( !(status & 0x80) ) break; + // Determine the number of bytes in the MIDI message. + if ( status < 0xC0 ) size = 3; + else if ( status < 0xE0 ) size = 2; + else if ( status < 0xF0 ) size = 3; + else if ( status == 0xF0 ) { + // A MIDI sysex + if ( data->ignoreFlags & 0x01 ) { + size = 0; + iByte = nBytes; + } + else size = nBytes - iByte; + continueSysex = packet->data[nBytes-1] != 0xF7; + } + else if ( status == 0xF1 ) { + // A MIDI time code message + if ( data->ignoreFlags & 0x02 ) { + size = 0; + iByte += 2; + } + else size = 2; + } + else if ( status == 0xF2 ) size = 3; + else if ( status == 0xF3 ) size = 2; + else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) { + // A MIDI timing tick message and we're ignoring it. + size = 0; + iByte += 1; + } + else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) { + // A MIDI active sensing message and we're ignoring it. + size = 0; + iByte += 1; + } + else size = 1; + + // Copy the MIDI data to our vector. + if ( size ) { + 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. + if ( data->usingCallback ) { + MidiCallback callback = (MidiCallback) data->userCallback; + callback( message.timeStamp, &message.bytes, data->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else + std::cerr << "\nMidiInCore: message queue limit reached!!\n\n"; + } + message.bytes.clear(); + } + iByte += size; + } + } + } + packet = MIDIPacketNext(packet); + } +} - MidiInCore :: MidiInCore( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) - { - initialize( clientName ); - } +MidiInCore :: MidiInCore( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) +{ + initialize( clientName ); +} - MidiInCore :: ~MidiInCore( void ) - { - // Close a connection if it exists. - closePort(); +MidiInCore :: ~MidiInCore( void ) +{ + // Close a connection if it exists. + closePort(); - // Cleanup. - CoreMidiData *data = static_cast (apiData_); - MIDIClientDispose( data->client ); - if ( data->endpoint ) MIDIEndpointDispose( data->endpoint ); - delete data; - } + // Cleanup. + CoreMidiData *data = static_cast (apiData_); + MIDIClientDispose( data->client ); + if ( data->endpoint ) MIDIEndpointDispose( data->endpoint ); + delete data; +} - void MidiInCore :: initialize( const std::string& clientName ) - { - // Set up our client. - MIDIClientRef client; - OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client ); - if ( result != noErr ) { - errorString_ = "MidiInCore::initialize: error creating OS-X MIDI client object."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Save our api-specific connection information. - CoreMidiData *data = (CoreMidiData *) new CoreMidiData; - data->client = client; - data->endpoint = 0; - apiData_ = (void *) data; - inputData_.apiData = (void *) data; - } +void MidiInCore :: initialize( const std::string& clientName ) +{ + // Set up our client. + MIDIClientRef client; + OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client ); + if ( result != noErr ) { + errorString_ = "MidiInCore::initialize: error creating OS-X MIDI client object."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Save our api-specific connection information. + CoreMidiData *data = (CoreMidiData *) new CoreMidiData; + data->client = client; + data->endpoint = 0; + apiData_ = (void *) data; + inputData_.apiData = (void *) data; +} - void MidiInCore :: openPort( unsigned int portNumber, const std::string portName ) - { - if ( connected_ ) { - errorString_ = "MidiInCore::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); - return; - } - - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - unsigned int nSrc = MIDIGetNumberOfSources(); - if (nSrc < 1) { - errorString_ = "MidiInCore::openPort: no MIDI input sources found!"; - error( Error::NO_DEVICES_FOUND, errorString_ ); - return; - } - - if ( portNumber >= nSrc ) { - std::ostringstream ost; - ost << "MidiInCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::INVALID_PARAMETER, errorString_ ); - return; - } - - MIDIPortRef port; - CoreMidiData *data = static_cast (apiData_); - OSStatus result = MIDIInputPortCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), - midiInputCallback, (void *)&inputData_, &port ); - if ( result != noErr ) { - MIDIClientDispose( data->client ); - errorString_ = "MidiInCore::openPort: error creating OS-X MIDI input port."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Get the desired input source identifier. - MIDIEndpointRef endpoint = MIDIGetSource( portNumber ); - if ( endpoint == 0 ) { - MIDIPortDispose( port ); - MIDIClientDispose( data->client ); - errorString_ = "MidiInCore::openPort: error getting MIDI input source reference."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Make the connection. - result = MIDIPortConnectSource( port, endpoint, NULL ); - if ( result != noErr ) { - MIDIPortDispose( port ); - MIDIClientDispose( data->client ); - errorString_ = "MidiInCore::openPort: error connecting OS-X MIDI input port."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Save our api-specific port information. - data->port = port; - - connected_ = true; - } +void MidiInCore :: openPort( unsigned int portNumber, const std::string portName ) +{ + if ( connected_ ) { + errorString_ = "MidiInCore::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + unsigned int nSrc = MIDIGetNumberOfSources(); + if (nSrc < 1) { + errorString_ = "MidiInCore::openPort: no MIDI input sources found!"; + error( Error::NO_DEVICES_FOUND, errorString_ ); + return; + } + + if ( portNumber >= nSrc ) { + std::ostringstream ost; + ost << "MidiInCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::INVALID_PARAMETER, errorString_ ); + return; + } + + MIDIPortRef port; + CoreMidiData *data = static_cast (apiData_); + OSStatus result = MIDIInputPortCreate( data->client, + CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), + midiInputCallback, (void *)&inputData_, &port ); + if ( result != noErr ) { + MIDIClientDispose( data->client ); + errorString_ = "MidiInCore::openPort: error creating OS-X MIDI input port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Get the desired input source identifier. + MIDIEndpointRef endpoint = MIDIGetSource( portNumber ); + if ( endpoint == 0 ) { + MIDIPortDispose( port ); + MIDIClientDispose( data->client ); + errorString_ = "MidiInCore::openPort: error getting MIDI input source reference."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Make the connection. + result = MIDIPortConnectSource( port, endpoint, NULL ); + if ( result != noErr ) { + MIDIPortDispose( port ); + MIDIClientDispose( data->client ); + errorString_ = "MidiInCore::openPort: error connecting OS-X MIDI input port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Save our api-specific port information. + data->port = port; + + connected_ = true; +} - void MidiInCore :: openVirtualPort( const std::string portName ) - { - CoreMidiData *data = static_cast (apiData_); - - // Create a virtual MIDI input destination. - MIDIEndpointRef endpoint; - OSStatus result = MIDIDestinationCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), - midiInputCallback, (void *)&inputData_, &endpoint ); - if ( result != noErr ) { - errorString_ = "MidiInCore::openVirtualPort: error creating virtual OS-X MIDI destination."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Save our api-specific connection information. - data->endpoint = endpoint; - } +void MidiInCore :: openVirtualPort( const std::string portName ) +{ + CoreMidiData *data = static_cast (apiData_); + + // Create a virtual MIDI input destination. + MIDIEndpointRef endpoint; + OSStatus result = MIDIDestinationCreate( data->client, + CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), + midiInputCallback, (void *)&inputData_, &endpoint ); + if ( result != noErr ) { + errorString_ = "MidiInCore::openVirtualPort: error creating virtual OS-X MIDI destination."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Save our api-specific connection information. + data->endpoint = endpoint; +} - void MidiInCore :: closePort( void ) - { - if ( connected_ ) { - CoreMidiData *data = static_cast (apiData_); - MIDIPortDispose( data->port ); - connected_ = false; - } - } +void MidiInCore :: closePort( void ) +{ + if ( connected_ ) { + CoreMidiData *data = static_cast (apiData_); + MIDIPortDispose( data->port ); + connected_ = false; + } +} - unsigned int MidiInCore :: getPortCount() - { - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - return MIDIGetNumberOfSources(); - } +unsigned int MidiInCore :: getPortCount() +{ + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + return MIDIGetNumberOfSources(); +} - // This function was submitted by Douglas Casey Tucker and apparently - // derived largely from PortMidi. - CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal ) - { - CFMutableStringRef result = CFStringCreateMutable( NULL, 0 ); - CFStringRef str; - - // Begin with the endpoint's name. - str = NULL; - MIDIObjectGetStringProperty( endpoint, kMIDIPropertyName, &str ); - if ( str != NULL ) { - CFStringAppend( result, str ); - CFRelease( str ); - } - - MIDIEntityRef entity = 0; - MIDIEndpointGetEntity( endpoint, &entity ); - if ( entity == 0 ) - // probably virtual - return result; - - if ( CFStringGetLength( result ) == 0 ) { - // endpoint name has zero length -- try the entity - str = NULL; - MIDIObjectGetStringProperty( entity, kMIDIPropertyName, &str ); - if ( str != NULL ) { - CFStringAppend( result, str ); - CFRelease( str ); - } - } - // now consider the device's name - MIDIDeviceRef device = 0; - MIDIEntityGetDevice( entity, &device ); - if ( device == 0 ) - return result; - - str = NULL; - MIDIObjectGetStringProperty( device, kMIDIPropertyName, &str ); - if ( CFStringGetLength( result ) == 0 ) { - CFRelease( result ); - return str; - } - if ( str != NULL ) { - // if an external device has only one entity, throw away - // the endpoint name and just use the device name - if ( isExternal && MIDIDeviceGetNumberOfEntities( device ) < 2 ) { - CFRelease( result ); - return str; - } else { - if ( CFStringGetLength( str ) == 0 ) { - CFRelease( str ); - return result; - } - // does the entity name already start with the device name? - // (some drivers do this though they shouldn't) - // if so, do not prepend - if ( CFStringCompareWithOptions( result, /* endpoint name */ - str /* device name */, - CFRangeMake(0, CFStringGetLength( str ) ), 0 ) != kCFCompareEqualTo ) { - // prepend the device name to the entity name - if ( CFStringGetLength( result ) > 0 ) - CFStringInsert( result, 0, CFSTR(" ") ); - CFStringInsert( result, 0, str ); - } - CFRelease( str ); - } - } - return result; - } +// This function was submitted by Douglas Casey Tucker and apparently +// derived largely from PortMidi. +CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal ) +{ + CFMutableStringRef result = CFStringCreateMutable( NULL, 0 ); + CFStringRef str; + + // Begin with the endpoint's name. + str = NULL; + MIDIObjectGetStringProperty( endpoint, kMIDIPropertyName, &str ); + if ( str != NULL ) { + CFStringAppend( result, str ); + CFRelease( str ); + } + + MIDIEntityRef entity = 0; + MIDIEndpointGetEntity( endpoint, &entity ); + if ( entity == 0 ) + // probably virtual + return result; + + if ( CFStringGetLength( result ) == 0 ) { + // endpoint name has zero length -- try the entity + str = NULL; + MIDIObjectGetStringProperty( entity, kMIDIPropertyName, &str ); + if ( str != NULL ) { + CFStringAppend( result, str ); + CFRelease( str ); + } + } + // now consider the device's name + MIDIDeviceRef device = 0; + MIDIEntityGetDevice( entity, &device ); + if ( device == 0 ) + return result; + + str = NULL; + MIDIObjectGetStringProperty( device, kMIDIPropertyName, &str ); + if ( CFStringGetLength( result ) == 0 ) { + CFRelease( result ); + return str; + } + if ( str != NULL ) { + // if an external device has only one entity, throw away + // the endpoint name and just use the device name + if ( isExternal && MIDIDeviceGetNumberOfEntities( device ) < 2 ) { + CFRelease( result ); + return str; + } else { + if ( CFStringGetLength( str ) == 0 ) { + CFRelease( str ); + return result; + } + // does the entity name already start with the device name? + // (some drivers do this though they shouldn't) + // if so, do not prepend + if ( CFStringCompareWithOptions( result, /* endpoint name */ + str /* device name */, + CFRangeMake(0, CFStringGetLength( str ) ), 0 ) != kCFCompareEqualTo ) { + // prepend the device name to the entity name + if ( CFStringGetLength( result ) > 0 ) + CFStringInsert( result, 0, CFSTR(" ") ); + CFStringInsert( result, 0, str ); + } + CFRelease( str ); + } + } + return result; +} - // This function was submitted by Douglas Casey Tucker and apparently - // derived largely from PortMidi. - static CFStringRef ConnectedEndpointName( MIDIEndpointRef endpoint ) - { - CFMutableStringRef result = CFStringCreateMutable( NULL, 0 ); - CFStringRef str; - OSStatus err; - int i; - - // Does the endpoint have connections? - CFDataRef connections = NULL; - int nConnected = 0; - bool anyStrings = false; - err = MIDIObjectGetDataProperty( endpoint, kMIDIPropertyConnectionUniqueID, &connections ); - if ( connections != NULL ) { - // It has connections, follow them - // Concatenate the names of all connected devices - nConnected = CFDataGetLength( connections ) / sizeof(MIDIUniqueID); - if ( nConnected ) { - const SInt32 *pid = (const SInt32 *)(CFDataGetBytePtr(connections)); - for ( i=0; i= MIDIGetNumberOfSources() ) { - std::ostringstream ost; - ost << "MidiInCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::WARNING, errorString_ ); - return stringName; - } - - portRef = MIDIGetSource( portNumber ); - nameRef = ConnectedEndpointName(portRef); - CFStringGetCString( nameRef, name, sizeof(name), CFStringGetSystemEncoding()); - CFRelease( nameRef ); - - return stringName = name; - } +std::string MidiInCore :: getPortName( unsigned int portNumber ) +{ + CFStringRef nameRef; + MIDIEndpointRef portRef; + char name[128]; + + std::string stringName; + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + if ( portNumber >= MIDIGetNumberOfSources() ) { + std::ostringstream ost; + ost << "MidiInCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::WARNING, errorString_ ); + return stringName; + } + + portRef = MIDIGetSource( portNumber ); + nameRef = ConnectedEndpointName(portRef); + CFStringGetCString( nameRef, name, sizeof(name), CFStringGetSystemEncoding()); + CFRelease( nameRef ); + + return stringName = name; +} - //*********************************************************************// - // API: OS-X - // Class Definitions: MidiOutCore - //*********************************************************************// +//*********************************************************************// +// API: OS-X +// Class Definitions: MidiOutCore +//*********************************************************************// - MidiOutCore :: MidiOutCore( const std::string clientName ) : MidiOutApi() - { - initialize( clientName ); - } +MidiOutCore :: MidiOutCore( const std::string clientName ) : MidiOutApi() +{ + initialize( clientName ); +} - MidiOutCore :: ~MidiOutCore( void ) - { - // Close a connection if it exists. - closePort(); +MidiOutCore :: ~MidiOutCore( void ) +{ + // Close a connection if it exists. + closePort(); - // Cleanup. - CoreMidiData *data = static_cast (apiData_); - MIDIClientDispose( data->client ); - if ( data->endpoint ) MIDIEndpointDispose( data->endpoint ); - delete data; - } + // Cleanup. + CoreMidiData *data = static_cast (apiData_); + MIDIClientDispose( data->client ); + if ( data->endpoint ) MIDIEndpointDispose( data->endpoint ); + delete data; +} - void MidiOutCore :: initialize( const std::string& clientName ) - { - // Set up our client. - MIDIClientRef client; - OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client ); - if ( result != noErr ) { - errorString_ = "MidiOutCore::initialize: error creating OS-X MIDI client object."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Save our api-specific connection information. - CoreMidiData *data = (CoreMidiData *) new CoreMidiData; - data->client = client; - data->endpoint = 0; - apiData_ = (void *) data; - } +void MidiOutCore :: initialize( const std::string& clientName ) +{ + // Set up our client. + MIDIClientRef client; + OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client ); + if ( result != noErr ) { + errorString_ = "MidiOutCore::initialize: error creating OS-X MIDI client object."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Save our api-specific connection information. + CoreMidiData *data = (CoreMidiData *) new CoreMidiData; + data->client = client; + data->endpoint = 0; + apiData_ = (void *) data; +} - unsigned int MidiOutCore :: getPortCount() - { - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - return MIDIGetNumberOfDestinations(); - } +unsigned int MidiOutCore :: getPortCount() +{ + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + return MIDIGetNumberOfDestinations(); +} - std::string MidiOutCore :: getPortName( unsigned int portNumber ) - { - CFStringRef nameRef; - MIDIEndpointRef portRef; - char name[128]; - - std::string stringName; - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - if ( portNumber >= MIDIGetNumberOfDestinations() ) { - std::ostringstream ost; - ost << "MidiOutCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::WARNING, errorString_ ); - return stringName; - } - - portRef = MIDIGetDestination( portNumber ); - nameRef = ConnectedEndpointName(portRef); - CFStringGetCString( nameRef, name, sizeof(name), CFStringGetSystemEncoding()); - CFRelease( nameRef ); +std::string MidiOutCore :: getPortName( unsigned int portNumber ) +{ + CFStringRef nameRef; + MIDIEndpointRef portRef; + char name[128]; + + std::string stringName; + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + if ( portNumber >= MIDIGetNumberOfDestinations() ) { + std::ostringstream ost; + ost << "MidiOutCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::WARNING, errorString_ ); + return stringName; + } + + portRef = MIDIGetDestination( portNumber ); + nameRef = ConnectedEndpointName(portRef); + CFStringGetCString( nameRef, name, sizeof(name), CFStringGetSystemEncoding()); + CFRelease( nameRef ); - return stringName = name; - } + return stringName = name; +} - void MidiOutCore :: openPort( unsigned int portNumber, const std::string portName ) - { - if ( connected_ ) { - errorString_ = "MidiOutCore::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); - return; - } - - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - unsigned int nDest = MIDIGetNumberOfDestinations(); - if (nDest < 1) { - errorString_ = "MidiOutCore::openPort: no MIDI output destinations found!"; - error( Error::NO_DEVICES_FOUND, errorString_ ); - return; - } - - if ( portNumber >= nDest ) { - std::ostringstream ost; - ost << "MidiOutCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::INVALID_PARAMETER, errorString_ ); - return; - } - - MIDIPortRef port; - CoreMidiData *data = static_cast (apiData_); - OSStatus result = MIDIOutputPortCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), - &port ); - if ( result != noErr ) { - MIDIClientDispose( data->client ); - errorString_ = "MidiOutCore::openPort: error creating OS-X MIDI output port."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Get the desired output port identifier. - MIDIEndpointRef destination = MIDIGetDestination( portNumber ); - if ( destination == 0 ) { - MIDIPortDispose( port ); - MIDIClientDispose( data->client ); - errorString_ = "MidiOutCore::openPort: error getting MIDI output destination reference."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Save our api-specific connection information. - data->port = port; - data->destinationId = destination; - connected_ = true; - } +void MidiOutCore :: openPort( unsigned int portNumber, const std::string portName ) +{ + if ( connected_ ) { + errorString_ = "MidiOutCore::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + unsigned int nDest = MIDIGetNumberOfDestinations(); + if (nDest < 1) { + errorString_ = "MidiOutCore::openPort: no MIDI output destinations found!"; + error( Error::NO_DEVICES_FOUND, errorString_ ); + return; + } + + if ( portNumber >= nDest ) { + std::ostringstream ost; + ost << "MidiOutCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::INVALID_PARAMETER, errorString_ ); + return; + } + + MIDIPortRef port; + CoreMidiData *data = static_cast (apiData_); + OSStatus result = MIDIOutputPortCreate( data->client, + CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), + &port ); + if ( result != noErr ) { + MIDIClientDispose( data->client ); + errorString_ = "MidiOutCore::openPort: error creating OS-X MIDI output port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Get the desired output port identifier. + MIDIEndpointRef destination = MIDIGetDestination( portNumber ); + if ( destination == 0 ) { + MIDIPortDispose( port ); + MIDIClientDispose( data->client ); + errorString_ = "MidiOutCore::openPort: error getting MIDI output destination reference."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Save our api-specific connection information. + data->port = port; + data->destinationId = destination; + connected_ = true; +} - void MidiOutCore :: closePort( void ) - { - if ( connected_ ) { - CoreMidiData *data = static_cast (apiData_); - MIDIPortDispose( data->port ); - connected_ = false; - } - } +void MidiOutCore :: closePort( void ) +{ + if ( connected_ ) { + CoreMidiData *data = static_cast (apiData_); + MIDIPortDispose( data->port ); + connected_ = false; + } +} - void MidiOutCore :: openVirtualPort( std::string portName ) - { - CoreMidiData *data = static_cast (apiData_); - - if ( data->endpoint ) { - errorString_ = "MidiOutCore::openVirtualPort: a virtual output port already exists!"; - error( Error::WARNING, errorString_ ); - return; - } - - // Create a virtual MIDI output source. - MIDIEndpointRef endpoint; - OSStatus result = MIDISourceCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), - &endpoint ); - if ( result != noErr ) { - errorString_ = "MidiOutCore::initialize: error creating OS-X virtual MIDI source."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Save our api-specific connection information. - data->endpoint = endpoint; - } +void MidiOutCore :: openVirtualPort( std::string portName ) +{ + CoreMidiData *data = static_cast (apiData_); + + if ( data->endpoint ) { + errorString_ = "MidiOutCore::openVirtualPort: a virtual output port already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + + // Create a virtual MIDI output source. + MIDIEndpointRef endpoint; + OSStatus result = MIDISourceCreate( data->client, + CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), + &endpoint ); + if ( result != noErr ) { + errorString_ = "MidiOutCore::initialize: error creating OS-X virtual MIDI source."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Save our api-specific connection information. + data->endpoint = endpoint; +} - // Not necessary if we don't treat sysex messages any differently than - // normal messages ... see below. - //static void sysexCompletionProc( MIDISysexSendRequest *sreq ) - //{ - // free( sreq ); - //} - - void MidiOutCore :: sendMessage( std::vector *message ) - { - // We use the MIDISendSysex() function to asynchronously send sysex - // messages. Otherwise, we use a single CoreMidi MIDIPacket. - unsigned int nBytes = message->size(); - if ( nBytes == 0 ) { - errorString_ = "MidiOutCore::sendMessage: no data in message argument!"; - error( Error::WARNING, errorString_ ); - return; - } - - // unsigned int packetBytes, bytesLeft = nBytes; - // unsigned int messageIndex = 0; - MIDITimeStamp timeStamp = AudioGetCurrentHostTime(); - CoreMidiData *data = static_cast (apiData_); - OSStatus result; - - /* - // I don't think this code is necessary. We can send sysex - // messages through the normal mechanism. In addition, this avoids - // the problem of virtual ports not receiving sysex messages. - - if ( message->at(0) == 0xF0 ) { - - // Apple's fantastic API requires us to free the allocated data in - // the completion callback but trashes the pointer and size before - // we get a chance to free it!! This is a somewhat ugly hack - // submitted by ptarabbia that puts the sysex buffer data right at - // the end of the MIDISysexSendRequest structure. This solution - // does not require that we wait for a previous sysex buffer to be - // sent before sending a new one, which was the old way we did it. - MIDISysexSendRequest *newRequest = (MIDISysexSendRequest *) malloc(sizeof(struct MIDISysexSendRequest) + nBytes); - char * sysexBuffer = ((char *) newRequest) + sizeof(struct MIDISysexSendRequest); - - // Copy data to buffer. - for ( unsigned int i=0; iat(i); - - newRequest->destination = data->destinationId; - newRequest->data = (Byte *)sysexBuffer; - newRequest->bytesToSend = nBytes; - newRequest->complete = 0; - newRequest->completionProc = sysexCompletionProc; - newRequest->completionRefCon = newRequest; - - result = MIDISendSysex(newRequest); - if ( result != noErr ) { - free( newRequest ); - errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; - error( Error::WARNING, errorString_ ); - return; - } - return; - } - else if ( nBytes > 3 ) { - errorString_ = "MidiOutCore::sendMessage: message format problem ... not sysex but > 3 bytes?"; - error( Error::WARNING, errorString_ ); - return; - } - */ - - MIDIPacketList packetList; - MIDIPacket *packet = MIDIPacketListInit( &packetList ); - packet = MIDIPacketListAdd( &packetList, sizeof(packetList), packet, timeStamp, nBytes, (const Byte *) &message->at( 0 ) ); - if ( !packet ) { - errorString_ = "MidiOutCore::sendMessage: could not allocate packet list"; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Send to any destinations that may have connected to us. - if ( data->endpoint ) { - result = MIDIReceived( data->endpoint, &packetList ); - if ( result != noErr ) { - errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; - error( Error::WARNING, errorString_ ); - } - } - - // And send to an explicit destination port if we're connected. - if ( connected_ ) { - result = MIDISend( data->port, data->destinationId, &packetList ); - if ( result != noErr ) { - errorString_ = "MidiOutCore::sendMessage: error sending MIDI message to port."; - error( Error::WARNING, errorString_ ); - } - } - } +// Not necessary if we don't treat sysex messages any differently than +// normal messages ... see below. +//static void sysexCompletionProc( MIDISysexSendRequest *sreq ) +//{ +// free( sreq ); +//} + +void MidiOutCore :: sendMessage( std::vector *message ) +{ + // We use the MIDISendSysex() function to asynchronously send sysex + // messages. Otherwise, we use a single CoreMidi MIDIPacket. + unsigned int nBytes = message->size(); + if ( nBytes == 0 ) { + errorString_ = "MidiOutCore::sendMessage: no data in message argument!"; + error( Error::WARNING, errorString_ ); + return; + } + + // unsigned int packetBytes, bytesLeft = nBytes; + // unsigned int messageIndex = 0; + MIDITimeStamp timeStamp = AudioGetCurrentHostTime(); + CoreMidiData *data = static_cast (apiData_); + OSStatus result; + + /* + // I don't think this code is necessary. We can send sysex + // messages through the normal mechanism. In addition, this avoids + // the problem of virtual ports not receiving sysex messages. + + if ( message->at(0) == 0xF0 ) { + + // Apple's fantastic API requires us to free the allocated data in + // the completion callback but trashes the pointer and size before + // we get a chance to free it!! This is a somewhat ugly hack + // submitted by ptarabbia that puts the sysex buffer data right at + // the end of the MIDISysexSendRequest structure. This solution + // does not require that we wait for a previous sysex buffer to be + // sent before sending a new one, which was the old way we did it. + MIDISysexSendRequest *newRequest = (MIDISysexSendRequest *) malloc(sizeof(struct MIDISysexSendRequest) + nBytes); + char * sysexBuffer = ((char *) newRequest) + sizeof(struct MIDISysexSendRequest); + + // Copy data to buffer. + for ( unsigned int i=0; iat(i); + + newRequest->destination = data->destinationId; + newRequest->data = (Byte *)sysexBuffer; + newRequest->bytesToSend = nBytes; + newRequest->complete = 0; + newRequest->completionProc = sysexCompletionProc; + newRequest->completionRefCon = newRequest; + + result = MIDISendSysex(newRequest); + if ( result != noErr ) { + free( newRequest ); + errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; + error( Error::WARNING, errorString_ ); + return; + } + return; + } + else if ( nBytes > 3 ) { + errorString_ = "MidiOutCore::sendMessage: message format problem ... not sysex but > 3 bytes?"; + error( Error::WARNING, errorString_ ); + return; + } + */ + + MIDIPacketList packetList; + MIDIPacket *packet = MIDIPacketListInit( &packetList ); + packet = MIDIPacketListAdd( &packetList, sizeof(packetList), packet, timeStamp, nBytes, (const Byte *) &message->at( 0 ) ); + if ( !packet ) { + errorString_ = "MidiOutCore::sendMessage: could not allocate packet list"; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Send to any destinations that may have connected to us. + if ( data->endpoint ) { + result = MIDIReceived( data->endpoint, &packetList ); + if ( result != noErr ) { + errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; + error( Error::WARNING, errorString_ ); + } + } + + // And send to an explicit destination port if we're connected. + if ( connected_ ) { + result = MIDISend( data->port, data->destinationId, &packetList ); + if ( result != noErr ) { + errorString_ = "MidiOutCore::sendMessage: error sending MIDI message to port."; + error( Error::WARNING, errorString_ ); + } + } } +NAMSPACE_RTMIDI_END #endif // __MACOSX_CORE__ - //*********************************************************************// - // API: LINUX ALSA SEQUENCER - //*********************************************************************// +//*********************************************************************// +// API: LINUX ALSA SEQUENCER +//*********************************************************************// - // API information found at: - // - http://www.alsa-project.org/documentation.php#Library +// API information found at: +// - http://www.alsa-project.org/documentation.php#Library #if defined(__LINUX_ALSA__) - // The ALSA Sequencer API is based on the use of a callback function for - // MIDI input. - // - // Thanks to Pedro Lopez-Cabanillas for help with the ALSA sequencer - // time stamps and other assorted fixes!!! +// The ALSA Sequencer API is based on the use of a callback function for +// MIDI input. +// +// Thanks to Pedro Lopez-Cabanillas for help with the ALSA sequencer +// time stamps and other assorted fixes!!! - // If you don't need timestamping for incoming MIDI events, define the - // preprocessor definition AVOID_TIMESTAMPING to save resources - // associated with the ALSA sequencer queues. +// If you don't need timestamping for incoming MIDI events, define the +// preprocessor definition AVOID_TIMESTAMPING to save resources +// associated with the ALSA sequencer queues. #include #include - // ALSA header file. +// ALSA header file. #include -namespace rtmidi { - // A structure to hold variables related to the ALSA API - // implementation. - struct AlsaMidiData { - snd_seq_t *seq; - unsigned int portNum; - int vport; - snd_seq_port_subscribe_t *subscription; - snd_midi_event_t *coder; - unsigned int bufferSize; - unsigned char *buffer; - pthread_t thread; - pthread_t dummy_thread_id; - unsigned long long lastTime; - int queue_id; // an input queue is needed to get timestamped events - int trigger_fds[2]; - }; +NAMSPACE_RTMIDI_START +// A structure to hold variables related to the ALSA API +// implementation. +struct AlsaMidiData { + snd_seq_t *seq; + unsigned int portNum; + int vport; + snd_seq_port_subscribe_t *subscription; + snd_midi_event_t *coder; + unsigned int bufferSize; + unsigned char *buffer; + pthread_t thread; + pthread_t dummy_thread_id; + unsigned long long lastTime; + int queue_id; // an input queue is needed to get timestamped events + int trigger_fds[2]; +}; #define PORT_TYPE( pinfo, bits ) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits)) - //*********************************************************************// - // API: LINUX ALSA - // Class Definitions: MidiInAlsa - //*********************************************************************// - - static void *alsaMidiHandler( void *ptr ) - { - MidiInApi::MidiInData *data = static_cast (ptr); - AlsaMidiData *apiData = static_cast (data->apiData); - - long nBytes; - unsigned long long time, lastTime; - bool continueSysex = false; - bool doDecode = false; - MidiInApi::MidiMessage message; - int poll_fd_count; - struct pollfd *poll_fds; - - snd_seq_event_t *ev; - int result; - apiData->bufferSize = 32; - result = snd_midi_event_new( 0, &apiData->coder ); - if ( result < 0 ) { - data->doInput = false; - std::cerr << "\nMidiInAlsa::alsaMidiHandler: error initializing MIDI event parser!\n\n"; - return 0; - } - unsigned char *buffer = (unsigned char *) malloc( apiData->bufferSize ); - if ( buffer == NULL ) { - data->doInput = false; - snd_midi_event_free( apiData->coder ); - apiData->coder = 0; - std::cerr << "\nMidiInAlsa::alsaMidiHandler: error initializing buffer memory!\n\n"; - return 0; - } - snd_midi_event_init( apiData->coder ); - snd_midi_event_no_status( apiData->coder, 1 ); // suppress running status messages - - poll_fd_count = snd_seq_poll_descriptors_count( apiData->seq, POLLIN ) + 1; - poll_fds = (struct pollfd*)alloca( poll_fd_count * sizeof( struct pollfd )); - snd_seq_poll_descriptors( apiData->seq, poll_fds + 1, poll_fd_count - 1, POLLIN ); - poll_fds[0].fd = apiData->trigger_fds[0]; - poll_fds[0].events = POLLIN; - - while ( data->doInput ) { - - if ( snd_seq_event_input_pending( apiData->seq, 1 ) == 0 ) { - // No data pending - if ( poll( poll_fds, poll_fd_count, -1) >= 0 ) { - if ( poll_fds[0].revents & POLLIN ) { - bool dummy; - int res = read( poll_fds[0].fd, &dummy, sizeof(dummy) ); - (void) res; - } - } - continue; - } - - // If here, there should be data. - result = snd_seq_event_input( apiData->seq, &ev ); - if ( result == -ENOSPC ) { - std::cerr << "\nMidiInAlsa::alsaMidiHandler: MIDI input buffer overrun!\n\n"; - continue; - } - else if ( result <= 0 ) { - std::cerr << "\nMidiInAlsa::alsaMidiHandler: unknown MIDI input error!\n"; - perror("System reports"); - continue; - } - - // This is a bit weird, but we now have to decode an ALSA MIDI - // event (back) into MIDI bytes. We'll ignore non-MIDI types. - if ( !continueSysex ) message.bytes.clear(); - - doDecode = false; - switch ( ev->type ) { - - case SND_SEQ_EVENT_PORT_SUBSCRIBED: +//*********************************************************************// +// API: LINUX ALSA +// Class Definitions: MidiInAlsa +//*********************************************************************// + +static void *alsaMidiHandler( void *ptr ) +{ + MidiInApi::MidiInData *data = static_cast (ptr); + AlsaMidiData *apiData = static_cast (data->apiData); + + long nBytes; + unsigned long long time, lastTime; + bool continueSysex = false; + bool doDecode = false; + MidiInApi::MidiMessage message; + int poll_fd_count; + struct pollfd *poll_fds; + + snd_seq_event_t *ev; + int result; + apiData->bufferSize = 32; + result = snd_midi_event_new( 0, &apiData->coder ); + if ( result < 0 ) { + data->doInput = false; + std::cerr << "\nMidiInAlsa::alsaMidiHandler: error initializing MIDI event parser!\n\n"; + return 0; + } + unsigned char *buffer = (unsigned char *) malloc( apiData->bufferSize ); + if ( buffer == NULL ) { + data->doInput = false; + snd_midi_event_free( apiData->coder ); + apiData->coder = 0; + std::cerr << "\nMidiInAlsa::alsaMidiHandler: error initializing buffer memory!\n\n"; + return 0; + } + snd_midi_event_init( apiData->coder ); + snd_midi_event_no_status( apiData->coder, 1 ); // suppress running status messages + + poll_fd_count = snd_seq_poll_descriptors_count( apiData->seq, POLLIN ) + 1; + poll_fds = (struct pollfd*)alloca( poll_fd_count * sizeof( struct pollfd )); + snd_seq_poll_descriptors( apiData->seq, poll_fds + 1, poll_fd_count - 1, POLLIN ); + poll_fds[0].fd = apiData->trigger_fds[0]; + poll_fds[0].events = POLLIN; + + while ( data->doInput ) { + + if ( snd_seq_event_input_pending( apiData->seq, 1 ) == 0 ) { + // No data pending + if ( poll( poll_fds, poll_fd_count, -1) >= 0 ) { + if ( poll_fds[0].revents & POLLIN ) { + bool dummy; + int res = read( poll_fds[0].fd, &dummy, sizeof(dummy) ); + (void) res; + } + } + continue; + } + + // If here, there should be data. + result = snd_seq_event_input( apiData->seq, &ev ); + if ( result == -ENOSPC ) { + std::cerr << "\nMidiInAlsa::alsaMidiHandler: MIDI input buffer overrun!\n\n"; + continue; + } + else if ( result <= 0 ) { + std::cerr << "\nMidiInAlsa::alsaMidiHandler: unknown MIDI input error!\n"; + perror("System reports"); + continue; + } + + // This is a bit weird, but we now have to decode an ALSA MIDI + // event (back) into MIDI bytes. We'll ignore non-MIDI types. + if ( !continueSysex ) message.bytes.clear(); + + doDecode = false; + switch ( ev->type ) { + + case SND_SEQ_EVENT_PORT_SUBSCRIBED: #if defined(__RTMIDI_DEBUG__) - std::cout << "MidiInAlsa::alsaMidiHandler: port connection made!\n"; + std::cout << "MidiInAlsa::alsaMidiHandler: port connection made!\n"; #endif - break; + break; - case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: + case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: #if defined(__RTMIDI_DEBUG__) - std::cerr << "MidiInAlsa::alsaMidiHandler: port connection has closed!\n"; - std::cout << "sender = " << (int) ev->data.connect.sender.client << ":" - << (int) ev->data.connect.sender.port - << ", dest = " << (int) ev->data.connect.dest.client << ":" - << (int) ev->data.connect.dest.port - << std::endl; + std::cerr << "MidiInAlsa::alsaMidiHandler: port connection has closed!\n"; + std::cout << "sender = " << (int) ev->data.connect.sender.client << ":" + << (int) ev->data.connect.sender.port + << ", dest = " << (int) ev->data.connect.dest.client << ":" + << (int) ev->data.connect.dest.port + << std::endl; #endif - break; - - case SND_SEQ_EVENT_QFRAME: // MIDI time code - if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true; - break; - - case SND_SEQ_EVENT_TICK: // 0xF9 ... MIDI timing tick - if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true; - break; - - case SND_SEQ_EVENT_CLOCK: // 0xF8 ... MIDI timing (clock) tick - if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true; - break; - - case SND_SEQ_EVENT_SENSING: // Active sensing - if ( !( data->ignoreFlags & 0x04 ) ) doDecode = true; - break; - - case SND_SEQ_EVENT_SYSEX: - if ( (data->ignoreFlags & 0x01) ) break; - if ( ev->data.ext.len > apiData->bufferSize ) { - apiData->bufferSize = ev->data.ext.len; - free( buffer ); - buffer = (unsigned char *) malloc( apiData->bufferSize ); - if ( buffer == NULL ) { - data->doInput = false; - std::cerr << "\nMidiInAlsa::alsaMidiHandler: error resizing buffer memory!\n\n"; - break; - } - } - - default: - doDecode = true; - } - - if ( doDecode ) { - - nBytes = snd_midi_event_decode( apiData->coder, buffer, apiData->bufferSize, ev ); - if ( nBytes > 0 ) { - // The ALSA sequencer has a maximum buffer size for MIDI sysex - // events of 256 bytes. If a device sends sysex messages larger - // than this, they are segmented into 256 byte chunks. So, - // we'll watch for this and concatenate sysex chunks into a - // single sysex message if necessary. - if ( !continueSysex ) - message.bytes.assign( buffer, &buffer[nBytes] ); - else - message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] ); - - continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) ); - if ( !continueSysex ) { - - // Calculate the time stamp: - message.timeStamp = 0.0; - - // Method 1: Use the system time. - //(void)gettimeofday(&tv, (struct timezone *)NULL); - //time = (tv.tv_sec * 1000000) + tv.tv_usec; - - // Method 2: Use the ALSA sequencer event time data. - // (thanks to Pedro Lopez-Cabanillas!). - time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 ); - lastTime = time; - time -= apiData->lastTime; - apiData->lastTime = lastTime; - if ( data->firstMessage == true ) - data->firstMessage = false; - else - message.timeStamp = time * 0.000001; - } - else { + break; + + case SND_SEQ_EVENT_QFRAME: // MIDI time code + if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true; + break; + + case SND_SEQ_EVENT_TICK: // 0xF9 ... MIDI timing tick + if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true; + break; + + case SND_SEQ_EVENT_CLOCK: // 0xF8 ... MIDI timing (clock) tick + if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true; + break; + + case SND_SEQ_EVENT_SENSING: // Active sensing + if ( !( data->ignoreFlags & 0x04 ) ) doDecode = true; + break; + + case SND_SEQ_EVENT_SYSEX: + if ( (data->ignoreFlags & 0x01) ) break; + if ( ev->data.ext.len > apiData->bufferSize ) { + apiData->bufferSize = ev->data.ext.len; + free( buffer ); + buffer = (unsigned char *) malloc( apiData->bufferSize ); + if ( buffer == NULL ) { + data->doInput = false; + std::cerr << "\nMidiInAlsa::alsaMidiHandler: error resizing buffer memory!\n\n"; + break; + } + } + + default: + doDecode = true; + } + + if ( doDecode ) { + + nBytes = snd_midi_event_decode( apiData->coder, buffer, apiData->bufferSize, ev ); + if ( nBytes > 0 ) { + // The ALSA sequencer has a maximum buffer size for MIDI sysex + // events of 256 bytes. If a device sends sysex messages larger + // than this, they are segmented into 256 byte chunks. So, + // we'll watch for this and concatenate sysex chunks into a + // single sysex message if necessary. + if ( !continueSysex ) + message.bytes.assign( buffer, &buffer[nBytes] ); + else + message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] ); + + continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) ); + if ( !continueSysex ) { + + // Calculate the time stamp: + message.timeStamp = 0.0; + + // Method 1: Use the system time. + //(void)gettimeofday(&tv, (struct timezone *)NULL); + //time = (tv.tv_sec * 1000000) + tv.tv_usec; + + // Method 2: Use the ALSA sequencer event time data. + // (thanks to Pedro Lopez-Cabanillas!). + time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 ); + lastTime = time; + time -= apiData->lastTime; + apiData->lastTime = lastTime; + if ( data->firstMessage == true ) + data->firstMessage = false; + else + message.timeStamp = time * 0.000001; + } + else { #if defined(__RTMIDI_DEBUG__) - std::cerr << "\nMidiInAlsa::alsaMidiHandler: event parsing error or not a MIDI event!\n\n"; + std::cerr << "\nMidiInAlsa::alsaMidiHandler: event parsing error or not a MIDI event!\n\n"; #endif - } - } - } - - snd_seq_free_event( ev ); - if ( message.bytes.size() == 0 || continueSysex ) continue; - - if ( data->usingCallback ) { - MidiCallback callback = (MidiCallback) data->userCallback; - callback( message.timeStamp, &message.bytes, data->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else - std::cerr << "\nMidiInAlsa: message queue limit reached!!\n\n"; - } - } - - if ( buffer ) free( buffer ); - snd_midi_event_free( apiData->coder ); - apiData->coder = 0; - apiData->thread = apiData->dummy_thread_id; - return 0; } + } + } + + snd_seq_free_event( ev ); + if ( message.bytes.size() == 0 || continueSysex ) continue; + + if ( data->usingCallback ) { + MidiCallback callback = (MidiCallback) data->userCallback; + callback( message.timeStamp, &message.bytes, data->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else + std::cerr << "\nMidiInAlsa: message queue limit reached!!\n\n"; + } + } + + if ( buffer ) free( buffer ); + snd_midi_event_free( apiData->coder ); + apiData->coder = 0; + apiData->thread = apiData->dummy_thread_id; + return 0; +} - MidiInAlsa :: MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) - { - initialize( clientName ); - } +MidiInAlsa :: MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) +{ + initialize( clientName ); +} - MidiInAlsa :: ~MidiInAlsa() - { - // Close a connection if it exists. - closePort(); - - // Shutdown the input thread. - AlsaMidiData *data = static_cast (apiData_); - if ( inputData_.doInput ) { - inputData_.doInput = false; - int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput) ); - (void) res; - if ( !pthread_equal(data->thread, data->dummy_thread_id) ) - pthread_join( data->thread, NULL ); - } - - // Cleanup. - close ( data->trigger_fds[0] ); - close ( data->trigger_fds[1] ); - if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport ); +MidiInAlsa :: ~MidiInAlsa() +{ + // Close a connection if it exists. + closePort(); + + // Shutdown the input thread. + AlsaMidiData *data = static_cast (apiData_); + if ( inputData_.doInput ) { + inputData_.doInput = false; + int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput) ); + (void) res; + if ( !pthread_equal(data->thread, data->dummy_thread_id) ) + pthread_join( data->thread, NULL ); + } + + // Cleanup. + close ( data->trigger_fds[0] ); + close ( data->trigger_fds[1] ); + if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport ); #ifndef AVOID_TIMESTAMPING - snd_seq_free_queue( data->seq, data->queue_id ); + snd_seq_free_queue( data->seq, data->queue_id ); #endif - snd_seq_close( data->seq ); - delete data; - } + snd_seq_close( data->seq ); + delete data; +} - void MidiInAlsa :: initialize( const std::string& clientName ) - { - // Set up the ALSA sequencer client. - snd_seq_t *seq; - int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); - if ( result < 0 ) { - errorString_ = "MidiInAlsa::initialize: error creating ALSA sequencer client object."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Set client name. - snd_seq_set_client_name( seq, clientName.c_str() ); - - // Save our api-specific connection information. - AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; - data->seq = seq; - data->portNum = -1; - data->vport = -1; - data->subscription = 0; - data->dummy_thread_id = pthread_self(); - data->thread = data->dummy_thread_id; - data->trigger_fds[0] = -1; - data->trigger_fds[1] = -1; - apiData_ = (void *) data; - inputData_.apiData = (void *) data; - - if ( pipe(data->trigger_fds) == -1 ) { - errorString_ = "MidiInAlsa::initialize: error creating pipe objects."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Create the input queue +void MidiInAlsa :: initialize( const std::string& clientName ) +{ + // Set up the ALSA sequencer client. + snd_seq_t *seq; + int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); + if ( result < 0 ) { + errorString_ = "MidiInAlsa::initialize: error creating ALSA sequencer client object."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Set client name. + snd_seq_set_client_name( seq, clientName.c_str() ); + + // Save our api-specific connection information. + AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; + data->seq = seq; + data->portNum = -1; + data->vport = -1; + data->subscription = 0; + data->dummy_thread_id = pthread_self(); + data->thread = data->dummy_thread_id; + data->trigger_fds[0] = -1; + data->trigger_fds[1] = -1; + apiData_ = (void *) data; + inputData_.apiData = (void *) data; + + if ( pipe(data->trigger_fds) == -1 ) { + errorString_ = "MidiInAlsa::initialize: error creating pipe objects."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Create the input queue #ifndef AVOID_TIMESTAMPING - data->queue_id = snd_seq_alloc_named_queue(seq, "Midi Queue"); - // Set arbitrary tempo (mm=100) and resolution (240) - snd_seq_queue_tempo_t *qtempo; - snd_seq_queue_tempo_alloca(&qtempo); - snd_seq_queue_tempo_set_tempo(qtempo, 600000); - snd_seq_queue_tempo_set_ppq(qtempo, 240); - snd_seq_set_queue_tempo(data->seq, data->queue_id, qtempo); - snd_seq_drain_output(data->seq); + data->queue_id = snd_seq_alloc_named_queue(seq, "Midi Queue"); + // Set arbitrary tempo (mm=100) and resolution (240) + snd_seq_queue_tempo_t *qtempo; + snd_seq_queue_tempo_alloca(&qtempo); + snd_seq_queue_tempo_set_tempo(qtempo, 600000); + snd_seq_queue_tempo_set_ppq(qtempo, 240); + snd_seq_set_queue_tempo(data->seq, data->queue_id, qtempo); + snd_seq_drain_output(data->seq); #endif - } +} - // This function is used to count or get the pinfo structure for a given port number. - unsigned int portInfo( snd_seq_t *seq, snd_seq_port_info_t *pinfo, unsigned int type, int portNumber ) - { - snd_seq_client_info_t *cinfo; - int client; - int count = 0; - snd_seq_client_info_alloca( &cinfo ); - - snd_seq_client_info_set_client( cinfo, -1 ); - while ( snd_seq_query_next_client( seq, cinfo ) >= 0 ) { - client = snd_seq_client_info_get_client( cinfo ); - if ( client == 0 ) continue; - // Reset query info - snd_seq_port_info_set_client( pinfo, client ); - snd_seq_port_info_set_port( pinfo, -1 ); - while ( snd_seq_query_next_port( seq, pinfo ) >= 0 ) { - unsigned int atyp = snd_seq_port_info_get_type( pinfo ); - if ( ( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) == 0 ) continue; - unsigned int caps = snd_seq_port_info_get_capability( pinfo ); - if ( ( caps & type ) != type ) continue; - if ( count == portNumber ) return 1; - ++count; - } - } - - // If a negative portNumber was used, return the port count. - if ( portNumber < 0 ) return count; - return 0; - } +// This function is used to count or get the pinfo structure for a given port number. +unsigned int portInfo( snd_seq_t *seq, snd_seq_port_info_t *pinfo, unsigned int type, int portNumber ) +{ + snd_seq_client_info_t *cinfo; + int client; + int count = 0; + snd_seq_client_info_alloca( &cinfo ); + + snd_seq_client_info_set_client( cinfo, -1 ); + while ( snd_seq_query_next_client( seq, cinfo ) >= 0 ) { + client = snd_seq_client_info_get_client( cinfo ); + if ( client == 0 ) continue; + // Reset query info + snd_seq_port_info_set_client( pinfo, client ); + snd_seq_port_info_set_port( pinfo, -1 ); + while ( snd_seq_query_next_port( seq, pinfo ) >= 0 ) { + unsigned int atyp = snd_seq_port_info_get_type( pinfo ); + if ( ( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) == 0 ) continue; + unsigned int caps = snd_seq_port_info_get_capability( pinfo ); + if ( ( caps & type ) != type ) continue; + if ( count == portNumber ) return 1; + ++count; + } + } + + // If a negative portNumber was used, return the port count. + if ( portNumber < 0 ) return count; + return 0; +} - unsigned int MidiInAlsa :: getPortCount() - { - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); +unsigned int MidiInAlsa :: getPortCount() +{ + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); - AlsaMidiData *data = static_cast (apiData_); - return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, -1 ); - } + AlsaMidiData *data = static_cast (apiData_); + return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, -1 ); +} - std::string MidiInAlsa :: getPortName( unsigned int portNumber ) - { - snd_seq_client_info_t *cinfo; - snd_seq_port_info_t *pinfo; - snd_seq_client_info_alloca( &cinfo ); - snd_seq_port_info_alloca( &pinfo ); - - std::string stringName; - AlsaMidiData *data = static_cast (apiData_); - if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) ) { - int cnum = snd_seq_port_info_get_client( pinfo ); - snd_seq_get_any_client_info( data->seq, cnum, cinfo ); - std::ostringstream os; - os << snd_seq_client_info_get_name( cinfo ); - os << " "; // These lines added to make sure devices are listed - os << snd_seq_port_info_get_client( pinfo ); // with full portnames added to ensure individual device names - os << ":"; - os << snd_seq_port_info_get_port( pinfo ); - stringName = os.str(); - return stringName; - } - - // If we get here, we didn't find a match. - errorString_ = "MidiInAlsa::getPortName: error looking for port name!"; - error( Error::WARNING, errorString_ ); - return stringName; - } +std::string MidiInAlsa :: getPortName( unsigned int portNumber ) +{ + snd_seq_client_info_t *cinfo; + snd_seq_port_info_t *pinfo; + snd_seq_client_info_alloca( &cinfo ); + snd_seq_port_info_alloca( &pinfo ); + + std::string stringName; + AlsaMidiData *data = static_cast (apiData_); + if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) ) { + int cnum = snd_seq_port_info_get_client( pinfo ); + snd_seq_get_any_client_info( data->seq, cnum, cinfo ); + std::ostringstream os; + os << snd_seq_client_info_get_name( cinfo ); + os << " "; // These lines added to make sure devices are listed + os << snd_seq_port_info_get_client( pinfo ); // with full portnames added to ensure individual device names + os << ":"; + os << snd_seq_port_info_get_port( pinfo ); + stringName = os.str(); + return stringName; + } + + // If we get here, we didn't find a match. + errorString_ = "MidiInAlsa::getPortName: error looking for port name!"; + error( Error::WARNING, errorString_ ); + return stringName; +} - void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName ) - { - if ( connected_ ) { - errorString_ = "MidiInAlsa::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); - return; - } - - unsigned int nSrc = this->getPortCount(); - if ( nSrc < 1 ) { - errorString_ = "MidiInAlsa::openPort: no MIDI input sources found!"; - error( Error::NO_DEVICES_FOUND, errorString_ ); - return; - } - - snd_seq_port_info_t *src_pinfo; - snd_seq_port_info_alloca( &src_pinfo ); - AlsaMidiData *data = static_cast (apiData_); - if ( portInfo( data->seq, src_pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) == 0 ) { - std::ostringstream ost; - ost << "MidiInAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::INVALID_PARAMETER, errorString_ ); - return; - } - - snd_seq_addr_t sender, receiver; - sender.client = snd_seq_port_info_get_client( src_pinfo ); - sender.port = snd_seq_port_info_get_port( src_pinfo ); - - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); - if ( data->vport < 0 ) { - snd_seq_port_info_set_client( pinfo, 0 ); - snd_seq_port_info_set_port( pinfo, 0 ); - snd_seq_port_info_set_capability( pinfo, - SND_SEQ_PORT_CAP_WRITE | - SND_SEQ_PORT_CAP_SUBS_WRITE ); - snd_seq_port_info_set_type( pinfo, - SND_SEQ_PORT_TYPE_MIDI_GENERIC | - SND_SEQ_PORT_TYPE_APPLICATION ); - snd_seq_port_info_set_midi_channels(pinfo, 16); +void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName ) +{ + if ( connected_ ) { + errorString_ = "MidiInAlsa::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + + unsigned int nSrc = this->getPortCount(); + if ( nSrc < 1 ) { + errorString_ = "MidiInAlsa::openPort: no MIDI input sources found!"; + error( Error::NO_DEVICES_FOUND, errorString_ ); + return; + } + + snd_seq_port_info_t *src_pinfo; + snd_seq_port_info_alloca( &src_pinfo ); + AlsaMidiData *data = static_cast (apiData_); + if ( portInfo( data->seq, src_pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) == 0 ) { + std::ostringstream ost; + ost << "MidiInAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::INVALID_PARAMETER, errorString_ ); + return; + } + + snd_seq_addr_t sender, receiver; + sender.client = snd_seq_port_info_get_client( src_pinfo ); + sender.port = snd_seq_port_info_get_port( src_pinfo ); + + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + if ( data->vport < 0 ) { + snd_seq_port_info_set_client( pinfo, 0 ); + snd_seq_port_info_set_port( pinfo, 0 ); + snd_seq_port_info_set_capability( pinfo, + SND_SEQ_PORT_CAP_WRITE | + SND_SEQ_PORT_CAP_SUBS_WRITE ); + snd_seq_port_info_set_type( pinfo, + SND_SEQ_PORT_TYPE_MIDI_GENERIC | + SND_SEQ_PORT_TYPE_APPLICATION ); + snd_seq_port_info_set_midi_channels(pinfo, 16); #ifndef AVOID_TIMESTAMPING - snd_seq_port_info_set_timestamping(pinfo, 1); - snd_seq_port_info_set_timestamp_real(pinfo, 1); - snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id); + snd_seq_port_info_set_timestamping(pinfo, 1); + snd_seq_port_info_set_timestamp_real(pinfo, 1); + snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id); #endif - snd_seq_port_info_set_name(pinfo, portName.c_str() ); - int createok = snd_seq_create_port(data->seq, pinfo); + snd_seq_port_info_set_name(pinfo, portName.c_str() ); + int createok = snd_seq_create_port(data->seq, pinfo); - if ( createok < 0 ) { - errorString_ = "MidiInAlsa::openPort: ALSA error creating input port."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - data->vport = snd_seq_port_info_get_port(pinfo); - } - - receiver.client = snd_seq_port_info_get_client( pinfo ); - receiver.port = data->vport; - - if ( !data->subscription ) { - // Make subscription - if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { - errorString_ = "MidiInAlsa::openPort: ALSA error allocation port subscription."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - snd_seq_port_subscribe_set_sender(data->subscription, &sender); - snd_seq_port_subscribe_set_dest(data->subscription, &receiver); - if ( snd_seq_subscribe_port(data->seq, data->subscription) ) { - snd_seq_port_subscribe_free( data->subscription ); - data->subscription = 0; - errorString_ = "MidiInAlsa::openPort: ALSA error making port connection."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - } - - if ( inputData_.doInput == false ) { - // Start the input queue + if ( createok < 0 ) { + errorString_ = "MidiInAlsa::openPort: ALSA error creating input port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + data->vport = snd_seq_port_info_get_port(pinfo); + } + + receiver.client = snd_seq_port_info_get_client( pinfo ); + receiver.port = data->vport; + + if ( !data->subscription ) { + // Make subscription + if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { + errorString_ = "MidiInAlsa::openPort: ALSA error allocation port subscription."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + snd_seq_port_subscribe_set_sender(data->subscription, &sender); + snd_seq_port_subscribe_set_dest(data->subscription, &receiver); + if ( snd_seq_subscribe_port(data->seq, data->subscription) ) { + snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; + errorString_ = "MidiInAlsa::openPort: ALSA error making port connection."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + } + + if ( inputData_.doInput == false ) { + // Start the input queue #ifndef AVOID_TIMESTAMPING - snd_seq_start_queue( data->seq, data->queue_id, NULL ); - snd_seq_drain_output( data->seq ); + snd_seq_start_queue( data->seq, data->queue_id, NULL ); + snd_seq_drain_output( data->seq ); #endif - // Start our MIDI input thread. - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - pthread_attr_setschedpolicy(&attr, SCHED_OTHER); - - inputData_.doInput = true; - int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_); - pthread_attr_destroy(&attr); - if ( err ) { - snd_seq_unsubscribe_port( data->seq, data->subscription ); - snd_seq_port_subscribe_free( data->subscription ); - data->subscription = 0; - inputData_.doInput = false; - errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!"; - error( Error::THREAD_ERROR, errorString_ ); - return; - } - } - - connected_ = true; - } + // Start our MIDI input thread. + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + pthread_attr_setschedpolicy(&attr, SCHED_OTHER); + + inputData_.doInput = true; + int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_); + pthread_attr_destroy(&attr); + if ( err ) { + snd_seq_unsubscribe_port( data->seq, data->subscription ); + snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; + inputData_.doInput = false; + errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!"; + error( Error::THREAD_ERROR, errorString_ ); + return; + } + } + + connected_ = true; +} - void MidiInAlsa :: openPort( const PortDescriptor & port, - const std::string portName = std::string( "RtMidi" ) ) - { - abort(); - } +void MidiInAlsa :: openPort( const PortDescriptor & port, + const std::string portName = std::string( "RtMidi" ) ) +{ + abort(); +} - Pointer MidiInAlsa :: getDescriptor() - { - abort(); - } - PortList MidiInAlsa :: getPortList(int capabilities) - { - abort(); - } +Pointer MidiInAlsa :: getDescriptor() +{ + abort(); +} +PortList MidiInAlsa :: getPortList(int capabilities) +{ + abort(); +} - void MidiInAlsa :: openVirtualPort( std::string portName ) - { - AlsaMidiData *data = static_cast (apiData_); - if ( data->vport < 0 ) { - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); - snd_seq_port_info_set_capability( pinfo, - SND_SEQ_PORT_CAP_WRITE | - SND_SEQ_PORT_CAP_SUBS_WRITE ); - snd_seq_port_info_set_type( pinfo, - SND_SEQ_PORT_TYPE_MIDI_GENERIC | - SND_SEQ_PORT_TYPE_APPLICATION ); - snd_seq_port_info_set_midi_channels(pinfo, 16); +void MidiInAlsa :: openVirtualPort( std::string portName ) +{ + AlsaMidiData *data = static_cast (apiData_); + if ( data->vport < 0 ) { + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + snd_seq_port_info_set_capability( pinfo, + SND_SEQ_PORT_CAP_WRITE | + SND_SEQ_PORT_CAP_SUBS_WRITE ); + snd_seq_port_info_set_type( pinfo, + SND_SEQ_PORT_TYPE_MIDI_GENERIC | + SND_SEQ_PORT_TYPE_APPLICATION ); + snd_seq_port_info_set_midi_channels(pinfo, 16); #ifndef AVOID_TIMESTAMPING - snd_seq_port_info_set_timestamping(pinfo, 1); - snd_seq_port_info_set_timestamp_real(pinfo, 1); - snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id); + snd_seq_port_info_set_timestamping(pinfo, 1); + snd_seq_port_info_set_timestamp_real(pinfo, 1); + snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id); #endif - snd_seq_port_info_set_name(pinfo, portName.c_str()); - int createok = snd_seq_create_port(data->seq, pinfo); - - if ( createok < 0 ) { - errorString_ = "MidiInAlsa::openVirtualPort: ALSA error creating virtual port."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - data->vport = snd_seq_port_info_get_port(pinfo); - } - - if ( inputData_.doInput == false ) { - // Wait for old thread to stop, if still running - if ( !pthread_equal(data->thread, data->dummy_thread_id) ) - pthread_join( data->thread, NULL ); - - // Start the input queue + snd_seq_port_info_set_name(pinfo, portName.c_str()); + int createok = snd_seq_create_port(data->seq, pinfo); + + if ( createok < 0 ) { + errorString_ = "MidiInAlsa::openVirtualPort: ALSA error creating virtual port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + data->vport = snd_seq_port_info_get_port(pinfo); + } + + if ( inputData_.doInput == false ) { + // Wait for old thread to stop, if still running + if ( !pthread_equal(data->thread, data->dummy_thread_id) ) + pthread_join( data->thread, NULL ); + + // Start the input queue #ifndef AVOID_TIMESTAMPING - snd_seq_start_queue( data->seq, data->queue_id, NULL ); - snd_seq_drain_output( data->seq ); + snd_seq_start_queue( data->seq, data->queue_id, NULL ); + snd_seq_drain_output( data->seq ); #endif - // Start our MIDI input thread. - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - pthread_attr_setschedpolicy(&attr, SCHED_OTHER); - - inputData_.doInput = true; - int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_); - pthread_attr_destroy(&attr); - if ( err ) { - if ( data->subscription ) { - snd_seq_unsubscribe_port( data->seq, data->subscription ); - snd_seq_port_subscribe_free( data->subscription ); - data->subscription = 0; - } - inputData_.doInput = false; - errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!"; - error( Error::THREAD_ERROR, errorString_ ); - return; - } - } - } + // Start our MIDI input thread. + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + pthread_attr_setschedpolicy(&attr, SCHED_OTHER); + + inputData_.doInput = true; + int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_); + pthread_attr_destroy(&attr); + if ( err ) { + if ( data->subscription ) { + snd_seq_unsubscribe_port( data->seq, data->subscription ); + snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; + } + inputData_.doInput = false; + errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!"; + error( Error::THREAD_ERROR, errorString_ ); + return; + } + } +} - void MidiInAlsa :: closePort( void ) - { - AlsaMidiData *data = static_cast (apiData_); - - if ( connected_ ) { - if ( data->subscription ) { - snd_seq_unsubscribe_port( data->seq, data->subscription ); - snd_seq_port_subscribe_free( data->subscription ); - data->subscription = 0; - } - // Stop the input queue +void MidiInAlsa :: closePort( void ) +{ + AlsaMidiData *data = static_cast (apiData_); + + if ( connected_ ) { + if ( data->subscription ) { + snd_seq_unsubscribe_port( data->seq, data->subscription ); + snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; + } + // Stop the input queue #ifndef AVOID_TIMESTAMPING - snd_seq_stop_queue( data->seq, data->queue_id, NULL ); - snd_seq_drain_output( data->seq ); + snd_seq_stop_queue( data->seq, data->queue_id, NULL ); + snd_seq_drain_output( data->seq ); #endif - connected_ = false; - } - - // Stop thread to avoid triggering the callback, while the port is intended to be closed - if ( inputData_.doInput ) { - inputData_.doInput = false; - int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput) ); - (void) res; - if ( !pthread_equal(data->thread, data->dummy_thread_id) ) - pthread_join( data->thread, NULL ); - } - } + connected_ = false; + } + + // Stop thread to avoid triggering the callback, while the port is intended to be closed + if ( inputData_.doInput ) { + inputData_.doInput = false; + int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput) ); + (void) res; + if ( !pthread_equal(data->thread, data->dummy_thread_id) ) + pthread_join( data->thread, NULL ); + } +} - //*********************************************************************// - // API: LINUX ALSA - // Class Definitions: MidiOutAlsa - //*********************************************************************// +//*********************************************************************// +// API: LINUX ALSA +// Class Definitions: MidiOutAlsa +//*********************************************************************// - MidiOutAlsa :: MidiOutAlsa( const std::string clientName ) : MidiOutApi() - { - initialize( clientName ); - } +MidiOutAlsa :: MidiOutAlsa( const std::string clientName ) : MidiOutApi() +{ + initialize( clientName ); +} - MidiOutAlsa :: ~MidiOutAlsa() - { - // Close a connection if it exists. - closePort(); - - // Cleanup. - AlsaMidiData *data = static_cast (apiData_); - if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport ); - if ( data->coder ) snd_midi_event_free( data->coder ); - if ( data->buffer ) free( data->buffer ); - snd_seq_close( data->seq ); - delete data; - } +MidiOutAlsa :: ~MidiOutAlsa() +{ + // Close a connection if it exists. + closePort(); + + // Cleanup. + AlsaMidiData *data = static_cast (apiData_); + if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport ); + if ( data->coder ) snd_midi_event_free( data->coder ); + if ( data->buffer ) free( data->buffer ); + snd_seq_close( data->seq ); + delete data; +} - void MidiOutAlsa :: initialize( const std::string& clientName ) - { - // Set up the ALSA sequencer client. - snd_seq_t *seq; - int result1 = snd_seq_open( &seq, "default", SND_SEQ_OPEN_OUTPUT, SND_SEQ_NONBLOCK ); - if ( result1 < 0 ) { - errorString_ = "MidiOutAlsa::initialize: error creating ALSA sequencer client object."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Set client name. - snd_seq_set_client_name( seq, clientName.c_str() ); - - // Save our api-specific connection information. - AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; - data->seq = seq; - data->portNum = -1; - data->vport = -1; - data->bufferSize = 32; - data->coder = 0; - data->buffer = 0; - int result = snd_midi_event_new( data->bufferSize, &data->coder ); - if ( result < 0 ) { - delete data; - errorString_ = "MidiOutAlsa::initialize: error initializing MIDI event parser!\n\n"; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - data->buffer = (unsigned char *) malloc( data->bufferSize ); - if ( data->buffer == NULL ) { - delete data; - errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n"; - error( Error::MEMORY_ERROR, errorString_ ); - return; - } - snd_midi_event_init( data->coder ); - apiData_ = (void *) data; - } +void MidiOutAlsa :: initialize( const std::string& clientName ) +{ + // Set up the ALSA sequencer client. + snd_seq_t *seq; + int result1 = snd_seq_open( &seq, "default", SND_SEQ_OPEN_OUTPUT, SND_SEQ_NONBLOCK ); + if ( result1 < 0 ) { + errorString_ = "MidiOutAlsa::initialize: error creating ALSA sequencer client object."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Set client name. + snd_seq_set_client_name( seq, clientName.c_str() ); + + // Save our api-specific connection information. + AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; + data->seq = seq; + data->portNum = -1; + data->vport = -1; + data->bufferSize = 32; + data->coder = 0; + data->buffer = 0; + int result = snd_midi_event_new( data->bufferSize, &data->coder ); + if ( result < 0 ) { + delete data; + errorString_ = "MidiOutAlsa::initialize: error initializing MIDI event parser!\n\n"; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + data->buffer = (unsigned char *) malloc( data->bufferSize ); + if ( data->buffer == NULL ) { + delete data; + errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n"; + error( Error::MEMORY_ERROR, errorString_ ); + return; + } + snd_midi_event_init( data->coder ); + apiData_ = (void *) data; +} - unsigned int MidiOutAlsa :: getPortCount() - { - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); +unsigned int MidiOutAlsa :: getPortCount() +{ + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); - AlsaMidiData *data = static_cast (apiData_); - return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, -1 ); - } + AlsaMidiData *data = static_cast (apiData_); + return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, -1 ); +} - std::string MidiOutAlsa :: getPortName( unsigned int portNumber ) - { - snd_seq_client_info_t *cinfo; - snd_seq_port_info_t *pinfo; - snd_seq_client_info_alloca( &cinfo ); - snd_seq_port_info_alloca( &pinfo ); - - std::string stringName; - AlsaMidiData *data = static_cast (apiData_); - if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) ) { - int cnum = snd_seq_port_info_get_client(pinfo); - snd_seq_get_any_client_info( data->seq, cnum, cinfo ); - std::ostringstream os; - os << snd_seq_client_info_get_name(cinfo); - os << " "; // These lines added to make sure devices are listed - os << snd_seq_port_info_get_client( pinfo ); // with full portnames added to ensure individual device names - os << ":"; - os << snd_seq_port_info_get_port(pinfo); - stringName = os.str(); - return stringName; - } - - // If we get here, we didn't find a match. - errorString_ = "MidiOutAlsa::getPortName: error looking for port name!"; - error( Error::WARNING, errorString_ ); - return stringName; - } +std::string MidiOutAlsa :: getPortName( unsigned int portNumber ) +{ + snd_seq_client_info_t *cinfo; + snd_seq_port_info_t *pinfo; + snd_seq_client_info_alloca( &cinfo ); + snd_seq_port_info_alloca( &pinfo ); + + std::string stringName; + AlsaMidiData *data = static_cast (apiData_); + if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) ) { + int cnum = snd_seq_port_info_get_client(pinfo); + snd_seq_get_any_client_info( data->seq, cnum, cinfo ); + std::ostringstream os; + os << snd_seq_client_info_get_name(cinfo); + os << " "; // These lines added to make sure devices are listed + os << snd_seq_port_info_get_client( pinfo ); // with full portnames added to ensure individual device names + os << ":"; + os << snd_seq_port_info_get_port(pinfo); + stringName = os.str(); + return stringName; + } + + // If we get here, we didn't find a match. + errorString_ = "MidiOutAlsa::getPortName: error looking for port name!"; + error( Error::WARNING, errorString_ ); + return stringName; +} - void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string portName ) - { - if ( connected_ ) { - errorString_ = "MidiOutAlsa::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); - return; - } - - unsigned int nSrc = this->getPortCount(); - if (nSrc < 1) { - errorString_ = "MidiOutAlsa::openPort: no MIDI output sources found!"; - error( Error::NO_DEVICES_FOUND, errorString_ ); - return; - } - - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); - AlsaMidiData *data = static_cast (apiData_); - if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) == 0 ) { - std::ostringstream ost; - ost << "MidiOutAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::INVALID_PARAMETER, errorString_ ); - return; - } - - snd_seq_addr_t sender, receiver; - receiver.client = snd_seq_port_info_get_client( pinfo ); - receiver.port = snd_seq_port_info_get_port( pinfo ); - sender.client = snd_seq_client_id( data->seq ); - - if ( data->vport < 0 ) { - data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(), - SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, - SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); - if ( data->vport < 0 ) { - errorString_ = "MidiOutAlsa::openPort: ALSA error creating output port."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - } - - sender.port = data->vport; - - // Make subscription - if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { - snd_seq_port_subscribe_free( data->subscription ); - errorString_ = "MidiOutAlsa::openPort: error allocating port subscription."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - snd_seq_port_subscribe_set_sender(data->subscription, &sender); - snd_seq_port_subscribe_set_dest(data->subscription, &receiver); - snd_seq_port_subscribe_set_time_update(data->subscription, 1); - snd_seq_port_subscribe_set_time_real(data->subscription, 1); - if ( snd_seq_subscribe_port(data->seq, data->subscription) ) { - snd_seq_port_subscribe_free( data->subscription ); - errorString_ = "MidiOutAlsa::openPort: ALSA error making port connection."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - connected_ = true; - } +void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string portName ) +{ + if ( connected_ ) { + errorString_ = "MidiOutAlsa::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + + unsigned int nSrc = this->getPortCount(); + if (nSrc < 1) { + errorString_ = "MidiOutAlsa::openPort: no MIDI output sources found!"; + error( Error::NO_DEVICES_FOUND, errorString_ ); + return; + } + + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + AlsaMidiData *data = static_cast (apiData_); + if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) == 0 ) { + std::ostringstream ost; + ost << "MidiOutAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::INVALID_PARAMETER, errorString_ ); + return; + } + + snd_seq_addr_t sender, receiver; + receiver.client = snd_seq_port_info_get_client( pinfo ); + receiver.port = snd_seq_port_info_get_port( pinfo ); + sender.client = snd_seq_client_id( data->seq ); + + if ( data->vport < 0 ) { + data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(), + SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, + SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); + if ( data->vport < 0 ) { + errorString_ = "MidiOutAlsa::openPort: ALSA error creating output port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + } + + sender.port = data->vport; + + // Make subscription + if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { + snd_seq_port_subscribe_free( data->subscription ); + errorString_ = "MidiOutAlsa::openPort: error allocating port subscription."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + snd_seq_port_subscribe_set_sender(data->subscription, &sender); + snd_seq_port_subscribe_set_dest(data->subscription, &receiver); + snd_seq_port_subscribe_set_time_update(data->subscription, 1); + snd_seq_port_subscribe_set_time_real(data->subscription, 1); + if ( snd_seq_subscribe_port(data->seq, data->subscription) ) { + snd_seq_port_subscribe_free( data->subscription ); + errorString_ = "MidiOutAlsa::openPort: ALSA error making port connection."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + connected_ = true; +} - void MidiOutAlsa :: closePort( void ) - { - if ( connected_ ) { - AlsaMidiData *data = static_cast (apiData_); - snd_seq_unsubscribe_port( data->seq, data->subscription ); - snd_seq_port_subscribe_free( data->subscription ); - connected_ = false; - } - } +void MidiOutAlsa :: closePort( void ) +{ + if ( connected_ ) { + AlsaMidiData *data = static_cast (apiData_); + snd_seq_unsubscribe_port( data->seq, data->subscription ); + snd_seq_port_subscribe_free( data->subscription ); + connected_ = false; + } +} - void MidiOutAlsa :: openVirtualPort( std::string portName ) - { - AlsaMidiData *data = static_cast (apiData_); - if ( data->vport < 0 ) { - data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(), - SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, - SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); - - if ( data->vport < 0 ) { - errorString_ = "MidiOutAlsa::openVirtualPort: ALSA error creating virtual port."; - error( Error::DRIVER_ERROR, errorString_ ); - } - } - } +void MidiOutAlsa :: openVirtualPort( std::string portName ) +{ + AlsaMidiData *data = static_cast (apiData_); + if ( data->vport < 0 ) { + data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(), + SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, + SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); + + if ( data->vport < 0 ) { + errorString_ = "MidiOutAlsa::openVirtualPort: ALSA error creating virtual port."; + error( Error::DRIVER_ERROR, errorString_ ); + } + } +} - void MidiOutAlsa :: sendMessage( std::vector &message ) - { - int result; - AlsaMidiData *data = static_cast (apiData_); - unsigned int nBytes = message.size(); - if ( nBytes > data->bufferSize ) { - data->bufferSize = nBytes; - result = snd_midi_event_resize_buffer ( data->coder, nBytes); - if ( result != 0 ) { - errorString_ = "MidiOutAlsa::sendMessage: ALSA error resizing MIDI event buffer."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - free (data->buffer); - data->buffer = (unsigned char *) malloc( data->bufferSize ); - if ( data->buffer == NULL ) { - errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n"; - error( Error::MEMORY_ERROR, errorString_ ); - return; - } - } - - snd_seq_event_t ev; - snd_seq_ev_clear(&ev); - snd_seq_ev_set_source(&ev, data->vport); - snd_seq_ev_set_subs(&ev); - snd_seq_ev_set_direct(&ev); - for ( unsigned int i=0; ibuffer[i] = message.at(i); - result = snd_midi_event_encode( data->coder, data->buffer, (long)nBytes, &ev ); - if ( result < (int)nBytes ) { - errorString_ = "MidiOutAlsa::sendMessage: event parsing error!"; - error( Error::WARNING, errorString_ ); - return; - } - - // Send the event. - result = snd_seq_event_output(data->seq, &ev); - if ( result < 0 ) { - errorString_ = "MidiOutAlsa::sendMessage: error sending MIDI message to port."; - error( Error::WARNING, errorString_ ); - return; - } - snd_seq_drain_output(data->seq); - } +void MidiOutAlsa :: sendMessage( std::vector &message ) +{ + int result; + AlsaMidiData *data = static_cast (apiData_); + unsigned int nBytes = message.size(); + if ( nBytes > data->bufferSize ) { + data->bufferSize = nBytes; + result = snd_midi_event_resize_buffer ( data->coder, nBytes); + if ( result != 0 ) { + errorString_ = "MidiOutAlsa::sendMessage: ALSA error resizing MIDI event buffer."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + free (data->buffer); + data->buffer = (unsigned char *) malloc( data->bufferSize ); + if ( data->buffer == NULL ) { + errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n"; + error( Error::MEMORY_ERROR, errorString_ ); + return; + } + } + + snd_seq_event_t ev; + snd_seq_ev_clear(&ev); + snd_seq_ev_set_source(&ev, data->vport); + snd_seq_ev_set_subs(&ev); + snd_seq_ev_set_direct(&ev); + for ( unsigned int i=0; ibuffer[i] = message.at(i); + result = snd_midi_event_encode( data->coder, data->buffer, (long)nBytes, &ev ); + if ( result < (int)nBytes ) { + errorString_ = "MidiOutAlsa::sendMessage: event parsing error!"; + error( Error::WARNING, errorString_ ); + return; + } + + // Send the event. + result = snd_seq_event_output(data->seq, &ev); + if ( result < 0 ) { + errorString_ = "MidiOutAlsa::sendMessage: error sending MIDI message to port."; + error( Error::WARNING, errorString_ ); + return; + } + snd_seq_drain_output(data->seq); +} - void MidiOutAlsa :: openPort( const PortDescriptor & port, - const std::string portName) - { - abort(); - } - Pointer MidiOutAlsa :: getDescriptor() - { - abort(); - } - PortList MidiOutAlsa :: getPortList(int capabilities) - { - abort(); - } +void MidiOutAlsa :: openPort( const PortDescriptor & port, + const std::string portName) +{ + abort(); +} +Pointer MidiOutAlsa :: getDescriptor() +{ + abort(); } +PortList MidiOutAlsa :: getPortList(int capabilities) +{ + abort(); +} +NAMSPACE_RTMIDI_END #endif // __LINUX_ALSA__ - //*********************************************************************// - // API: Windows Multimedia Library (MM) - //*********************************************************************// +//*********************************************************************// +// API: Windows Multimedia Library (MM) +//*********************************************************************// - // API information deciphered from: - // - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_midi_reference.asp +// API information deciphered from: +// - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_midi_reference.asp - // Thanks to Jean-Baptiste Berruchon for the sysex code. +// Thanks to Jean-Baptiste Berruchon for the sysex code. #if defined(__WINDOWS_MM__) - // The Windows MM API is based on the use of a callback function for - // MIDI input. We convert the system specific time stamps to delta - // time values. +// The Windows MM API is based on the use of a callback function for +// MIDI input. We convert the system specific time stamps to delta +// time values. - // Windows MM MIDI header files. +// Windows MM MIDI header files. #include #include #define RT_SYSEX_BUFFER_SIZE 1024 #define RT_SYSEX_BUFFER_COUNT 4 namespace rtmidi{ - // A structure to hold variables related to the CoreMIDI API - // implementation. - struct WinMidiData { - HMIDIIN inHandle; // Handle to Midi Input Device - HMIDIOUT outHandle; // Handle to Midi Output Device - DWORD lastTime; - MidiInApi::MidiMessage message; - LPMIDIHDR sysexBuffer[RT_SYSEX_BUFFER_COUNT]; - CRITICAL_SECTION _mutex; // [Patrice] see https://groups.google.com/forum/#!topic/mididev/6OUjHutMpEo - }; - - //*********************************************************************// - // API: Windows MM - // Class Definitions: MidiInWinMM - //*********************************************************************// - - static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, - UINT inputStatus, - DWORD_PTR instancePtr, - DWORD_PTR midiMessage, - DWORD timestamp ) - { - if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA && inputStatus != MIM_LONGERROR ) return; - - //MidiInApi::MidiInData *data = static_cast (instancePtr); - MidiInApi::MidiInData *data = (MidiInApi::MidiInData *)instancePtr; - WinMidiData *apiData = static_cast (data->apiData); - - // Calculate time stamp. - if ( data->firstMessage == true ) { - apiData->message.timeStamp = 0.0; - data->firstMessage = false; - } - else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001; - apiData->lastTime = timestamp; - - if ( inputStatus == MIM_DATA ) { // Channel or system message - - // Make sure the first byte is a status byte. - unsigned char status = (unsigned char) (midiMessage & 0x000000FF); - if ( !(status & 0x80) ) return; - - // Determine the number of bytes in the MIDI message. - unsigned short nBytes = 1; - if ( status < 0xC0 ) nBytes = 3; - else if ( status < 0xE0 ) nBytes = 2; - else if ( status < 0xF0 ) nBytes = 3; - else if ( status == 0xF1 ) { - if ( data->ignoreFlags & 0x02 ) return; - else nBytes = 2; - } - else if ( status == 0xF2 ) nBytes = 3; - else if ( status == 0xF3 ) nBytes = 2; - else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) { - // A MIDI timing tick message and we're ignoring it. - return; - } - else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { - // A MIDI active sensing message and we're ignoring it. - return; - } - - // Copy bytes to our MIDI message. - unsigned char *ptr = (unsigned char *) &midiMessage; - for ( int i=0; imessage.bytes.push_back( *ptr++ ); - } - else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) - MIDIHDR *sysex = ( MIDIHDR *) midiMessage; - if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { - // Sysex message and we're not ignoring it - for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) - apiData->message.bytes.push_back( sysex->lpData[i] ); - } - - // The WinMM API requires that the sysex buffer be requeued after - // input of each sysex message. Even if we are ignoring sysex - // messages, we still need to requeue the buffer in case the user - // decides to not ignore sysex messages in the future. However, - // it seems that WinMM calls this function with an empty sysex - // buffer when an application closes and in this case, we should - // avoid requeueing it, else the computer suddenly reboots after - // one or two minutes. - if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { - //if ( sysex->dwBytesRecorded > 0 ) { - EnterCriticalSection( &(apiData->_mutex) ); - MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); - LeaveCriticalSection( &(apiData->_mutex) ); - if ( result != MMSYSERR_NOERROR ) - std::cerr << "\nMidiIn::midiInputCallback: error sending sysex to Midi device!!\n\n"; - - if ( data->ignoreFlags & 0x01 ) return; - } - else return; - } - - if ( data->usingCallback ) { - MidiCallback callback = (MidiCallback) data->userCallback; - callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = apiData->message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else - std::cerr << "\nMidiIn: message queue limit reached!!\n\n"; - } - - // Clear the vector for the next input message. - apiData->message.bytes.clear(); - } - - MidiInWinMM :: MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) - { - initialize( clientName ); - } - - MidiInWinMM :: ~MidiInWinMM() - { - // Close a connection if it exists. - closePort(); - - WinMidiData *data = static_cast (apiData_); - DeleteCriticalSection( &(data->_mutex) ); - - // Cleanup. - delete data; - } - - void MidiInWinMM :: initialize( const std::string& /*clientName*/ ) - { - // We'll issue a warning here if no devices are available but not - // throw an error since the user can plugin something later. - unsigned int nDevices = midiInGetNumDevs(); - if ( nDevices == 0 ) { - errorString_ = "MidiInWinMM::initialize: no MIDI input devices currently available."; - error( Error::WARNING, errorString_ ); - } - - // Save our api-specific connection information. - WinMidiData *data = (WinMidiData *) new WinMidiData; - apiData_ = (void *) data; - inputData_.apiData = (void *) data; - data->message.bytes.clear(); // needs to be empty for first input message - - if ( !InitializeCriticalSectionAndSpinCount(&(data->_mutex), 0x00000400) ) { - errorString_ = "MidiInWinMM::initialize: InitializeCriticalSectionAndSpinCount failed."; - error( Error::WARNING, errorString_ ); - } - } - - void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) - { - if ( connected_ ) { - errorString_ = "MidiInWinMM::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); - return; - } - - unsigned int nDevices = midiInGetNumDevs(); - if (nDevices == 0) { - errorString_ = "MidiInWinMM::openPort: no MIDI input sources found!"; - error( Error::NO_DEVICES_FOUND, errorString_ ); - return; - } - - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiInWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::INVALID_PARAMETER, errorString_ ); - return; - } - - WinMidiData *data = static_cast (apiData_); - MMRESULT result = midiInOpen( &data->inHandle, - portNumber, - (DWORD_PTR)&midiInputCallback, - (DWORD_PTR)&inputData_, - CALLBACK_FUNCTION ); - if ( result != MMSYSERR_NOERROR ) { - errorString_ = "MidiInWinMM::openPort: error creating Windows MM MIDI input port."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Allocate and init the sysex buffers. - for ( int i=0; isysexBuffer[i] = (MIDIHDR*) new char[ sizeof(MIDIHDR) ]; - data->sysexBuffer[i]->lpData = new char[ RT_SYSEX_BUFFER_SIZE ]; - data->sysexBuffer[i]->dwBufferLength = RT_SYSEX_BUFFER_SIZE; - data->sysexBuffer[i]->dwUser = i; // We use the dwUser parameter as buffer indicator - data->sysexBuffer[i]->dwFlags = 0; - - result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (PrepareHeader)."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Register the buffer. - result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (AddBuffer)."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - } - - result = midiInStart( data->inHandle ); - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - connected_ = true; - } - - void MidiInWinMM :: openVirtualPort( std::string /*portName*/ ) - { - // This function cannot be implemented for the Windows MM MIDI API. - errorString_ = "MidiInWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; - error( Error::WARNING, errorString_ ); - } - - void MidiInWinMM :: closePort( void ) - { - if ( connected_ ) { - WinMidiData *data = static_cast (apiData_); - EnterCriticalSection( &(data->_mutex) ); - midiInReset( data->inHandle ); - midiInStop( data->inHandle ); - - for ( int i=0; iinHandle, data->sysexBuffer[i], sizeof(MIDIHDR)); - delete [] data->sysexBuffer[i]->lpData; - delete [] data->sysexBuffer[i]; - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader)."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - } - - midiInClose( data->inHandle ); - connected_ = false; - LeaveCriticalSection( &(data->_mutex) ); - } - } - - unsigned int MidiInWinMM :: getPortCount() - { - return midiInGetNumDevs(); - } - - std::string MidiInWinMM :: getPortName( unsigned int portNumber ) - { - std::string stringName; - unsigned int nDevices = midiInGetNumDevs(); - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiInWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::WARNING, errorString_ ); - return stringName; - } - - MIDIINCAPS deviceCaps; - midiInGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIINCAPS)); + // A structure to hold variables related to the CoreMIDI API + // implementation. + struct WinMidiData { + HMIDIIN inHandle; // Handle to Midi Input Device + HMIDIOUT outHandle; // Handle to Midi Output Device + DWORD lastTime; + MidiInApi::MidiMessage message; + LPMIDIHDR sysexBuffer[RT_SYSEX_BUFFER_COUNT]; + CRITICAL_SECTION _mutex; // [Patrice] see https://groups.google.com/forum/#!topic/mididev/6OUjHutMpEo + }; + + //*********************************************************************// + // API: Windows MM + // Class Definitions: MidiInWinMM + //*********************************************************************// + + static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, + UINT inputStatus, + DWORD_PTR instancePtr, + DWORD_PTR midiMessage, + DWORD timestamp ) + { + if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA && inputStatus != MIM_LONGERROR ) return; + + //MidiInApi::MidiInData *data = static_cast (instancePtr); + MidiInApi::MidiInData *data = (MidiInApi::MidiInData *)instancePtr; + WinMidiData *apiData = static_cast (data->apiData); + + // Calculate time stamp. + if ( data->firstMessage == true ) { + apiData->message.timeStamp = 0.0; + data->firstMessage = false; + } + else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001; + apiData->lastTime = timestamp; + + if ( inputStatus == MIM_DATA ) { // Channel or system message + + // Make sure the first byte is a status byte. + unsigned char status = (unsigned char) (midiMessage & 0x000000FF); + if ( !(status & 0x80) ) return; + + // Determine the number of bytes in the MIDI message. + unsigned short nBytes = 1; + if ( status < 0xC0 ) nBytes = 3; + else if ( status < 0xE0 ) nBytes = 2; + else if ( status < 0xF0 ) nBytes = 3; + else if ( status == 0xF1 ) { + if ( data->ignoreFlags & 0x02 ) return; + else nBytes = 2; + } + else if ( status == 0xF2 ) nBytes = 3; + else if ( status == 0xF3 ) nBytes = 2; + else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) { + // A MIDI timing tick message and we're ignoring it. + return; + } + else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { + // A MIDI active sensing message and we're ignoring it. + return; + } + + // Copy bytes to our MIDI message. + unsigned char *ptr = (unsigned char *) &midiMessage; + for ( int i=0; imessage.bytes.push_back( *ptr++ ); + } + else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) + MIDIHDR *sysex = ( MIDIHDR *) midiMessage; + if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { + // Sysex message and we're not ignoring it + for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) + apiData->message.bytes.push_back( sysex->lpData[i] ); + } + + // The WinMM API requires that the sysex buffer be requeued after + // input of each sysex message. Even if we are ignoring sysex + // messages, we still need to requeue the buffer in case the user + // decides to not ignore sysex messages in the future. However, + // it seems that WinMM calls this function with an empty sysex + // buffer when an application closes and in this case, we should + // avoid requeueing it, else the computer suddenly reboots after + // one or two minutes. + if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { + //if ( sysex->dwBytesRecorded > 0 ) { + EnterCriticalSection( &(apiData->_mutex) ); + MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); + LeaveCriticalSection( &(apiData->_mutex) ); + if ( result != MMSYSERR_NOERROR ) + std::cerr << "\nMidiIn::midiInputCallback: error sending sysex to Midi device!!\n\n"; + + if ( data->ignoreFlags & 0x01 ) return; + } + else return; + } + + if ( data->usingCallback ) { + MidiCallback callback = (MidiCallback) data->userCallback; + callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = apiData->message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else + std::cerr << "\nMidiIn: message queue limit reached!!\n\n"; + } + + // Clear the vector for the next input message. + apiData->message.bytes.clear(); + } + + MidiInWinMM :: MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) + { + initialize( clientName ); + } + + MidiInWinMM :: ~MidiInWinMM() + { + // Close a connection if it exists. + closePort(); + + WinMidiData *data = static_cast (apiData_); + DeleteCriticalSection( &(data->_mutex) ); + + // Cleanup. + delete data; + } + + void MidiInWinMM :: initialize( const std::string& /*clientName*/ ) + { + // We'll issue a warning here if no devices are available but not + // throw an error since the user can plugin something later. + unsigned int nDevices = midiInGetNumDevs(); + if ( nDevices == 0 ) { + errorString_ = "MidiInWinMM::initialize: no MIDI input devices currently available."; + error( Error::WARNING, errorString_ ); + } + + // Save our api-specific connection information. + WinMidiData *data = (WinMidiData *) new WinMidiData; + apiData_ = (void *) data; + inputData_.apiData = (void *) data; + data->message.bytes.clear(); // needs to be empty for first input message + + if ( !InitializeCriticalSectionAndSpinCount(&(data->_mutex), 0x00000400) ) { + errorString_ = "MidiInWinMM::initialize: InitializeCriticalSectionAndSpinCount failed."; + error( Error::WARNING, errorString_ ); + } + } + + void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) + { + if ( connected_ ) { + errorString_ = "MidiInWinMM::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + + unsigned int nDevices = midiInGetNumDevs(); + if (nDevices == 0) { + errorString_ = "MidiInWinMM::openPort: no MIDI input sources found!"; + error( Error::NO_DEVICES_FOUND, errorString_ ); + return; + } + + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiInWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::INVALID_PARAMETER, errorString_ ); + return; + } + + WinMidiData *data = static_cast (apiData_); + MMRESULT result = midiInOpen( &data->inHandle, + portNumber, + (DWORD_PTR)&midiInputCallback, + (DWORD_PTR)&inputData_, + CALLBACK_FUNCTION ); + if ( result != MMSYSERR_NOERROR ) { + errorString_ = "MidiInWinMM::openPort: error creating Windows MM MIDI input port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Allocate and init the sysex buffers. + for ( int i=0; isysexBuffer[i] = (MIDIHDR*) new char[ sizeof(MIDIHDR) ]; + data->sysexBuffer[i]->lpData = new char[ RT_SYSEX_BUFFER_SIZE ]; + data->sysexBuffer[i]->dwBufferLength = RT_SYSEX_BUFFER_SIZE; + data->sysexBuffer[i]->dwUser = i; // We use the dwUser parameter as buffer indicator + data->sysexBuffer[i]->dwFlags = 0; + + result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (PrepareHeader)."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Register the buffer. + result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (AddBuffer)."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + } + + result = midiInStart( data->inHandle ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + connected_ = true; + } + + void MidiInWinMM :: openVirtualPort( std::string /*portName*/ ) + { + // This function cannot be implemented for the Windows MM MIDI API. + errorString_ = "MidiInWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; + error( Error::WARNING, errorString_ ); + } + + void MidiInWinMM :: closePort( void ) + { + if ( connected_ ) { + WinMidiData *data = static_cast (apiData_); + EnterCriticalSection( &(data->_mutex) ); + midiInReset( data->inHandle ); + midiInStop( data->inHandle ); + + for ( int i=0; iinHandle, data->sysexBuffer[i], sizeof(MIDIHDR)); + delete [] data->sysexBuffer[i]->lpData; + delete [] data->sysexBuffer[i]; + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + errorString_ = "MidiInWinMM::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader)."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + } + + midiInClose( data->inHandle ); + connected_ = false; + LeaveCriticalSection( &(data->_mutex) ); + } + } + + unsigned int MidiInWinMM :: getPortCount() + { + return midiInGetNumDevs(); + } + + std::string MidiInWinMM :: getPortName( unsigned int portNumber ) + { + std::string stringName; + unsigned int nDevices = midiInGetNumDevs(); + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiInWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::WARNING, errorString_ ); + return stringName; + } + + MIDIINCAPS deviceCaps; + midiInGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIINCAPS)); #if defined( UNICODE ) || defined( _UNICODE ) - int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; - stringName.assign( length, 0 ); - length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); + int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; + stringName.assign( length, 0 ); + length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); #else - stringName = std::string( deviceCaps.szPname ); + stringName = std::string( deviceCaps.szPname ); #endif - // 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 - std::ostringstream os; - os << " "; - os << portNumber; - stringName += os.str(); - - return stringName; - } - - //*********************************************************************// - // API: Windows MM - // Class Definitions: MidiOutWinMM - //*********************************************************************// - - MidiOutWinMM :: MidiOutWinMM( const std::string clientName ) : MidiOutApi() - { - initialize( clientName ); - } - - MidiOutWinMM :: ~MidiOutWinMM() - { - // Close a connection if it exists. - closePort(); - - // Cleanup. - WinMidiData *data = static_cast (apiData_); - delete data; - } - - void MidiOutWinMM :: initialize( const std::string& /*clientName*/ ) - { - // We'll issue a warning here if no devices are available but not - // throw an error since the user can plug something in later. - unsigned int nDevices = midiOutGetNumDevs(); - if ( nDevices == 0 ) { - errorString_ = "MidiOutWinMM::initialize: no MIDI output devices currently available."; - error( Error::WARNING, errorString_ ); - } - - // Save our api-specific connection information. - WinMidiData *data = (WinMidiData *) new WinMidiData; - apiData_ = (void *) data; - } - - unsigned int MidiOutWinMM :: getPortCount() - { - return midiOutGetNumDevs(); - } - - std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) - { - std::string stringName; - unsigned int nDevices = midiOutGetNumDevs(); - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiOutWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::WARNING, errorString_ ); - return stringName; - } - - MIDIOUTCAPS deviceCaps; - midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS)); + // 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 + std::ostringstream os; + os << " "; + os << portNumber; + stringName += os.str(); + + return stringName; + } + + //*********************************************************************// + // API: Windows MM + // Class Definitions: MidiOutWinMM + //*********************************************************************// + + MidiOutWinMM :: MidiOutWinMM( const std::string clientName ) : MidiOutApi() + { + initialize( clientName ); + } + + MidiOutWinMM :: ~MidiOutWinMM() + { + // Close a connection if it exists. + closePort(); + + // Cleanup. + WinMidiData *data = static_cast (apiData_); + delete data; + } + + void MidiOutWinMM :: initialize( const std::string& /*clientName*/ ) + { + // We'll issue a warning here if no devices are available but not + // throw an error since the user can plug something in later. + unsigned int nDevices = midiOutGetNumDevs(); + if ( nDevices == 0 ) { + errorString_ = "MidiOutWinMM::initialize: no MIDI output devices currently available."; + error( Error::WARNING, errorString_ ); + } + + // Save our api-specific connection information. + WinMidiData *data = (WinMidiData *) new WinMidiData; + apiData_ = (void *) data; + } + + unsigned int MidiOutWinMM :: getPortCount() + { + return midiOutGetNumDevs(); + } + + std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) + { + std::string stringName; + unsigned int nDevices = midiOutGetNumDevs(); + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiOutWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::WARNING, errorString_ ); + return stringName; + } + + MIDIOUTCAPS deviceCaps; + midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS)); #if defined( UNICODE ) || defined( _UNICODE ) - int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; - stringName.assign( length, 0 ); - length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); + int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; + stringName.assign( length, 0 ); + length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); #else - stringName = std::string( deviceCaps.szPname ); + stringName = std::string( deviceCaps.szPname ); #endif - return stringName; - } - - void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) - { - if ( connected_ ) { - errorString_ = "MidiOutWinMM::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); - return; - } - - unsigned int nDevices = midiOutGetNumDevs(); - if (nDevices < 1) { - errorString_ = "MidiOutWinMM::openPort: no MIDI output destinations found!"; - error( Error::NO_DEVICES_FOUND, errorString_ ); - return; - } - - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiOutWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::INVALID_PARAMETER, errorString_ ); - return; - } - - WinMidiData *data = static_cast (apiData_); - MMRESULT result = midiOutOpen( &data->outHandle, - portNumber, - (DWORD)NULL, - (DWORD)NULL, - CALLBACK_NULL ); - if ( result != MMSYSERR_NOERROR ) { - errorString_ = "MidiOutWinMM::openPort: error creating Windows MM MIDI output port."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - connected_ = true; - } - - void MidiOutWinMM :: closePort( void ) - { - if ( connected_ ) { - WinMidiData *data = static_cast (apiData_); - midiOutReset( data->outHandle ); - midiOutClose( data->outHandle ); - connected_ = false; - } - } - - void MidiOutWinMM :: openVirtualPort( std::string /*portName*/ ) - { - // This function cannot be implemented for the Windows MM MIDI API. - errorString_ = "MidiOutWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; - error( Error::WARNING, errorString_ ); - } - - void MidiOutWinMM :: sendMessage( std::vector *message ) - { - if ( !connected_ ) return; - - unsigned int nBytes = static_cast(message->size()); - if ( nBytes == 0 ) { - errorString_ = "MidiOutWinMM::sendMessage: message argument is empty!"; - error( Error::WARNING, errorString_ ); - return; - } - - MMRESULT result; - WinMidiData *data = static_cast (apiData_); - if ( message->at(0) == 0xF0 ) { // Sysex message - - // Allocate buffer for sysex data. - char *buffer = (char *) malloc( nBytes ); - if ( buffer == NULL ) { - errorString_ = "MidiOutWinMM::sendMessage: error allocating sysex message memory!"; - error( Error::MEMORY_ERROR, errorString_ ); - return; - } - - // Copy data to buffer. - for ( unsigned int i=0; iat(i); - - // Create and prepare MIDIHDR structure. - MIDIHDR sysex; - sysex.lpData = (LPSTR) buffer; - sysex.dwBufferLength = nBytes; - sysex.dwFlags = 0; - result = midiOutPrepareHeader( data->outHandle, &sysex, sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - free( buffer ); - errorString_ = "MidiOutWinMM::sendMessage: error preparing sysex header."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Send the message. - result = midiOutLongMsg( data->outHandle, &sysex, sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - free( buffer ); - errorString_ = "MidiOutWinMM::sendMessage: error sending sysex message."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Unprepare the buffer and MIDIHDR. - while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof (MIDIHDR) ) ) Sleep( 1 ); - free( buffer ); - } - else { // Channel or system message. - - // Make sure the message size isn't too big. - if ( nBytes > 3 ) { - errorString_ = "MidiOutWinMM::sendMessage: message size is greater than 3 bytes (and not sysex)!"; - error( Error::WARNING, errorString_ ); - return; - } - - // Pack MIDI bytes into double word. - DWORD packet; - unsigned char *ptr = (unsigned char *) &packet; - for ( unsigned int i=0; iat(i); - ++ptr; - } - - // Send the message immediately. - result = midiOutShortMsg( data->outHandle, packet ); - if ( result != MMSYSERR_NOERROR ) { - errorString_ = "MidiOutWinMM::sendMessage: error sending MIDI message."; - error( Error::DRIVER_ERROR, errorString_ ); - } - } - } -} + return stringName; + } + + void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) + { + if ( connected_ ) { + errorString_ = "MidiOutWinMM::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + + unsigned int nDevices = midiOutGetNumDevs(); + if (nDevices < 1) { + errorString_ = "MidiOutWinMM::openPort: no MIDI output destinations found!"; + error( Error::NO_DEVICES_FOUND, errorString_ ); + return; + } + + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiOutWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::INVALID_PARAMETER, errorString_ ); + return; + } + + WinMidiData *data = static_cast (apiData_); + MMRESULT result = midiOutOpen( &data->outHandle, + portNumber, + (DWORD)NULL, + (DWORD)NULL, + CALLBACK_NULL ); + if ( result != MMSYSERR_NOERROR ) { + errorString_ = "MidiOutWinMM::openPort: error creating Windows MM MIDI output port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + connected_ = true; + } + + void MidiOutWinMM :: closePort( void ) + { + if ( connected_ ) { + WinMidiData *data = static_cast (apiData_); + midiOutReset( data->outHandle ); + midiOutClose( data->outHandle ); + connected_ = false; + } + } + + void MidiOutWinMM :: openVirtualPort( std::string /*portName*/ ) + { + // This function cannot be implemented for the Windows MM MIDI API. + errorString_ = "MidiOutWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; + error( Error::WARNING, errorString_ ); + } + + void MidiOutWinMM :: sendMessage( std::vector *message ) + { + if ( !connected_ ) return; + + unsigned int nBytes = static_cast(message->size()); + if ( nBytes == 0 ) { + errorString_ = "MidiOutWinMM::sendMessage: message argument is empty!"; + error( Error::WARNING, errorString_ ); + return; + } + + MMRESULT result; + WinMidiData *data = static_cast (apiData_); + if ( message->at(0) == 0xF0 ) { // Sysex message + + // Allocate buffer for sysex data. + char *buffer = (char *) malloc( nBytes ); + if ( buffer == NULL ) { + errorString_ = "MidiOutWinMM::sendMessage: error allocating sysex message memory!"; + error( Error::MEMORY_ERROR, errorString_ ); + return; + } + + // Copy data to buffer. + for ( unsigned int i=0; iat(i); + + // Create and prepare MIDIHDR structure. + MIDIHDR sysex; + sysex.lpData = (LPSTR) buffer; + sysex.dwBufferLength = nBytes; + sysex.dwFlags = 0; + result = midiOutPrepareHeader( data->outHandle, &sysex, sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + free( buffer ); + errorString_ = "MidiOutWinMM::sendMessage: error preparing sysex header."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Send the message. + result = midiOutLongMsg( data->outHandle, &sysex, sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + free( buffer ); + errorString_ = "MidiOutWinMM::sendMessage: error sending sysex message."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Unprepare the buffer and MIDIHDR. + while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof (MIDIHDR) ) ) Sleep( 1 ); + free( buffer ); + } + else { // Channel or system message. + + // Make sure the message size isn't too big. + if ( nBytes > 3 ) { + errorString_ = "MidiOutWinMM::sendMessage: message size is greater than 3 bytes (and not sysex)!"; + error( Error::WARNING, errorString_ ); + return; + } + + // Pack MIDI bytes into double word. + DWORD packet; + unsigned char *ptr = (unsigned char *) &packet; + for ( unsigned int i=0; iat(i); + ++ptr; + } + + // Send the message immediately. + result = midiOutShortMsg( data->outHandle, packet ); + if ( result != MMSYSERR_NOERROR ) { + errorString_ = "MidiOutWinMM::sendMessage: error sending MIDI message."; + error( Error::DRIVER_ERROR, errorString_ ); + } + } + } + NAMSPACE_RTMIDI_END #endif // __WINDOWS_MM__ - //*********************************************************************// - // API: UNIX JACK - // - // Written primarily by Alexander Svetalkin, with updates for delta - // time by Gary Scavone, April 2011. - // - // *********************************************************************// + //*********************************************************************// + // API: UNIX JACK + // + // Written primarily by Alexander Svetalkin, with updates for delta + // time by Gary Scavone, April 2011. + // + // *********************************************************************// #if defined(__UNIX_JACK__) - // JACK header files + // JACK header files #include #include #include #define JACK_RINGBUFFER_SIZE 16384 // Default size for ringbuffer -namespace rtmidi { - - struct JackMidiData { - jack_client_t *client; - jack_port_t *port; - jack_ringbuffer_t *buffSize; - jack_ringbuffer_t *buffMessage; - jack_time_t lastTime; - MidiInApi :: MidiInData *rtMidiIn; - }; - - //*********************************************************************// - // API: JACK - // Class Definitions: MidiInJack - //*********************************************************************// - - static int jackProcessIn( jack_nframes_t nframes, void *arg ) - { - JackMidiData *jData = (JackMidiData *) arg; - MidiInApi :: MidiInData *rtData = jData->rtMidiIn; - jack_midi_event_t event; - jack_time_t time; - - // Is port created? - if ( jData->port == NULL ) return 0; - void *buff = jack_port_get_buffer( jData->port, nframes ); - - // 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(); - - 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 ) - rtData->firstMessage = false; - else - message.timeStamp = ( time - jData->lastTime ) * 0.000001; - - jData->lastTime = time; - - if ( !rtData->continueSysex ) { - if ( rtData->usingCallback ) { - MidiCallback callback = (MidiCallback) rtData->userCallback; - callback( message.timeStamp, &message.bytes, rtData->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( rtData->queue.size < rtData->queue.ringSize ) { - rtData->queue.ring[rtData->queue.back++] = message; - if ( rtData->queue.back == rtData->queue.ringSize ) - rtData->queue.back = 0; - rtData->queue.size++; - } - else - std::cerr << "\nMidiInJack: message queue limit reached!!\n\n"; - } - } - } - - return 0; - } - - MidiInJack :: MidiInJack( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) - { - initialize( clientName ); - } - - void MidiInJack :: initialize( const std::string& clientName ) - { - JackMidiData *data = new JackMidiData; - apiData_ = (void *) data; - - data->rtMidiIn = &inputData_; - data->port = NULL; - data->client = NULL; - this->clientName = clientName; - - connect(); - } - - void MidiInJack :: connect() - { - JackMidiData *data = static_cast (apiData_); - if ( data->client ) - return; - - // Initialize JACK client - if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { - errorString_ = "MidiInJack::initialize: JACK server not running?"; - error( Error::WARNING, errorString_ ); - return; - } - - jack_set_process_callback( data->client, jackProcessIn, data ); - jack_activate( data->client ); - } - - MidiInJack :: ~MidiInJack() - { - JackMidiData *data = static_cast (apiData_); - closePort(); - - if ( data->client ) - jack_client_close( data->client ); - delete data; - } - - void MidiInJack :: openPort( unsigned int portNumber, const std::string portName ) - { - JackMidiData *data = static_cast (apiData_); - - connect(); - - // Creating new port - if ( data->port == NULL) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); - - if ( data->port == NULL) { - errorString_ = "MidiInJack::openPort: JACK error creating port"; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Connecting to the output - std::string name = getPortName( portNumber ); - jack_connect( data->client, name.c_str(), jack_port_name( data->port ) ); - } - - void MidiInJack :: openVirtualPort( const std::string portName ) - { - JackMidiData *data = static_cast (apiData_); - - connect(); - if ( data->port == NULL ) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); - - if ( data->port == NULL ) { - errorString_ = "MidiInJack::openVirtualPort: JACK error creating virtual port"; - error( Error::DRIVER_ERROR, errorString_ ); - } - } - - unsigned int MidiInJack :: getPortCount() - { - int count = 0; - JackMidiData *data = static_cast (apiData_); - connect(); - if ( !data->client ) - return 0; - - // List of available ports - const char **ports = jack_get_ports( data->client, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); - - if ( ports == NULL ) return 0; - while ( ports[count] != NULL ) - count++; - - free( ports ); - - return count; - } - - std::string MidiInJack :: getPortName( unsigned int portNumber ) - { - JackMidiData *data = static_cast (apiData_); - std::string retStr(""); - - connect(); - - // List of available ports - const char **ports = jack_get_ports( data->client, NULL, - JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); - - // Check port validity - if ( ports == NULL ) { - errorString_ = "MidiInJack::getPortName: no ports available!"; - error( Error::WARNING, errorString_ ); - return retStr; - } - - if ( ports[portNumber] == NULL ) { - std::ostringstream ost; - ost << "MidiInJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::WARNING, errorString_ ); - } - else retStr.assign( ports[portNumber] ); - - free( ports ); - return retStr; - } - - void MidiInJack :: closePort() - { - JackMidiData *data = static_cast (apiData_); - - if ( data->port == NULL ) return; - jack_port_unregister( data->client, data->port ); - data->port = NULL; - } - - //*********************************************************************// - // API: JACK - // Class Definitions: MidiOutJack - //*********************************************************************// - - // Jack process callback - static int jackProcessOut( jack_nframes_t nframes, void *arg ) - { - JackMidiData *data = (JackMidiData *) arg; - jack_midi_data_t *midiData; - int space; - - // Is port created? - if ( data->port == NULL ) return 0; - - void *buff = jack_port_get_buffer( data->port, nframes ); - jack_midi_clear_buffer( buff ); - - while ( jack_ringbuffer_read_space( data->buffSize ) > 0 ) { - jack_ringbuffer_read( data->buffSize, (char *) &space, (size_t) sizeof(space) ); - midiData = jack_midi_event_reserve( buff, 0, space ); - - jack_ringbuffer_read( data->buffMessage, (char *) midiData, (size_t) space ); - } - - return 0; - } - - MidiOutJack :: MidiOutJack( const std::string clientName ) : MidiOutApi() - { - initialize( clientName ); - } - - void MidiOutJack :: initialize( const std::string& clientName ) - { - JackMidiData *data = new JackMidiData; - apiData_ = (void *) data; - - data->port = NULL; - data->client = NULL; - this->clientName = clientName; - - connect(); - } - - void MidiOutJack :: connect() - { - JackMidiData *data = static_cast (apiData_); - if ( data->client ) - return; - - // Initialize JACK client - if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { - errorString_ = "MidiOutJack::initialize: JACK server not running?"; - error( Error::WARNING, errorString_ ); - return; - } - - jack_set_process_callback( data->client, jackProcessOut, data ); - data->buffSize = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); - data->buffMessage = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); - jack_activate( data->client ); - } - - MidiOutJack :: ~MidiOutJack() - { - JackMidiData *data = static_cast (apiData_); - closePort(); - - if ( data->client ) { - // Cleanup - jack_client_close( data->client ); - jack_ringbuffer_free( data->buffSize ); - jack_ringbuffer_free( data->buffMessage ); - } - - delete data; - } - - void MidiOutJack :: openPort( unsigned int portNumber, const std::string portName ) - { - JackMidiData *data = static_cast (apiData_); - - connect(); - - // Creating new port - if ( data->port == NULL ) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); - - if ( data->port == NULL ) { - errorString_ = "MidiOutJack::openPort: JACK error creating port"; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Connecting to the output - std::string name = getPortName( portNumber ); - jack_connect( data->client, jack_port_name( data->port ), name.c_str() ); - } - - void MidiOutJack :: openVirtualPort( const std::string portName ) - { - JackMidiData *data = static_cast (apiData_); - - connect(); - if ( data->port == NULL ) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); - - if ( data->port == NULL ) { - errorString_ = "MidiOutJack::openVirtualPort: JACK error creating virtual port"; - error( Error::DRIVER_ERROR, errorString_ ); - } - } - - unsigned int MidiOutJack :: getPortCount() - { - int count = 0; - JackMidiData *data = static_cast (apiData_); - connect(); - if ( !data->client ) - return 0; - - // List of available ports - const char **ports = jack_get_ports( data->client, NULL, - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); - - if ( ports == NULL ) return 0; - while ( ports[count] != NULL ) - count++; - - free( ports ); - - return count; - } - - std::string MidiOutJack :: getPortName( unsigned int portNumber ) - { - JackMidiData *data = static_cast (apiData_); - std::string retStr(""); - - connect(); - - // List of available ports - const char **ports = jack_get_ports( data->client, NULL, - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); - - // Check port validity - if ( ports == NULL) { - errorString_ = "MidiOutJack::getPortName: no ports available!"; - error( Error::WARNING, errorString_ ); - return retStr; - } - - if ( ports[portNumber] == NULL) { - std::ostringstream ost; - ost << "MidiOutJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::WARNING, errorString_ ); - } - else retStr.assign( ports[portNumber] ); - - free( ports ); - return retStr; - } - - void MidiOutJack :: closePort() - { - JackMidiData *data = static_cast (apiData_); - - if ( data->port == NULL ) return; - jack_port_unregister( data->client, data->port ); - data->port = NULL; - } - - void MidiOutJack :: sendMessage( std::vector *message ) - { - int nBytes = message->size(); - JackMidiData *data = static_cast (apiData_); - - // Write full message to buffer - jack_ringbuffer_write( data->buffMessage, ( const char * ) &( *message )[0], - message->size() ); - jack_ringbuffer_write( data->buffSize, ( char * ) &nBytes, sizeof( nBytes ) ); - } -} + NAMSPACE_RTMIDI_START + + struct JackMidiData { + jack_client_t *client; + jack_port_t *port; + jack_ringbuffer_t *buffSize; + jack_ringbuffer_t *buffMessage; + jack_time_t lastTime; + MidiInApi :: MidiInData *rtMidiIn; + }; + + //*********************************************************************// + // API: JACK + // Class Definitions: MidiInJack + //*********************************************************************// + + static int jackProcessIn( jack_nframes_t nframes, void *arg ) + { + JackMidiData *jData = (JackMidiData *) arg; + MidiInApi :: MidiInData *rtData = jData->rtMidiIn; + jack_midi_event_t event; + jack_time_t time; + + // Is port created? + if ( jData->port == NULL ) return 0; + void *buff = jack_port_get_buffer( jData->port, nframes ); + + // 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(); + + 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 ) + rtData->firstMessage = false; + else + message.timeStamp = ( time - jData->lastTime ) * 0.000001; + + jData->lastTime = time; + + if ( !rtData->continueSysex ) { + if ( rtData->usingCallback ) { + MidiCallback callback = (MidiCallback) rtData->userCallback; + callback( message.timeStamp, &message.bytes, rtData->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( rtData->queue.size < rtData->queue.ringSize ) { + rtData->queue.ring[rtData->queue.back++] = message; + if ( rtData->queue.back == rtData->queue.ringSize ) + rtData->queue.back = 0; + rtData->queue.size++; + } + else + std::cerr << "\nMidiInJack: message queue limit reached!!\n\n"; + } + } + } + + return 0; + } + + MidiInJack :: MidiInJack( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) + { + initialize( clientName ); + } + + void MidiInJack :: initialize( const std::string& clientName ) + { + JackMidiData *data = new JackMidiData; + apiData_ = (void *) data; + + data->rtMidiIn = &inputData_; + data->port = NULL; + data->client = NULL; + this->clientName = clientName; + + connect(); + } + + void MidiInJack :: connect() + { + JackMidiData *data = static_cast (apiData_); + if ( data->client ) + return; + + // Initialize JACK client + if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { + errorString_ = "MidiInJack::initialize: JACK server not running?"; + error( Error::WARNING, errorString_ ); + return; + } + + jack_set_process_callback( data->client, jackProcessIn, data ); + jack_activate( data->client ); + } + + MidiInJack :: ~MidiInJack() + { + JackMidiData *data = static_cast (apiData_); + closePort(); + + if ( data->client ) + jack_client_close( data->client ); + delete data; + } + + void MidiInJack :: openPort( unsigned int portNumber, const std::string portName ) + { + JackMidiData *data = static_cast (apiData_); + + connect(); + + // Creating new port + if ( data->port == NULL) + data->port = jack_port_register( data->client, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); + + if ( data->port == NULL) { + errorString_ = "MidiInJack::openPort: JACK error creating port"; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Connecting to the output + std::string name = getPortName( portNumber ); + jack_connect( data->client, name.c_str(), jack_port_name( data->port ) ); + } + + void MidiInJack :: openVirtualPort( const std::string portName ) + { + JackMidiData *data = static_cast (apiData_); + + connect(); + if ( data->port == NULL ) + data->port = jack_port_register( data->client, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); + + if ( data->port == NULL ) { + errorString_ = "MidiInJack::openVirtualPort: JACK error creating virtual port"; + error( Error::DRIVER_ERROR, errorString_ ); + } + } + + unsigned int MidiInJack :: getPortCount() + { + int count = 0; + JackMidiData *data = static_cast (apiData_); + connect(); + if ( !data->client ) + return 0; + + // List of available ports + const char **ports = jack_get_ports( data->client, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); + + if ( ports == NULL ) return 0; + while ( ports[count] != NULL ) + count++; + + free( ports ); + + return count; + } + + std::string MidiInJack :: getPortName( unsigned int portNumber ) + { + JackMidiData *data = static_cast (apiData_); + std::string retStr(""); + + connect(); + + // List of available ports + const char **ports = jack_get_ports( data->client, NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); + + // Check port validity + if ( ports == NULL ) { + errorString_ = "MidiInJack::getPortName: no ports available!"; + error( Error::WARNING, errorString_ ); + return retStr; + } + + if ( ports[portNumber] == NULL ) { + std::ostringstream ost; + ost << "MidiInJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::WARNING, errorString_ ); + } + else retStr.assign( ports[portNumber] ); + + free( ports ); + return retStr; + } + + void MidiInJack :: closePort() + { + JackMidiData *data = static_cast (apiData_); + + if ( data->port == NULL ) return; + jack_port_unregister( data->client, data->port ); + data->port = NULL; + } + + //*********************************************************************// + // API: JACK + // Class Definitions: MidiOutJack + //*********************************************************************// + + // Jack process callback + static int jackProcessOut( jack_nframes_t nframes, void *arg ) + { + JackMidiData *data = (JackMidiData *) arg; + jack_midi_data_t *midiData; + int space; + + // Is port created? + if ( data->port == NULL ) return 0; + + void *buff = jack_port_get_buffer( data->port, nframes ); + jack_midi_clear_buffer( buff ); + + while ( jack_ringbuffer_read_space( data->buffSize ) > 0 ) { + jack_ringbuffer_read( data->buffSize, (char *) &space, (size_t) sizeof(space) ); + midiData = jack_midi_event_reserve( buff, 0, space ); + + jack_ringbuffer_read( data->buffMessage, (char *) midiData, (size_t) space ); + } + + return 0; + } + + MidiOutJack :: MidiOutJack( const std::string clientName ) : MidiOutApi() + { + initialize( clientName ); + } + + void MidiOutJack :: initialize( const std::string& clientName ) + { + JackMidiData *data = new JackMidiData; + apiData_ = (void *) data; + + data->port = NULL; + data->client = NULL; + this->clientName = clientName; + + connect(); + } + + void MidiOutJack :: connect() + { + JackMidiData *data = static_cast (apiData_); + if ( data->client ) + return; + + // Initialize JACK client + if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { + errorString_ = "MidiOutJack::initialize: JACK server not running?"; + error( Error::WARNING, errorString_ ); + return; + } + + jack_set_process_callback( data->client, jackProcessOut, data ); + data->buffSize = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); + data->buffMessage = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); + jack_activate( data->client ); + } + + MidiOutJack :: ~MidiOutJack() + { + JackMidiData *data = static_cast (apiData_); + closePort(); + + if ( data->client ) { + // Cleanup + jack_client_close( data->client ); + jack_ringbuffer_free( data->buffSize ); + jack_ringbuffer_free( data->buffMessage ); + } + + delete data; + } + + void MidiOutJack :: openPort( unsigned int portNumber, const std::string portName ) + { + JackMidiData *data = static_cast (apiData_); + + connect(); + + // Creating new port + if ( data->port == NULL ) + data->port = jack_port_register( data->client, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); + + if ( data->port == NULL ) { + errorString_ = "MidiOutJack::openPort: JACK error creating port"; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + + // Connecting to the output + std::string name = getPortName( portNumber ); + jack_connect( data->client, jack_port_name( data->port ), name.c_str() ); + } + + void MidiOutJack :: openVirtualPort( const std::string portName ) + { + JackMidiData *data = static_cast (apiData_); + + connect(); + if ( data->port == NULL ) + data->port = jack_port_register( data->client, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); + + if ( data->port == NULL ) { + errorString_ = "MidiOutJack::openVirtualPort: JACK error creating virtual port"; + error( Error::DRIVER_ERROR, errorString_ ); + } + } + + unsigned int MidiOutJack :: getPortCount() + { + int count = 0; + JackMidiData *data = static_cast (apiData_); + connect(); + if ( !data->client ) + return 0; + + // List of available ports + const char **ports = jack_get_ports( data->client, NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); + + if ( ports == NULL ) return 0; + while ( ports[count] != NULL ) + count++; + + free( ports ); + + return count; + } + + std::string MidiOutJack :: getPortName( unsigned int portNumber ) + { + JackMidiData *data = static_cast (apiData_); + std::string retStr(""); + + connect(); + + // List of available ports + const char **ports = jack_get_ports( data->client, NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); + + // Check port validity + if ( ports == NULL) { + errorString_ = "MidiOutJack::getPortName: no ports available!"; + error( Error::WARNING, errorString_ ); + return retStr; + } + + if ( ports[portNumber] == NULL) { + std::ostringstream ost; + ost << "MidiOutJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::WARNING, errorString_ ); + } + else retStr.assign( ports[portNumber] ); + + free( ports ); + return retStr; + } + + void MidiOutJack :: closePort() + { + JackMidiData *data = static_cast (apiData_); + + if ( data->port == NULL ) return; + jack_port_unregister( data->client, data->port ); + data->port = NULL; + } + + void MidiOutJack :: sendMessage( std::vector *message ) + { + int nBytes = message->size(); + JackMidiData *data = static_cast (apiData_); + + // Write full message to buffer + jack_ringbuffer_write( data->buffMessage, ( const char * ) &( *message )[0], + message->size() ); + jack_ringbuffer_write( data->buffSize, ( char * ) &nBytes, sizeof( nBytes ) ); + } + NAMSPACE_RTMIDI_END #endif // __UNIX_JACK__ diff --git a/RtMidi.h b/RtMidi.h index 43aa353e..21e3f5f5 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -61,1082 +61,1084 @@ #include #include -namespace rtmidi { - - //! MIDI API specifier arguments. - enum ApiType { - UNSPECIFIED, /*!< Search for a working compiled API. */ - MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ - LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ - UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ - WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ - WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ - RTMIDI_DUMMY /*!< A compilable but non-functional API. */ - }; - - //! User callback function type definition. - /*! - \param timeStamp timestamp indicating when the event has been received - \param message a pointer to the binary MIDI message - \param userData a pointer that can be set using setUserdata - \sa MidiIn - \sa MidiInApi - */ - typedef void (*MidiCallback)( double timeStamp, std::vector *message, void *userData); - - /************************************************************************/ - /*! \class Error - \brief Exception handling class for RtMidi. - - The Error class is quite simple but it does allow errors to be - "caught" by Error::Type. See the RtMidi documentation to know - which methods can throw an Error. - */ - /************************************************************************/ - - class Error : public std::exception - { - public: - //! Defined Error types. - enum Type { - WARNING, /*!< A non-critical error. */ - DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ - UNSPECIFIED, /*!< The default, unspecified error type. */ - NO_DEVICES_FOUND, /*!< No devices found on system. */ - INVALID_DEVICE, /*!< An invalid device ID was specified. */ - MEMORY_ERROR, /*!< An error occured during memory allocation. */ - INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ - INVALID_USE, /*!< The function was called incorrectly. */ - DRIVER_ERROR, /*!< A system driver error occured. */ - SYSTEM_ERROR, /*!< A system error occured. */ - THREAD_ERROR /*!< A thread error occured. */ - }; - - //! The constructor. - Error( const std::string& message, Type type = Error::UNSPECIFIED ) throw() : message_(message), type_(type) {} - - //! The destructor. - virtual ~Error( void ) throw() {} - - //! Prints thrown error message to stderr. - virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } - - //! Returns the thrown error message type. - virtual const Type& getType(void) const throw() { return type_; } - - //! Returns the thrown error message string. - virtual const std::string& getMessage(void) const throw() { return message_; } - - //! Returns the thrown error message as a c-style string. - virtual const char* what( void ) const throw() { return message_.c_str(); } - - protected: - std::string message_; - Type type_; - }; - - //! RtMidi error callback function prototype. - /*! - \param type Type of error. - \param errorText Error description. - - Note that class behaviour is undefined after a critical error (not - a warning) is reported. - */ - typedef void (*ErrorCallback)( Error::Type type, const std::string &errorText ); +#define NAMESPACE_RTMIDI_START namespace rtmidi { +#define NAMESPACE_RTMIDI_END } + +NAMESPACE_RTMIDI_START +//! MIDI API specifier arguments. +enum ApiType { +UNSPECIFIED, /*!< Search for a working compiled API. */ +MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ +LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ +UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ +WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ +WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ +RTMIDI_DUMMY /*!< A compilable but non-functional API. */ +}; + +//! User callback function type definition. +/*! + \param timeStamp timestamp indicating when the event has been received + \param message a pointer to the binary MIDI message + \param userData a pointer that can be set using setUserdata + \sa MidiIn + \sa MidiInApi +*/ +typedef void (*MidiCallback)( double timeStamp, std::vector *message, void *userData); + +/************************************************************************/ +/*! \class Error + \brief Exception handling class for RtMidi. + + The Error class is quite simple but it does allow errors to be + "caught" by Error::Type. See the RtMidi documentation to know + which methods can throw an Error. +*/ +/************************************************************************/ + +class Error : public std::exception +{ +public: + //! Defined Error types. + enum Type { + WARNING, /*!< A non-critical error. */ + DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ + UNSPECIFIED, /*!< The default, unspecified error type. */ + NO_DEVICES_FOUND, /*!< No devices found on system. */ + INVALID_DEVICE, /*!< An invalid device ID was specified. */ + MEMORY_ERROR, /*!< An error occured during memory allocation. */ + INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ + INVALID_USE, /*!< The function was called incorrectly. */ + DRIVER_ERROR, /*!< A system driver error occured. */ + SYSTEM_ERROR, /*!< A system error occured. */ + THREAD_ERROR /*!< A thread error occured. */ + }; + + //! The constructor. + Error( const std::string& message, Type type = Error::UNSPECIFIED ) throw() : message_(message), type_(type) {} + + //! The destructor. + virtual ~Error( void ) throw() {} + + //! Prints thrown error message to stderr. + virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } + + //! Returns the thrown error message type. + virtual const Type& getType(void) const throw() { return type_; } + + //! Returns the thrown error message string. + virtual const std::string& getMessage(void) const throw() { return message_; } + + //! Returns the thrown error message as a c-style string. + virtual const char* what( void ) const throw() { return message_.c_str(); } + +protected: + std::string message_; + Type type_; +}; + +//! RtMidi error callback function prototype. +/*! + \param type Type of error. + \param errorText Error description. + + Note that class behaviour is undefined after a critical error (not + a warning) is reported. +*/ +typedef void (*ErrorCallback)( Error::Type type, const std::string &errorText ); #if __cplusplus < 201103L - class PortDescriptor; - - template - class Pointer { - public: - typedef T datatype; - protected: - struct countPointer { - int count; - datatype * descriptor; - }; - public: - Pointer(datatype * p):ptr(new countPointer) { - ptr->count = 1; - ptr->descriptor = p; - } - Pointer(const Pointer & other): - ptr(other.ptr) { - ptr->count++; - } - - ~Pointer() { - if (!ptr) return; - if (!ptr->descriptor) { - delete ptr; - return; - } - if (!(--ptr->count)) { - delete ptr->descriptor; - delete ptr; - } - } - - datatype * operator -> () { - if (!ptr) return 0; - // this should throw an exception - - return ptr->descriptor; - } - protected: - countPointer * ptr; - }; +class PortDescriptor; + +template +class Pointer { +public: + typedef T datatype; +protected: + struct countPointer { + int count; + datatype * descriptor; + }; +public: + Pointer(datatype * p):ptr(new countPointer) { + ptr->count = 1; + ptr->descriptor = p; + } + Pointer(const Pointer & other): + ptr(other.ptr) { + ptr->count++; + } + + ~Pointer() { + if (!ptr) return; + if (!ptr->descriptor) { + delete ptr; + return; + } + if (!(--ptr->count)) { + delete ptr->descriptor; + delete ptr; + } + } + + datatype * operator -> () { + if (!ptr) return 0; + // this should throw an exception + + return ptr->descriptor; + } +protected: + countPointer * ptr; +}; #else - template - typedef shared_ptr Pointer; +template +typedef shared_ptr Pointer; #endif - class MidiApi; - - struct PortDescriptor { - //! Flags for formatting a string description of the port. - /*! These flags just mark the requirements that the string - should fulfil. An API may return the same string for - different requirements e.g. the same short and long - name. */ - enum NamingType { - SHORT_NAME =0, /*!< A short human readable name - depending on the API - e.g. “Ensoniq AudioPCI” */ - LONG_NAME, /*!< A complete human readable - name depending on the API - e.g. "Ensoniq AudioPCI: ES1371" */ - SESSION_PATH, /*!< A unique description that can - be used to identify the port - during runtime. It may be a - cryptic string. */ - STORAGE_PATH, /*!< A unique description that is - optimised for storage in - configuration files. This is a - more textual representation that - is more robust to small changes in - the surrounding environment than - \ref SESSION_PATH */ - UNIQUE_NAME = 0x10, /*!< Make all names uniqe. This - is usually done by adding - numbers to the end of the - string */ - INCLUDE_API = 0x20 /*!< Add a string describing the - API at the beginning of the - string. */ - }; - - //! Flags describing the capabilities of a given port. - enum PortCapabilities { - INPUT = 1, /*!< Ports that can be read from. */ - OUTPUT = 2, /*!< Ports that can be written to. */ - INOUTPUT = 3 /*!< Ports that allow reading and writing (INPUT | OUTPUT) */ - }; - - //! Default constructor. - /*! - * Derived classes should have a constructor. - */ - PortDescriptor() {}; - - //! A virtual destructor - /*! As we might have to destruct the object from the application code - * each port id must have a virtual destructor. - */ - virtual ~PortDescriptor() = 0; - - //! Get the MIDI api for the current port. - /*! This is the only information RtMidi needs to know: Which - * API should handle this object. - * - * \return API that can handle this object. - */ - virtual MidiApi * getAPI() = 0; - - //! Return the port name - /*! - * \param flags A description of the requirements of the returned name. - * \return A name that is formatted according to \ref flags. - * \sa NamingTypes - */ - virtual std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) = 0; - - //! Get capabilities - /*! \return a capabilities flag describing the capabilities of the port. - * \sa PortCapabilities - */ - virtual int getCapabilities(); - }; - - //! A list of port descriptors. - /*! Port descriptors are stored as shared pointers. This avoids - unnecessary duplication of the data structure and handles automatic - deletion if all references have been removed. */ - typedef std::list > PortList; - - - - // **************************************************************** // - // - // MidiInApi / MidiOutApi class declarations. - // - // Subclasses of MidiInApi and MidiOutApi contain all API- and - // OS-specific code necessary to fully implement the RtMidi API. - // - // Note that MidiInApi and MidiOutApi are abstract base classes and - // cannot be explicitly instantiated. MidiIn and MidiOut will - // create instances of a MidiInApi or MidiOutApi subclass. - // - // **************************************************************** // - - class MidiApi - { - public: - - MidiApi(); - virtual ~MidiApi(); - - //! Pure virtal function to create a virtual port, with optional name. - /*! - This function creates a virtual MIDI port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, any JACK, - and Linux ALSA APIs (the function returns an error for the other APIs). - - \param portName An optional name for the applicaction port that is - used to connect to portId can be specified. - */ - virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0; - - //! Pure virtual function to open a MIDI connection given by enumeration number. - /*! \param portNumber An optional port number greater than 0 - can be specified. Otherwise, the default or first port - found is opened. - - \param portName An optional name for the applicaction port - that will be generated to connect to portId can be - specified. - */ - virtual void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi" ) ) = 0; - - //! Pure virtual function to open a MIDI connection given by a port descriptor. - /*! - \param port A port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - */ - virtual void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi" ) ) = 0; - - //! Pure virtual function to return a port descirptor if the port is open - virtual Pointer getDescriptor() = 0; - - //! Pure virtual function to return a list of all available ports of the current API. - /*! - \param capabilities an optional parameter that describes which - device types are returned. - - \return This function returns a list of port descriptors. - - \note An input API may but need not necessarily report - output devices which cannot be used as input if - \ref PortDescriptor::OUTPUT is passed as \ref capabilities parameter. - */ - virtual PortList getPortList(int capabilities = PortDescriptor:: INOUTPUT) = 0; - - //! Pure virtual to return the number of available MIDI ports of the current API. - /*! - \return This function returns the number of MIDI ports of - the selected API. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortName - */ - virtual unsigned int getPortCount() = 0; - - //! Pure virtual function to return a string identifier for the specified MIDI port number. - /*! - \param portNumber Number of the device to be referred to. - \return The name of the port with the given Id is returned. - \retval An empty string is returned if an invalid port specifier is provided. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortCount() - */ - virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; - - //! Pure virtual function to close an open MIDI connection (if one exists). - virtual void closePort( void ) = 0; - - // ! A basic error reporting function for RtMidi classes. - // static void error( Error::Type type, std::string &errorString ); - - //! Pure virtual function to return whether a port is open or not. - /*! \retval true if a port is open and - \retval false if the port is not open (e.g. not opend or closed). - */ - bool isPortOpen() const { return connected_; } - - //! Pure virtual function to set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. - */ - virtual void setErrorCallback( ErrorCallback errorCallback = NULL ); - - - //! Returns the MIDI API specifier for the current instance of RtMidiIn. - virtual ApiType getCurrentApi( void ) throw() = 0; - - //! A basic error reporting function for RtMidi classes. - void error( Error::Type type, std::string errorString ); - - protected: - virtual void initialize( const std::string& clientName ) = 0; - - void *apiData_; - bool connected_; - std::string errorString_; - ErrorCallback errorCallback_; - }; - - class MidiInApi : public MidiApi - { - public: - - MidiInApi( unsigned int queueSizeLimit ); - virtual ~MidiInApi( void ); - void setCallback( MidiCallback callback, void *userData ); - void cancelCallback( void ); - virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); - RTMIDI_DEPRECATED(double getMessage( std::vector *message )) - { - if (!message) { - errorString_ = "MidiInApi::getMessage: passed NULL pointer"; - error( Error::WARNING, errorString_ ); - } - return getMessage(*message); - } - double getMessage( std::vector &message ); - - // A MIDI structure used internally by the class to store incoming - // messages. Each message represents one and only one MIDI message. - struct MidiMessage { - std::vector bytes; - double timeStamp; - - // Default constructor. - MidiMessage() - :bytes(0), timeStamp(0.0) {} - }; - - struct MidiQueue { - unsigned int front; - unsigned int back; - unsigned int size; - unsigned int ringSize; - MidiMessage *ring; - - // Default constructor. - MidiQueue() - :front(0), back(0), size(0), ringSize(0) {} - }; - - // The RtMidiInData structure is used to pass private class data to - // the MIDI input handling function or thread. - struct MidiInData { - MidiQueue queue; - MidiMessage message; - unsigned char ignoreFlags; - bool doInput; - bool firstMessage; - void *apiData; - bool usingCallback; - MidiCallback userCallback; - void *userData; - bool continueSysex; - - // Default constructor. - MidiInData() - : ignoreFlags(7), doInput(false), firstMessage(true), - apiData(0), usingCallback(false), userCallback(0), userData(0), - continueSysex(false) {} - }; - - protected: - MidiInData inputData_; - }; - - class MidiOutApi : public MidiApi - { - public: - - MidiOutApi( void ); - virtual ~MidiOutApi( void ); - RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) - { - if (!message) { - errorString_ = "MidiOutApi::sendMessage: no data in message argument!"; - error( Error::WARNING, errorString_ ); - } - sendMessage(*message); - } - virtual void sendMessage( std::vector &message ) = 0; - }; - - - /*! \class Midi - \brief A global class that implements basic backend API handling. - - This class enhances \ref MidiApi by some functionality to handle - backend API objects. It serves as base class for the public RtMidi - API. - - by Gary P. Scavone, 2003-2014. - */ - /**********************************************************************/ - class Midi { - public: - typedef rtmidi::ApiType Api; - //! defined for compatibility - enum Api2 { - UNSPECIFIED = rtmidi::UNSPECIFIED, - MACOSX_CORE = rtmidi::MACOSX_CORE, - LINUX_ALSA = rtmidi::LINUX_ALSA, - UNIX_JACK = rtmidi::UNIX_JACK, - WINDOWS_MM = rtmidi::WINDOWS_MM, - WINDOWS_KS = rtmidi::WINDOWS_KS, - RTMIDI_DUMMY = rtmidi::RTMIDI_DUMMY - }; - - - //! A static function to determine the current RtMidi version. - static std::string getVersion( void ) throw(); - - //! A static function to determine the available compiled MIDI APIs. - /*! - The values returned in the std::vector can be compared against - the enumerated list values. Note that there can be more than one - API compiled for certain operating systems. - */ - static void getCompiledApi( std::vector &apis ) throw(); - - //! Returns the MIDI API specifier for the current instance of RtMidiIn. - ApiType getCurrentApi( void ) throw() - { - if (rtapi_) return rtapi_->getCurrentApi(); - else return rtmidi::UNSPECIFIED; - } - - //! Function to create a virtual port, with optional name. - /*! - This function creates a virtual MIDI port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, any JACK, - and Linux ALSA APIs (the function returns an error for the other APIs). - - \param portName An optional name for the applicaction port that is - used to connect to portId can be specified. - */ - void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) - { - if (rtapi_) rtapi_->openVirtualPort(portName); - } +class MidiApi; + +struct PortDescriptor { + //! Flags for formatting a string description of the port. + /*! These flags just mark the requirements that the string + should fulfil. An API may return the same string for + different requirements e.g. the same short and long + name. */ + enum NamingType { + SHORT_NAME =0, /*!< A short human readable name + depending on the API + e.g. “Ensoniq AudioPCI” */ + LONG_NAME, /*!< A complete human readable + name depending on the API + e.g. "Ensoniq AudioPCI: ES1371" */ + SESSION_PATH, /*!< A unique description that can + be used to identify the port + during runtime. It may be a + cryptic string. */ + STORAGE_PATH, /*!< A unique description that is + optimised for storage in + configuration files. This is a + more textual representation that + is more robust to small changes in + the surrounding environment than + \ref SESSION_PATH */ + UNIQUE_NAME = 0x10, /*!< Make all names uniqe. This + is usually done by adding + numbers to the end of the + string */ + INCLUDE_API = 0x20 /*!< Add a string describing the + API at the beginning of the + string. */ + }; + + //! Flags describing the capabilities of a given port. + enum PortCapabilities { + INPUT = 1, /*!< Ports that can be read from. */ + OUTPUT = 2, /*!< Ports that can be written to. */ + INOUTPUT = 3 /*!< Ports that allow reading and writing (INPUT | OUTPUT) */ + }; + + //! Default constructor. + /*! + * Derived classes should have a constructor. + */ + PortDescriptor() {}; + + //! A virtual destructor + /*! As we might have to destruct the object from the application code + * each port id must have a virtual destructor. + */ + virtual ~PortDescriptor() = 0; + + //! Get the MIDI api for the current port. + /*! This is the only information RtMidi needs to know: Which + * API should handle this object. + * + * \return API that can handle this object. + */ + virtual MidiApi * getAPI() = 0; + + //! Return the port name + /*! + * \param flags A description of the requirements of the returned name. + * \return A name that is formatted according to \ref flags. + * \sa NamingTypes + */ + virtual std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) = 0; + + //! Get capabilities + /*! \return a capabilities flag describing the capabilities of the port. + * \sa PortCapabilities + */ + virtual int getCapabilities(); +}; + +//! A list of port descriptors. +/*! Port descriptors are stored as shared pointers. This avoids + unnecessary duplication of the data structure and handles automatic + deletion if all references have been removed. */ +typedef std::list > PortList; + + + +// **************************************************************** // +// +// MidiInApi / MidiOutApi class declarations. +// +// Subclasses of MidiInApi and MidiOutApi contain all API- and +// OS-specific code necessary to fully implement the RtMidi API. +// +// Note that MidiInApi and MidiOutApi are abstract base classes and +// cannot be explicitly instantiated. MidiIn and MidiOut will +// create instances of a MidiInApi or MidiOutApi subclass. +// +// **************************************************************** // + +class MidiApi +{ +public: + + MidiApi(); + virtual ~MidiApi(); + + //! Pure virtal function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + */ + virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. + + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. + */ + virtual void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + virtual void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual function to return a port descirptor if the port is open + virtual Pointer getDescriptor() = 0; + + //! Pure virtual function to return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that describes which + device types are returned. + + \return This function returns a list of port descriptors. + + \note An input API may but need not necessarily report + output devices which cannot be used as input if + \ref PortDescriptor::OUTPUT is passed as \ref capabilities parameter. + */ + virtual PortList getPortList(int capabilities = PortDescriptor:: INOUTPUT) = 0; + + //! Pure virtual to return the number of available MIDI ports of the current API. + /*! + \return This function returns the number of MIDI ports of + the selected API. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortName + */ + virtual unsigned int getPortCount() = 0; + + //! Pure virtual function to return a string identifier for the specified MIDI port number. + /*! + \param portNumber Number of the device to be referred to. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortCount() + */ + virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; + + //! Pure virtual function to close an open MIDI connection (if one exists). + virtual void closePort( void ) = 0; + + // ! A basic error reporting function for RtMidi classes. + // static void error( Error::Type type, std::string &errorString ); + + //! Pure virtual function to return whether a port is open or not. + /*! \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). + */ + bool isPortOpen() const { return connected_; } + + //! Pure virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + virtual void setErrorCallback( ErrorCallback errorCallback = NULL ); + + + //! Returns the MIDI API specifier for the current instance of RtMidiIn. + virtual ApiType getCurrentApi( void ) throw() = 0; + + //! A basic error reporting function for RtMidi classes. + void error( Error::Type type, std::string errorString ); + +protected: + virtual void initialize( const std::string& clientName ) = 0; + + void *apiData_; + bool connected_; + std::string errorString_; + ErrorCallback errorCallback_; +}; + +class MidiInApi : public MidiApi +{ +public: + + MidiInApi( unsigned int queueSizeLimit ); + virtual ~MidiInApi( void ); + void setCallback( MidiCallback callback, void *userData ); + void cancelCallback( void ); + virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); + RTMIDI_DEPRECATED(double getMessage( std::vector *message )) + { + if (!message) { + errorString_ = "MidiInApi::getMessage: passed NULL pointer"; + error( Error::WARNING, errorString_ ); + } + return getMessage(*message); + } + double getMessage( std::vector &message ); + + // A MIDI structure used internally by the class to store incoming + // messages. Each message represents one and only one MIDI message. + struct MidiMessage { + std::vector bytes; + double timeStamp; + + // Default constructor. + MidiMessage() + :bytes(0), timeStamp(0.0) {} + }; + + struct MidiQueue { + unsigned int front; + unsigned int back; + unsigned int size; + unsigned int ringSize; + MidiMessage *ring; + + // Default constructor. + MidiQueue() + :front(0), back(0), size(0), ringSize(0) {} + }; + + // The RtMidiInData structure is used to pass private class data to + // the MIDI input handling function or thread. + struct MidiInData { + MidiQueue queue; + MidiMessage message; + unsigned char ignoreFlags; + bool doInput; + bool firstMessage; + void *apiData; + bool usingCallback; + MidiCallback userCallback; + void *userData; + bool continueSysex; + + // Default constructor. + MidiInData() + : ignoreFlags(7), doInput(false), firstMessage(true), + apiData(0), usingCallback(false), userCallback(0), userData(0), + continueSysex(false) {} + }; + +protected: + MidiInData inputData_; +}; + +class MidiOutApi : public MidiApi +{ +public: + + MidiOutApi( void ); + virtual ~MidiOutApi( void ); + RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) + { + if (!message) { + errorString_ = "MidiOutApi::sendMessage: no data in message argument!"; + error( Error::WARNING, errorString_ ); + } + sendMessage(*message); + } + virtual void sendMessage( std::vector &message ) = 0; +}; + + +/*! \class Midi + \brief A global class that implements basic backend API handling. + + This class enhances \ref MidiApi by some functionality to handle + backend API objects. It serves as base class for the public RtMidi + API. + + by Gary P. Scavone, 2003-2014. +*/ +/**********************************************************************/ +class Midi { +public: + typedef rtmidi::ApiType Api; + //! defined for compatibility + enum Api2 { + UNSPECIFIED = rtmidi::UNSPECIFIED, + MACOSX_CORE = rtmidi::MACOSX_CORE, + LINUX_ALSA = rtmidi::LINUX_ALSA, + UNIX_JACK = rtmidi::UNIX_JACK, + WINDOWS_MM = rtmidi::WINDOWS_MM, + WINDOWS_KS = rtmidi::WINDOWS_KS, + RTMIDI_DUMMY = rtmidi::RTMIDI_DUMMY + }; + + + //! A static function to determine the current RtMidi version. + static std::string getVersion( void ) throw(); + + //! A static function to determine the available compiled MIDI APIs. + /*! + The values returned in the std::vector can be compared against + the enumerated list values. Note that there can be more than one + API compiled for certain operating systems. + */ + static void getCompiledApi( std::vector &apis ) throw(); + + //! Returns the MIDI API specifier for the current instance of RtMidiIn. + ApiType getCurrentApi( void ) throw() + { + if (rtapi_) return rtapi_->getCurrentApi(); + else return rtmidi::UNSPECIFIED; + } + + //! Function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + */ + void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) + { + if (rtapi_) rtapi_->openVirtualPort(portName); + } - //! Pure virtual function to open a MIDI connection given by enumeration number. - /*! \param portNumber An optional port number greater than 0 - can be specified. Otherwise, the default or first port - found is opened. - - \param portName An optional name for the applicaction port - that will be generated to connect to portId can be - specified. - */ - void openPort( unsigned int portNumber = 0, - const std::string portName = std::string( "RtMidi" ) ) - { - if (rtapi_) rtapi_->openPort(portNumber,portName); - } - - //! Pure virtual function to open a MIDI connection given by a port descriptor. - /*! - \param port A port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - */ - void openPort( const PortDescriptor & port, - const std::string portName = std::string( "RtMidi" ) ) - { - if (rtapi_) rtapi_->openPort(port,portName); - } - - //! Pure virtual function to return a port descirptor if the port is open - Pointer getDescriptor() - { - if (rtapi_) return rtapi_->getDescriptor(); - return 0; - } - - //! Pure virtual function to return a list of all available ports of the current API. - /*! - \param capabilities an optional parameter that describes which - device types are returned. - - \return This function returns a list of port descriptors. - - \note An input API may but need not necessarily report - output devices which cannot be used as input if - \ref PortDescriptor::OUTPUT is passed as \ref capabilities parameter. - */ - PortList getPortList(int capabilities = PortDescriptor:: INOUTPUT) - { - if (rtapi_) return rtapi_->getPortList(capabilities); - return PortList(); - } - - //! Pure virtual to return the number of available MIDI ports of the current API. - /*! - \return This function returns the number of MIDI ports of - the selected API. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortName - */ - unsigned int getPortCount() - { - if (rtapi_) return rtapi_->getPortCount(); - return 0; - } - - //! Pure virtual function to return a string identifier for the specified MIDI port number. - /*! - \param portNumber Number of the device to be referred to. - \return The name of the port with the given Id is returned. - \retval An empty string is returned if an invalid port specifier is provided. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortCount() - */ - std::string getPortName( unsigned int portNumber = 0 ) - { - if (rtapi_) return rtapi_->getPortName(portNumber); - return ""; - } - - //! Close an open MIDI connection (if one exists). - void closePort( void ) - { - if (rtapi_) rtapi_->closePort(); - } - - // ! A basic error reporting function for RtMidi classes. - // static void error( Error::Type type, std::string &errorString ); - - //! Pure virtual function to return whether a port is open or not. - /*! \retval true if a port is open and - \retval false if the port is not open (e.g. not opend or closed). - */ - bool isPortOpen( void ) const - { - if (rtapi_) return rtapi_->isPortOpen(); - return false; - } - - //! Pure virtual function to set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. - */ - void setErrorCallback( ErrorCallback errorCallback = NULL ) - { - if (rtapi_) rtapi_->setErrorCallback(errorCallback); - } - - //! A basic error reporting function for RtMidi classes. - void error( Error::Type type, std::string errorString ); - protected: - MidiApi *rtapi_; - - Midi():rtapi_(0) {} - ~Midi() - { - if (rtapi_) { - delete rtapi_; - rtapi_ = 0; - } - } - }; - - /**********************************************************************/ - /*! \class MidiIn - \brief A realtime MIDI input class. - - This class provides a common, platform-independent API for - realtime MIDI input. It allows access to a single MIDI input - port. Incoming MIDI messages are either saved to a queue for - retrieval using the getMessage() function or immediately passed to - a user-specified callback function. Create multiple instances of - this class to connect to more than one MIDI device at the same - time. With the OS-X and Linux ALSA 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-2014. - */ - /**********************************************************************/ - - // **************************************************************** // - // - // MidiIn and MidiOut class declarations. - // - // MidiIn / MidiOut are "controllers" used to select an available - // MIDI input or output interface. They present common APIs for the - // user to call but all functionality is implemented by the classes - // MidiInApi, MidiOutApi and their subclasses. MidiIn and MidiOut - // each create an instance of a MidiInApi or MidiOutApi subclass based - // on the user's API choice. If no choice is made, they attempt to - // make a "logical" API selection. - // - // **************************************************************** // - - class MidiIn : public Midi - { - public: - - - //! Default constructor that allows an optional api, client name and queue size. - /*! - An exception will be thrown if a MIDI system initialization - error occurs. The queue size defines the maximum number of - messages that can be held in the MIDI queue (when not using a - callback function). If the queue size limit is reached, - incoming messages will be ignored. - - If no API argument is specified and multiple API support has been - compiled, the default order of use is JACK, ALSA (Linux) and CORE, - JACK (OS-X). - - \param api An optional API id can be specified. - \param clientName An optional Client name can be specified. This - will be used to group the ports that are created - by the application. - \param queueSizeLimit An optional size of the MIDI input queue can be specified. - */ - MidiIn( ApiType api=rtmidi::UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Input Client"), - unsigned int queueSizeLimit = 100 ); - - //! If a MIDI connection is still open, it will be closed by the destructor. - ~MidiIn ( void ) throw(); - - - //! Set a callback function to be invoked for incoming MIDI messages. - /*! - The callback function will be called whenever an incoming MIDI - message is received. While not absolutely necessary, it is best - to set the callback function before opening a MIDI port to avoid - leaving some messages in the queue. - - \param callback A callback function must be given. - \param userData Opitionally, a pointer to additional data can be - passed to the callback function whenever it is called. - */ - void setCallback( MidiCallback callback, void *userData = 0 ) - { - if (rtapi_) - static_cast(rtapi_)->setCallback(callback,userData); - } - - //! Cancel use of the current callback function (if one exists). - /*! - Subsequent incoming MIDI messages will be written to the queue - and can be retrieved with the \e getMessage function. - */ - void cancelCallback() - { - if (rtapi_) - static_cast(rtapi_)->cancelCallback(); - } - - //! Specify whether certain MIDI message types should be queued or ignored during input. - /*! - By default, MIDI timing and active sensing messages are ignored - during message input because of their relative high data rates. - MIDI sysex messages are ignored by default as well. Variable - values of "true" imply that the respective message type will be - ignored. - */ - void ignoreTypes( bool midiSysex = true, - bool midiTime = true, - bool midiSense = true ) - { - if (rtapi_) - static_cast(rtapi_)->ignoreTypes(midiSysex, midiTime, midiSense); - } - - //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. - /*! - This function returns immediately whether a new message is - available or not. A valid message is indicated by a non-zero - vector size. An exception is thrown if an error occurs during - message retrieval or an input connection was not previously - established. - */ - double getMessage( std::vector &message ) - { - if (rtapi_) - return static_cast(rtapi_)->getMessage(message); - std::string errorString_ = "MidiIn::getMessage: No valid API found."; - error( Error::WARNING, errorString_ ); - return 0.0; - } - - //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. - /*! - This function returns immediately whether a new message is - available or not. A valid message is indicated by a non-zero - vector size. An exception is thrown if an error occurs during - message retrieval or an input connection was not previously - established. - - \deprecated - */ - RTMIDI_DEPRECATED(double getMessage( std::vector *message )) - { - if (!message) { - error( Error::WARNING, - "MidiIn::getMessage: passed NULL pointer"); - } - if (rtapi_) - return static_cast(rtapi_)->getMessage(*message); - error( Error::WARNING, - "MidiIn::getMessage: No valid API found."); - return 0.0; - } - - protected: - void openMidiApi( ApiType api, const std::string clientName, unsigned int queueSizeLimit ); - - }; - - /**********************************************************************/ - /*! \class MidiOut - \brief A realtime MIDI output class. - - This class provides a common, platform-independent API for MIDI - output. It allows one to probe available MIDI output ports, to - connect to one such port, and to send MIDI bytes immediately over - the connection. Create multiple instances of this class to - connect to more than one MIDI device at the same time. With the - OS-X and Linux ALSA MIDI APIs, it is also possible to open a - virtual port to which other MIDI software clients can connect. - - by Gary P. Scavone, 2003-2014. - */ - /**********************************************************************/ - - class MidiOut : public Midi - { - public: - - //! Default constructor that allows an optional client name. - /*! - An exception will be thrown if a MIDI system initialization error occurs. - - If no API argument is specified and multiple API support has been - compiled, the default order of use is JACK, ALSA (Linux) and CORE, - JACK (OS-X). - */ - MidiOut( ApiType api=rtmidi::UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Output Client") ); - - //! The destructor closes any open MIDI connections. - ~MidiOut( void ) throw(); - - //! Immediately send a single message out an open MIDI output port. - /*! - An exception is thrown if an error occurs during output or an - output connection was not previously established. + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. + + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. + */ + void openPort( unsigned int portNumber = 0, + const std::string portName = std::string( "RtMidi" ) ) + { + if (rtapi_) rtapi_->openPort(portNumber,portName); + } + + //! Pure virtual function to open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + void openPort( const PortDescriptor & port, + const std::string portName = std::string( "RtMidi" ) ) + { + if (rtapi_) rtapi_->openPort(port,portName); + } + + //! Pure virtual function to return a port descirptor if the port is open + Pointer getDescriptor() + { + if (rtapi_) return rtapi_->getDescriptor(); + return 0; + } + + //! Pure virtual function to return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that describes which + device types are returned. + + \return This function returns a list of port descriptors. + + \note An input API may but need not necessarily report + output devices which cannot be used as input if + \ref PortDescriptor::OUTPUT is passed as \ref capabilities parameter. + */ + PortList getPortList(int capabilities = PortDescriptor:: INOUTPUT) + { + if (rtapi_) return rtapi_->getPortList(capabilities); + return PortList(); + } + + //! Pure virtual to return the number of available MIDI ports of the current API. + /*! + \return This function returns the number of MIDI ports of + the selected API. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortName + */ + unsigned int getPortCount() + { + if (rtapi_) return rtapi_->getPortCount(); + return 0; + } + + //! Pure virtual function to return a string identifier for the specified MIDI port number. + /*! + \param portNumber Number of the device to be referred to. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortCount() + */ + std::string getPortName( unsigned int portNumber = 0 ) + { + if (rtapi_) return rtapi_->getPortName(portNumber); + return ""; + } + + //! Close an open MIDI connection (if one exists). + void closePort( void ) + { + if (rtapi_) rtapi_->closePort(); + } + + // ! A basic error reporting function for RtMidi classes. + // static void error( Error::Type type, std::string &errorString ); + + //! Pure virtual function to return whether a port is open or not. + /*! \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). + */ + bool isPortOpen( void ) const + { + if (rtapi_) return rtapi_->isPortOpen(); + return false; + } + + //! Pure virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + void setErrorCallback( ErrorCallback errorCallback = NULL ) + { + if (rtapi_) rtapi_->setErrorCallback(errorCallback); + } + + //! A basic error reporting function for RtMidi classes. + void error( Error::Type type, std::string errorString ); +protected: + MidiApi *rtapi_; + + Midi():rtapi_(0) {} + ~Midi() + { + if (rtapi_) { + delete rtapi_; + rtapi_ = 0; + } + } +}; + +/**********************************************************************/ +/*! \class MidiIn + \brief A realtime MIDI input class. + + This class provides a common, platform-independent API for + realtime MIDI input. It allows access to a single MIDI input + port. Incoming MIDI messages are either saved to a queue for + retrieval using the getMessage() function or immediately passed to + a user-specified callback function. Create multiple instances of + this class to connect to more than one MIDI device at the same + time. With the OS-X and Linux ALSA 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-2014. +*/ +/**********************************************************************/ + +// **************************************************************** // +// +// MidiIn and MidiOut class declarations. +// +// MidiIn / MidiOut are "controllers" used to select an available +// MIDI input or output interface. They present common APIs for the +// user to call but all functionality is implemented by the classes +// MidiInApi, MidiOutApi and their subclasses. MidiIn and MidiOut +// each create an instance of a MidiInApi or MidiOutApi subclass based +// on the user's API choice. If no choice is made, they attempt to +// make a "logical" API selection. +// +// **************************************************************** // + +class MidiIn : public Midi +{ +public: + + + //! Default constructor that allows an optional api, client name and queue size. + /*! + An exception will be thrown if a MIDI system initialization + error occurs. The queue size defines the maximum number of + messages that can be held in the MIDI queue (when not using a + callback function). If the queue size limit is reached, + incoming messages will be ignored. + + If no API argument is specified and multiple API support has been + compiled, the default order of use is JACK, ALSA (Linux) and CORE, + JACK (OS-X). + + \param api An optional API id can be specified. + \param clientName An optional Client name can be specified. This + will be used to group the ports that are created + by the application. + \param queueSizeLimit An optional size of the MIDI input queue can be specified. + */ + MidiIn( ApiType api=rtmidi::UNSPECIFIED, + const std::string clientName = std::string( "RtMidi Input Client"), + unsigned int queueSizeLimit = 100 ); + + //! If a MIDI connection is still open, it will be closed by the destructor. + ~MidiIn ( void ) throw(); + + + //! Set a callback function to be invoked for incoming MIDI messages. + /*! + The callback function will be called whenever an incoming MIDI + message is received. While not absolutely necessary, it is best + to set the callback function before opening a MIDI port to avoid + leaving some messages in the queue. + + \param callback A callback function must be given. + \param userData Opitionally, a pointer to additional data can be + passed to the callback function whenever it is called. + */ + void setCallback( MidiCallback callback, void *userData = 0 ) + { + if (rtapi_) + static_cast(rtapi_)->setCallback(callback,userData); + } + + //! Cancel use of the current callback function (if one exists). + /*! + Subsequent incoming MIDI messages will be written to the queue + and can be retrieved with the \e getMessage function. + */ + void cancelCallback() + { + if (rtapi_) + static_cast(rtapi_)->cancelCallback(); + } + + //! Specify whether certain MIDI message types should be queued or ignored during input. + /*! + By default, MIDI timing and active sensing messages are ignored + during message input because of their relative high data rates. + MIDI sysex messages are ignored by default as well. Variable + values of "true" imply that the respective message type will be + ignored. + */ + void ignoreTypes( bool midiSysex = true, + bool midiTime = true, + bool midiSense = true ) + { + if (rtapi_) + static_cast(rtapi_)->ignoreTypes(midiSysex, midiTime, midiSense); + } + + //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. + /*! + This function returns immediately whether a new message is + available or not. A valid message is indicated by a non-zero + vector size. An exception is thrown if an error occurs during + message retrieval or an input connection was not previously + established. + */ + double getMessage( std::vector &message ) + { + if (rtapi_) + return static_cast(rtapi_)->getMessage(message); + std::string errorString_ = "MidiIn::getMessage: No valid API found."; + error( Error::WARNING, errorString_ ); + return 0.0; + } + + //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. + /*! + This function returns immediately whether a new message is + available or not. A valid message is indicated by a non-zero + vector size. An exception is thrown if an error occurs during + message retrieval or an input connection was not previously + established. + + \deprecated + */ + RTMIDI_DEPRECATED(double getMessage( std::vector *message )) + { + if (!message) { + error( Error::WARNING, + "MidiIn::getMessage: passed NULL pointer"); + } + if (rtapi_) + return static_cast(rtapi_)->getMessage(*message); + error( Error::WARNING, + "MidiIn::getMessage: No valid API found."); + return 0.0; + } + +protected: + void openMidiApi( ApiType api, const std::string clientName, unsigned int queueSizeLimit ); + +}; + +/**********************************************************************/ +/*! \class MidiOut + \brief A realtime MIDI output class. + + This class provides a common, platform-independent API for MIDI + output. It allows one to probe available MIDI output ports, to + connect to one such port, and to send MIDI bytes immediately over + the connection. Create multiple instances of this class to + connect to more than one MIDI device at the same time. With the + OS-X and Linux ALSA MIDI APIs, it is also possible to open a + virtual port to which other MIDI software clients can connect. + + by Gary P. Scavone, 2003-2014. +*/ +/**********************************************************************/ + +class MidiOut : public Midi +{ +public: + + //! Default constructor that allows an optional client name. + /*! + An exception will be thrown if a MIDI system initialization error occurs. + + If no API argument is specified and multiple API support has been + compiled, the default order of use is JACK, ALSA (Linux) and CORE, + JACK (OS-X). + */ + MidiOut( ApiType api=rtmidi::UNSPECIFIED, + const std::string clientName = std::string( "RtMidi Output Client") ); + + //! The destructor closes any open MIDI connections. + ~MidiOut( void ) throw(); + + //! Immediately send a single message out an open MIDI output port. + /*! + An exception is thrown if an error occurs during output or an + output connection was not previously established. - \deprecated - */ - RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) - { - if (!message) { - error( Error::WARNING, - "MidiOutApi::sendMessage: no data in message argument!"); - } - if (rtapi_) - static_cast(rtapi_)->sendMessage(*message); - error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); - } - - - //! Immediately send a single message out an open MIDI output port. - /*! - An exception is thrown if an error occurs during output or an - output connection was not previously established. - */ - void sendMessage( std::vector &message ) { - if (rtapi_) - static_cast(rtapi_)->sendMessage(message); - error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); - } - protected: - void openMidiApi( ApiType api, const std::string clientName ); - }; - - - // **************************************************************** // - // - // MidiInApi and MidiOutApi subclass prototypes. - // - // **************************************************************** // + \deprecated + */ + RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) + { + if (!message) { + error( Error::WARNING, + "MidiOutApi::sendMessage: no data in message argument!"); + } + if (rtapi_) + static_cast(rtapi_)->sendMessage(*message); + error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); + } + + + //! Immediately send a single message out an open MIDI output port. + /*! + An exception is thrown if an error occurs during output or an + output connection was not previously established. + */ + void sendMessage( std::vector &message ) { + if (rtapi_) + static_cast(rtapi_)->sendMessage(message); + error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); + } +protected: + void openMidiApi( ApiType api, const std::string clientName ); +}; + + +// **************************************************************** // +// +// MidiInApi and MidiOutApi subclass prototypes. +// +// **************************************************************** // #if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__) - #define __RTMIDI_DUMMY__ +#define __RTMIDI_DUMMY__ #endif #if defined(__MACOSX_CORE__) - class MidiInCore: public MidiInApi - { - public: - MidiInCore( const std::string clientName, unsigned int queueSizeLimit ); - ~MidiInCore( void ); - ApiType getCurrentApi( void ) { return MACOSX_CORE; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - 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 ); - ApiType getCurrentApi( void ) { return MACOSX_CORE; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector &message ); - - protected: - void initialize( const std::string& clientName ); - }; +class MidiInCore: public MidiInApi +{ +public: + MidiInCore( const std::string clientName, unsigned int queueSizeLimit ); + ~MidiInCore( void ); + ApiType getCurrentApi( void ) { return MACOSX_CORE; }; + void openPort( unsigned int portNumber, const std::string portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + 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 ); + ApiType getCurrentApi( void ) { return MACOSX_CORE; }; + void openPort( unsigned int portNumber, const std::string portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + void closePort( void ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( std::vector &message ); + +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 ); - ApiType getCurrentApi( void ) { return UNIX_JACK; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - 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 ); - ApiType getCurrentApi( void ) { return UNIX_JACK; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector &message ); - - protected: - std::string clientName; - - void connect( void ); - void initialize( const std::string& clientName ); - }; +class MidiInJack: public MidiInApi +{ +public: + MidiInJack( const std::string clientName, unsigned int queueSizeLimit ); + ~MidiInJack( void ); + ApiType getCurrentApi( void ) { return UNIX_JACK; }; + void openPort( unsigned int portNumber, const std::string portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + 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 ); + ApiType getCurrentApi( void ) { return UNIX_JACK; }; + void openPort( unsigned int portNumber, const std::string portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + void closePort( void ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( std::vector &message ); + +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 ); - ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - 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 ); - ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector &message ); - - protected: - void initialize( const std::string& clientName ); - }; +class MidiInAlsa: public MidiInApi +{ +public: + MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit ); + ~MidiInAlsa( void ); + ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; + void openPort( unsigned int portNumber, const std::string portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + 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 ); + ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; + void openPort( unsigned int portNumber, const std::string portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + void closePort( void ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( std::vector &message ); + +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 ); - ApiType getCurrentApi( void ) { return WINDOWS_MM; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - 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 ); - ApiType getCurrentApi( void ) { return WINDOWS_MM; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector &message ); - - protected: - void initialize( const std::string& clientName ); - }; +class MidiInWinMM: public MidiInApi +{ +public: + MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ); + ~MidiInWinMM( void ); + ApiType getCurrentApi( void ) { return WINDOWS_MM; }; + void openPort( unsigned int portNumber, const std::string portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + 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 ); + ApiType getCurrentApi( void ) { return WINDOWS_MM; }; + void openPort( unsigned int portNumber, const std::string portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + void closePort( void ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( std::vector &message ); + +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( Error::WARNING, errorString_ ); - } - ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } - void openPort( unsigned int /*portNumber*/, const std::string /*portName*/ ) {} - void openVirtualPort( const std::string /*portName*/ ) {} - void openPort( const PortDescriptor & port, const std::string portName) {} - Pointer getDescriptor() { return 0; } - PortList getPortList(int capabilities) { return PortList(); } - 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( Error::WARNING, errorString_ ); - } - ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } - void openPort( unsigned int /*portNumber*/, const std::string /*portName*/ ) {} - void openVirtualPort( const std::string /*portName*/ ) {} - void openPort( const PortDescriptor & port, const std::string portName) {} - Pointer getDescriptor() { return 0; } - PortList getPortList(int capabilities) { return PortList(); } - void closePort( void ) {} - unsigned int getPortCount( void ) { return 0; } - std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } - void sendMessage( std::vector & /*message*/ ) {} - - protected: - void initialize( const std::string& /*clientName*/ ) {} - }; +class MidiInDummy: public MidiInApi +{ +public: + MidiInDummy( const std::string /*clientName*/, unsigned int queueSizeLimit ) + : MidiInApi( queueSizeLimit ) { + errorString_ = "MidiInDummy: This class provides no functionality."; + error( Error::WARNING, errorString_ ); + } + ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } + void openPort( unsigned int /*portNumber*/, const std::string /*portName*/ ) {} + void openVirtualPort( const std::string /*portName*/ ) {} + void openPort( const PortDescriptor & port, const std::string portName) {} + Pointer getDescriptor() { return 0; } + PortList getPortList(int capabilities) { return PortList(); } + 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( Error::WARNING, errorString_ ); + } + ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } + void openPort( unsigned int /*portNumber*/, const std::string /*portName*/ ) {} + void openVirtualPort( const std::string /*portName*/ ) {} + void openPort( const PortDescriptor & port, const std::string portName) {} + Pointer getDescriptor() { return 0; } + PortList getPortList(int capabilities) { return PortList(); } + void closePort( void ) {} + unsigned int getPortCount( void ) { return 0; } + std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } + void sendMessage( std::vector & /*message*/ ) {} + +protected: + void initialize( const std::string& /*clientName*/ ) {} +}; #endif -} +NAMESPACE_RTMIDI_END typedef rtmidi::Midi RtMidi; typedef rtmidi::MidiIn RtMidiIn; From bf0504cf46354924eb693ca3ebaa3c18c15a0ed2 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 30 Mar 2014 16:16:52 +0200 Subject: [PATCH 010/210] Fix phony make target tests. --- Makefile.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile.in b/Makefile.in index 82ad7ad7..b51713dd 100644 --- a/Makefile.in +++ b/Makefile.in @@ -22,6 +22,8 @@ CFLAGS = @CXXFLAGS@ -Iinclude -fPIC PREFIX = @prefix@ +.PHONY: tests + all : $(LIBRARIES) tests: From 687a039604292a0a5f402b64a5d10c1e8eb993c6 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 30 Mar 2014 16:19:24 +0200 Subject: [PATCH 011/210] Bump library version. Even though this feature is currently unused we should use a different library version for future development. While we provide workarounds for the API the ABI has changed. --- Makefile.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile.in b/Makefile.in index b51713dd..4d8dabfd 100644 --- a/Makefile.in +++ b/Makefile.in @@ -9,8 +9,13 @@ OBJECTS = RtMidi.o LIBNAME = librtmidi STATIC = $(LIBNAME).a SHARED = @sharedlib@ +<<<<<<< HEAD RELEASE = 2.1.0 MAJOR = 2 +======= +RELEASE = 3.0.0 +MAJOR = 3 +>>>>>>> Bump library version. LIBRARIES = $(STATIC) $(SHARED) CC = @CXX@ From 68f2e38270a04ba47f215c54c328924465840cfe Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 30 Mar 2014 16:20:03 +0200 Subject: [PATCH 012/210] Silence some warnings about unused parameters. --- tests/midiout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/midiout.cpp b/tests/midiout.cpp index 05505cc6..49c5b081 100644 --- a/tests/midiout.cpp +++ b/tests/midiout.cpp @@ -24,7 +24,7 @@ // It returns false if there are no ports available. bool chooseMidiPort( RtMidiOut *rtmidi ); -int main( void ) +int main( int /* argc*/, char */*argv*/[] ) { RtMidiOut *midiout = 0; std::vector message; From 7d36db3b7ede619a140ddb2db8ec0e6c34f7657c Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 5 Apr 2014 10:34:05 +0200 Subject: [PATCH 013/210] Provide some abstraction layer that will eventually handle all generic ALSA calls. This layer provides an API that is more consistent with the data used by RtMidi. On the other hand it allows to optionally use a locking mechanism for all sequencer calls so that ALSA may use one client for all threads for certain tasks (or if it is requested). --- RtMidi.cpp | 462 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 446 insertions(+), 16 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 356ce6d4..5cd691fe 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1134,22 +1134,452 @@ NAMSPACE_RTMIDI_END #include NAMSPACE_RTMIDI_START -// A structure to hold variables related to the ALSA API -// implementation. -struct AlsaMidiData { - snd_seq_t *seq; - unsigned int portNum; - int vport; - snd_seq_port_subscribe_t *subscription; - snd_midi_event_t *coder; - unsigned int bufferSize; - unsigned char *buffer; - pthread_t thread; - pthread_t dummy_thread_id; - unsigned long long lastTime; - int queue_id; // an input queue is needed to get timestamped events - int trigger_fds[2]; -}; + struct AlsaMidiData; + + /*! An abstraction layer for the ALSA sequencer layer. It provides + the following functionality: + - dynamic allocation of the sequencer + - optionallay avoid concurrent access to the ALSA sequencer, + which is not thread proof. This feature is controlled by + the parameter \ref locking. + */ + + template + class AlsaSequencer { + public: + AlsaSequencer():seq(0) + { + if (locking) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); + } + } + + AlsaSequencer(const std::string & name):seq(0) + { + if (locking) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); + } + init(); + { + scoped_lock lock(mutex); + snd_seq_set_client_name( seq, name.c_str() ); + } + } + + ~AlsaSequencer() + { + if (locking) { + pthread_mutex_destroy(&mutex); + } + } + + std::string GetPortName(int client, int port, int flags) { + init(); + snd_seq_client_info_t *cinfo; + snd_seq_client_info_alloca( &cinfo ); + { + scoped_lock lock (mutex); + snd_seq_get_any_client_info(seq,client,cinfo); + } + + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + { + scoped_lock lock (mutex); + snd_seq_get_any_port_info(seq,client,port,pinfo); + } + + int naming = flags & PortDescriptor::NAMING_MASK; + + std::ostringstream os; + switch (naming) { + case PortDescriptor::SESSION_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "ALSA:"; + os << client << ":" << port; + break; + case PortDescriptor::STORAGE_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "ALSA:"; + os << snd_seq_client_info_get_name(cinfo); + os << ":"; + os << snd_seq_port_info_get_name(pinfo); + if (flags & PortDescriptor::UNIQUE_NAME) + os << ";" << client << ":" << port; + break; + case PortDescriptor::LONG_NAME: + os << snd_seq_client_info_get_name( cinfo ); + if (flags & PortDescriptor::UNIQUE_NAME) { + os << " " << client; + } + os << ":"; + if (flags & PortDescriptor::UNIQUE_NAME) { + os << port; + } + + os << " " << snd_seq_port_info_get_name(pinfo); + if (flags & PortDescriptor::INCLUDE_API) + os << " (ALSA)"; + break; + case PortDescriptor::SHORT_NAME: + default: + os << snd_seq_client_info_get_name( cinfo ); + if (flags & PortDescriptor::UNIQUE_NAME) { + os << " "; + os << client; + } + os << ":" << port; + if (flags & PortDescriptor::INCLUDE_API) + os << " (ALSA)"; + + break; + } + return os.str(); + } + + int getPortCapabilities(int client, int port) { + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + { + scoped_lock lock (mutex); + snd_seq_get_any_port_info(seq,client,port,pinfo); + } + unsigned int caps = snd_seq_port_info_get_capability(pinfo); + int retval = (caps & (SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ))? + PortDescriptor::INPUT:0; + if (caps & (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) + retval |= PortDescriptor::OUTPUT; + return retval; + } + + int getNextClient(snd_seq_client_info_t * cinfo ) { + init(); + scoped_lock lock (mutex); + return snd_seq_query_next_client (seq, cinfo); + } + int getNextPort(snd_seq_port_info_t * pinfo ) { + init(); + scoped_lock lock (mutex); + return snd_seq_query_next_port (seq, pinfo); + } + + int createPort (snd_seq_port_info_t *pinfo) { + init(); + scoped_lock lock (mutex); + return snd_seq_create_port(seq, pinfo); + } + + void deletePort(int port) { + init(); + scoped_lock lock (mutex); + snd_seq_delete_port( seq, port ); + } + + snd_seq_port_subscribe_t * connectPorts(const snd_seq_addr_t & from, + const snd_seq_addr_t & to) { + init(); + snd_seq_port_subscribe_t *subscription; + + if (snd_seq_port_subscribe_malloc( &subscription ) < 0) { + throw Error("MidiInAlsa::openPort: ALSA error allocation port subscription.", + Error::DRIVER_ERROR ); + return 0; + } + snd_seq_port_subscribe_set_sender(subscription, &from); + snd_seq_port_subscribe_set_dest(subscription, &to); + { + scoped_lock lock (mutex); + if ( snd_seq_subscribe_port(seq, subscription) ) { + snd_seq_port_subscribe_free( subscription ); + subscription = 0; + throw Error("MidiInAlsa::openPort: ALSA error making port connection.", + Error::DRIVER_ERROR); + return 0; + } + return subscription; + } + } + + void closePort(snd_seq_port_subscribe_t * subscription ) { + init(); + scoped_lock lock(mutex); + snd_seq_unsubscribe_port( seq, subscription ); + } + + void startQueue(int queue_id) { + init(); + scoped_lock lock(mutex); + snd_seq_start_queue( seq, queue_id, NULL ); + snd_seq_drain_output( seq ); + } + + /*! Use AlsaSequencer like a C pointer. + \note This function breaks the design to control thread safety + by the selection of the \ref locking parameter to the class. + It should be removed as soon as possible in order ensure the + thread policy that has been intended by creating this class. + */ + operator snd_seq_t * () + { + return seq; + } + protected: + struct scoped_lock { + pthread_mutex_t * mutex; + scoped_lock(pthread_mutex_t & m): mutex(&m) + { + if (locking) + pthread_mutex_lock(mutex); + } + ~scoped_lock() + { + if (locking) + pthread_mutex_unlock(mutex); + } + }; + pthread_mutex_t mutex; + snd_seq_t * seq; + + + snd_seq_client_info_t * GetClient(int id) { + init(); + snd_seq_client_info_t * cinfo; + scoped_lock lock(mutex); + snd_seq_get_any_client_info(seq,id,cinfo); + return cinfo; + } + + void init() + { + init (seq); + } + + void init(snd_seq_t * &s) + { + if (s) return; + { + scoped_lock lock(mutex); + int result = snd_seq_open(&s, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); + if ( result < 0 ) { + throw Error( "MidiInAlsa::initialize: error creating ALSA sequencer client object.", + Error::DRIVER_ERROR ); + return; + } + } + } + }; + typedef AlsaSequencer<1> LockingAlsaSequencer; + typedef AlsaSequencer<0> NonLockingAlsaSequencer; + + struct AlsaPortDescriptor:public PortDescriptor, + public snd_seq_addr_t + { + MidiApi * api; + static LockingAlsaSequencer seq; + AlsaPortDescriptor():api(0) + { + client = 0; + port = 0; + } + AlsaPortDescriptor(int c, int p):api(0) + { + client = c; + port = p; + } + ~AlsaPortDescriptor() {} + MidiApi * getAPI() { + return NULL; + } + std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) { + return seq.GetPortName(client,port,flags); + } + int getCapabilities() { + return seq.getPortCapabilities(client,port); + } + static PortList getPortList(int capabilities); + }; + + LockingAlsaSequencer AlsaPortDescriptor::seq; + + + + PortList AlsaPortDescriptor :: getPortList(int capabilities) + { + PortList list; + snd_seq_client_info_t *cinfo; + snd_seq_port_info_t *pinfo; + int client; + snd_seq_client_info_alloca( &cinfo ); + snd_seq_port_info_alloca( &pinfo ); + + snd_seq_client_info_set_client( cinfo, -1 ); + while ( seq.getNextClient(cinfo ) >= 0 ) { + client = snd_seq_client_info_get_client( cinfo ); + // ignore default device (it is included in the following results again) + if ( client == 0 ) continue; + // Reset query info + snd_seq_port_info_set_client( pinfo, client ); + snd_seq_port_info_set_port( pinfo, -1 ); + while ( seq.getNextPort( pinfo ) >= 0 ) { + unsigned int atyp = snd_seq_port_info_get_type( pinfo ); + // otherwise we get ports without any + if ( !(capabilities & UNLIMITED) && + !( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) ) continue; + unsigned int caps = snd_seq_port_info_get_capability( pinfo ); + if (capabilities & INPUT) { + /* we need both READ and SUBS_READ */ + if ((caps & (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) + != (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) + continue; + } + if (capabilities & OUTPUT) { + /* we need both WRITE and SUBS_WRITE */ + if ((caps & (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) + != (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) + continue; + } + list.push_back(new AlsaPortDescriptor(client,snd_seq_port_info_get_port(pinfo))); + } + } + return list; + } + + static void *alsaMidiHandler( void *ptr ); + + + /*! A structure to hold variables related to the ALSA API + implementation. + + \note After all sequencer handling is covered by the \ref + AlsaSequencer class, we should make seq to be a pointer in order + to allow a common client implementation. + */ + + struct AlsaMidiData:public AlsaPortDescriptor { + AlsaMidiData():seq() { + init(); + } + AlsaMidiData(const std::string &clientName):seq(clientName) { + init(); + } + ~AlsaMidiData() { + if (local.client) + deletePort(); + } + void init () { + local.port = 0; + local.client = 0; + port = -1; + subscription = 0; + coder = 0; + bufferSize = 32; + buffer = 0; + dummy_thread_id = pthread_self(); + thread = dummy_thread_id; + trigger_fds[0] = -1; + trigger_fds[1] = -1; + } + snd_seq_addr_t local; /*!< Our port and client id. If client = 0 (default) this means we didn't aquire a port so far. */ + NonLockingAlsaSequencer seq; + // unsigned int portNum; + snd_seq_port_subscribe_t *subscription; + snd_midi_event_t *coder; + unsigned int bufferSize; + unsigned char *buffer; + pthread_t thread; + pthread_t dummy_thread_id; + unsigned long long lastTime; + int queue_id; // an input queue is needed to get timestamped events + int trigger_fds[2]; + + void setRemote(const AlsaPortDescriptor * remote) { + port = remote->port; + client = remote->client; + } + void connectPorts(const snd_seq_addr_t &from, + const snd_seq_addr_t &to) { + subscription = seq.connectPorts(from, to); + } + + int openPort(int alsaCapabilities, + const std::string & portName) { + if (subscription) { + api->error( Error::DRIVER_ERROR, + "MidiInAlsa::openPort: ALSA error allocation port subscription." ); + return -99; + } + + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + + snd_seq_port_info_set_client( pinfo, 0 ); + snd_seq_port_info_set_port( pinfo, 0 ); + snd_seq_port_info_set_capability( pinfo, + alsaCapabilities); + snd_seq_port_info_set_type( pinfo, + SND_SEQ_PORT_TYPE_MIDI_GENERIC | + SND_SEQ_PORT_TYPE_APPLICATION ); + snd_seq_port_info_set_midi_channels(pinfo, 16); +#ifndef AVOID_TIMESTAMPING + snd_seq_port_info_set_timestamping(pinfo, 1); + snd_seq_port_info_set_timestamp_real(pinfo, 1); + snd_seq_port_info_set_timestamp_queue(pinfo, queue_id); +#endif + snd_seq_port_info_set_name(pinfo, portName.c_str() ); + int createok = seq.createPort(pinfo); + + if ( createok < 0 ) { + api->error( Error::DRIVER_ERROR, + "MidiInAlsa::openPort: ALSA error creating input port." ); + return createok; + } + + local.client = snd_seq_port_info_get_client( pinfo ); + local.port = snd_seq_port_info_get_port(pinfo); + return 0; + } + + void deletePort() { + seq.deletePort(local.port); + local.client = 0; + local.port = 0; + } + + void closePort() { + seq.closePort(subscription ); + snd_seq_port_subscribe_free( subscription ); + subscription = 0; + } + + bool startQueue(void * userdata) { + // Start the input queue +#ifndef AVOID_TIMESTAMPING + seq.startQueue(queue_id); +#endif + // Start our MIDI input thread. + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + pthread_attr_setschedpolicy(&attr, SCHED_OTHER); + + int err = pthread_create(&thread, &attr, alsaMidiHandler, userdata); + pthread_attr_destroy(&attr); + if ( err ) { + closePort(); + api->error( Error::THREAD_ERROR, + "MidiInAlsa::openPort: error starting MIDI input thread!" ); + return false; + } + return true; + } + }; + #define PORT_TYPE( pinfo, bits ) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits)) From 179360856e516b8ad99296f5f07e6cccbc0bf64b Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 5 Apr 2014 10:41:35 +0200 Subject: [PATCH 014/210] Provide the implementation part of the prvious patch. The ALSA output devices should be still considered broken. --- RtMidi.cpp | 75 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 5cd691fe..f6cd9411 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1803,7 +1803,7 @@ MidiInAlsa :: ~MidiInAlsa() // Cleanup. close ( data->trigger_fds[0] ); close ( data->trigger_fds[1] ); - if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport ); + if ( data->local.client ) data->deletePort(); #ifndef AVOID_TIMESTAMPING snd_seq_free_queue( data->seq, data->queue_id ); #endif @@ -1813,6 +1813,8 @@ MidiInAlsa :: ~MidiInAlsa() void MidiInAlsa :: initialize( const std::string& clientName ) { +#if 0 + /* this will be done in the AlsaSequencer class */ // Set up the ALSA sequencer client. snd_seq_t *seq; int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); @@ -1821,20 +1823,16 @@ void MidiInAlsa :: initialize( const std::string& clientName ) error( Error::DRIVER_ERROR, errorString_ ); return; } +#endif + // Save our api-specific connection information. + AlsaMidiData *data = new AlsaMidiData (clientName); // Set client name. - snd_seq_set_client_name( seq, clientName.c_str() ); - // Save our api-specific connection information. - AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; - data->seq = seq; - data->portNum = -1; - data->vport = -1; - data->subscription = 0; - data->dummy_thread_id = pthread_self(); - data->thread = data->dummy_thread_id; - data->trigger_fds[0] = -1; - data->trigger_fds[1] = -1; + + + //data->seq = seq; + // data->portNum = -1; apiData_ = (void *) data; inputData_.apiData = (void *) data; @@ -1956,7 +1954,7 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName snd_seq_port_info_t *pinfo; snd_seq_port_info_alloca( &pinfo ); - if ( data->vport < 0 ) { + if ( !data->local.client ) { snd_seq_port_info_set_client( pinfo, 0 ); snd_seq_port_info_set_port( pinfo, 0 ); snd_seq_port_info_set_capability( pinfo, @@ -1966,6 +1964,7 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION ); snd_seq_port_info_set_midi_channels(pinfo, 16); + #ifndef AVOID_TIMESTAMPING snd_seq_port_info_set_timestamping(pinfo, 1); snd_seq_port_info_set_timestamp_real(pinfo, 1); @@ -1979,11 +1978,11 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName error( Error::DRIVER_ERROR, errorString_ ); return; } - data->vport = snd_seq_port_info_get_port(pinfo); + data->local.port = snd_seq_port_info_get_port(pinfo); + data->local.client = snd_seq_port_info_get_client(pinfo); } - receiver.client = snd_seq_port_info_get_client( pinfo ); - receiver.port = data->vport; + receiver = data->local; if ( !data->subscription ) { // Make subscription @@ -2005,6 +2004,7 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName if ( inputData_.doInput == false ) { // Start the input queue + #ifndef AVOID_TIMESTAMPING snd_seq_start_queue( data->seq, data->queue_id, NULL ); snd_seq_drain_output( data->seq ); @@ -2052,7 +2052,7 @@ PortList MidiInAlsa :: getPortList(int capabilities) void MidiInAlsa :: openVirtualPort( std::string portName ) { AlsaMidiData *data = static_cast (apiData_); - if ( data->vport < 0 ) { + if ( !data->local.client ) { snd_seq_port_info_t *pinfo; snd_seq_port_info_alloca( &pinfo ); snd_seq_port_info_set_capability( pinfo, @@ -2075,7 +2075,8 @@ void MidiInAlsa :: openVirtualPort( std::string portName ) error( Error::DRIVER_ERROR, errorString_ ); return; } - data->vport = snd_seq_port_info_get_port(pinfo); + data->local.port = snd_seq_port_info_get_port(pinfo); + data->local.client = snd_seq_port_info_get_client(pinfo); } if ( inputData_.doInput == false ) { @@ -2084,6 +2085,7 @@ void MidiInAlsa :: openVirtualPort( std::string portName ) pthread_join( data->thread, NULL ); // Start the input queue + #ifndef AVOID_TIMESTAMPING snd_seq_start_queue( data->seq, data->queue_id, NULL ); snd_seq_drain_output( data->seq ); @@ -2126,6 +2128,7 @@ void MidiInAlsa :: closePort( void ) snd_seq_stop_queue( data->seq, data->queue_id, NULL ); snd_seq_drain_output( data->seq ); #endif + connected_ = false; } @@ -2156,7 +2159,7 @@ MidiOutAlsa :: ~MidiOutAlsa() // Cleanup. AlsaMidiData *data = static_cast (apiData_); - if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport ); + if ( data->local.port >= 0 ) snd_seq_delete_port( data->seq, data->local.port ); if ( data->coder ) snd_midi_event_free( data->coder ); if ( data->buffer ) free( data->buffer ); snd_seq_close( data->seq ); @@ -2165,6 +2168,7 @@ MidiOutAlsa :: ~MidiOutAlsa() void MidiOutAlsa :: initialize( const std::string& clientName ) { +#if 0 // Set up the ALSA sequencer client. snd_seq_t *seq; int result1 = snd_seq_open( &seq, "default", SND_SEQ_OPEN_OUTPUT, SND_SEQ_NONBLOCK ); @@ -2176,15 +2180,13 @@ void MidiOutAlsa :: initialize( const std::string& clientName ) // Set client name. snd_seq_set_client_name( seq, clientName.c_str() ); +#endif // Save our api-specific connection information. - AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; - data->seq = seq; - data->portNum = -1; - data->vport = -1; - data->bufferSize = 32; - data->coder = 0; - data->buffer = 0; + AlsaMidiData *data = new AlsaMidiData(clientName); + // data->seq = seq; + // data->portNum = -1; + int result = snd_midi_event_new( data->bufferSize, &data->coder ); if ( result < 0 ) { delete data; @@ -2271,18 +2273,18 @@ void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string portNam receiver.port = snd_seq_port_info_get_port( pinfo ); sender.client = snd_seq_client_id( data->seq ); - if ( data->vport < 0 ) { - data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(), + if ( data->local.port < 0 ) { + data->local.port = snd_seq_create_simple_port( data->seq, portName.c_str(), SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); - if ( data->vport < 0 ) { + if ( data->local.port < 0 ) { errorString_ = "MidiOutAlsa::openPort: ALSA error creating output port."; error( Error::DRIVER_ERROR, errorString_ ); return; } } - sender.port = data->vport; + sender.port = data->local.port; // Make subscription if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { @@ -2318,18 +2320,19 @@ void MidiOutAlsa :: closePort( void ) void MidiOutAlsa :: openVirtualPort( std::string portName ) { AlsaMidiData *data = static_cast (apiData_); - if ( data->vport < 0 ) { - data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(), - SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, - SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); + if ( data->local.port < 0 ) { + data->local.port = snd_seq_create_simple_port( data->seq, portName.c_str(), + SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, + SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); - if ( data->vport < 0 ) { + if ( data->local.port < 0 ) { errorString_ = "MidiOutAlsa::openVirtualPort: ALSA error creating virtual port."; error( Error::DRIVER_ERROR, errorString_ ); } } } + void MidiOutAlsa :: sendMessage( std::vector &message ) { int result; @@ -2354,7 +2357,7 @@ void MidiOutAlsa :: sendMessage( std::vector &message ) snd_seq_event_t ev; snd_seq_ev_clear(&ev); - snd_seq_ev_set_source(&ev, data->vport); + snd_seq_ev_set_source(&ev, data->local.port); snd_seq_ev_set_subs(&ev); snd_seq_ev_set_direct(&ev); for ( unsigned int i=0; ibuffer[i] = message.at(i); From 6bbeebc07d1825bf7c4fa6e64371696ff06c0a89 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 8 Aug 2018 10:18:42 +0200 Subject: [PATCH 015/210] Provide the implementation part of the prvious patch. The ALSA output devices should be still considered broken. # Conflicts: # RtMidi.cpp --- RtMidi.cpp | 897 ++++++++++++------------ RtMidi.h | 1982 +++++++++++++++++++++++++++------------------------- 2 files changed, 1474 insertions(+), 1405 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index f6cd9411..595a86b1 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1134,452 +1134,451 @@ NAMSPACE_RTMIDI_END #include NAMSPACE_RTMIDI_START - struct AlsaMidiData; - - /*! An abstraction layer for the ALSA sequencer layer. It provides - the following functionality: - - dynamic allocation of the sequencer - - optionallay avoid concurrent access to the ALSA sequencer, - which is not thread proof. This feature is controlled by - the parameter \ref locking. - */ - - template - class AlsaSequencer { - public: - AlsaSequencer():seq(0) - { - if (locking) { - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); - pthread_mutex_init(&mutex, &attr); - } - } - - AlsaSequencer(const std::string & name):seq(0) - { - if (locking) { - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); - pthread_mutex_init(&mutex, &attr); - } - init(); - { - scoped_lock lock(mutex); - snd_seq_set_client_name( seq, name.c_str() ); - } - } - - ~AlsaSequencer() - { - if (locking) { - pthread_mutex_destroy(&mutex); - } - } - - std::string GetPortName(int client, int port, int flags) { - init(); - snd_seq_client_info_t *cinfo; - snd_seq_client_info_alloca( &cinfo ); - { - scoped_lock lock (mutex); - snd_seq_get_any_client_info(seq,client,cinfo); - } - - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); - { - scoped_lock lock (mutex); - snd_seq_get_any_port_info(seq,client,port,pinfo); - } - - int naming = flags & PortDescriptor::NAMING_MASK; - - std::ostringstream os; - switch (naming) { - case PortDescriptor::SESSION_PATH: - if (flags & PortDescriptor::INCLUDE_API) - os << "ALSA:"; - os << client << ":" << port; - break; - case PortDescriptor::STORAGE_PATH: - if (flags & PortDescriptor::INCLUDE_API) - os << "ALSA:"; - os << snd_seq_client_info_get_name(cinfo); - os << ":"; - os << snd_seq_port_info_get_name(pinfo); - if (flags & PortDescriptor::UNIQUE_NAME) - os << ";" << client << ":" << port; - break; - case PortDescriptor::LONG_NAME: - os << snd_seq_client_info_get_name( cinfo ); - if (flags & PortDescriptor::UNIQUE_NAME) { - os << " " << client; - } - os << ":"; - if (flags & PortDescriptor::UNIQUE_NAME) { - os << port; - } - - os << " " << snd_seq_port_info_get_name(pinfo); - if (flags & PortDescriptor::INCLUDE_API) - os << " (ALSA)"; - break; - case PortDescriptor::SHORT_NAME: - default: - os << snd_seq_client_info_get_name( cinfo ); - if (flags & PortDescriptor::UNIQUE_NAME) { - os << " "; - os << client; - } - os << ":" << port; - if (flags & PortDescriptor::INCLUDE_API) - os << " (ALSA)"; - - break; - } - return os.str(); - } - - int getPortCapabilities(int client, int port) { - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); - { - scoped_lock lock (mutex); - snd_seq_get_any_port_info(seq,client,port,pinfo); - } - unsigned int caps = snd_seq_port_info_get_capability(pinfo); - int retval = (caps & (SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ))? - PortDescriptor::INPUT:0; - if (caps & (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) - retval |= PortDescriptor::OUTPUT; - return retval; - } - - int getNextClient(snd_seq_client_info_t * cinfo ) { - init(); - scoped_lock lock (mutex); - return snd_seq_query_next_client (seq, cinfo); - } - int getNextPort(snd_seq_port_info_t * pinfo ) { - init(); - scoped_lock lock (mutex); - return snd_seq_query_next_port (seq, pinfo); - } - - int createPort (snd_seq_port_info_t *pinfo) { - init(); - scoped_lock lock (mutex); - return snd_seq_create_port(seq, pinfo); - } - - void deletePort(int port) { - init(); - scoped_lock lock (mutex); - snd_seq_delete_port( seq, port ); - } - - snd_seq_port_subscribe_t * connectPorts(const snd_seq_addr_t & from, - const snd_seq_addr_t & to) { - init(); - snd_seq_port_subscribe_t *subscription; - - if (snd_seq_port_subscribe_malloc( &subscription ) < 0) { - throw Error("MidiInAlsa::openPort: ALSA error allocation port subscription.", - Error::DRIVER_ERROR ); - return 0; - } - snd_seq_port_subscribe_set_sender(subscription, &from); - snd_seq_port_subscribe_set_dest(subscription, &to); - { - scoped_lock lock (mutex); - if ( snd_seq_subscribe_port(seq, subscription) ) { - snd_seq_port_subscribe_free( subscription ); - subscription = 0; - throw Error("MidiInAlsa::openPort: ALSA error making port connection.", - Error::DRIVER_ERROR); - return 0; - } - return subscription; - } - } - - void closePort(snd_seq_port_subscribe_t * subscription ) { - init(); - scoped_lock lock(mutex); - snd_seq_unsubscribe_port( seq, subscription ); - } - - void startQueue(int queue_id) { - init(); - scoped_lock lock(mutex); - snd_seq_start_queue( seq, queue_id, NULL ); - snd_seq_drain_output( seq ); - } - - /*! Use AlsaSequencer like a C pointer. - \note This function breaks the design to control thread safety - by the selection of the \ref locking parameter to the class. - It should be removed as soon as possible in order ensure the - thread policy that has been intended by creating this class. - */ - operator snd_seq_t * () - { - return seq; - } - protected: - struct scoped_lock { - pthread_mutex_t * mutex; - scoped_lock(pthread_mutex_t & m): mutex(&m) - { - if (locking) - pthread_mutex_lock(mutex); - } - ~scoped_lock() - { - if (locking) - pthread_mutex_unlock(mutex); - } - }; - pthread_mutex_t mutex; - snd_seq_t * seq; - - - snd_seq_client_info_t * GetClient(int id) { - init(); - snd_seq_client_info_t * cinfo; - scoped_lock lock(mutex); - snd_seq_get_any_client_info(seq,id,cinfo); - return cinfo; - } - - void init() - { - init (seq); - } - - void init(snd_seq_t * &s) - { - if (s) return; - { - scoped_lock lock(mutex); - int result = snd_seq_open(&s, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); - if ( result < 0 ) { - throw Error( "MidiInAlsa::initialize: error creating ALSA sequencer client object.", - Error::DRIVER_ERROR ); - return; - } - } - } - }; - typedef AlsaSequencer<1> LockingAlsaSequencer; - typedef AlsaSequencer<0> NonLockingAlsaSequencer; - - struct AlsaPortDescriptor:public PortDescriptor, - public snd_seq_addr_t - { - MidiApi * api; - static LockingAlsaSequencer seq; - AlsaPortDescriptor():api(0) - { - client = 0; - port = 0; - } - AlsaPortDescriptor(int c, int p):api(0) - { - client = c; - port = p; - } - ~AlsaPortDescriptor() {} - MidiApi * getAPI() { - return NULL; - } - std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) { - return seq.GetPortName(client,port,flags); - } - int getCapabilities() { - return seq.getPortCapabilities(client,port); - } - static PortList getPortList(int capabilities); - }; - - LockingAlsaSequencer AlsaPortDescriptor::seq; - - - - PortList AlsaPortDescriptor :: getPortList(int capabilities) - { - PortList list; - snd_seq_client_info_t *cinfo; - snd_seq_port_info_t *pinfo; - int client; - snd_seq_client_info_alloca( &cinfo ); - snd_seq_port_info_alloca( &pinfo ); - - snd_seq_client_info_set_client( cinfo, -1 ); - while ( seq.getNextClient(cinfo ) >= 0 ) { - client = snd_seq_client_info_get_client( cinfo ); - // ignore default device (it is included in the following results again) - if ( client == 0 ) continue; - // Reset query info - snd_seq_port_info_set_client( pinfo, client ); - snd_seq_port_info_set_port( pinfo, -1 ); - while ( seq.getNextPort( pinfo ) >= 0 ) { - unsigned int atyp = snd_seq_port_info_get_type( pinfo ); - // otherwise we get ports without any - if ( !(capabilities & UNLIMITED) && - !( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) ) continue; - unsigned int caps = snd_seq_port_info_get_capability( pinfo ); - if (capabilities & INPUT) { - /* we need both READ and SUBS_READ */ - if ((caps & (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) - != (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) - continue; - } - if (capabilities & OUTPUT) { - /* we need both WRITE and SUBS_WRITE */ - if ((caps & (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) - != (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) - continue; - } - list.push_back(new AlsaPortDescriptor(client,snd_seq_port_info_get_port(pinfo))); - } - } - return list; - } +struct AlsaMidiData; + +/*! An abstraction layer for the ALSA sequencer layer. It provides + the following functionality: + - dynamic allocation of the sequencer + - optionallay avoid concurrent access to the ALSA sequencer, + which is not thread proof. This feature is controlled by + the parameter \ref locking. +*/ + +template +class AlsaSequencer { +public: + AlsaSequencer():seq(0) + { + if (locking) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); + } + } + + AlsaSequencer(const std::string & name):seq(0) + { + if (locking) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); + } + init(); + { + scoped_lock lock(mutex); + snd_seq_set_client_name( seq, name.c_str() ); + } + } + + ~AlsaSequencer() + { + if (locking) { + pthread_mutex_destroy(&mutex); + } + } + + std::string GetPortName(int client, int port, int flags) { + init(); + snd_seq_client_info_t *cinfo; + snd_seq_client_info_alloca( &cinfo ); + { + scoped_lock lock (mutex); + snd_seq_get_any_client_info(seq,client,cinfo); + } + + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + { + scoped_lock lock (mutex); + snd_seq_get_any_port_info(seq,client,port,pinfo); + } - static void *alsaMidiHandler( void *ptr ); - - - /*! A structure to hold variables related to the ALSA API - implementation. - - \note After all sequencer handling is covered by the \ref - AlsaSequencer class, we should make seq to be a pointer in order - to allow a common client implementation. - */ - - struct AlsaMidiData:public AlsaPortDescriptor { - AlsaMidiData():seq() { - init(); - } - AlsaMidiData(const std::string &clientName):seq(clientName) { - init(); - } - ~AlsaMidiData() { - if (local.client) - deletePort(); - } - void init () { - local.port = 0; - local.client = 0; - port = -1; - subscription = 0; - coder = 0; - bufferSize = 32; - buffer = 0; - dummy_thread_id = pthread_self(); - thread = dummy_thread_id; - trigger_fds[0] = -1; - trigger_fds[1] = -1; - } - snd_seq_addr_t local; /*!< Our port and client id. If client = 0 (default) this means we didn't aquire a port so far. */ - NonLockingAlsaSequencer seq; - // unsigned int portNum; - snd_seq_port_subscribe_t *subscription; - snd_midi_event_t *coder; - unsigned int bufferSize; - unsigned char *buffer; - pthread_t thread; - pthread_t dummy_thread_id; - unsigned long long lastTime; - int queue_id; // an input queue is needed to get timestamped events - int trigger_fds[2]; - - void setRemote(const AlsaPortDescriptor * remote) { - port = remote->port; - client = remote->client; - } - void connectPorts(const snd_seq_addr_t &from, - const snd_seq_addr_t &to) { - subscription = seq.connectPorts(from, to); - } - - int openPort(int alsaCapabilities, - const std::string & portName) { - if (subscription) { - api->error( Error::DRIVER_ERROR, - "MidiInAlsa::openPort: ALSA error allocation port subscription." ); - return -99; - } - - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); - - snd_seq_port_info_set_client( pinfo, 0 ); - snd_seq_port_info_set_port( pinfo, 0 ); - snd_seq_port_info_set_capability( pinfo, - alsaCapabilities); - snd_seq_port_info_set_type( pinfo, - SND_SEQ_PORT_TYPE_MIDI_GENERIC | - SND_SEQ_PORT_TYPE_APPLICATION ); - snd_seq_port_info_set_midi_channels(pinfo, 16); + int naming = flags & PortDescriptor::NAMING_MASK; + + std::ostringstream os; + switch (naming) { + case PortDescriptor::SESSION_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "ALSA:"; + os << client << ":" << port; + break; + case PortDescriptor::STORAGE_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "ALSA:"; + os << snd_seq_client_info_get_name(cinfo); + os << ":"; + os << snd_seq_port_info_get_name(pinfo); + if (flags & PortDescriptor::UNIQUE_NAME) + os << ";" << client << ":" << port; + break; + case PortDescriptor::LONG_NAME: + os << snd_seq_client_info_get_name( cinfo ); + if (flags & PortDescriptor::UNIQUE_NAME) { + os << " " << client; + } + os << ":"; + if (flags & PortDescriptor::UNIQUE_NAME) { + os << port; + } + + os << " " << snd_seq_port_info_get_name(pinfo); + if (flags & PortDescriptor::INCLUDE_API) + os << " (ALSA)"; + break; + case PortDescriptor::SHORT_NAME: + default: + os << snd_seq_client_info_get_name( cinfo ); + if (flags & PortDescriptor::UNIQUE_NAME) { + os << " "; + os << client; + } + os << ":" << port; + if (flags & PortDescriptor::INCLUDE_API) + os << " (ALSA)"; + + break; + } + return os.str(); + } + + int getPortCapabilities(int client, int port) { + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + { + scoped_lock lock (mutex); + snd_seq_get_any_port_info(seq,client,port,pinfo); + } + unsigned int caps = snd_seq_port_info_get_capability(pinfo); + int retval = (caps & (SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ))? + PortDescriptor::INPUT:0; + if (caps & (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) + retval |= PortDescriptor::OUTPUT; + return retval; + } + + int getNextClient(snd_seq_client_info_t * cinfo ) { + init(); + scoped_lock lock (mutex); + return snd_seq_query_next_client (seq, cinfo); + } + int getNextPort(snd_seq_port_info_t * pinfo ) { + init(); + scoped_lock lock (mutex); + return snd_seq_query_next_port (seq, pinfo); + } + + int createPort (snd_seq_port_info_t *pinfo) { + init(); + scoped_lock lock (mutex); + return snd_seq_create_port(seq, pinfo); + } + + void deletePort(int port) { + init(); + scoped_lock lock (mutex); + snd_seq_delete_port( seq, port ); + } + + snd_seq_port_subscribe_t * connectPorts(const snd_seq_addr_t & from, + const snd_seq_addr_t & to) { + init(); + snd_seq_port_subscribe_t *subscription; + + if (snd_seq_port_subscribe_malloc( &subscription ) < 0) { + throw Error("MidiInAlsa::openPort: ALSA error allocation port subscription.", + Error::DRIVER_ERROR ); + return 0; + } + snd_seq_port_subscribe_set_sender(subscription, &from); + snd_seq_port_subscribe_set_dest(subscription, &to); + { + scoped_lock lock (mutex); + if ( snd_seq_subscribe_port(seq, subscription) ) { + snd_seq_port_subscribe_free( subscription ); + subscription = 0; + throw Error("MidiInAlsa::openPort: ALSA error making port connection.", + Error::DRIVER_ERROR); + return 0; + } + return subscription; + } + } + + void closePort(snd_seq_port_subscribe_t * subscription ) { + init(); + scoped_lock lock(mutex); + snd_seq_unsubscribe_port( seq, subscription ); + } + + void startQueue(int queue_id) { + init(); + scoped_lock lock(mutex); + snd_seq_start_queue( seq, queue_id, NULL ); + snd_seq_drain_output( seq ); + } + + /*! Use AlsaSequencer like a C pointer. + \note This function breaks the design to control thread safety + by the selection of the \ref locking parameter to the class. + It should be removed as soon as possible in order ensure the + thread policy that has been intended by creating this class. + */ + operator snd_seq_t * () + { + return seq; + } +protected: + struct scoped_lock { + pthread_mutex_t * mutex; + scoped_lock(pthread_mutex_t & m): mutex(&m) + { + if (locking) + pthread_mutex_lock(mutex); + } + ~scoped_lock() + { + if (locking) + pthread_mutex_unlock(mutex); + } + }; + pthread_mutex_t mutex; + snd_seq_t * seq; + + + snd_seq_client_info_t * GetClient(int id) { + init(); + snd_seq_client_info_t * cinfo; + scoped_lock lock(mutex); + snd_seq_get_any_client_info(seq,id,cinfo); + return cinfo; + } + + void init() + { + init (seq); + } + + void init(snd_seq_t * &s) + { + if (s) return; + { + scoped_lock lock(mutex); + int result = snd_seq_open(&s, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); + if ( result < 0 ) { + throw Error( "MidiInAlsa::initialize: error creating ALSA sequencer client object.", + Error::DRIVER_ERROR ); + return; + } + } + } +}; +typedef AlsaSequencer<1> LockingAlsaSequencer; +typedef AlsaSequencer<0> NonLockingAlsaSequencer; + +struct AlsaPortDescriptor:public PortDescriptor, + public snd_seq_addr_t +{ + MidiApi * api; + static LockingAlsaSequencer seq; + AlsaPortDescriptor():api(0) + { + client = 0; + port = 0; + } + AlsaPortDescriptor(int c, int p):api(0) + { + client = c; + port = p; + } + ~AlsaPortDescriptor() {} + MidiApi * getAPI() { + return NULL; + } + std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) { + return seq.GetPortName(client,port,flags); + } + int getCapabilities() { + return seq.getPortCapabilities(client,port); + } + static PortList getPortList(int capabilities); +}; + +LockingAlsaSequencer AlsaPortDescriptor::seq; + + + +PortList AlsaPortDescriptor :: getPortList(int capabilities) +{ + PortList list; + snd_seq_client_info_t *cinfo; + snd_seq_port_info_t *pinfo; + int client; + snd_seq_client_info_alloca( &cinfo ); + snd_seq_port_info_alloca( &pinfo ); + + snd_seq_client_info_set_client( cinfo, -1 ); + while ( seq.getNextClient(cinfo ) >= 0 ) { + client = snd_seq_client_info_get_client( cinfo ); + // ignore default device (it is included in the following results again) + if ( client == 0 ) continue; + // Reset query info + snd_seq_port_info_set_client( pinfo, client ); + snd_seq_port_info_set_port( pinfo, -1 ); + while ( seq.getNextPort( pinfo ) >= 0 ) { + unsigned int atyp = snd_seq_port_info_get_type( pinfo ); + // otherwise we get ports without any + if ( !(capabilities & UNLIMITED) && + !( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) ) continue; + unsigned int caps = snd_seq_port_info_get_capability( pinfo ); + if (capabilities & INPUT) { + /* we need both READ and SUBS_READ */ + if ((caps & (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) + != (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) + continue; + } + if (capabilities & OUTPUT) { + /* we need both WRITE and SUBS_WRITE */ + if ((caps & (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) + != (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) + continue; + } + list.push_back(new AlsaPortDescriptor(client,snd_seq_port_info_get_port(pinfo))); + } + } + return list; +} + +static void *alsaMidiHandler( void *ptr ); + + +/*! A structure to hold variables related to the ALSA API + implementation. + + \note After all sequencer handling is covered by the \ref + AlsaSequencer class, we should make seq to be a pointer in order + to allow a common client implementation. +*/ + +struct AlsaMidiData:public AlsaPortDescriptor { + AlsaMidiData():seq() { + init(); + } + AlsaMidiData(const std::string &clientName):seq(clientName) { + init(); + } + ~AlsaMidiData() { + if (local.client) + deletePort(); + } + void init () { + local.port = 0; + local.client = 0; + port = -1; + subscription = 0; + coder = 0; + bufferSize = 32; + buffer = 0; + dummy_thread_id = pthread_self(); + thread = dummy_thread_id; + trigger_fds[0] = -1; + trigger_fds[1] = -1; + } + snd_seq_addr_t local; /*!< Our port and client id. If client = 0 (default) this means we didn't aquire a port so far. */ + NonLockingAlsaSequencer seq; + // unsigned int portNum; + snd_seq_port_subscribe_t *subscription; + snd_midi_event_t *coder; + unsigned int bufferSize; + unsigned char *buffer; + pthread_t thread; + pthread_t dummy_thread_id; + unsigned long long lastTime; + int queue_id; // an input queue is needed to get timestamped events + int trigger_fds[2]; + + void setRemote(const AlsaPortDescriptor * remote) { + port = remote->port; + client = remote->client; + } + void connectPorts(const snd_seq_addr_t &from, + const snd_seq_addr_t &to) { + subscription = seq.connectPorts(from, to); + } + + int openPort(int alsaCapabilities, + const std::string & portName) { + if (subscription) { + api->error( Error::DRIVER_ERROR, + "MidiInAlsa::openPort: ALSA error allocation port subscription." ); + return -99; + } + + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + + snd_seq_port_info_set_client( pinfo, 0 ); + snd_seq_port_info_set_port( pinfo, 0 ); + snd_seq_port_info_set_capability( pinfo, + alsaCapabilities); + snd_seq_port_info_set_type( pinfo, + SND_SEQ_PORT_TYPE_MIDI_GENERIC | + SND_SEQ_PORT_TYPE_APPLICATION ); + snd_seq_port_info_set_midi_channels(pinfo, 16); #ifndef AVOID_TIMESTAMPING - snd_seq_port_info_set_timestamping(pinfo, 1); - snd_seq_port_info_set_timestamp_real(pinfo, 1); - snd_seq_port_info_set_timestamp_queue(pinfo, queue_id); + snd_seq_port_info_set_timestamping(pinfo, 1); + snd_seq_port_info_set_timestamp_real(pinfo, 1); + snd_seq_port_info_set_timestamp_queue(pinfo, queue_id); #endif - snd_seq_port_info_set_name(pinfo, portName.c_str() ); - int createok = seq.createPort(pinfo); - - if ( createok < 0 ) { - api->error( Error::DRIVER_ERROR, - "MidiInAlsa::openPort: ALSA error creating input port." ); - return createok; - } - - local.client = snd_seq_port_info_get_client( pinfo ); - local.port = snd_seq_port_info_get_port(pinfo); - return 0; - } - - void deletePort() { - seq.deletePort(local.port); - local.client = 0; - local.port = 0; - } - - void closePort() { - seq.closePort(subscription ); - snd_seq_port_subscribe_free( subscription ); - subscription = 0; - } - - bool startQueue(void * userdata) { - // Start the input queue + snd_seq_port_info_set_name(pinfo, portName.c_str() ); + int createok = seq.createPort(pinfo); + + if ( createok < 0 ) { + api->error( Error::DRIVER_ERROR, + "MidiInAlsa::openPort: ALSA error creating input port." ); + return createok; + } + + local.client = snd_seq_port_info_get_client( pinfo ); + local.port = snd_seq_port_info_get_port(pinfo); + return 0; + } + + void deletePort() { + seq.deletePort(local.port); + local.client = 0; + local.port = 0; + } + + void closePort() { + seq.closePort(subscription ); + snd_seq_port_subscribe_free( subscription ); + subscription = 0; + } + + bool startQueue(void * userdata) { + // Start the input queue #ifndef AVOID_TIMESTAMPING - seq.startQueue(queue_id); + seq.startQueue(queue_id); #endif - // Start our MIDI input thread. - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - pthread_attr_setschedpolicy(&attr, SCHED_OTHER); - - int err = pthread_create(&thread, &attr, alsaMidiHandler, userdata); - pthread_attr_destroy(&attr); - if ( err ) { - closePort(); - api->error( Error::THREAD_ERROR, - "MidiInAlsa::openPort: error starting MIDI input thread!" ); - return false; - } - return true; - } - }; + // Start our MIDI input thread. + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + pthread_attr_setschedpolicy(&attr, SCHED_OTHER); + int err = pthread_create(&thread, &attr, alsaMidiHandler, userdata); + pthread_attr_destroy(&attr); + if ( err ) { + closePort(); + api->error( Error::THREAD_ERROR, + "MidiInAlsa::openPort: error starting MIDI input thread!" ); + return false; + } + return true; + } +}; #define PORT_TYPE( pinfo, bits ) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits)) @@ -1844,7 +1843,7 @@ void MidiInAlsa :: initialize( const std::string& clientName ) // Create the input queue #ifndef AVOID_TIMESTAMPING - data->queue_id = snd_seq_alloc_named_queue(seq, "Midi Queue"); + data->queue_id = snd_seq_alloc_named_queue(data->seq, "Midi Queue"); // Set arbitrary tempo (mm=100) and resolution (240) snd_seq_queue_tempo_t *qtempo; snd_seq_queue_tempo_alloca(&qtempo); @@ -1922,7 +1921,7 @@ std::string MidiInAlsa :: getPortName( unsigned int portNumber ) return stringName; } -void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName ) +void MidiInAlsa :: openPort( unsigned int portNumber, const std::string & portName ) { if ( connected_ ) { errorString_ = "MidiInAlsa::openPort: a valid connection already exists!"; @@ -1964,7 +1963,6 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION ); snd_seq_port_info_set_midi_channels(pinfo, 16); - #ifndef AVOID_TIMESTAMPING snd_seq_port_info_set_timestamping(pinfo, 1); snd_seq_port_info_set_timestamp_real(pinfo, 1); @@ -2004,7 +2002,6 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName if ( inputData_.doInput == false ) { // Start the input queue - #ifndef AVOID_TIMESTAMPING snd_seq_start_queue( data->seq, data->queue_id, NULL ); snd_seq_drain_output( data->seq ); @@ -2033,7 +2030,7 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName } void MidiInAlsa :: openPort( const PortDescriptor & port, - const std::string portName = std::string( "RtMidi" ) ) + const std::string & portName) { abort(); } @@ -2128,7 +2125,6 @@ void MidiInAlsa :: closePort( void ) snd_seq_stop_queue( data->seq, data->queue_id, NULL ); snd_seq_drain_output( data->seq ); #endif - connected_ = false; } @@ -2242,7 +2238,7 @@ std::string MidiOutAlsa :: getPortName( unsigned int portNumber ) return stringName; } -void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string portName ) +void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string & portName ) { if ( connected_ ) { errorString_ = "MidiOutAlsa::openPort: a valid connection already exists!"; @@ -2275,8 +2271,8 @@ void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string portNam if ( data->local.port < 0 ) { data->local.port = snd_seq_create_simple_port( data->seq, portName.c_str(), - SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, - SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); + SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, + SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); if ( data->local.port < 0 ) { errorString_ = "MidiOutAlsa::openPort: ALSA error creating output port."; error( Error::DRIVER_ERROR, errorString_ ); @@ -2284,6 +2280,7 @@ void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string portNam } } + sender.port = data->local.port; // Make subscription @@ -2379,7 +2376,7 @@ void MidiOutAlsa :: sendMessage( std::vector &message ) } void MidiOutAlsa :: openPort( const PortDescriptor & port, - const std::string portName) + const std::string & portName) { abort(); } diff --git a/RtMidi.h b/RtMidi.h index 21e3f5f5..2befb2d8 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -60,6 +60,7 @@ #include #include #include +#include #define NAMESPACE_RTMIDI_START namespace rtmidi { #define NAMESPACE_RTMIDI_END } @@ -150,763 +151,834 @@ typedef void (*ErrorCallback)( Error::Type type, const std::string &errorText ); #if __cplusplus < 201103L -class PortDescriptor; - -template -class Pointer { -public: - typedef T datatype; -protected: - struct countPointer { - int count; - datatype * descriptor; - }; -public: - Pointer(datatype * p):ptr(new countPointer) { - ptr->count = 1; - ptr->descriptor = p; - } - Pointer(const Pointer & other): - ptr(other.ptr) { - ptr->count++; - } - - ~Pointer() { - if (!ptr) return; - if (!ptr->descriptor) { - delete ptr; - return; - } - if (!(--ptr->count)) { - delete ptr->descriptor; - delete ptr; - } - } - - datatype * operator -> () { - if (!ptr) return 0; - // this should throw an exception - - return ptr->descriptor; - } -protected: - countPointer * ptr; -}; + class PortDescriptor; + + template + class Pointer { + public: + typedef T datatype; + protected: + struct countPointer { + int count; + datatype * descriptor; + }; + public: + Pointer():ptr(0) {} + Pointer(datatype * p):ptr(new countPointer) { + ptr->count = 1; + ptr->descriptor = p; + } + Pointer(const Pointer & other): + ptr(other.ptr) { + if (ptr) + ptr->count++; + } + + ~Pointer() { + if (!ptr) return; + if (!ptr->descriptor) { + delete ptr; + return; + } + if (!(--ptr->count)) { + delete ptr->descriptor; + delete ptr; + } + } + + datatype * operator -> () { + if (!ptr) return 0; + // this should throw an exception + + return ptr->descriptor; + } + + datatype & operator * () { + if (!ptr || !ptr->descriptor) { + throw std::invalid_argument("rtmidi::Pointer: trying to dereference a NULL pointer."); + } + else return (*ptr->descriptor); + } + + bool operator ! () { + return (!ptr || !ptr->descriptor); + } + + Pointer & operator = (const Pointer & other) { + if (ptr) { + if (!(--ptr->count)) { + delete ptr->descriptor; + delete ptr; + } + } + ptr = other.ptr; + ptr->count++; + return *this; + } + protected: + countPointer * ptr; + }; #else -template -typedef shared_ptr Pointer; + template + typedef std::shared_ptr Pointer; #endif -class MidiApi; - -struct PortDescriptor { - //! Flags for formatting a string description of the port. - /*! These flags just mark the requirements that the string - should fulfil. An API may return the same string for - different requirements e.g. the same short and long - name. */ - enum NamingType { - SHORT_NAME =0, /*!< A short human readable name - depending on the API - e.g. “Ensoniq AudioPCI” */ - LONG_NAME, /*!< A complete human readable - name depending on the API - e.g. "Ensoniq AudioPCI: ES1371" */ - SESSION_PATH, /*!< A unique description that can - be used to identify the port - during runtime. It may be a - cryptic string. */ - STORAGE_PATH, /*!< A unique description that is - optimised for storage in - configuration files. This is a - more textual representation that - is more robust to small changes in - the surrounding environment than - \ref SESSION_PATH */ - UNIQUE_NAME = 0x10, /*!< Make all names uniqe. This - is usually done by adding - numbers to the end of the - string */ - INCLUDE_API = 0x20 /*!< Add a string describing the - API at the beginning of the - string. */ - }; - - //! Flags describing the capabilities of a given port. - enum PortCapabilities { - INPUT = 1, /*!< Ports that can be read from. */ - OUTPUT = 2, /*!< Ports that can be written to. */ - INOUTPUT = 3 /*!< Ports that allow reading and writing (INPUT | OUTPUT) */ - }; - - //! Default constructor. - /*! - * Derived classes should have a constructor. - */ - PortDescriptor() {}; - - //! A virtual destructor - /*! As we might have to destruct the object from the application code - * each port id must have a virtual destructor. - */ - virtual ~PortDescriptor() = 0; - - //! Get the MIDI api for the current port. - /*! This is the only information RtMidi needs to know: Which - * API should handle this object. - * - * \return API that can handle this object. - */ - virtual MidiApi * getAPI() = 0; - - //! Return the port name - /*! - * \param flags A description of the requirements of the returned name. - * \return A name that is formatted according to \ref flags. - * \sa NamingTypes - */ - virtual std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) = 0; - - //! Get capabilities - /*! \return a capabilities flag describing the capabilities of the port. - * \sa PortCapabilities - */ - virtual int getCapabilities(); -}; - -//! A list of port descriptors. -/*! Port descriptors are stored as shared pointers. This avoids - unnecessary duplication of the data structure and handles automatic - deletion if all references have been removed. */ -typedef std::list > PortList; - - - -// **************************************************************** // -// -// MidiInApi / MidiOutApi class declarations. -// -// Subclasses of MidiInApi and MidiOutApi contain all API- and -// OS-specific code necessary to fully implement the RtMidi API. -// -// Note that MidiInApi and MidiOutApi are abstract base classes and -// cannot be explicitly instantiated. MidiIn and MidiOut will -// create instances of a MidiInApi or MidiOutApi subclass. -// -// **************************************************************** // - -class MidiApi -{ -public: - - MidiApi(); - virtual ~MidiApi(); - - //! Pure virtal function to create a virtual port, with optional name. - /*! - This function creates a virtual MIDI port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, any JACK, - and Linux ALSA APIs (the function returns an error for the other APIs). - - \param portName An optional name for the applicaction port that is - used to connect to portId can be specified. - */ - virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0; - - //! Pure virtual function to open a MIDI connection given by enumeration number. - /*! \param portNumber An optional port number greater than 0 - can be specified. Otherwise, the default or first port - found is opened. - - \param portName An optional name for the applicaction port - that will be generated to connect to portId can be - specified. - */ - virtual void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi" ) ) = 0; - - //! Pure virtual function to open a MIDI connection given by a port descriptor. - /*! - \param port A port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - */ - virtual void openPort( const PortDescriptor & port, const std::string portName = std::string( "RtMidi" ) ) = 0; - - //! Pure virtual function to return a port descirptor if the port is open - virtual Pointer getDescriptor() = 0; - - //! Pure virtual function to return a list of all available ports of the current API. - /*! - \param capabilities an optional parameter that describes which - device types are returned. - - \return This function returns a list of port descriptors. - - \note An input API may but need not necessarily report - output devices which cannot be used as input if - \ref PortDescriptor::OUTPUT is passed as \ref capabilities parameter. - */ - virtual PortList getPortList(int capabilities = PortDescriptor:: INOUTPUT) = 0; - - //! Pure virtual to return the number of available MIDI ports of the current API. - /*! - \return This function returns the number of MIDI ports of - the selected API. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortName - */ - virtual unsigned int getPortCount() = 0; - - //! Pure virtual function to return a string identifier for the specified MIDI port number. - /*! - \param portNumber Number of the device to be referred to. - \return The name of the port with the given Id is returned. - \retval An empty string is returned if an invalid port specifier is provided. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortCount() - */ - virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; - - //! Pure virtual function to close an open MIDI connection (if one exists). - virtual void closePort( void ) = 0; - - // ! A basic error reporting function for RtMidi classes. - // static void error( Error::Type type, std::string &errorString ); - - //! Pure virtual function to return whether a port is open or not. - /*! \retval true if a port is open and - \retval false if the port is not open (e.g. not opend or closed). - */ - bool isPortOpen() const { return connected_; } - - //! Pure virtual function to set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. - */ - virtual void setErrorCallback( ErrorCallback errorCallback = NULL ); - - - //! Returns the MIDI API specifier for the current instance of RtMidiIn. - virtual ApiType getCurrentApi( void ) throw() = 0; - - //! A basic error reporting function for RtMidi classes. - void error( Error::Type type, std::string errorString ); - -protected: - virtual void initialize( const std::string& clientName ) = 0; - - void *apiData_; - bool connected_; - std::string errorString_; - ErrorCallback errorCallback_; -}; - -class MidiInApi : public MidiApi -{ -public: - - MidiInApi( unsigned int queueSizeLimit ); - virtual ~MidiInApi( void ); - void setCallback( MidiCallback callback, void *userData ); - void cancelCallback( void ); - virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); - RTMIDI_DEPRECATED(double getMessage( std::vector *message )) - { - if (!message) { - errorString_ = "MidiInApi::getMessage: passed NULL pointer"; - error( Error::WARNING, errorString_ ); - } - return getMessage(*message); - } - double getMessage( std::vector &message ); - - // A MIDI structure used internally by the class to store incoming - // messages. Each message represents one and only one MIDI message. - struct MidiMessage { - std::vector bytes; - double timeStamp; - - // Default constructor. - MidiMessage() - :bytes(0), timeStamp(0.0) {} - }; - - struct MidiQueue { - unsigned int front; - unsigned int back; - unsigned int size; - unsigned int ringSize; - MidiMessage *ring; - - // Default constructor. - MidiQueue() - :front(0), back(0), size(0), ringSize(0) {} - }; - - // The RtMidiInData structure is used to pass private class data to - // the MIDI input handling function or thread. - struct MidiInData { - MidiQueue queue; - MidiMessage message; - unsigned char ignoreFlags; - bool doInput; - bool firstMessage; - void *apiData; - bool usingCallback; - MidiCallback userCallback; - void *userData; - bool continueSysex; - - // Default constructor. - MidiInData() - : ignoreFlags(7), doInput(false), firstMessage(true), - apiData(0), usingCallback(false), userCallback(0), userData(0), - continueSysex(false) {} - }; - -protected: - MidiInData inputData_; -}; - -class MidiOutApi : public MidiApi -{ -public: - - MidiOutApi( void ); - virtual ~MidiOutApi( void ); - RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) - { - if (!message) { - errorString_ = "MidiOutApi::sendMessage: no data in message argument!"; - error( Error::WARNING, errorString_ ); - } - sendMessage(*message); - } - virtual void sendMessage( std::vector &message ) = 0; -}; - - -/*! \class Midi - \brief A global class that implements basic backend API handling. - - This class enhances \ref MidiApi by some functionality to handle - backend API objects. It serves as base class for the public RtMidi - API. - - by Gary P. Scavone, 2003-2014. -*/ -/**********************************************************************/ -class Midi { -public: - typedef rtmidi::ApiType Api; - //! defined for compatibility - enum Api2 { - UNSPECIFIED = rtmidi::UNSPECIFIED, - MACOSX_CORE = rtmidi::MACOSX_CORE, - LINUX_ALSA = rtmidi::LINUX_ALSA, - UNIX_JACK = rtmidi::UNIX_JACK, - WINDOWS_MM = rtmidi::WINDOWS_MM, - WINDOWS_KS = rtmidi::WINDOWS_KS, - RTMIDI_DUMMY = rtmidi::RTMIDI_DUMMY - }; - - - //! A static function to determine the current RtMidi version. - static std::string getVersion( void ) throw(); - - //! A static function to determine the available compiled MIDI APIs. - /*! - The values returned in the std::vector can be compared against - the enumerated list values. Note that there can be more than one - API compiled for certain operating systems. - */ - static void getCompiledApi( std::vector &apis ) throw(); - - //! Returns the MIDI API specifier for the current instance of RtMidiIn. - ApiType getCurrentApi( void ) throw() - { - if (rtapi_) return rtapi_->getCurrentApi(); - else return rtmidi::UNSPECIFIED; - } - - //! Function to create a virtual port, with optional name. - /*! - This function creates a virtual MIDI port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, any JACK, - and Linux ALSA APIs (the function returns an error for the other APIs). - - \param portName An optional name for the applicaction port that is - used to connect to portId can be specified. - */ - void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) - { - if (rtapi_) rtapi_->openVirtualPort(portName); - } - - //! Pure virtual function to open a MIDI connection given by enumeration number. - /*! \param portNumber An optional port number greater than 0 - can be specified. Otherwise, the default or first port - found is opened. - - \param portName An optional name for the applicaction port - that will be generated to connect to portId can be - specified. - */ - void openPort( unsigned int portNumber = 0, - const std::string portName = std::string( "RtMidi" ) ) - { - if (rtapi_) rtapi_->openPort(portNumber,portName); - } - - //! Pure virtual function to open a MIDI connection given by a port descriptor. - /*! - \param port A port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - */ - void openPort( const PortDescriptor & port, - const std::string portName = std::string( "RtMidi" ) ) - { - if (rtapi_) rtapi_->openPort(port,portName); - } - - //! Pure virtual function to return a port descirptor if the port is open - Pointer getDescriptor() - { - if (rtapi_) return rtapi_->getDescriptor(); - return 0; - } - - //! Pure virtual function to return a list of all available ports of the current API. - /*! - \param capabilities an optional parameter that describes which - device types are returned. - - \return This function returns a list of port descriptors. - - \note An input API may but need not necessarily report - output devices which cannot be used as input if - \ref PortDescriptor::OUTPUT is passed as \ref capabilities parameter. - */ - PortList getPortList(int capabilities = PortDescriptor:: INOUTPUT) - { - if (rtapi_) return rtapi_->getPortList(capabilities); - return PortList(); - } - - //! Pure virtual to return the number of available MIDI ports of the current API. - /*! - \return This function returns the number of MIDI ports of - the selected API. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortName - */ - unsigned int getPortCount() - { - if (rtapi_) return rtapi_->getPortCount(); - return 0; - } - - //! Pure virtual function to return a string identifier for the specified MIDI port number. - /*! - \param portNumber Number of the device to be referred to. - \return The name of the port with the given Id is returned. - \retval An empty string is returned if an invalid port specifier is provided. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortCount() - */ - std::string getPortName( unsigned int portNumber = 0 ) - { - if (rtapi_) return rtapi_->getPortName(portNumber); - return ""; - } - - //! Close an open MIDI connection (if one exists). - void closePort( void ) - { - if (rtapi_) rtapi_->closePort(); - } - - // ! A basic error reporting function for RtMidi classes. - // static void error( Error::Type type, std::string &errorString ); - - //! Pure virtual function to return whether a port is open or not. - /*! \retval true if a port is open and - \retval false if the port is not open (e.g. not opend or closed). - */ - bool isPortOpen( void ) const - { - if (rtapi_) return rtapi_->isPortOpen(); - return false; - } - - //! Pure virtual function to set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. - */ - void setErrorCallback( ErrorCallback errorCallback = NULL ) - { - if (rtapi_) rtapi_->setErrorCallback(errorCallback); - } - - //! A basic error reporting function for RtMidi classes. - void error( Error::Type type, std::string errorString ); -protected: - MidiApi *rtapi_; - - Midi():rtapi_(0) {} - ~Midi() - { - if (rtapi_) { - delete rtapi_; - rtapi_ = 0; - } - } -}; - -/**********************************************************************/ -/*! \class MidiIn - \brief A realtime MIDI input class. - - This class provides a common, platform-independent API for - realtime MIDI input. It allows access to a single MIDI input - port. Incoming MIDI messages are either saved to a queue for - retrieval using the getMessage() function or immediately passed to - a user-specified callback function. Create multiple instances of - this class to connect to more than one MIDI device at the same - time. With the OS-X and Linux ALSA 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-2014. -*/ -/**********************************************************************/ - -// **************************************************************** // -// -// MidiIn and MidiOut class declarations. -// -// MidiIn / MidiOut are "controllers" used to select an available -// MIDI input or output interface. They present common APIs for the -// user to call but all functionality is implemented by the classes -// MidiInApi, MidiOutApi and their subclasses. MidiIn and MidiOut -// each create an instance of a MidiInApi or MidiOutApi subclass based -// on the user's API choice. If no choice is made, they attempt to -// make a "logical" API selection. -// -// **************************************************************** // - -class MidiIn : public Midi -{ -public: - - - //! Default constructor that allows an optional api, client name and queue size. - /*! - An exception will be thrown if a MIDI system initialization - error occurs. The queue size defines the maximum number of - messages that can be held in the MIDI queue (when not using a - callback function). If the queue size limit is reached, - incoming messages will be ignored. - - If no API argument is specified and multiple API support has been - compiled, the default order of use is JACK, ALSA (Linux) and CORE, - JACK (OS-X). - - \param api An optional API id can be specified. - \param clientName An optional Client name can be specified. This - will be used to group the ports that are created - by the application. - \param queueSizeLimit An optional size of the MIDI input queue can be specified. - */ - MidiIn( ApiType api=rtmidi::UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Input Client"), - unsigned int queueSizeLimit = 100 ); - - //! If a MIDI connection is still open, it will be closed by the destructor. - ~MidiIn ( void ) throw(); - - - //! Set a callback function to be invoked for incoming MIDI messages. - /*! - The callback function will be called whenever an incoming MIDI - message is received. While not absolutely necessary, it is best - to set the callback function before opening a MIDI port to avoid - leaving some messages in the queue. - - \param callback A callback function must be given. - \param userData Opitionally, a pointer to additional data can be - passed to the callback function whenever it is called. - */ - void setCallback( MidiCallback callback, void *userData = 0 ) - { - if (rtapi_) - static_cast(rtapi_)->setCallback(callback,userData); - } - - //! Cancel use of the current callback function (if one exists). - /*! - Subsequent incoming MIDI messages will be written to the queue - and can be retrieved with the \e getMessage function. - */ - void cancelCallback() - { - if (rtapi_) - static_cast(rtapi_)->cancelCallback(); - } - - //! Specify whether certain MIDI message types should be queued or ignored during input. - /*! - By default, MIDI timing and active sensing messages are ignored - during message input because of their relative high data rates. - MIDI sysex messages are ignored by default as well. Variable - values of "true" imply that the respective message type will be - ignored. - */ - void ignoreTypes( bool midiSysex = true, - bool midiTime = true, - bool midiSense = true ) - { - if (rtapi_) - static_cast(rtapi_)->ignoreTypes(midiSysex, midiTime, midiSense); - } - - //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. - /*! - This function returns immediately whether a new message is - available or not. A valid message is indicated by a non-zero - vector size. An exception is thrown if an error occurs during - message retrieval or an input connection was not previously - established. - */ - double getMessage( std::vector &message ) - { - if (rtapi_) - return static_cast(rtapi_)->getMessage(message); - std::string errorString_ = "MidiIn::getMessage: No valid API found."; - error( Error::WARNING, errorString_ ); - return 0.0; - } - - //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. - /*! - This function returns immediately whether a new message is - available or not. A valid message is indicated by a non-zero - vector size. An exception is thrown if an error occurs during - message retrieval or an input connection was not previously - established. - - \deprecated - */ - RTMIDI_DEPRECATED(double getMessage( std::vector *message )) - { - if (!message) { - error( Error::WARNING, - "MidiIn::getMessage: passed NULL pointer"); - } - if (rtapi_) - return static_cast(rtapi_)->getMessage(*message); - error( Error::WARNING, - "MidiIn::getMessage: No valid API found."); - return 0.0; - } - -protected: - void openMidiApi( ApiType api, const std::string clientName, unsigned int queueSizeLimit ); - -}; - -/**********************************************************************/ -/*! \class MidiOut - \brief A realtime MIDI output class. - - This class provides a common, platform-independent API for MIDI - output. It allows one to probe available MIDI output ports, to - connect to one such port, and to send MIDI bytes immediately over - the connection. Create multiple instances of this class to - connect to more than one MIDI device at the same time. With the - OS-X and Linux ALSA MIDI APIs, it is also possible to open a - virtual port to which other MIDI software clients can connect. - - by Gary P. Scavone, 2003-2014. -*/ -/**********************************************************************/ - -class MidiOut : public Midi -{ -public: - - //! Default constructor that allows an optional client name. - /*! - An exception will be thrown if a MIDI system initialization error occurs. - - If no API argument is specified and multiple API support has been - compiled, the default order of use is JACK, ALSA (Linux) and CORE, - JACK (OS-X). - */ - MidiOut( ApiType api=rtmidi::UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Output Client") ); - - //! The destructor closes any open MIDI connections. - ~MidiOut( void ) throw(); - - //! Immediately send a single message out an open MIDI output port. - /*! - An exception is thrown if an error occurs during output or an - output connection was not previously established. - - \deprecated - */ - RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) - { - if (!message) { - error( Error::WARNING, - "MidiOutApi::sendMessage: no data in message argument!"); - } - if (rtapi_) - static_cast(rtapi_)->sendMessage(*message); - error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); - } - - - //! Immediately send a single message out an open MIDI output port. - /*! - An exception is thrown if an error occurs during output or an - output connection was not previously established. - */ - void sendMessage( std::vector &message ) { - if (rtapi_) - static_cast(rtapi_)->sendMessage(message); - error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); - } -protected: - void openMidiApi( ApiType api, const std::string clientName ); -}; - - -// **************************************************************** // -// -// MidiInApi and MidiOutApi subclass prototypes. -// -// **************************************************************** // + class MidiApi; + + struct PortDescriptor { + //! Flags for formatting a string description of the port. + /*! These flags just mark the requirements that the string + should fulfil. An API may return the same string for + different requirements e.g. the same short and long + name. */ + enum NamingType { + SHORT_NAME =0, /*!< A short human readable name + depending on the API + e.g. “Ensoniq AudioPCI” */ + LONG_NAME, /*!< A complete human readable + name depending on the API + e.g. "Ensoniq AudioPCI: ES1371" */ + SESSION_PATH, /*!< A unique description that can + be used to identify the port + during runtime. It may be a + cryptic string. */ + STORAGE_PATH, /*!< A unique description that is + optimised for storage in + configuration files. This is a + more textual representation that + is more robust to small changes in + the surrounding environment than + \ref SESSION_PATH */ + NAMING_MASK = 0x0F, /*!< part of the flags + that is concerned with + naming. + */ + UNIQUE_NAME = 0x10, /*!< Make all names uniqe. This + is usually done by adding + numbers to the end of the + string */ + INCLUDE_API = 0x20 /*!< Add a string describing the + API at the beginning of the + string. */ + }; + + //! Flags describing the capabilities of a given port. + enum PortCapabilities { + INPUT = 1, /*!< Ports that can be read from. */ + OUTPUT = 2, /*!< Ports that can be written to. */ + INOUTPUT = 3, /*!< Ports that allow reading and writing (INPUT | OUTPUT) */ + UNLIMITED = 0x10 /*!< Some APIs can filter out certain ports which they consider + not to be useful. This flags supresses this behaviour and + selects all ports that are useable. */ + }; + + //! Default constructor. + /*! + * Derived classes should have a constructor. + */ + PortDescriptor() {}; + + //! A virtual destructor + /*! As we might have to destruct the object from the application code + * each port id must have a virtual destructor. + */ + virtual ~PortDescriptor() {}; + + //! Get the MIDI api for the current port. + /*! This is the only information RtMidi needs to know: Which + * API should handle this object. + * + * \return API that can handle this object. + */ + virtual MidiApi * getAPI() = 0; + + //! Return the port name + /*! + * \param flags A description of the requirements of the returned name. + * \return A name that is formatted according to \ref flags. + * \sa NamingTypes + */ + virtual std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) = 0; + + //! Get capabilities + /*! \return a capabilities flag describing the capabilities of the port. + * \sa PortCapabilities + */ + virtual int getCapabilities() = 0; + }; + + //! A list of port descriptors. + /*! Port descriptors are stored as shared pointers. This avoids + unnecessary duplication of the data structure and handles automatic + deletion if all references have been removed. */ + typedef std::list > PortList; + + + + // **************************************************************** // + // + // MidiInApi / MidiOutApi class declarations. + // + // Subclasses of MidiInApi and MidiOutApi contain all API- and + // OS-specific code necessary to fully implement the RtMidi API. + // + // Note that MidiInApi and MidiOutApi are abstract base classes and + // cannot be explicitly instantiated. MidiIn and MidiOut will + // create instances of a MidiInApi or MidiOutApi subclass. + // + // **************************************************************** // + + class MidiApi + { + public: + + MidiApi(); + virtual ~MidiApi(); + + //! Pure virtal function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + */ + virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. + + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. + */ + virtual void openPort( unsigned int portNumber = 0, const std::string & portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + virtual void openPort( const PortDescriptor & port, const std::string & portName = std::string( "RtMidi" ) ) = 0; + + //! Open a MIDI connection given by a port descriptor pointer. + /*! + \param port A pointer to a port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + \sa openPort(const PortDescriptor &,const std::string &); + */ + void openPort( Pointer p, const std::string & portName = std::string( "RtMidi" ) ) { + if (!p) { + errorString_ = "MidiApi::openPort: passed NULL pointer"; + error( Error::INVALID_PARAMETER, errorString_ ); + return; + } + openPort(*p, portName); + } + + //! Pure virtual function to return a port descirptor if the port is open + virtual Pointer getDescriptor() = 0; + + //! Pure virtual function to return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that describes which + capabilities the device typu + + \return This function returns a list of port descriptors. + + \note An input API may but need not necessarily report + output devices which cannot be used as input if + \ref 0 is passed as \ref capabilities parameter. + \sa PortDescriptor::PortCapabilitiers + */ + virtual PortList getPortList(int capabilities = 0) = 0; + + //! Pure virtual to return the number of available MIDI ports of the current API. + /*! + \return This function returns the number of MIDI ports of + the selected API. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortName + */ + virtual unsigned int getPortCount() = 0; + + //! Pure virtual function to return a string identifier for the specified MIDI port number. + /*! + \param portNumber Number of the device to be referred to. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortCount() + */ + virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; + + //! Pure virtual function to close an open MIDI connection (if one exists). + virtual void closePort( void ) = 0; + + // ! A basic error reporting function for RtMidi classes. + // static void error( Error::Type type, std::string &errorString ); + + //! Pure virtual function to return whether a port is open or not. + /*! \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). + */ + bool isPortOpen() const { return connected_; } + + //! Pure virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + virtual void setErrorCallback( ErrorCallback errorCallback = NULL ); + + + //! Returns the MIDI API specifier for the current instance of RtMidiIn. + virtual ApiType getCurrentApi( void ) throw() = 0; + + //! A basic error reporting function for RtMidi classes. + void error( Error::Type type, std::string errorString ); + + protected: + virtual void initialize( const std::string& clientName ) = 0; + + void *apiData_; + bool connected_; + std::string errorString_; + ErrorCallback errorCallback_; + }; + + class MidiInApi : public MidiApi + { + public: + + MidiInApi( unsigned int queueSizeLimit ); + virtual ~MidiInApi( void ); + void setCallback( MidiCallback callback, void *userData ); + void cancelCallback( void ); + virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); + RTMIDI_DEPRECATED(double getMessage( std::vector *message )) + { + if (!message) { + errorString_ = "MidiInApi::getMessage: passed NULL pointer"; + error( Error::WARNING, errorString_ ); + } + return getMessage(*message); + } + double getMessage( std::vector &message ); + + // A MIDI structure used internally by the class to store incoming + // messages. Each message represents one and only one MIDI message. + struct MidiMessage { + std::vector bytes; + double timeStamp; + + // Default constructor. + MidiMessage() + :bytes(0), timeStamp(0.0) {} + }; + + struct MidiQueue { + unsigned int front; + unsigned int back; + unsigned int size; + unsigned int ringSize; + MidiMessage *ring; + + // Default constructor. + MidiQueue() + :front(0), back(0), size(0), ringSize(0) {} + }; + + // The RtMidiInData structure is used to pass private class data to + // the MIDI input handling function or thread. + struct MidiInData { + MidiQueue queue; + MidiMessage message; + unsigned char ignoreFlags; + bool doInput; + bool firstMessage; + void *apiData; + bool usingCallback; + MidiCallback userCallback; + void *userData; + bool continueSysex; + + // Default constructor. + MidiInData() + : ignoreFlags(7), doInput(false), firstMessage(true), + apiData(0), usingCallback(false), userCallback(0), userData(0), + continueSysex(false) {} + }; + + protected: + MidiInData inputData_; + }; + + class MidiOutApi : public MidiApi + { + public: + + MidiOutApi( void ); + virtual ~MidiOutApi( void ); + RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) + { + if (!message) { + errorString_ = "MidiOutApi::sendMessage: no data in message argument!"; + error( Error::WARNING, errorString_ ); + } + sendMessage(*message); + } + virtual void sendMessage( std::vector &message ) = 0; + }; + + + /*! \class Midi + \brief A global class that implements basic backend API handling. + + This class enhances \ref MidiApi by some functionality to handle + backend API objects. It serves as base class for the public RtMidi + API. + + by Gary P. Scavone, 2003-2014. + */ + /**********************************************************************/ + class Midi { + public: + typedef rtmidi::ApiType Api; + //! defined for compatibility + enum Api2 { + UNSPECIFIED = rtmidi::UNSPECIFIED, + MACOSX_CORE = rtmidi::MACOSX_CORE, + LINUX_ALSA = rtmidi::LINUX_ALSA, + UNIX_JACK = rtmidi::UNIX_JACK, + WINDOWS_MM = rtmidi::WINDOWS_MM, + WINDOWS_KS = rtmidi::WINDOWS_KS, + RTMIDI_DUMMY = rtmidi::RTMIDI_DUMMY + }; + + + //! A static function to determine the current RtMidi version. + static std::string getVersion( void ) throw(); + + //! A static function to determine the available compiled MIDI APIs. + /*! + The values returned in the std::vector can be compared against + the enumerated list values. Note that there can be more than one + API compiled for certain operating systems. + */ + static void getCompiledApi( std::vector &apis ) throw(); + + //! Returns the MIDI API specifier for the current instance of RtMidiIn. + ApiType getCurrentApi( void ) throw() + { + if (rtapi_) return rtapi_->getCurrentApi(); + else return rtmidi::UNSPECIFIED; + } + + //! Function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + */ + void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) + { + if (rtapi_) rtapi_->openVirtualPort(portName); + } + + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. + + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. + */ + void openPort( unsigned int portNumber = 0, + const std::string portName = std::string( "RtMidi" ) ) + { + if (rtapi_) rtapi_->openPort(portNumber,portName); + } + + //! Pure virtual function to open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + void openPort( const PortDescriptor & port, + const std::string & portName = std::string( "RtMidi" ) ) + { + if (rtapi_) rtapi_->openPort(port,portName); + } + + //! Open a MIDI connection given by a port descriptor pointer. + /*! + \param port A pointer to a port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + \sa openPort(const PortDescriptor &,const std::string &); + */ + void openPort( Pointer p, + const std::string & portName = std::string( "RtMidi" ) ) { + if (!p) { + error( Error::INVALID_PARAMETER, "MidiApi::openPort: passed NULL pointer" ); + return; + } + openPort(*p, portName); + } + + //! Pure virtual function to return a port descirptor if the port is open + Pointer getDescriptor() + { + if (rtapi_) return rtapi_->getDescriptor(); + return 0; + } + + //! Return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that + describes which capabilities the returned devices + must support. The returned devices may have + additional capabilities to those which have been + requested, but not less. + + \return This function returns a list of port descriptors. + + \note Each API will request additonal + capabilites. An output API will set always add \ref + PortDescriptor::OUTPUT to the mask while an input + device will always add \ref PortDescriptor::OUTPUT. + + \note An input API may but need not necessarily + report output devices which cannot be used as input + if \ref PortDescriptor::OUTPUT is passed as \ref + capabilities parameter. + */ + PortList getPortList(int capabilities = 0) + { + if (rtapi_) return rtapi_->getPortList(capabilities); + return PortList(); + } + + //! Pure virtual to return the number of available MIDI ports of the current API. + /*! + \return This function returns the number of MIDI ports of + the selected API. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortName + */ + unsigned int getPortCount() + { + if (rtapi_) return rtapi_->getPortCount(); + return 0; + } + + //! Pure virtual function to return a string identifier for the specified MIDI port number. + /*! + \param portNumber Number of the device to be referred to. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortCount() + */ + std::string getPortName( unsigned int portNumber = 0 ) + { + if (rtapi_) return rtapi_->getPortName(portNumber); + return ""; + } + + //! Close an open MIDI connection (if one exists). + void closePort( void ) + { + if (rtapi_) rtapi_->closePort(); + } + + // ! A basic error reporting function for RtMidi classes. + // static void error( Error::Type type, std::string &errorString ); + + //! Pure virtual function to return whether a port is open or not. + /*! \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). + */ + bool isPortOpen( void ) const + { + if (rtapi_) return rtapi_->isPortOpen(); + return false; + } + + //! Pure virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + void setErrorCallback( ErrorCallback errorCallback = NULL ) + { + if (rtapi_) rtapi_->setErrorCallback(errorCallback); + } + + //! A basic error reporting function for RtMidi classes. + void error( Error::Type type, std::string errorString ); + protected: + MidiApi *rtapi_; + + Midi():rtapi_(0) {} + ~Midi() + { + if (rtapi_) { + delete rtapi_; + rtapi_ = 0; + } + } + }; + + /**********************************************************************/ + /*! \class MidiIn + \brief A realtime MIDI input class. + + This class provides a common, platform-independent API for + realtime MIDI input. It allows access to a single MIDI input + port. Incoming MIDI messages are either saved to a queue for + retrieval using the getMessage() function or immediately passed to + a user-specified callback function. Create multiple instances of + this class to connect to more than one MIDI device at the same + time. With the OS-X and Linux ALSA 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-2014. + */ + /**********************************************************************/ + + // **************************************************************** // + // + // MidiIn and MidiOut class declarations. + // + // MidiIn / MidiOut are "controllers" used to select an available + // MIDI input or output interface. They present common APIs for the + // user to call but all functionality is implemented by the classes + // MidiInApi, MidiOutApi and their subclasses. MidiIn and MidiOut + // each create an instance of a MidiInApi or MidiOutApi subclass based + // on the user's API choice. If no choice is made, they attempt to + // make a "logical" API selection. + // + // **************************************************************** // + + class MidiIn : public Midi + { + public: + + + //! Default constructor that allows an optional api, client name and queue size. + /*! + An exception will be thrown if a MIDI system initialization + error occurs. The queue size defines the maximum number of + messages that can be held in the MIDI queue (when not using a + callback function). If the queue size limit is reached, + incoming messages will be ignored. + + If no API argument is specified and multiple API support has been + compiled, the default order of use is JACK, ALSA (Linux) and CORE, + JACK (OS-X). + + \param api An optional API id can be specified. + \param clientName An optional Client name can be specified. This + will be used to group the ports that are created + by the application. + \param queueSizeLimit An optional size of the MIDI input queue can be specified. + */ + MidiIn( ApiType api=rtmidi::UNSPECIFIED, + const std::string clientName = std::string( "RtMidi Input Client"), + unsigned int queueSizeLimit = 100 ); + + //! If a MIDI connection is still open, it will be closed by the destructor. + ~MidiIn ( void ) throw(); + + //! Set a callback function to be invoked for incoming MIDI messages. + /*! + The callback function will be called whenever an incoming MIDI + message is received. While not absolutely necessary, it is best + to set the callback function before opening a MIDI port to avoid + leaving some messages in the queue. + + \param callback A callback function must be given. + \param userData Opitionally, a pointer to additional data can be + passed to the callback function whenever it is called. + */ + void setCallback( MidiCallback callback, void *userData = 0 ) + { + if (rtapi_) + static_cast(rtapi_)->setCallback(callback,userData); + } + + //! Cancel use of the current callback function (if one exists). + /*! + Subsequent incoming MIDI messages will be written to the queue + and can be retrieved with the \e getMessage function. + */ + void cancelCallback() + { + if (rtapi_) + static_cast(rtapi_)->cancelCallback(); + } + + //! Specify whether certain MIDI message types should be queued or ignored during input. + /*! + By default, MIDI timing and active sensing messages are ignored + during message input because of their relative high data rates. + MIDI sysex messages are ignored by default as well. Variable + values of "true" imply that the respective message type will be + ignored. + */ + void ignoreTypes( bool midiSysex = true, + bool midiTime = true, + bool midiSense = true ) + { + if (rtapi_) + static_cast(rtapi_)->ignoreTypes(midiSysex, midiTime, midiSense); + } + + //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. + /*! + This function returns immediately whether a new message is + available or not. A valid message is indicated by a non-zero + vector size. An exception is thrown if an error occurs during + message retrieval or an input connection was not previously + established. + */ + double getMessage( std::vector &message ) + { + if (rtapi_) + return static_cast(rtapi_)->getMessage(message); + std::string errorString_ = "MidiIn::getMessage: No valid API found."; + error( Error::WARNING, errorString_ ); + return 0.0; + } + + //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. + /*! + This function returns immediately whether a new message is + available or not. A valid message is indicated by a non-zero + vector size. An exception is thrown if an error occurs during + message retrieval or an input connection was not previously + established. + + \deprecated + */ + RTMIDI_DEPRECATED(double getMessage( std::vector *message )) + { + if (!message) { + error( Error::WARNING, + "MidiIn::getMessage: passed NULL pointer"); + } + if (rtapi_) + return static_cast(rtapi_)->getMessage(*message); + error( Error::WARNING, + "MidiIn::getMessage: No valid API found."); + return 0.0; + } + + protected: + void openMidiApi( ApiType api, const std::string clientName, unsigned int queueSizeLimit ); + + }; + + /**********************************************************************/ + /*! \class MidiOut + \brief A realtime MIDI output class. + + This class provides a common, platform-independent API for MIDI + output. It allows one to probe available MIDI output ports, to + connect to one such port, and to send MIDI bytes immediately over + the connection. Create multiple instances of this class to + connect to more than one MIDI device at the same time. With the + OS-X and Linux ALSA MIDI APIs, it is also possible to open a + virtual port to which other MIDI software clients can connect. + + by Gary P. Scavone, 2003-2014. + */ + /**********************************************************************/ + + class MidiOut : public Midi + { + public: + + //! Default constructor that allows an optional client name. + /*! + An exception will be thrown if a MIDI system initialization error occurs. + + If no API argument is specified and multiple API support has been + compiled, the default order of use is JACK, ALSA (Linux) and CORE, + JACK (OS-X). + */ + MidiOut( ApiType api=rtmidi::UNSPECIFIED, + const std::string clientName = std::string( "RtMidi Output Client") ); + + //! The destructor closes any open MIDI connections. + ~MidiOut( void ) throw(); + + //! Immediately send a single message out an open MIDI output port. + /*! + An exception is thrown if an error occurs during output or an + output connection was not previously established. + + \deprecated + */ + RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) + { + if (!message) { + error( Error::WARNING, + "MidiOutApi::sendMessage: no data in message argument!"); + } + if (rtapi_) + static_cast(rtapi_)->sendMessage(*message); + error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); + } + + + //! Immediately send a single message out an open MIDI output port. + /*! + An exception is thrown if an error occurs during output or an + output connection was not previously established. + */ + void sendMessage( std::vector &message ) { + if (rtapi_) + static_cast(rtapi_)->sendMessage(message); + error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); + } + protected: + void openMidiApi( ApiType api, const std::string clientName ); + }; + + + // **************************************************************** // + // + // MidiInApi and MidiOutApi subclass prototypes. + // + // **************************************************************** // #if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__) #define __RTMIDI_DUMMY__ @@ -914,227 +986,227 @@ class MidiOut : public Midi #if defined(__MACOSX_CORE__) -class MidiInCore: public MidiInApi -{ -public: - MidiInCore( const std::string clientName, unsigned int queueSizeLimit ); - ~MidiInCore( void ); - ApiType getCurrentApi( void ) { return MACOSX_CORE; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - 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 ); - ApiType getCurrentApi( void ) { return MACOSX_CORE; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector &message ); - -protected: - void initialize( const std::string& clientName ); -}; + class MidiInCore: public MidiInApi + { + public: + MidiInCore( const std::string clientName, unsigned int queueSizeLimit ); + ~MidiInCore( void ); + ApiType getCurrentApi( void ) { return MACOSX_CORE; }; + void openPort( unsigned int portNumber, const std::string & portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string & portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + 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 ); + ApiType getCurrentApi( void ) { return MACOSX_CORE; }; + void openPort( unsigned int portNumber, const std::string & portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string & portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + void closePort( void ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( std::vector &message ); + + 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 ); - ApiType getCurrentApi( void ) { return UNIX_JACK; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - 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 ); - ApiType getCurrentApi( void ) { return UNIX_JACK; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector &message ); - -protected: - std::string clientName; - - void connect( void ); - void initialize( const std::string& clientName ); -}; + class MidiInJack: public MidiInApi + { + public: + MidiInJack( const std::string clientName, unsigned int queueSizeLimit ); + ~MidiInJack( void ); + ApiType getCurrentApi( void ) { return UNIX_JACK; }; + void openPort( unsigned int portNumber, const std::string & portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string & portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + 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 ); + ApiType getCurrentApi( void ) { return UNIX_JACK; }; + void openPort( unsigned int portNumber, const std::string & portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string & portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + void closePort( void ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( std::vector &message ); + + 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 ); - ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - 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 ); - ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector &message ); - -protected: - void initialize( const std::string& clientName ); -}; + class MidiInAlsa: public MidiInApi + { + public: + MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit ); + ~MidiInAlsa( void ); + ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; + void openPort( unsigned int portNumber, const std::string & portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string & portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + 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 ); + ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; + void openPort( unsigned int portNumber, const std::string & portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string & portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + void closePort( void ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( std::vector &message ); + + 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 ); - ApiType getCurrentApi( void ) { return WINDOWS_MM; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - 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 ); - ApiType getCurrentApi( void ) { return WINDOWS_MM; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector &message ); - -protected: - void initialize( const std::string& clientName ); -}; + class MidiInWinMM: public MidiInApi + { + public: + MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ); + ~MidiInWinMM( void ); + ApiType getCurrentApi( void ) { return WINDOWS_MM; }; + void openPort( unsigned int portNumber, const std::string & portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string & portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + 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 ); + ApiType getCurrentApi( void ) { return WINDOWS_MM; }; + void openPort( unsigned int portNumber, const std::string & portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string & portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + void closePort( void ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( std::vector &message ); + + 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( Error::WARNING, errorString_ ); - } - ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } - void openPort( unsigned int /*portNumber*/, const std::string /*portName*/ ) {} - void openVirtualPort( const std::string /*portName*/ ) {} - void openPort( const PortDescriptor & port, const std::string portName) {} - Pointer getDescriptor() { return 0; } - PortList getPortList(int capabilities) { return PortList(); } - 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( Error::WARNING, errorString_ ); - } - ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } - void openPort( unsigned int /*portNumber*/, const std::string /*portName*/ ) {} - void openVirtualPort( const std::string /*portName*/ ) {} - void openPort( const PortDescriptor & port, const std::string portName) {} - Pointer getDescriptor() { return 0; } - PortList getPortList(int capabilities) { return PortList(); } - void closePort( void ) {} - unsigned int getPortCount( void ) { return 0; } - std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } - void sendMessage( std::vector & /*message*/ ) {} - -protected: - void initialize( const std::string& /*clientName*/ ) {} -}; + class MidiInDummy: public MidiInApi + { + public: + MidiInDummy( const std::string /*clientName*/, unsigned int queueSizeLimit ) + : MidiInApi( queueSizeLimit ) { + errorString_ = "MidiInDummy: This class provides no functionality."; + error( Error::WARNING, errorString_ ); + } + ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } + void openPort( unsigned int /*portNumber*/, const & std::string /*portName*/ ) {} + void openVirtualPort( const std::string /*portName*/ ) {} + void openPort( const PortDescriptor & port, const & std::string portName) {} + Pointer getDescriptor() { return 0; } + PortList getPortList(int capabilities) { return PortList(); } + 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( Error::WARNING, errorString_ ); + } + ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } + void openPort( unsigned int /*portNumber*/, const & std::string /*portName*/ ) {} + void openVirtualPort( const std::string /*portName*/ ) {} + void openPort( const PortDescriptor & port, const & std::string portName) {} + Pointer getDescriptor() { return 0; } + PortList getPortList(int capabilities) { return PortList(); } + void closePort( void ) {} + unsigned int getPortCount( void ) { return 0; } + std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } + void sendMessage( std::vector & /*message*/ ) {} + + protected: + void initialize( const std::string& /*clientName*/ ) {} + }; #endif From be26958d7b96371a98106cdea52c60d265e82e6e Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 5 Apr 2014 10:46:15 +0200 Subject: [PATCH 016/210] Some whitespace fixes --- RtMidi.cpp | 653 +++++++++-------- RtMidi.h | 2066 ++++++++++++++++++++++++++-------------------------- 2 files changed, 1358 insertions(+), 1361 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 595a86b1..14c7bf69 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -636,7 +636,7 @@ void MidiInCore :: openPort( unsigned int portNumber, const std::string portName MIDIPortRef port; CoreMidiData *data = static_cast (apiData_); - OSStatus result = MIDIInputPortCreate( data->client, + OSStatus result = MIDIInputPortCreate( data->client, CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), midiInputCallback, (void *)&inputData_, &port ); if ( result != noErr ) { @@ -920,7 +920,7 @@ std::string MidiOutCore :: getPortName( unsigned int portNumber ) nameRef = ConnectedEndpointName(portRef); CFStringGetCString( nameRef, name, sizeof(name), CFStringGetSystemEncoding()); CFRelease( nameRef ); - + return stringName = name; } @@ -950,7 +950,7 @@ void MidiOutCore :: openPort( unsigned int portNumber, const std::string portNam MIDIPortRef port; CoreMidiData *data = static_cast (apiData_); - OSStatus result = MIDIOutputPortCreate( data->client, + OSStatus result = MIDIOutputPortCreate( data->client, CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), &port ); if ( result != noErr ) { @@ -1970,7 +1970,7 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string & portNa #endif snd_seq_port_info_set_name(pinfo, portName.c_str() ); int createok = snd_seq_create_port(data->seq, pinfo); - + if ( createok < 0 ) { errorString_ = "MidiInAlsa::openPort: ALSA error creating input port."; error( Error::DRIVER_ERROR, errorString_ ); @@ -2082,7 +2082,6 @@ void MidiInAlsa :: openVirtualPort( std::string portName ) pthread_join( data->thread, NULL ); // Start the input queue - #ifndef AVOID_TIMESTAMPING snd_seq_start_queue( data->seq, data->queue_id, NULL ); snd_seq_drain_output( data->seq ); @@ -2280,7 +2279,6 @@ void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string & portN } } - sender.port = data->local.port; // Make subscription @@ -2329,7 +2327,6 @@ void MidiOutAlsa :: openVirtualPort( std::string portName ) } } - void MidiOutAlsa :: sendMessage( std::vector &message ) { int result; @@ -2701,7 +2698,7 @@ namespace rtmidi{ stringName = std::string( deviceCaps.szPname ); #endif - // 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 // even when they have the same brand name std::ostringstream os; @@ -2864,7 +2861,7 @@ namespace rtmidi{ sysex.lpData = (LPSTR) buffer; sysex.dwBufferLength = nBytes; sysex.dwFlags = 0; - result = midiOutPrepareHeader( data->outHandle, &sysex, sizeof(MIDIHDR) ); + result = midiOutPrepareHeader( data->outHandle, &sysex, sizeof(MIDIHDR) ); if ( result != MMSYSERR_NOERROR ) { free( buffer ); errorString_ = "MidiOutWinMM::sendMessage: error preparing sysex header."; @@ -2910,423 +2907,423 @@ namespace rtmidi{ } } } - NAMSPACE_RTMIDI_END +} #endif // __WINDOWS_MM__ - //*********************************************************************// - // API: UNIX JACK - // - // Written primarily by Alexander Svetalkin, with updates for delta - // time by Gary Scavone, April 2011. - // - // *********************************************************************// +//*********************************************************************// +// API: UNIX JACK +// +// Written primarily by Alexander Svetalkin, with updates for delta +// time by Gary Scavone, April 2011. +// +// *********************************************************************// #if defined(__UNIX_JACK__) - // JACK header files +// JACK header files #include #include #include #define JACK_RINGBUFFER_SIZE 16384 // Default size for ringbuffer - NAMSPACE_RTMIDI_START +NAMSPACE_RTMIDI_START - struct JackMidiData { - jack_client_t *client; - jack_port_t *port; - jack_ringbuffer_t *buffSize; - jack_ringbuffer_t *buffMessage; - jack_time_t lastTime; - MidiInApi :: MidiInData *rtMidiIn; - }; +struct JackMidiData { + jack_client_t *client; + jack_port_t *port; + jack_ringbuffer_t *buffSize; + jack_ringbuffer_t *buffMessage; + jack_time_t lastTime; + MidiInApi :: MidiInData *rtMidiIn; +}; - //*********************************************************************// - // API: JACK - // Class Definitions: MidiInJack - //*********************************************************************// +//*********************************************************************// +// API: JACK +// Class Definitions: MidiInJack +//*********************************************************************// - static int jackProcessIn( jack_nframes_t nframes, void *arg ) - { - JackMidiData *jData = (JackMidiData *) arg; - MidiInApi :: MidiInData *rtData = jData->rtMidiIn; - jack_midi_event_t event; - jack_time_t time; - - // Is port created? - if ( jData->port == NULL ) return 0; - void *buff = jack_port_get_buffer( jData->port, nframes ); - - // 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(); - - 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 ) - rtData->firstMessage = false; - else - message.timeStamp = ( time - jData->lastTime ) * 0.000001; +static int jackProcessIn( jack_nframes_t nframes, void *arg ) +{ + JackMidiData *jData = (JackMidiData *) arg; + MidiInApi :: MidiInData *rtData = jData->rtMidiIn; + jack_midi_event_t event; + jack_time_t time; - jData->lastTime = time; + // Is port created? + if ( jData->port == NULL ) return 0; + void *buff = jack_port_get_buffer( jData->port, nframes ); - if ( !rtData->continueSysex ) { - if ( rtData->usingCallback ) { - MidiCallback callback = (MidiCallback) rtData->userCallback; - callback( message.timeStamp, &message.bytes, rtData->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( rtData->queue.size < rtData->queue.ringSize ) { - rtData->queue.ring[rtData->queue.back++] = message; - if ( rtData->queue.back == rtData->queue.ringSize ) - rtData->queue.back = 0; - rtData->queue.size++; - } - else - std::cerr << "\nMidiInJack: message queue limit reached!!\n\n"; + // 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(); + + 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 ) + rtData->firstMessage = false; + else + message.timeStamp = ( time - jData->lastTime ) * 0.000001; + + jData->lastTime = time; + + if ( !rtData->continueSysex ) { + if ( rtData->usingCallback ) { + MidiCallback callback = (MidiCallback) rtData->userCallback; + callback( message.timeStamp, &message.bytes, rtData->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( rtData->queue.size < rtData->queue.ringSize ) { + rtData->queue.ring[rtData->queue.back++] = message; + if ( rtData->queue.back == rtData->queue.ringSize ) + rtData->queue.back = 0; + rtData->queue.size++; } + else + std::cerr << "\nMidiInJack: message queue limit reached!!\n\n"; } } - - return 0; } - MidiInJack :: MidiInJack( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) - { - initialize( clientName ); - } + return 0; +} - void MidiInJack :: initialize( const std::string& clientName ) - { - JackMidiData *data = new JackMidiData; - apiData_ = (void *) data; +MidiInJack :: MidiInJack( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) +{ + initialize( clientName ); +} - data->rtMidiIn = &inputData_; - data->port = NULL; - data->client = NULL; - this->clientName = clientName; +void MidiInJack :: initialize( const std::string& clientName ) +{ + JackMidiData *data = new JackMidiData; + apiData_ = (void *) data; - connect(); - } + data->rtMidiIn = &inputData_; + data->port = NULL; + data->client = NULL; + this->clientName = clientName; - void MidiInJack :: connect() - { - JackMidiData *data = static_cast (apiData_); - if ( data->client ) - return; + connect(); +} - // Initialize JACK client - if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { - errorString_ = "MidiInJack::initialize: JACK server not running?"; - error( Error::WARNING, errorString_ ); - return; - } +void MidiInJack :: connect() +{ + JackMidiData *data = static_cast (apiData_); + if ( data->client ) + return; - jack_set_process_callback( data->client, jackProcessIn, data ); - jack_activate( data->client ); + // Initialize JACK client + if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { + errorString_ = "MidiInJack::initialize: JACK server not running?"; + error( Error::WARNING, errorString_ ); + return; } - MidiInJack :: ~MidiInJack() - { - JackMidiData *data = static_cast (apiData_); - closePort(); + jack_set_process_callback( data->client, jackProcessIn, data ); + jack_activate( data->client ); +} - if ( data->client ) - jack_client_close( data->client ); - delete data; - } +MidiInJack :: ~MidiInJack() +{ + JackMidiData *data = static_cast (apiData_); + closePort(); - void MidiInJack :: openPort( unsigned int portNumber, const std::string portName ) - { - JackMidiData *data = static_cast (apiData_); + if ( data->client ) + jack_client_close( data->client ); + delete data; +} - connect(); +void MidiInJack :: openPort( unsigned int portNumber, const std::string portName ) +{ + JackMidiData *data = static_cast (apiData_); - // Creating new port - if ( data->port == NULL) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); + connect(); - if ( data->port == NULL) { - errorString_ = "MidiInJack::openPort: JACK error creating port"; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } + // Creating new port + if ( data->port == NULL) + data->port = jack_port_register( data->client, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); - // Connecting to the output - std::string name = getPortName( portNumber ); - jack_connect( data->client, name.c_str(), jack_port_name( data->port ) ); + if ( data->port == NULL) { + errorString_ = "MidiInJack::openPort: JACK error creating port"; + error( Error::DRIVER_ERROR, errorString_ ); + return; } - void MidiInJack :: openVirtualPort( const std::string portName ) - { - JackMidiData *data = static_cast (apiData_); - - connect(); - if ( data->port == NULL ) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); + // Connecting to the output + std::string name = getPortName( portNumber ); + jack_connect( data->client, name.c_str(), jack_port_name( data->port ) ); +} - if ( data->port == NULL ) { - errorString_ = "MidiInJack::openVirtualPort: JACK error creating virtual port"; - error( Error::DRIVER_ERROR, errorString_ ); - } - } +void MidiInJack :: openVirtualPort( const std::string portName ) +{ + JackMidiData *data = static_cast (apiData_); - unsigned int MidiInJack :: getPortCount() - { - int count = 0; - JackMidiData *data = static_cast (apiData_); - connect(); - if ( !data->client ) - return 0; + connect(); + if ( data->port == NULL ) + data->port = jack_port_register( data->client, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); - // List of available ports - const char **ports = jack_get_ports( data->client, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); + if ( data->port == NULL ) { + errorString_ = "MidiInJack::openVirtualPort: JACK error creating virtual port"; + error( Error::DRIVER_ERROR, errorString_ ); + } +} - if ( ports == NULL ) return 0; - while ( ports[count] != NULL ) - count++; +unsigned int MidiInJack :: getPortCount() +{ + int count = 0; + JackMidiData *data = static_cast (apiData_); + connect(); + if ( !data->client ) + return 0; - free( ports ); + // List of available ports + const char **ports = jack_get_ports( data->client, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); - return count; - } + if ( ports == NULL ) return 0; + while ( ports[count] != NULL ) + count++; - std::string MidiInJack :: getPortName( unsigned int portNumber ) - { - JackMidiData *data = static_cast (apiData_); - std::string retStr(""); + free( ports ); - connect(); + return count; +} - // List of available ports - const char **ports = jack_get_ports( data->client, NULL, - JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); +std::string MidiInJack :: getPortName( unsigned int portNumber ) +{ + JackMidiData *data = static_cast (apiData_); + std::string retStr(""); - // Check port validity - if ( ports == NULL ) { - errorString_ = "MidiInJack::getPortName: no ports available!"; - error( Error::WARNING, errorString_ ); - return retStr; - } + connect(); - if ( ports[portNumber] == NULL ) { - std::ostringstream ost; - ost << "MidiInJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::WARNING, errorString_ ); - } - else retStr.assign( ports[portNumber] ); + // List of available ports + const char **ports = jack_get_ports( data->client, NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); - free( ports ); + // Check port validity + if ( ports == NULL ) { + errorString_ = "MidiInJack::getPortName: no ports available!"; + error( Error::WARNING, errorString_ ); return retStr; } - void MidiInJack :: closePort() - { - JackMidiData *data = static_cast (apiData_); - - if ( data->port == NULL ) return; - jack_port_unregister( data->client, data->port ); - data->port = NULL; + if ( ports[portNumber] == NULL ) { + std::ostringstream ost; + ost << "MidiInJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::WARNING, errorString_ ); } + else retStr.assign( ports[portNumber] ); - //*********************************************************************// - // API: JACK - // Class Definitions: MidiOutJack - //*********************************************************************// + free( ports ); + return retStr; +} - // Jack process callback - static int jackProcessOut( jack_nframes_t nframes, void *arg ) - { - JackMidiData *data = (JackMidiData *) arg; - jack_midi_data_t *midiData; - int space; +void MidiInJack :: closePort() +{ + JackMidiData *data = static_cast (apiData_); - // Is port created? - if ( data->port == NULL ) return 0; + if ( data->port == NULL ) return; + jack_port_unregister( data->client, data->port ); + data->port = NULL; +} - void *buff = jack_port_get_buffer( data->port, nframes ); - jack_midi_clear_buffer( buff ); +//*********************************************************************// +// API: JACK +// Class Definitions: MidiOutJack +//*********************************************************************// - while ( jack_ringbuffer_read_space( data->buffSize ) > 0 ) { - jack_ringbuffer_read( data->buffSize, (char *) &space, (size_t) sizeof(space) ); - midiData = jack_midi_event_reserve( buff, 0, space ); +// Jack process callback +static int jackProcessOut( jack_nframes_t nframes, void *arg ) +{ + JackMidiData *data = (JackMidiData *) arg; + jack_midi_data_t *midiData; + int space; - jack_ringbuffer_read( data->buffMessage, (char *) midiData, (size_t) space ); - } + // Is port created? + if ( data->port == NULL ) return 0; - return 0; - } + void *buff = jack_port_get_buffer( data->port, nframes ); + jack_midi_clear_buffer( buff ); - MidiOutJack :: MidiOutJack( const std::string clientName ) : MidiOutApi() - { - initialize( clientName ); + while ( jack_ringbuffer_read_space( data->buffSize ) > 0 ) { + jack_ringbuffer_read( data->buffSize, (char *) &space, (size_t) sizeof(space) ); + midiData = jack_midi_event_reserve( buff, 0, space ); + + jack_ringbuffer_read( data->buffMessage, (char *) midiData, (size_t) space ); } - void MidiOutJack :: initialize( const std::string& clientName ) - { - JackMidiData *data = new JackMidiData; - apiData_ = (void *) data; + return 0; +} + +MidiOutJack :: MidiOutJack( const std::string clientName ) : MidiOutApi() +{ + initialize( clientName ); +} - data->port = NULL; - data->client = NULL; - this->clientName = clientName; +void MidiOutJack :: initialize( const std::string& clientName ) +{ + JackMidiData *data = new JackMidiData; + apiData_ = (void *) data; - connect(); - } + data->port = NULL; + data->client = NULL; + this->clientName = clientName; - void MidiOutJack :: connect() - { - JackMidiData *data = static_cast (apiData_); - if ( data->client ) - return; + connect(); +} - // Initialize JACK client - if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { - errorString_ = "MidiOutJack::initialize: JACK server not running?"; - error( Error::WARNING, errorString_ ); - return; - } +void MidiOutJack :: connect() +{ + JackMidiData *data = static_cast (apiData_); + if ( data->client ) + return; - jack_set_process_callback( data->client, jackProcessOut, data ); - data->buffSize = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); - data->buffMessage = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); - jack_activate( data->client ); + // Initialize JACK client + if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { + errorString_ = "MidiOutJack::initialize: JACK server not running?"; + error( Error::WARNING, errorString_ ); + return; } - MidiOutJack :: ~MidiOutJack() - { - JackMidiData *data = static_cast (apiData_); - closePort(); + jack_set_process_callback( data->client, jackProcessOut, data ); + data->buffSize = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); + data->buffMessage = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); + jack_activate( data->client ); +} - if ( data->client ) { - // Cleanup - jack_client_close( data->client ); - jack_ringbuffer_free( data->buffSize ); - jack_ringbuffer_free( data->buffMessage ); - } +MidiOutJack :: ~MidiOutJack() +{ + JackMidiData *data = static_cast (apiData_); + closePort(); - delete data; + if ( data->client ) { + // Cleanup + jack_client_close( data->client ); + jack_ringbuffer_free( data->buffSize ); + jack_ringbuffer_free( data->buffMessage ); } - void MidiOutJack :: openPort( unsigned int portNumber, const std::string portName ) - { - JackMidiData *data = static_cast (apiData_); + delete data; +} - connect(); +void MidiOutJack :: openPort( unsigned int portNumber, const std::string portName ) +{ + JackMidiData *data = static_cast (apiData_); - // Creating new port - if ( data->port == NULL ) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); + connect(); - if ( data->port == NULL ) { - errorString_ = "MidiOutJack::openPort: JACK error creating port"; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } + // Creating new port + if ( data->port == NULL ) + data->port = jack_port_register( data->client, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); - // Connecting to the output - std::string name = getPortName( portNumber ); - jack_connect( data->client, jack_port_name( data->port ), name.c_str() ); + if ( data->port == NULL ) { + errorString_ = "MidiOutJack::openPort: JACK error creating port"; + error( Error::DRIVER_ERROR, errorString_ ); + return; } - void MidiOutJack :: openVirtualPort( const std::string portName ) - { - JackMidiData *data = static_cast (apiData_); - - connect(); - if ( data->port == NULL ) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); + // Connecting to the output + std::string name = getPortName( portNumber ); + jack_connect( data->client, jack_port_name( data->port ), name.c_str() ); +} - if ( data->port == NULL ) { - errorString_ = "MidiOutJack::openVirtualPort: JACK error creating virtual port"; - error( Error::DRIVER_ERROR, errorString_ ); - } - } +void MidiOutJack :: openVirtualPort( const std::string portName ) +{ + JackMidiData *data = static_cast (apiData_); - unsigned int MidiOutJack :: getPortCount() - { - int count = 0; - JackMidiData *data = static_cast (apiData_); - connect(); - if ( !data->client ) - return 0; + connect(); + if ( data->port == NULL ) + data->port = jack_port_register( data->client, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); - // List of available ports - const char **ports = jack_get_ports( data->client, NULL, - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); + if ( data->port == NULL ) { + errorString_ = "MidiOutJack::openVirtualPort: JACK error creating virtual port"; + error( Error::DRIVER_ERROR, errorString_ ); + } +} - if ( ports == NULL ) return 0; - while ( ports[count] != NULL ) - count++; +unsigned int MidiOutJack :: getPortCount() +{ + int count = 0; + JackMidiData *data = static_cast (apiData_); + connect(); + if ( !data->client ) + return 0; - free( ports ); + // List of available ports + const char **ports = jack_get_ports( data->client, NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); - return count; - } + if ( ports == NULL ) return 0; + while ( ports[count] != NULL ) + count++; - std::string MidiOutJack :: getPortName( unsigned int portNumber ) - { - JackMidiData *data = static_cast (apiData_); - std::string retStr(""); + free( ports ); - connect(); + return count; +} - // List of available ports - const char **ports = jack_get_ports( data->client, NULL, - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); +std::string MidiOutJack :: getPortName( unsigned int portNumber ) +{ + JackMidiData *data = static_cast (apiData_); + std::string retStr(""); - // Check port validity - if ( ports == NULL) { - errorString_ = "MidiOutJack::getPortName: no ports available!"; - error( Error::WARNING, errorString_ ); - return retStr; - } + connect(); - if ( ports[portNumber] == NULL) { - std::ostringstream ost; - ost << "MidiOutJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::WARNING, errorString_ ); - } - else retStr.assign( ports[portNumber] ); + // List of available ports + const char **ports = jack_get_ports( data->client, NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); - free( ports ); + // Check port validity + if ( ports == NULL) { + errorString_ = "MidiOutJack::getPortName: no ports available!"; + error( Error::WARNING, errorString_ ); return retStr; } - void MidiOutJack :: closePort() - { - JackMidiData *data = static_cast (apiData_); - - if ( data->port == NULL ) return; - jack_port_unregister( data->client, data->port ); - data->port = NULL; + if ( ports[portNumber] == NULL) { + std::ostringstream ost; + ost << "MidiOutJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::WARNING, errorString_ ); } + else retStr.assign( ports[portNumber] ); - void MidiOutJack :: sendMessage( std::vector *message ) - { - int nBytes = message->size(); - JackMidiData *data = static_cast (apiData_); + free( ports ); + return retStr; +} - // Write full message to buffer - jack_ringbuffer_write( data->buffMessage, ( const char * ) &( *message )[0], - message->size() ); - jack_ringbuffer_write( data->buffSize, ( char * ) &nBytes, sizeof( nBytes ) ); - } - NAMSPACE_RTMIDI_END +void MidiOutJack :: closePort() +{ + JackMidiData *data = static_cast (apiData_); + + if ( data->port == NULL ) return; + jack_port_unregister( data->client, data->port ); + data->port = NULL; +} + +void MidiOutJack :: sendMessage( std::vector *message ) +{ + int nBytes = message->size(); + JackMidiData *data = static_cast (apiData_); + + // Write full message to buffer + jack_ringbuffer_write( data->buffMessage, ( const char * ) &( *message )[0], + message->size() ); + jack_ringbuffer_write( data->buffSize, ( char * ) &nBytes, sizeof( nBytes ) ); +} +NAMSPACE_RTMIDI_END #endif // __UNIX_JACK__ diff --git a/RtMidi.h b/RtMidi.h index 2befb2d8..453f3da5 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -68,13 +68,13 @@ NAMESPACE_RTMIDI_START //! MIDI API specifier arguments. enum ApiType { -UNSPECIFIED, /*!< Search for a working compiled API. */ -MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ -LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ -UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ -WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ -WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ -RTMIDI_DUMMY /*!< A compilable but non-functional API. */ + UNSPECIFIED, /*!< Search for a working compiled API. */ + MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ + LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ + UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ + WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ + WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ + RTMIDI_DUMMY /*!< A compilable but non-functional API. */ }; //! User callback function type definition. @@ -151,834 +151,834 @@ typedef void (*ErrorCallback)( Error::Type type, const std::string &errorText ); #if __cplusplus < 201103L - class PortDescriptor; - - template - class Pointer { - public: - typedef T datatype; - protected: - struct countPointer { - int count; - datatype * descriptor; - }; - public: - Pointer():ptr(0) {} - Pointer(datatype * p):ptr(new countPointer) { - ptr->count = 1; - ptr->descriptor = p; - } - Pointer(const Pointer & other): - ptr(other.ptr) { - if (ptr) - ptr->count++; - } - - ~Pointer() { - if (!ptr) return; - if (!ptr->descriptor) { - delete ptr; - return; - } - if (!(--ptr->count)) { - delete ptr->descriptor; - delete ptr; - } - } - - datatype * operator -> () { - if (!ptr) return 0; - // this should throw an exception - - return ptr->descriptor; - } - - datatype & operator * () { - if (!ptr || !ptr->descriptor) { - throw std::invalid_argument("rtmidi::Pointer: trying to dereference a NULL pointer."); - } - else return (*ptr->descriptor); - } - - bool operator ! () { - return (!ptr || !ptr->descriptor); - } - - Pointer & operator = (const Pointer & other) { - if (ptr) { - if (!(--ptr->count)) { - delete ptr->descriptor; - delete ptr; - } - } - ptr = other.ptr; - ptr->count++; - return *this; - } - protected: - countPointer * ptr; - }; +class PortDescriptor; + +template +class Pointer { +public: + typedef T datatype; +protected: + struct countPointer { + int count; + datatype * descriptor; + }; +public: + Pointer():ptr(0) {} + Pointer(datatype * p):ptr(new countPointer) { + ptr->count = 1; + ptr->descriptor = p; + } + Pointer(const Pointer & other): + ptr(other.ptr) { + if (ptr) + ptr->count++; + } + + ~Pointer() { + if (!ptr) return; + if (!ptr->descriptor) { + delete ptr; + return; + } + if (!(--ptr->count)) { + delete ptr->descriptor; + delete ptr; + } + } + + datatype * operator -> () { + if (!ptr) return 0; + // this should throw an exception + + return ptr->descriptor; + } + + datatype & operator * () { + if (!ptr || !ptr->descriptor) { + throw std::invalid_argument("rtmidi::Pointer: trying to dereference a NULL pointer."); + } + else return (*ptr->descriptor); + } + + bool operator ! () { + return (!ptr || !ptr->descriptor); + } + + Pointer & operator = (const Pointer & other) { + if (ptr) { + if (!(--ptr->count)) { + delete ptr->descriptor; + delete ptr; + } + } + ptr = other.ptr; + ptr->count++; + return *this; + } +protected: + countPointer * ptr; +}; #else - template - typedef std::shared_ptr Pointer; +template +typedef std::shared_ptr Pointer; #endif - class MidiApi; - - struct PortDescriptor { - //! Flags for formatting a string description of the port. - /*! These flags just mark the requirements that the string - should fulfil. An API may return the same string for - different requirements e.g. the same short and long - name. */ - enum NamingType { - SHORT_NAME =0, /*!< A short human readable name - depending on the API - e.g. “Ensoniq AudioPCI” */ - LONG_NAME, /*!< A complete human readable - name depending on the API - e.g. "Ensoniq AudioPCI: ES1371" */ - SESSION_PATH, /*!< A unique description that can - be used to identify the port - during runtime. It may be a - cryptic string. */ - STORAGE_PATH, /*!< A unique description that is - optimised for storage in - configuration files. This is a - more textual representation that - is more robust to small changes in - the surrounding environment than - \ref SESSION_PATH */ - NAMING_MASK = 0x0F, /*!< part of the flags - that is concerned with - naming. - */ - UNIQUE_NAME = 0x10, /*!< Make all names uniqe. This - is usually done by adding - numbers to the end of the - string */ - INCLUDE_API = 0x20 /*!< Add a string describing the - API at the beginning of the - string. */ - }; - - //! Flags describing the capabilities of a given port. - enum PortCapabilities { - INPUT = 1, /*!< Ports that can be read from. */ - OUTPUT = 2, /*!< Ports that can be written to. */ - INOUTPUT = 3, /*!< Ports that allow reading and writing (INPUT | OUTPUT) */ - UNLIMITED = 0x10 /*!< Some APIs can filter out certain ports which they consider - not to be useful. This flags supresses this behaviour and - selects all ports that are useable. */ - }; - - //! Default constructor. - /*! - * Derived classes should have a constructor. - */ - PortDescriptor() {}; - - //! A virtual destructor - /*! As we might have to destruct the object from the application code - * each port id must have a virtual destructor. - */ - virtual ~PortDescriptor() {}; - - //! Get the MIDI api for the current port. - /*! This is the only information RtMidi needs to know: Which - * API should handle this object. - * - * \return API that can handle this object. - */ - virtual MidiApi * getAPI() = 0; - - //! Return the port name - /*! - * \param flags A description of the requirements of the returned name. - * \return A name that is formatted according to \ref flags. - * \sa NamingTypes - */ - virtual std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) = 0; - - //! Get capabilities - /*! \return a capabilities flag describing the capabilities of the port. - * \sa PortCapabilities - */ - virtual int getCapabilities() = 0; - }; - - //! A list of port descriptors. - /*! Port descriptors are stored as shared pointers. This avoids - unnecessary duplication of the data structure and handles automatic - deletion if all references have been removed. */ - typedef std::list > PortList; - - - - // **************************************************************** // - // - // MidiInApi / MidiOutApi class declarations. - // - // Subclasses of MidiInApi and MidiOutApi contain all API- and - // OS-specific code necessary to fully implement the RtMidi API. - // - // Note that MidiInApi and MidiOutApi are abstract base classes and - // cannot be explicitly instantiated. MidiIn and MidiOut will - // create instances of a MidiInApi or MidiOutApi subclass. - // - // **************************************************************** // - - class MidiApi - { - public: - - MidiApi(); - virtual ~MidiApi(); - - //! Pure virtal function to create a virtual port, with optional name. - /*! - This function creates a virtual MIDI port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, any JACK, - and Linux ALSA APIs (the function returns an error for the other APIs). - - \param portName An optional name for the applicaction port that is - used to connect to portId can be specified. - */ - virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0; - - //! Pure virtual function to open a MIDI connection given by enumeration number. - /*! \param portNumber An optional port number greater than 0 - can be specified. Otherwise, the default or first port - found is opened. - - \param portName An optional name for the applicaction port - that will be generated to connect to portId can be - specified. - */ - virtual void openPort( unsigned int portNumber = 0, const std::string & portName = std::string( "RtMidi" ) ) = 0; - - //! Pure virtual function to open a MIDI connection given by a port descriptor. - /*! - \param port A port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - */ - virtual void openPort( const PortDescriptor & port, const std::string & portName = std::string( "RtMidi" ) ) = 0; - - //! Open a MIDI connection given by a port descriptor pointer. - /*! - \param port A pointer to a port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - \sa openPort(const PortDescriptor &,const std::string &); - */ - void openPort( Pointer p, const std::string & portName = std::string( "RtMidi" ) ) { - if (!p) { - errorString_ = "MidiApi::openPort: passed NULL pointer"; - error( Error::INVALID_PARAMETER, errorString_ ); - return; - } - openPort(*p, portName); - } - - //! Pure virtual function to return a port descirptor if the port is open - virtual Pointer getDescriptor() = 0; - - //! Pure virtual function to return a list of all available ports of the current API. - /*! - \param capabilities an optional parameter that describes which - capabilities the device typu - - \return This function returns a list of port descriptors. - - \note An input API may but need not necessarily report - output devices which cannot be used as input if - \ref 0 is passed as \ref capabilities parameter. - \sa PortDescriptor::PortCapabilitiers - */ - virtual PortList getPortList(int capabilities = 0) = 0; - - //! Pure virtual to return the number of available MIDI ports of the current API. - /*! - \return This function returns the number of MIDI ports of - the selected API. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortName - */ - virtual unsigned int getPortCount() = 0; - - //! Pure virtual function to return a string identifier for the specified MIDI port number. - /*! - \param portNumber Number of the device to be referred to. - \return The name of the port with the given Id is returned. - \retval An empty string is returned if an invalid port specifier is provided. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortCount() - */ - virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; - - //! Pure virtual function to close an open MIDI connection (if one exists). - virtual void closePort( void ) = 0; - - // ! A basic error reporting function for RtMidi classes. - // static void error( Error::Type type, std::string &errorString ); - - //! Pure virtual function to return whether a port is open or not. - /*! \retval true if a port is open and - \retval false if the port is not open (e.g. not opend or closed). - */ - bool isPortOpen() const { return connected_; } - - //! Pure virtual function to set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. - */ - virtual void setErrorCallback( ErrorCallback errorCallback = NULL ); - - - //! Returns the MIDI API specifier for the current instance of RtMidiIn. - virtual ApiType getCurrentApi( void ) throw() = 0; - - //! A basic error reporting function for RtMidi classes. - void error( Error::Type type, std::string errorString ); - - protected: - virtual void initialize( const std::string& clientName ) = 0; - - void *apiData_; - bool connected_; - std::string errorString_; - ErrorCallback errorCallback_; - }; - - class MidiInApi : public MidiApi - { - public: - - MidiInApi( unsigned int queueSizeLimit ); - virtual ~MidiInApi( void ); - void setCallback( MidiCallback callback, void *userData ); - void cancelCallback( void ); - virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); - RTMIDI_DEPRECATED(double getMessage( std::vector *message )) - { - if (!message) { - errorString_ = "MidiInApi::getMessage: passed NULL pointer"; - error( Error::WARNING, errorString_ ); - } - return getMessage(*message); - } - double getMessage( std::vector &message ); - - // A MIDI structure used internally by the class to store incoming - // messages. Each message represents one and only one MIDI message. - struct MidiMessage { - std::vector bytes; - double timeStamp; - - // Default constructor. - MidiMessage() - :bytes(0), timeStamp(0.0) {} - }; - - struct MidiQueue { - unsigned int front; - unsigned int back; - unsigned int size; - unsigned int ringSize; - MidiMessage *ring; - - // Default constructor. - MidiQueue() - :front(0), back(0), size(0), ringSize(0) {} - }; - - // The RtMidiInData structure is used to pass private class data to - // the MIDI input handling function or thread. - struct MidiInData { - MidiQueue queue; - MidiMessage message; - unsigned char ignoreFlags; - bool doInput; - bool firstMessage; - void *apiData; - bool usingCallback; - MidiCallback userCallback; - void *userData; - bool continueSysex; - - // Default constructor. - MidiInData() - : ignoreFlags(7), doInput(false), firstMessage(true), - apiData(0), usingCallback(false), userCallback(0), userData(0), - continueSysex(false) {} - }; - - protected: - MidiInData inputData_; - }; - - class MidiOutApi : public MidiApi - { - public: - - MidiOutApi( void ); - virtual ~MidiOutApi( void ); - RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) - { - if (!message) { - errorString_ = "MidiOutApi::sendMessage: no data in message argument!"; - error( Error::WARNING, errorString_ ); - } - sendMessage(*message); - } - virtual void sendMessage( std::vector &message ) = 0; - }; - - - /*! \class Midi - \brief A global class that implements basic backend API handling. - - This class enhances \ref MidiApi by some functionality to handle - backend API objects. It serves as base class for the public RtMidi - API. - - by Gary P. Scavone, 2003-2014. - */ - /**********************************************************************/ - class Midi { - public: - typedef rtmidi::ApiType Api; - //! defined for compatibility - enum Api2 { - UNSPECIFIED = rtmidi::UNSPECIFIED, - MACOSX_CORE = rtmidi::MACOSX_CORE, - LINUX_ALSA = rtmidi::LINUX_ALSA, - UNIX_JACK = rtmidi::UNIX_JACK, - WINDOWS_MM = rtmidi::WINDOWS_MM, - WINDOWS_KS = rtmidi::WINDOWS_KS, - RTMIDI_DUMMY = rtmidi::RTMIDI_DUMMY - }; - - - //! A static function to determine the current RtMidi version. - static std::string getVersion( void ) throw(); - - //! A static function to determine the available compiled MIDI APIs. - /*! - The values returned in the std::vector can be compared against - the enumerated list values. Note that there can be more than one - API compiled for certain operating systems. - */ - static void getCompiledApi( std::vector &apis ) throw(); - - //! Returns the MIDI API specifier for the current instance of RtMidiIn. - ApiType getCurrentApi( void ) throw() - { - if (rtapi_) return rtapi_->getCurrentApi(); - else return rtmidi::UNSPECIFIED; - } - - //! Function to create a virtual port, with optional name. - /*! - This function creates a virtual MIDI port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, any JACK, - and Linux ALSA APIs (the function returns an error for the other APIs). - - \param portName An optional name for the applicaction port that is - used to connect to portId can be specified. - */ - void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) - { - if (rtapi_) rtapi_->openVirtualPort(portName); - } - - //! Pure virtual function to open a MIDI connection given by enumeration number. - /*! \param portNumber An optional port number greater than 0 - can be specified. Otherwise, the default or first port - found is opened. - - \param portName An optional name for the applicaction port - that will be generated to connect to portId can be - specified. - */ - void openPort( unsigned int portNumber = 0, - const std::string portName = std::string( "RtMidi" ) ) - { - if (rtapi_) rtapi_->openPort(portNumber,portName); - } - - //! Pure virtual function to open a MIDI connection given by a port descriptor. - /*! - \param port A port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - */ - void openPort( const PortDescriptor & port, - const std::string & portName = std::string( "RtMidi" ) ) - { - if (rtapi_) rtapi_->openPort(port,portName); - } - - //! Open a MIDI connection given by a port descriptor pointer. - /*! - \param port A pointer to a port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - \sa openPort(const PortDescriptor &,const std::string &); - */ - void openPort( Pointer p, - const std::string & portName = std::string( "RtMidi" ) ) { - if (!p) { - error( Error::INVALID_PARAMETER, "MidiApi::openPort: passed NULL pointer" ); - return; - } - openPort(*p, portName); - } - - //! Pure virtual function to return a port descirptor if the port is open - Pointer getDescriptor() - { - if (rtapi_) return rtapi_->getDescriptor(); - return 0; - } - - //! Return a list of all available ports of the current API. - /*! - \param capabilities an optional parameter that - describes which capabilities the returned devices - must support. The returned devices may have - additional capabilities to those which have been - requested, but not less. - - \return This function returns a list of port descriptors. - - \note Each API will request additonal - capabilites. An output API will set always add \ref - PortDescriptor::OUTPUT to the mask while an input - device will always add \ref PortDescriptor::OUTPUT. - - \note An input API may but need not necessarily - report output devices which cannot be used as input - if \ref PortDescriptor::OUTPUT is passed as \ref - capabilities parameter. - */ - PortList getPortList(int capabilities = 0) - { - if (rtapi_) return rtapi_->getPortList(capabilities); - return PortList(); - } - - //! Pure virtual to return the number of available MIDI ports of the current API. - /*! - \return This function returns the number of MIDI ports of - the selected API. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortName - */ - unsigned int getPortCount() - { - if (rtapi_) return rtapi_->getPortCount(); - return 0; - } - - //! Pure virtual function to return a string identifier for the specified MIDI port number. - /*! - \param portNumber Number of the device to be referred to. - \return The name of the port with the given Id is returned. - \retval An empty string is returned if an invalid port specifier is provided. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortCount() - */ - std::string getPortName( unsigned int portNumber = 0 ) - { - if (rtapi_) return rtapi_->getPortName(portNumber); - return ""; - } - - //! Close an open MIDI connection (if one exists). - void closePort( void ) - { - if (rtapi_) rtapi_->closePort(); - } - - // ! A basic error reporting function for RtMidi classes. - // static void error( Error::Type type, std::string &errorString ); - - //! Pure virtual function to return whether a port is open or not. - /*! \retval true if a port is open and - \retval false if the port is not open (e.g. not opend or closed). - */ - bool isPortOpen( void ) const - { - if (rtapi_) return rtapi_->isPortOpen(); - return false; - } - - //! Pure virtual function to set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. - */ - void setErrorCallback( ErrorCallback errorCallback = NULL ) - { - if (rtapi_) rtapi_->setErrorCallback(errorCallback); - } - - //! A basic error reporting function for RtMidi classes. - void error( Error::Type type, std::string errorString ); - protected: - MidiApi *rtapi_; - - Midi():rtapi_(0) {} - ~Midi() - { - if (rtapi_) { - delete rtapi_; - rtapi_ = 0; - } - } - }; - - /**********************************************************************/ - /*! \class MidiIn - \brief A realtime MIDI input class. - - This class provides a common, platform-independent API for - realtime MIDI input. It allows access to a single MIDI input - port. Incoming MIDI messages are either saved to a queue for - retrieval using the getMessage() function or immediately passed to - a user-specified callback function. Create multiple instances of - this class to connect to more than one MIDI device at the same - time. With the OS-X and Linux ALSA 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-2014. - */ - /**********************************************************************/ - - // **************************************************************** // - // - // MidiIn and MidiOut class declarations. - // - // MidiIn / MidiOut are "controllers" used to select an available - // MIDI input or output interface. They present common APIs for the - // user to call but all functionality is implemented by the classes - // MidiInApi, MidiOutApi and their subclasses. MidiIn and MidiOut - // each create an instance of a MidiInApi or MidiOutApi subclass based - // on the user's API choice. If no choice is made, they attempt to - // make a "logical" API selection. - // - // **************************************************************** // - - class MidiIn : public Midi - { - public: - - - //! Default constructor that allows an optional api, client name and queue size. - /*! - An exception will be thrown if a MIDI system initialization - error occurs. The queue size defines the maximum number of - messages that can be held in the MIDI queue (when not using a - callback function). If the queue size limit is reached, - incoming messages will be ignored. - - If no API argument is specified and multiple API support has been - compiled, the default order of use is JACK, ALSA (Linux) and CORE, - JACK (OS-X). - - \param api An optional API id can be specified. - \param clientName An optional Client name can be specified. This - will be used to group the ports that are created - by the application. - \param queueSizeLimit An optional size of the MIDI input queue can be specified. - */ - MidiIn( ApiType api=rtmidi::UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Input Client"), - unsigned int queueSizeLimit = 100 ); - - //! If a MIDI connection is still open, it will be closed by the destructor. - ~MidiIn ( void ) throw(); - - //! Set a callback function to be invoked for incoming MIDI messages. - /*! - The callback function will be called whenever an incoming MIDI - message is received. While not absolutely necessary, it is best - to set the callback function before opening a MIDI port to avoid - leaving some messages in the queue. - - \param callback A callback function must be given. - \param userData Opitionally, a pointer to additional data can be - passed to the callback function whenever it is called. - */ - void setCallback( MidiCallback callback, void *userData = 0 ) - { - if (rtapi_) - static_cast(rtapi_)->setCallback(callback,userData); - } - - //! Cancel use of the current callback function (if one exists). - /*! - Subsequent incoming MIDI messages will be written to the queue - and can be retrieved with the \e getMessage function. - */ - void cancelCallback() - { - if (rtapi_) - static_cast(rtapi_)->cancelCallback(); - } - - //! Specify whether certain MIDI message types should be queued or ignored during input. - /*! - By default, MIDI timing and active sensing messages are ignored - during message input because of their relative high data rates. - MIDI sysex messages are ignored by default as well. Variable - values of "true" imply that the respective message type will be - ignored. - */ - void ignoreTypes( bool midiSysex = true, - bool midiTime = true, - bool midiSense = true ) - { - if (rtapi_) - static_cast(rtapi_)->ignoreTypes(midiSysex, midiTime, midiSense); - } - - //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. - /*! - This function returns immediately whether a new message is - available or not. A valid message is indicated by a non-zero - vector size. An exception is thrown if an error occurs during - message retrieval or an input connection was not previously - established. - */ - double getMessage( std::vector &message ) - { - if (rtapi_) - return static_cast(rtapi_)->getMessage(message); - std::string errorString_ = "MidiIn::getMessage: No valid API found."; - error( Error::WARNING, errorString_ ); - return 0.0; - } - - //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. - /*! - This function returns immediately whether a new message is - available or not. A valid message is indicated by a non-zero - vector size. An exception is thrown if an error occurs during - message retrieval or an input connection was not previously - established. - - \deprecated - */ - RTMIDI_DEPRECATED(double getMessage( std::vector *message )) - { - if (!message) { - error( Error::WARNING, - "MidiIn::getMessage: passed NULL pointer"); - } - if (rtapi_) - return static_cast(rtapi_)->getMessage(*message); - error( Error::WARNING, - "MidiIn::getMessage: No valid API found."); - return 0.0; - } - - protected: - void openMidiApi( ApiType api, const std::string clientName, unsigned int queueSizeLimit ); - - }; - - /**********************************************************************/ - /*! \class MidiOut - \brief A realtime MIDI output class. - - This class provides a common, platform-independent API for MIDI - output. It allows one to probe available MIDI output ports, to - connect to one such port, and to send MIDI bytes immediately over - the connection. Create multiple instances of this class to - connect to more than one MIDI device at the same time. With the - OS-X and Linux ALSA MIDI APIs, it is also possible to open a - virtual port to which other MIDI software clients can connect. - - by Gary P. Scavone, 2003-2014. - */ - /**********************************************************************/ - - class MidiOut : public Midi - { - public: - - //! Default constructor that allows an optional client name. - /*! - An exception will be thrown if a MIDI system initialization error occurs. - - If no API argument is specified and multiple API support has been - compiled, the default order of use is JACK, ALSA (Linux) and CORE, - JACK (OS-X). - */ - MidiOut( ApiType api=rtmidi::UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Output Client") ); - - //! The destructor closes any open MIDI connections. - ~MidiOut( void ) throw(); - - //! Immediately send a single message out an open MIDI output port. - /*! - An exception is thrown if an error occurs during output or an - output connection was not previously established. - - \deprecated - */ - RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) - { - if (!message) { - error( Error::WARNING, - "MidiOutApi::sendMessage: no data in message argument!"); - } - if (rtapi_) - static_cast(rtapi_)->sendMessage(*message); - error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); - } - - - //! Immediately send a single message out an open MIDI output port. - /*! - An exception is thrown if an error occurs during output or an - output connection was not previously established. - */ - void sendMessage( std::vector &message ) { - if (rtapi_) - static_cast(rtapi_)->sendMessage(message); - error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); - } - protected: - void openMidiApi( ApiType api, const std::string clientName ); - }; - - - // **************************************************************** // - // - // MidiInApi and MidiOutApi subclass prototypes. - // - // **************************************************************** // +class MidiApi; + +struct PortDescriptor { + //! Flags for formatting a string description of the port. + /*! These flags just mark the requirements that the string + should fulfil. An API may return the same string for + different requirements e.g. the same short and long + name. */ + enum NamingType { + SHORT_NAME =0, /*!< A short human readable name + depending on the API + e.g. “Ensoniq AudioPCI” */ + LONG_NAME, /*!< A complete human readable + name depending on the API + e.g. "Ensoniq AudioPCI: ES1371" */ + SESSION_PATH, /*!< A unique description that can + be used to identify the port + during runtime. It may be a + cryptic string. */ + STORAGE_PATH, /*!< A unique description that is + optimised for storage in + configuration files. This is a + more textual representation that + is more robust to small changes in + the surrounding environment than + \ref SESSION_PATH */ + NAMING_MASK = 0x0F, /*!< part of the flags + that is concerned with + naming. + */ + UNIQUE_NAME = 0x10, /*!< Make all names uniqe. This + is usually done by adding + numbers to the end of the + string */ + INCLUDE_API = 0x20 /*!< Add a string describing the + API at the beginning of the + string. */ + }; + + //! Flags describing the capabilities of a given port. + enum PortCapabilities { + INPUT = 1, /*!< Ports that can be read from. */ + OUTPUT = 2, /*!< Ports that can be written to. */ + INOUTPUT = 3, /*!< Ports that allow reading and writing (INPUT | OUTPUT) */ + UNLIMITED = 0x10 /*!< Some APIs can filter out certain ports which they consider + not to be useful. This flags supresses this behaviour and + selects all ports that are useable. */ + }; + + //! Default constructor. + /*! + * Derived classes should have a constructor. + */ + PortDescriptor() {}; + + //! A virtual destructor + /*! As we might have to destruct the object from the application code + * each port id must have a virtual destructor. + */ + virtual ~PortDescriptor() {}; + + //! Get the MIDI api for the current port. + /*! This is the only information RtMidi needs to know: Which + * API should handle this object. + * + * \return API that can handle this object. + */ + virtual MidiApi * getAPI() = 0; + + //! Return the port name + /*! + * \param flags A description of the requirements of the returned name. + * \return A name that is formatted according to \ref flags. + * \sa NamingTypes + */ + virtual std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) = 0; + + //! Get capabilities + /*! \return a capabilities flag describing the capabilities of the port. + * \sa PortCapabilities + */ + virtual int getCapabilities() = 0; +}; + +//! A list of port descriptors. +/*! Port descriptors are stored as shared pointers. This avoids + unnecessary duplication of the data structure and handles automatic + deletion if all references have been removed. */ +typedef std::list > PortList; + + + +// **************************************************************** // +// +// MidiInApi / MidiOutApi class declarations. +// +// Subclasses of MidiInApi and MidiOutApi contain all API- and +// OS-specific code necessary to fully implement the RtMidi API. +// +// Note that MidiInApi and MidiOutApi are abstract base classes and +// cannot be explicitly instantiated. MidiIn and MidiOut will +// create instances of a MidiInApi or MidiOutApi subclass. +// +// **************************************************************** // + +class MidiApi +{ +public: + + MidiApi(); + virtual ~MidiApi(); + + //! Pure virtal function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + */ + virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. + + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. + */ + virtual void openPort( unsigned int portNumber = 0, const std::string & portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + virtual void openPort( const PortDescriptor & port, const std::string & portName = std::string( "RtMidi" ) ) = 0; + + //! Open a MIDI connection given by a port descriptor pointer. + /*! + \param port A pointer to a port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + \sa openPort(const PortDescriptor &,const std::string &); + */ + void openPort( Pointer p, const std::string & portName = std::string( "RtMidi" ) ) { + if (!p) { + errorString_ = "MidiApi::openPort: passed NULL pointer"; + error( Error::INVALID_PARAMETER, errorString_ ); + return; + } + openPort(*p, portName); + } + + //! Pure virtual function to return a port descirptor if the port is open + virtual Pointer getDescriptor() = 0; + + //! Pure virtual function to return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that describes which + capabilities the device typu + + \return This function returns a list of port descriptors. + + \note An input API may but need not necessarily report + output devices which cannot be used as input if + \ref 0 is passed as \ref capabilities parameter. + \sa PortDescriptor::PortCapabilitiers + */ + virtual PortList getPortList(int capabilities = 0) = 0; + + //! Pure virtual to return the number of available MIDI ports of the current API. + /*! + \return This function returns the number of MIDI ports of + the selected API. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortName + */ + virtual unsigned int getPortCount() = 0; + + //! Pure virtual function to return a string identifier for the specified MIDI port number. + /*! + \param portNumber Number of the device to be referred to. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortCount() + */ + virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; + + //! Pure virtual function to close an open MIDI connection (if one exists). + virtual void closePort( void ) = 0; + + // ! A basic error reporting function for RtMidi classes. + // static void error( Error::Type type, std::string &errorString ); + + //! Pure virtual function to return whether a port is open or not. + /*! \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). + */ + bool isPortOpen() const { return connected_; } + + //! Pure virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + virtual void setErrorCallback( ErrorCallback errorCallback = NULL ); + + + //! Returns the MIDI API specifier for the current instance of RtMidiIn. + virtual ApiType getCurrentApi( void ) throw() = 0; + + //! A basic error reporting function for RtMidi classes. + void error( Error::Type type, std::string errorString ); + +protected: + virtual void initialize( const std::string& clientName ) = 0; + + void *apiData_; + bool connected_; + std::string errorString_; + ErrorCallback errorCallback_; +}; + +class MidiInApi : public MidiApi +{ +public: + + MidiInApi( unsigned int queueSizeLimit ); + virtual ~MidiInApi( void ); + void setCallback( MidiCallback callback, void *userData ); + void cancelCallback( void ); + virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); + RTMIDI_DEPRECATED(double getMessage( std::vector *message )) + { + if (!message) { + errorString_ = "MidiInApi::getMessage: passed NULL pointer"; + error( Error::WARNING, errorString_ ); + } + return getMessage(*message); + } + double getMessage( std::vector &message ); + + // A MIDI structure used internally by the class to store incoming + // messages. Each message represents one and only one MIDI message. + struct MidiMessage { + std::vector bytes; + double timeStamp; + + // Default constructor. + MidiMessage() + :bytes(0), timeStamp(0.0) {} + }; + + struct MidiQueue { + unsigned int front; + unsigned int back; + unsigned int size; + unsigned int ringSize; + MidiMessage *ring; + + // Default constructor. + MidiQueue() + :front(0), back(0), size(0), ringSize(0) {} + }; + + // The RtMidiInData structure is used to pass private class data to + // the MIDI input handling function or thread. + struct MidiInData { + MidiQueue queue; + MidiMessage message; + unsigned char ignoreFlags; + bool doInput; + bool firstMessage; + void *apiData; + bool usingCallback; + MidiCallback userCallback; + void *userData; + bool continueSysex; + + // Default constructor. + MidiInData() + : ignoreFlags(7), doInput(false), firstMessage(true), + apiData(0), usingCallback(false), userCallback(0), userData(0), + continueSysex(false) {} + }; + +protected: + MidiInData inputData_; +}; + +class MidiOutApi : public MidiApi +{ +public: + + MidiOutApi( void ); + virtual ~MidiOutApi( void ); + RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) + { + if (!message) { + errorString_ = "MidiOutApi::sendMessage: no data in message argument!"; + error( Error::WARNING, errorString_ ); + } + sendMessage(*message); + } + virtual void sendMessage( std::vector &message ) = 0; +}; + + +/*! \class Midi + \brief A global class that implements basic backend API handling. + + This class enhances \ref MidiApi by some functionality to handle + backend API objects. It serves as base class for the public RtMidi + API. + + by Gary P. Scavone, 2003-2014. +*/ +/**********************************************************************/ +class Midi { +public: + typedef rtmidi::ApiType Api; + //! defined for compatibility + enum Api2 { + UNSPECIFIED = rtmidi::UNSPECIFIED, + MACOSX_CORE = rtmidi::MACOSX_CORE, + LINUX_ALSA = rtmidi::LINUX_ALSA, + UNIX_JACK = rtmidi::UNIX_JACK, + WINDOWS_MM = rtmidi::WINDOWS_MM, + WINDOWS_KS = rtmidi::WINDOWS_KS, + RTMIDI_DUMMY = rtmidi::RTMIDI_DUMMY + }; + + + //! A static function to determine the current RtMidi version. + static std::string getVersion( void ) throw(); + + //! A static function to determine the available compiled MIDI APIs. + /*! + The values returned in the std::vector can be compared against + the enumerated list values. Note that there can be more than one + API compiled for certain operating systems. + */ + static void getCompiledApi( std::vector &apis ) throw(); + + //! Returns the MIDI API specifier for the current instance of RtMidiIn. + ApiType getCurrentApi( void ) throw() + { + if (rtapi_) return rtapi_->getCurrentApi(); + else return rtmidi::UNSPECIFIED; + } + + //! Function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + */ + void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) + { + if (rtapi_) rtapi_->openVirtualPort(portName); + } + + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. + + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. + */ + void openPort( unsigned int portNumber = 0, + const std::string portName = std::string( "RtMidi" ) ) + { + if (rtapi_) rtapi_->openPort(portNumber,portName); + } + + //! Pure virtual function to open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + void openPort( const PortDescriptor & port, + const std::string & portName = std::string( "RtMidi" ) ) + { + if (rtapi_) rtapi_->openPort(port,portName); + } + + //! Open a MIDI connection given by a port descriptor pointer. + /*! + \param port A pointer to a port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + \sa openPort(const PortDescriptor &,const std::string &); + */ + void openPort( Pointer p, + const std::string & portName = std::string( "RtMidi" ) ) { + if (!p) { + error( Error::INVALID_PARAMETER, "MidiApi::openPort: passed NULL pointer" ); + return; + } + openPort(*p, portName); + } + + //! Pure virtual function to return a port descirptor if the port is open + Pointer getDescriptor() + { + if (rtapi_) return rtapi_->getDescriptor(); + return 0; + } + + //! Return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that + describes which capabilities the returned devices + must support. The returned devices may have + additional capabilities to those which have been + requested, but not less. + + \return This function returns a list of port descriptors. + + \note Each API will request additonal + capabilites. An output API will set always add \ref + PortDescriptor::OUTPUT to the mask while an input + device will always add \ref PortDescriptor::OUTPUT. + + \note An input API may but need not necessarily + report output devices which cannot be used as input + if \ref PortDescriptor::OUTPUT is passed as \ref + capabilities parameter. + */ + PortList getPortList(int capabilities = 0) + { + if (rtapi_) return rtapi_->getPortList(capabilities); + return PortList(); + } + + //! Pure virtual to return the number of available MIDI ports of the current API. + /*! + \return This function returns the number of MIDI ports of + the selected API. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortName + */ + unsigned int getPortCount() + { + if (rtapi_) return rtapi_->getPortCount(); + return 0; + } + + //! Pure virtual function to return a string identifier for the specified MIDI port number. + /*! + \param portNumber Number of the device to be referred to. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortCount() + */ + std::string getPortName( unsigned int portNumber = 0 ) + { + if (rtapi_) return rtapi_->getPortName(portNumber); + return ""; + } + + //! Close an open MIDI connection (if one exists). + void closePort( void ) + { + if (rtapi_) rtapi_->closePort(); + } + + // ! A basic error reporting function for RtMidi classes. + // static void error( Error::Type type, std::string &errorString ); + + //! Pure virtual function to return whether a port is open or not. + /*! \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). + */ + bool isPortOpen( void ) const + { + if (rtapi_) return rtapi_->isPortOpen(); + return false; + } + + //! Pure virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + void setErrorCallback( ErrorCallback errorCallback = NULL ) + { + if (rtapi_) rtapi_->setErrorCallback(errorCallback); + } + + //! A basic error reporting function for RtMidi classes. + void error( Error::Type type, std::string errorString ); +protected: + MidiApi *rtapi_; + + Midi():rtapi_(0) {} + ~Midi() + { + if (rtapi_) { + delete rtapi_; + rtapi_ = 0; + } + } +}; + +/**********************************************************************/ +/*! \class MidiIn + \brief A realtime MIDI input class. + + This class provides a common, platform-independent API for + realtime MIDI input. It allows access to a single MIDI input + port. Incoming MIDI messages are either saved to a queue for + retrieval using the getMessage() function or immediately passed to + a user-specified callback function. Create multiple instances of + this class to connect to more than one MIDI device at the same + time. With the OS-X and Linux ALSA 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-2014. +*/ +/**********************************************************************/ + +// **************************************************************** // +// +// MidiIn and MidiOut class declarations. +// +// MidiIn / MidiOut are "controllers" used to select an available +// MIDI input or output interface. They present common APIs for the +// user to call but all functionality is implemented by the classes +// MidiInApi, MidiOutApi and their subclasses. MidiIn and MidiOut +// each create an instance of a MidiInApi or MidiOutApi subclass based +// on the user's API choice. If no choice is made, they attempt to +// make a "logical" API selection. +// +// **************************************************************** // + +class MidiIn : public Midi +{ +public: + + + //! Default constructor that allows an optional api, client name and queue size. + /*! + An exception will be thrown if a MIDI system initialization + error occurs. The queue size defines the maximum number of + messages that can be held in the MIDI queue (when not using a + callback function). If the queue size limit is reached, + incoming messages will be ignored. + + If no API argument is specified and multiple API support has been + compiled, the default order of use is JACK, ALSA (Linux) and CORE, + JACK (OS-X). + + \param api An optional API id can be specified. + \param clientName An optional Client name can be specified. This + will be used to group the ports that are created + by the application. + \param queueSizeLimit An optional size of the MIDI input queue can be specified. + */ + MidiIn( ApiType api=rtmidi::UNSPECIFIED, + const std::string clientName = std::string( "RtMidi Input Client"), + unsigned int queueSizeLimit = 100 ); + + //! If a MIDI connection is still open, it will be closed by the destructor. + ~MidiIn ( void ) throw(); + + //! Set a callback function to be invoked for incoming MIDI messages. + /*! + The callback function will be called whenever an incoming MIDI + message is received. While not absolutely necessary, it is best + to set the callback function before opening a MIDI port to avoid + leaving some messages in the queue. + + \param callback A callback function must be given. + \param userData Opitionally, a pointer to additional data can be + passed to the callback function whenever it is called. + */ + void setCallback( MidiCallback callback, void *userData = 0 ) + { + if (rtapi_) + static_cast(rtapi_)->setCallback(callback,userData); + } + + //! Cancel use of the current callback function (if one exists). + /*! + Subsequent incoming MIDI messages will be written to the queue + and can be retrieved with the \e getMessage function. + */ + void cancelCallback() + { + if (rtapi_) + static_cast(rtapi_)->cancelCallback(); + } + + //! Specify whether certain MIDI message types should be queued or ignored during input. + /*! + By default, MIDI timing and active sensing messages are ignored + during message input because of their relative high data rates. + MIDI sysex messages are ignored by default as well. Variable + values of "true" imply that the respective message type will be + ignored. + */ + void ignoreTypes( bool midiSysex = true, + bool midiTime = true, + bool midiSense = true ) + { + if (rtapi_) + static_cast(rtapi_)->ignoreTypes(midiSysex, midiTime, midiSense); + } + + //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. + /*! + This function returns immediately whether a new message is + available or not. A valid message is indicated by a non-zero + vector size. An exception is thrown if an error occurs during + message retrieval or an input connection was not previously + established. + */ + double getMessage( std::vector &message ) + { + if (rtapi_) + return static_cast(rtapi_)->getMessage(message); + std::string errorString_ = "MidiIn::getMessage: No valid API found."; + error( Error::WARNING, errorString_ ); + return 0.0; + } + + //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. + /*! + This function returns immediately whether a new message is + available or not. A valid message is indicated by a non-zero + vector size. An exception is thrown if an error occurs during + message retrieval or an input connection was not previously + established. + + \deprecated + */ + RTMIDI_DEPRECATED(double getMessage( std::vector *message )) + { + if (!message) { + error( Error::WARNING, + "MidiIn::getMessage: passed NULL pointer"); + } + if (rtapi_) + return static_cast(rtapi_)->getMessage(*message); + error( Error::WARNING, + "MidiIn::getMessage: No valid API found."); + return 0.0; + } + +protected: + void openMidiApi( ApiType api, const std::string clientName, unsigned int queueSizeLimit ); + +}; + +/**********************************************************************/ +/*! \class MidiOut + \brief A realtime MIDI output class. + + This class provides a common, platform-independent API for MIDI + output. It allows one to probe available MIDI output ports, to + connect to one such port, and to send MIDI bytes immediately over + the connection. Create multiple instances of this class to + connect to more than one MIDI device at the same time. With the + OS-X and Linux ALSA MIDI APIs, it is also possible to open a + virtual port to which other MIDI software clients can connect. + + by Gary P. Scavone, 2003-2014. +*/ +/**********************************************************************/ + +class MidiOut : public Midi +{ +public: + + //! Default constructor that allows an optional client name. + /*! + An exception will be thrown if a MIDI system initialization error occurs. + + If no API argument is specified and multiple API support has been + compiled, the default order of use is JACK, ALSA (Linux) and CORE, + JACK (OS-X). + */ + MidiOut( ApiType api=rtmidi::UNSPECIFIED, + const std::string clientName = std::string( "RtMidi Output Client") ); + + //! The destructor closes any open MIDI connections. + ~MidiOut( void ) throw(); + + //! Immediately send a single message out an open MIDI output port. + /*! + An exception is thrown if an error occurs during output or an + output connection was not previously established. + + \deprecated + */ + RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) + { + if (!message) { + error( Error::WARNING, + "MidiOutApi::sendMessage: no data in message argument!"); + } + if (rtapi_) + static_cast(rtapi_)->sendMessage(*message); + error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); + } + + + //! Immediately send a single message out an open MIDI output port. + /*! + An exception is thrown if an error occurs during output or an + output connection was not previously established. + */ + void sendMessage( std::vector &message ) { + if (rtapi_) + static_cast(rtapi_)->sendMessage(message); + error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); + } +protected: + void openMidiApi( ApiType api, const std::string clientName ); +}; + + +// **************************************************************** // +// +// MidiInApi and MidiOutApi subclass prototypes. +// +// **************************************************************** // #if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__) #define __RTMIDI_DUMMY__ @@ -986,227 +986,227 @@ typedef void (*ErrorCallback)( Error::Type type, const std::string &errorText ); #if defined(__MACOSX_CORE__) - class MidiInCore: public MidiInApi - { - public: - MidiInCore( const std::string clientName, unsigned int queueSizeLimit ); - ~MidiInCore( void ); - ApiType getCurrentApi( void ) { return MACOSX_CORE; }; - void openPort( unsigned int portNumber, const std::string & portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string & portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - 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 ); - ApiType getCurrentApi( void ) { return MACOSX_CORE; }; - void openPort( unsigned int portNumber, const std::string & portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string & portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector &message ); - - protected: - void initialize( const std::string& clientName ); - }; +class MidiInCore: public MidiInApi +{ +public: + MidiInCore( const std::string clientName, unsigned int queueSizeLimit ); + ~MidiInCore( void ); + ApiType getCurrentApi( void ) { return MACOSX_CORE; }; + void openPort( unsigned int portNumber, const std::string & portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string & portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + 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 ); + ApiType getCurrentApi( void ) { return MACOSX_CORE; }; + void openPort( unsigned int portNumber, const std::string & portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string & portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + void closePort( void ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( std::vector &message ); + +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 ); - ApiType getCurrentApi( void ) { return UNIX_JACK; }; - void openPort( unsigned int portNumber, const std::string & portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string & portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - 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 ); - ApiType getCurrentApi( void ) { return UNIX_JACK; }; - void openPort( unsigned int portNumber, const std::string & portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string & portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector &message ); - - protected: - std::string clientName; - - void connect( void ); - void initialize( const std::string& clientName ); - }; +class MidiInJack: public MidiInApi +{ +public: + MidiInJack( const std::string clientName, unsigned int queueSizeLimit ); + ~MidiInJack( void ); + ApiType getCurrentApi( void ) { return UNIX_JACK; }; + void openPort( unsigned int portNumber, const std::string & portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string & portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + 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 ); + ApiType getCurrentApi( void ) { return UNIX_JACK; }; + void openPort( unsigned int portNumber, const std::string & portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string & portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + void closePort( void ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( std::vector &message ); + +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 ); - ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; - void openPort( unsigned int portNumber, const std::string & portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string & portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - 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 ); - ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; - void openPort( unsigned int portNumber, const std::string & portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string & portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector &message ); - - protected: - void initialize( const std::string& clientName ); - }; +class MidiInAlsa: public MidiInApi +{ +public: + MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit ); + ~MidiInAlsa( void ); + ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; + void openPort( unsigned int portNumber, const std::string & portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string & portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + 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 ); + ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; + void openPort( unsigned int portNumber, const std::string & portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string & portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + void closePort( void ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( std::vector &message ); + +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 ); - ApiType getCurrentApi( void ) { return WINDOWS_MM; }; - void openPort( unsigned int portNumber, const std::string & portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string & portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - 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 ); - ApiType getCurrentApi( void ) { return WINDOWS_MM; }; - void openPort( unsigned int portNumber, const std::string & portName ); - void openVirtualPort( const std::string portName ); - void openPort( const PortDescriptor & port, const std::string & portName); - Pointer getDescriptor(); - PortList getPortList(int capabilities); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector &message ); - - protected: - void initialize( const std::string& clientName ); - }; +class MidiInWinMM: public MidiInApi +{ +public: + MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ); + ~MidiInWinMM( void ); + ApiType getCurrentApi( void ) { return WINDOWS_MM; }; + void openPort( unsigned int portNumber, const std::string & portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string & portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + 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 ); + ApiType getCurrentApi( void ) { return WINDOWS_MM; }; + void openPort( unsigned int portNumber, const std::string & portName ); + void openVirtualPort( const std::string portName ); + void openPort( const PortDescriptor & port, const std::string & portName); + Pointer getDescriptor(); + PortList getPortList(int capabilities); + void closePort( void ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( std::vector &message ); + +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( Error::WARNING, errorString_ ); - } - ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } - void openPort( unsigned int /*portNumber*/, const & std::string /*portName*/ ) {} - void openVirtualPort( const std::string /*portName*/ ) {} - void openPort( const PortDescriptor & port, const & std::string portName) {} - Pointer getDescriptor() { return 0; } - PortList getPortList(int capabilities) { return PortList(); } - 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( Error::WARNING, errorString_ ); - } - ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } - void openPort( unsigned int /*portNumber*/, const & std::string /*portName*/ ) {} - void openVirtualPort( const std::string /*portName*/ ) {} - void openPort( const PortDescriptor & port, const & std::string portName) {} - Pointer getDescriptor() { return 0; } - PortList getPortList(int capabilities) { return PortList(); } - void closePort( void ) {} - unsigned int getPortCount( void ) { return 0; } - std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } - void sendMessage( std::vector & /*message*/ ) {} - - protected: - void initialize( const std::string& /*clientName*/ ) {} - }; +class MidiInDummy: public MidiInApi +{ +public: + MidiInDummy( const std::string /*clientName*/, unsigned int queueSizeLimit ) + : MidiInApi( queueSizeLimit ) { + errorString_ = "MidiInDummy: This class provides no functionality."; + error( Error::WARNING, errorString_ ); + } + ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } + void openPort( unsigned int /*portNumber*/, const & std::string /*portName*/ ) {} + void openVirtualPort( const std::string /*portName*/ ) {} + void openPort( const PortDescriptor & port, const & std::string portName) {} + Pointer getDescriptor() { return 0; } + PortList getPortList(int capabilities) { return PortList(); } + 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( Error::WARNING, errorString_ ); + } + ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } + void openPort( unsigned int /*portNumber*/, const & std::string /*portName*/ ) {} + void openVirtualPort( const std::string /*portName*/ ) {} + void openPort( const PortDescriptor & port, const & std::string portName) {} + Pointer getDescriptor() { return 0; } + PortList getPortList(int capabilities) { return PortList(); } + void closePort( void ) {} + unsigned int getPortCount( void ) { return 0; } + std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } + void sendMessage( std::vector & /*message*/ ) {} + +protected: + void initialize( const std::string& /*clientName*/ ) {} +}; #endif From b39eb3da5411c772af474cf540562c3dff4fa795 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 5 Apr 2014 10:47:54 +0200 Subject: [PATCH 017/210] Implement some functions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MidiInAlsa::openPort MidiInAlsa::getPortList MidiOutAlsa::getPortList Now, we can do some first tests. Test files follow… --- RtMidi.cpp | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 14c7bf69..2410c42b 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -2032,7 +2032,42 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string & portNa void MidiInAlsa :: openPort( const PortDescriptor & port, const std::string & portName) { - abort(); + AlsaMidiData *data = static_cast (apiData_); + const AlsaPortDescriptor * remote = dynamic_cast(&port); + + if ( !data ) { + errorString_ = "MidiInAlsa::openPort: Internal error: data has not been allocated!"; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + if ( connected_ ) { + errorString_ = "MidiInAlsa::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + if (data->subscription) { + error( Error::DRIVER_ERROR, + "MidiInAlsa::openPort: ALSA error allocation port subscription." ); + return; + } + if (!remote) { + errorString_ = "MidiInAlsa::openPort: an invalid (i.e. non-ALSA) port descriptor has been passed to openPort!"; + error( Error::WARNING, errorString_ ); + return; + } + + if (!data->local.client) + data->openPort (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, + portName); + data->setRemote(remote); + data->connectPorts(*remote,data->local); + + + if ( inputData_.doInput == false ) { + inputData_.doInput = data->startQueue(&inputData_); + } + + connected_ = true; } Pointer MidiInAlsa :: getDescriptor() @@ -2041,7 +2076,7 @@ Pointer MidiInAlsa :: getDescriptor() } PortList MidiInAlsa :: getPortList(int capabilities) { - abort(); + return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::INPUT); } @@ -2383,7 +2418,7 @@ Pointer MidiOutAlsa :: getDescriptor() } PortList MidiOutAlsa :: getPortList(int capabilities) { - abort(); + return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT); } NAMSPACE_RTMIDI_END #endif // __LINUX_ALSA__ From 1056eac7f8c7a9d523dbe538d65f1e5ed11ebcfa Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 5 Apr 2014 10:50:31 +0200 Subject: [PATCH 018/210] Add first tests for the new port selection API. --- tests/Makefile.in | 8 ++- tests/cmidiin2.cpp | 113 ++++++++++++++++++++++++++++++++++++ tests/midiprobe2.cpp | 134 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 tests/cmidiin2.cpp create mode 100644 tests/midiprobe2.cpp diff --git a/tests/Makefile.in b/tests/Makefile.in index 1826737e..6fe470bd 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -1,7 +1,7 @@ ### Do not edit -- Generated by 'configure --with-whatever' from Makefile.in ### RtMidi tests Makefile - for various flavors of unix -PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest +PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest midiprobe2 cmidiin2 RM = /bin/rm SRC_PATH = .. INCLUDE = .. @@ -24,6 +24,9 @@ all : $(PROGRAMS) midiprobe : midiprobe.cpp $(OBJECTS) $(CC) $(CFLAGS) $(DEFS) -o midiprobe midiprobe.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) +midiprobe2 : midiprobe2.cpp $(OBJECTS) + $(CC) $(CFLAGS) $(DEFS) -o midiprobe2 midiprobe2.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) + midiout : midiout.cpp $(OBJECTS) $(CC) $(CFLAGS) $(DEFS) -o midiout midiout.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) @@ -33,6 +36,9 @@ qmidiin : qmidiin.cpp $(OBJECTS) cmidiin : cmidiin.cpp $(OBJECTS) $(CC) $(CFLAGS) $(DEFS) -o cmidiin cmidiin.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) +cmidiin2 : cmidiin2.cpp $(OBJECTS) + $(CC) $(CFLAGS) $(DEFS) -o cmidiin2 cmidiin2.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) + sysextest : sysextest.cpp $(OBJECTS) $(CC) $(CFLAGS) $(DEFS) -o sysextest sysextest.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) diff --git a/tests/cmidiin2.cpp b/tests/cmidiin2.cpp new file mode 100644 index 00000000..0d16eea9 --- /dev/null +++ b/tests/cmidiin2.cpp @@ -0,0 +1,113 @@ +//*****************************************// +// cmidiin.cpp +// by Gary Scavone, 2003-2004. +// +// Simple program to test MIDI input and +// use of a user callback function. +// +//*****************************************// + +#include +#include +#include "RtMidi.h" + +void usage( void ) { + // Error function in case of incorrect command-line + // argument specifications. + std::cout << "\nuseage: cmidiin2 \n"; + std::cout << " where port = the device to use (default = 0).\n\n"; + exit( 0 ); +} + +void mycallback( double deltatime, std::vector< unsigned char > *message, void * /* userData */ ) +{ + unsigned int nBytes = message->size(); + for ( unsigned int i=0; i 0 ) + std::cout << "stamp = " << deltatime << std::endl; +} + +// This function should be embedded in a try/catch block in case of +// an exception. It offers the user a choice of MIDI ports to open. +// It returns false if there are no ports available. +bool chooseMidiPort( RtMidiIn &rtmidi ); + +int main( int argc, char */*argv*/[] ) +{ + + // Minimal command-line check. + if ( argc > 2 ) usage(); + + try { + + // RtMidiIn constructor + RtMidiIn midiin; + + // Call function to select port. + if ( chooseMidiPort( midiin ) == false ) return 0; + + // Set our callback function. This should be done immediately after + // opening the port to avoid having incoming messages written to the + // queue instead of sent to the callback function. + midiin.setCallback( &mycallback ); + + // Don't ignore sysex, timing, or active sensing messages. + midiin.ignoreTypes( false, false, false ); + + std::cout << "\nReading MIDI input ... press to quit.\n"; + char input; + std::cin.get(input); + + } catch ( RtMidiError &error ) { + error.printMessage(); + } +} + +bool chooseMidiPort( RtMidiIn &midi ) +{ + std::cout << "\nWould you like to open a virtual input port? [y/N] "; + + std::string keyHit; + std::getline( std::cin, keyHit ); + if ( keyHit == "y" ) { + midi.openVirtualPort(); + return true; + } + + std::string portName; + rtmidi::PortList list = midi.getPortList(rtmidi::PortDescriptor::INPUT); + if ( list.empty() ) { + std::cout << "No input ports available!" << std::endl; + return false; + } + + rtmidi::Pointer selected = list.front(); + if ( list.size() == 1 ) { + std::cout << "\nOpening " << selected->getName() << std::endl; + } else { + int nr; + std::vector > pointers(list.size()); + // copy the data into a structure that is used by the user interface. + std::copy(list.begin(),list.end(),pointers.begin()); + for (nr = 0 ; nr < (int)pointers.size(); nr++) { + portName = pointers[nr]->getName(rtmidi::PortDescriptor::LONG_NAME + | rtmidi::PortDescriptor::UNIQUE_NAME + | rtmidi::PortDescriptor::INCLUDE_API); + std::cout << " Input port #" << nr << ": " << portName << '\n'; + } + + do { + std::cout << "\nChoose a port number: "; + std::cin >> nr; + } while ( nr >= (int)pointers.size() ); + std::getline( std::cin, keyHit ); // used to clear out stdin + selected = pointers[nr]; + } + + /* The midi setup might have changed meanwhile. + Our portlist is under our control. So we enumerate this list. */ + // midi.openPort( i ); + midi.openPort(selected); + return true; +} diff --git a/tests/midiprobe2.cpp b/tests/midiprobe2.cpp new file mode 100644 index 00000000..9c599c9e --- /dev/null +++ b/tests/midiprobe2.cpp @@ -0,0 +1,134 @@ +// midiprobe.cpp +// +// Simple program to check MIDI inputs and outputs. +// +// by Gary Scavone, 2003-2012. + +#include +#include +#include +#include "RtMidi.h" + +int main() +{ + // Create an api map. + std::map apiMap; + apiMap[RtMidi::MACOSX_CORE] = "OS-X CoreMidi"; + apiMap[RtMidi::WINDOWS_MM] = "Windows MultiMedia"; + apiMap[RtMidi::WINDOWS_KS] = "Windows Kernel Straming"; + apiMap[RtMidi::UNIX_JACK] = "Jack Client"; + apiMap[RtMidi::LINUX_ALSA] = "Linux ALSA"; + apiMap[RtMidi::RTMIDI_DUMMY] = "RtMidi Dummy"; + + std::vector< RtMidi::Api > apis; + RtMidi :: getCompiledApi( apis ); + + std::cout << "\nCompiled APIs:\n"; + for ( unsigned int i=0; igetName() << std::endl; + for (int j = 0 ; j < 4 ; j++ ) { + std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME) << std::endl; + std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME + | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << std::endl; + } + std::cout << std::endl; + } + + std::cout << "**********************************************************************" << std::endl; + + // RtMidiOut constructor ... exception possible + RtMidiOut midiout; + + std::cout << "\nCurrent output API: " << apiMap[ midiout.getCurrentApi() ] << std::endl; + + list = midiout.getPortList(); + + // Check inputs. + std::cout << "\nThere are " << list.size() << " MIDI output sinks available.\n"; + + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); + i++) { + std::cout << " Output Port: " << (*i)->getName() << std::endl; + for (int j = 0 ; j < 4 ; j++ ) { + std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME) << std::endl; + std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME + | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << std::endl; + } + std::cout << std::endl; + } + + std::cout << "**********************************************************************" << std::endl; + std::cout << "* entering unlimited mode *" << std::endl; + std::cout << "**********************************************************************" << std::endl; + + list = midiin.getPortList(rtmidi::PortDescriptor::UNLIMITED); + // Check inputs. + std::cout << "\nThere are " << list.size() << " MIDI input sources available in unlimited mode.\n"; + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); + i++) { + std::cout << " Input Port: " << (*i)->getName() << std::endl; + for (int j = 0 ; j < 4 ; j++ ) { + std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME) << std::endl; + std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME + | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << std::endl; + } + std::cout << std::endl; + } + + std::cout << "**********************************************************************" << std::endl; + list = midiout.getPortList(rtmidi::PortDescriptor::UNLIMITED); + + // Check inputs. + std::cout << "\nThere are " << list.size() << " MIDI output sinks available in unlimited mode.\n"; + + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); + i++) { + std::cout << " Output Port: " << (*i)->getName() << std::endl; + for (int j = 0 ; j < 4 ; j++ ) { + std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME) << std::endl; + std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME + | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << std::endl; + } + std::cout << std::endl; + } + + + + } catch ( RtMidiError &error ) { + error.printMessage(); + } + + return 0; +} From e350a7cd4dd8f7bffb5a4745bd0ed8615911cc5a Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 6 Apr 2014 10:50:22 +0200 Subject: [PATCH 019/210] Implement opening ALSA output ports. --- RtMidi.cpp | 51 +++++++++++++-- tests/Makefile.in | 8 ++- tests/midiout2.cpp | 159 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 212 insertions(+), 6 deletions(-) create mode 100644 tests/midiout2.cpp diff --git a/RtMidi.cpp b/RtMidi.cpp index 2410c42b..ca0286e0 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1282,7 +1282,8 @@ class AlsaSequencer { } snd_seq_port_subscribe_t * connectPorts(const snd_seq_addr_t & from, - const snd_seq_addr_t & to) { + const snd_seq_addr_t & to, + bool real_time) { init(); snd_seq_port_subscribe_t *subscription; @@ -1293,6 +1294,10 @@ class AlsaSequencer { } snd_seq_port_subscribe_set_sender(subscription, &from); snd_seq_port_subscribe_set_dest(subscription, &to); + if (real_time) { + snd_seq_port_subscribe_set_time_update(subscription, 1); + snd_seq_port_subscribe_set_time_real(subscription, 1); + } { scoped_lock lock (mutex); if ( snd_seq_subscribe_port(seq, subscription) ) { @@ -1302,8 +1307,8 @@ class AlsaSequencer { Error::DRIVER_ERROR); return 0; } - return subscription; } + return subscription; } void closePort(snd_seq_port_subscribe_t * subscription ) { @@ -1503,8 +1508,9 @@ struct AlsaMidiData:public AlsaPortDescriptor { client = remote->client; } void connectPorts(const snd_seq_addr_t &from, - const snd_seq_addr_t &to) { - subscription = seq.connectPorts(from, to); + const snd_seq_addr_t &to, + bool real_time) { + subscription = seq.connectPorts(from, to, real_time); } int openPort(int alsaCapabilities, @@ -2410,7 +2416,37 @@ void MidiOutAlsa :: sendMessage( std::vector &message ) void MidiOutAlsa :: openPort( const PortDescriptor & port, const std::string & portName) { - abort(); + AlsaMidiData *data = static_cast (apiData_); + const AlsaPortDescriptor * remote = dynamic_cast(&port); + + if ( !data ) { + errorString_ = "MidiOutAlsa::openPort: Internal error: data has not been allocated!"; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + if ( connected_ ) { + errorString_ = "MidiOutAlsa::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + if (data->subscription) { + error( Error::DRIVER_ERROR, + "MidiOutAlsa::openPort: ALSA error allocation port subscription." ); + return; + } + if (!remote) { + errorString_ = "MidiOutAlsa::openPort: an invalid (i.e. non-ALSA) port descriptor has been passed to openPort!"; + error( Error::WARNING, errorString_ ); + return; + } + + if (!data->local.client) + data->openPort (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, + portName); + data->setRemote(remote); + data->connectPorts(data->local,*remote,true); + + connected_ = true; } Pointer MidiOutAlsa :: getDescriptor() { @@ -2420,6 +2456,11 @@ PortList MidiOutAlsa :: getPortList(int capabilities) { return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT); } +} +PortList MidiOutAlsa :: getPortList(int capabilities) +{ + return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT); +} NAMSPACE_RTMIDI_END #endif // __LINUX_ALSA__ diff --git a/tests/Makefile.in b/tests/Makefile.in index 6fe470bd..bea71da1 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -1,7 +1,7 @@ ### Do not edit -- Generated by 'configure --with-whatever' from Makefile.in ### RtMidi tests Makefile - for various flavors of unix -PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest midiprobe2 cmidiin2 +PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest midiprobe2 cmidiin2 qmidiin2 midiout2 RM = /bin/rm SRC_PATH = .. INCLUDE = .. @@ -30,9 +30,15 @@ midiprobe2 : midiprobe2.cpp $(OBJECTS) midiout : midiout.cpp $(OBJECTS) $(CC) $(CFLAGS) $(DEFS) -o midiout midiout.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) +midiout2 : midiout2.cpp $(OBJECTS) + $(CC) $(CFLAGS) $(DEFS) -o midiout2 midiout2.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) + qmidiin : qmidiin.cpp $(OBJECTS) $(CC) $(CFLAGS) $(DEFS) -o qmidiin qmidiin.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) +qmidiin2 : qmidiin2.cpp $(OBJECTS) + $(CC) $(CFLAGS) $(DEFS) -o qmidiin2 qmidiin2.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) + cmidiin : cmidiin.cpp $(OBJECTS) $(CC) $(CFLAGS) $(DEFS) -o cmidiin cmidiin.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) diff --git a/tests/midiout2.cpp b/tests/midiout2.cpp new file mode 100644 index 00000000..5d09b97d --- /dev/null +++ b/tests/midiout2.cpp @@ -0,0 +1,159 @@ +//*****************************************// +// midiout.cpp +// by Gary Scavone, 2003-2004. +// +// Simple program to test MIDI output. +// +//*****************************************// + +#include +#include +#include "RtMidi.h" + +// Platform-dependent sleep routines. +#if defined(__WINDOWS_MM__) +#include +#define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) +#else // Unix variants +#include +#define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) +#endif + +// This function should be embedded in a try/catch block in case of +// an exception. It offers the user a choice of MIDI ports to open. +// It returns false if there are no ports available. +bool chooseMidiPort( RtMidiOut &ortmidi ); + +int main( int /* argc*/, char */*argv*/[] ) +{ + std::vector message; + + // RtMidiOut constructor + try { + RtMidiOut midiout; + + // Call function to select port. + try { + if ( chooseMidiPort( midiout ) == false ) return 1; + } + catch ( RtMidiError &error ) { + error.printMessage(); + return 2; + } + + + SLEEP( 5000 ); + + // Send out a series of MIDI messages. + + // Program change: 192, 5 + message.push_back( 192 ); + message.push_back( 5 ); + midiout.sendMessage( &message ); + + SLEEP( 500 ); + + message[0] = 0xF1; + message[1] = 60; + midiout.sendMessage( &message ); + + // Control Change: 176, 7, 100 (volume) + message[0] = 176; + message[1] = 7; + message.push_back( 100 ); + midiout.sendMessage( &message ); + + // Note On: 144, 64, 90 + message[0] = 144; + message[1] = 64; + message[2] = 90; + midiout.sendMessage( &message ); + + SLEEP( 500 ); + + // Note Off: 128, 64, 40 + message[0] = 128; + message[1] = 64; + message[2] = 40; + midiout.sendMessage( &message ); + + SLEEP( 500 ); + + // Control Change: 176, 7, 40 + message[0] = 176; + message[1] = 7; + message[2] = 40; + midiout.sendMessage( &message ); + + SLEEP( 500 ); + + // Sysex: 240, 67, 4, 3, 2, 247 + message[0] = 240; + message[1] = 67; + message[2] = 4; + message.push_back( 3 ); + message.push_back( 2 ); + message.push_back( 247 ); + midiout.sendMessage( &message ); + + + } + catch ( RtMidiError &error ) { + error.printMessage(); + exit( EXIT_FAILURE ); + } + + return 0; +} + +bool chooseMidiPort( RtMidiOut &midi ) +{ + std::cout << "\nWould you like to open a virtual input port? [y/N] "; + + std::string keyHit; + std::getline( std::cin, keyHit ); + if ( keyHit == "y" ) { + midi.openVirtualPort(); + std::cout << "Press return to start the transmission." << std::endl; + std::getline( std::cin, keyHit ); + + return true; + } + + std::string portName; + rtmidi::PortList list = midi.getPortList(rtmidi::PortDescriptor::INPUT); + if ( list.empty() ) { + std::cout << "No output ports available!" << std::endl; + return false; + } + + rtmidi::Pointer selected = list.front(); + if ( list.size() == 1 ) { + std::cout << "\nOpening " << selected->getName() << std::endl; + } else { + int nr; + std::vector > pointers(list.size()); + // copy the data into a structure that is used by the user interface. + std::copy(list.begin(),list.end(),pointers.begin()); + for (nr = 0 ; nr < (int)pointers.size(); nr++) { + portName = pointers[nr]->getName(rtmidi::PortDescriptor::LONG_NAME + | rtmidi::PortDescriptor::UNIQUE_NAME + | rtmidi::PortDescriptor::INCLUDE_API); + std::cout << " Output port #" << nr << ": " << portName << '\n'; + } + + do { + std::cout << "\nChoose a port number: "; + std::cin >> nr; + } while ( nr >= (int)pointers.size() ); + std::getline( std::cin, keyHit ); // used to clear out stdin + selected = pointers[nr]; + } + + /* The midi setup might have changed meanwhile. + Our portlist is under our control. So we enumerate this list. */ + // midi.openPort( i ); + midi.openPort(selected); + + return true; +} From 3606ea7820e2cc69966507cabceba154ac2a2049 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 6 Apr 2014 10:52:53 +0200 Subject: [PATCH 020/210] Fix port handling of old port handling. This was broken as we use ALSA addresses to store port ids, now. These are stored as unsigned values. --- RtMidi.cpp | 50 +++++++++++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index ca0286e0..0b390d32 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1282,7 +1282,7 @@ class AlsaSequencer { } snd_seq_port_subscribe_t * connectPorts(const snd_seq_addr_t & from, - const snd_seq_addr_t & to, + const snd_seq_addr_t & to, bool real_time) { init(); snd_seq_port_subscribe_t *subscription; @@ -2066,7 +2066,7 @@ void MidiInAlsa :: openPort( const PortDescriptor & port, data->openPort (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, portName); data->setRemote(remote); - data->connectPorts(*remote,data->local); + data->connectPorts(*remote,data->local,false); if ( inputData_.doInput == false ) { @@ -2195,7 +2195,7 @@ MidiOutAlsa :: ~MidiOutAlsa() // Cleanup. AlsaMidiData *data = static_cast (apiData_); - if ( data->local.port >= 0 ) snd_seq_delete_port( data->seq, data->local.port ); + if ( data->local.client > 0 ) snd_seq_delete_port( data->seq, data->local.port ); if ( data->coder ) snd_midi_event_free( data->coder ); if ( data->buffer ) free( data->buffer ); snd_seq_close( data->seq ); @@ -2304,23 +2304,22 @@ void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string & portN return; } - snd_seq_addr_t sender, receiver; - receiver.client = snd_seq_port_info_get_client( pinfo ); - receiver.port = snd_seq_port_info_get_port( pinfo ); - sender.client = snd_seq_client_id( data->seq ); - - if ( data->local.port < 0 ) { - data->local.port = snd_seq_create_simple_port( data->seq, portName.c_str(), - SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, - SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); - if ( data->local.port < 0 ) { + data->client = snd_seq_port_info_get_client( pinfo ); + data->port = snd_seq_port_info_get_port( pinfo ); + data->local.client = snd_seq_client_id( data->seq ); + + if ( !data->local.client ) { + int port = snd_seq_create_simple_port( data->seq, portName.c_str(), + SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, + SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); + if ( port < 0 ) { errorString_ = "MidiOutAlsa::openPort: ALSA error creating output port."; error( Error::DRIVER_ERROR, errorString_ ); return; } - } - sender.port = data->local.port; + data->local.port = port; + } // Make subscription if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { @@ -2329,8 +2328,8 @@ void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string & portN error( Error::DRIVER_ERROR, errorString_ ); return; } - snd_seq_port_subscribe_set_sender(data->subscription, &sender); - snd_seq_port_subscribe_set_dest(data->subscription, &receiver); + snd_seq_port_subscribe_set_sender(data->subscription, data); + snd_seq_port_subscribe_set_dest(data->subscription, &data->local); snd_seq_port_subscribe_set_time_update(data->subscription, 1); snd_seq_port_subscribe_set_time_real(data->subscription, 1); if ( snd_seq_subscribe_port(data->seq, data->subscription) ) { @@ -2356,15 +2355,17 @@ void MidiOutAlsa :: closePort( void ) void MidiOutAlsa :: openVirtualPort( std::string portName ) { AlsaMidiData *data = static_cast (apiData_); - if ( data->local.port < 0 ) { - data->local.port = snd_seq_create_simple_port( data->seq, portName.c_str(), - SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, - SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); + if ( !data->local.client ) { + int port = snd_seq_create_simple_port( data->seq, portName.c_str(), + SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, + SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); - if ( data->local.port < 0 ) { + if ( port < 0 ) { errorString_ = "MidiOutAlsa::openVirtualPort: ALSA error creating virtual port."; error( Error::DRIVER_ERROR, errorString_ ); } + data->local.port = port; + data->local.client = snd_seq_client_id(data->seq); } } @@ -2456,11 +2457,6 @@ PortList MidiOutAlsa :: getPortList(int capabilities) { return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT); } -} -PortList MidiOutAlsa :: getPortList(int capabilities) -{ - return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT); -} NAMSPACE_RTMIDI_END #endif // __LINUX_ALSA__ From 00e8774e0089871f104dcc82094eed2ba71816f6 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 6 Apr 2014 10:53:21 +0200 Subject: [PATCH 021/210] fix sendMessage which got an error. --- RtMidi.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RtMidi.h b/RtMidi.h index 453f3da5..ba465594 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -955,7 +955,8 @@ class MidiOut : public Midi } if (rtapi_) static_cast(rtapi_)->sendMessage(*message); - error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); + else + error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); } From 1d7cddc4c766ef8550f5db0cf219402c11dea766 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 6 Apr 2014 10:55:22 +0200 Subject: [PATCH 022/210] Adapt qmidiin to the new API. --- tests/qmidiin2.cpp | 117 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 tests/qmidiin2.cpp diff --git a/tests/qmidiin2.cpp b/tests/qmidiin2.cpp new file mode 100644 index 00000000..e3e1a996 --- /dev/null +++ b/tests/qmidiin2.cpp @@ -0,0 +1,117 @@ +//*****************************************// +// qmidiin.cpp +// by Gary Scavone, 2003-2004. +// +// Simple program to test MIDI input and +// retrieval from the queue. +// +//*****************************************// + +#include +#include +#include +#include "RtMidi.h" + +// Platform-dependent sleep routines. +#if defined(__WINDOWS_MM__) +#include +#define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) +#else // Unix variants +#include +#define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) +#endif + +bool done; +static void finish( int /*ignore*/ ){ done = true; } + +void usage( rtmidi::PortList list ) { + // Error function in case of incorrect command-line + // argument specifications. + std::cout << "\nusage: qmidiin \n"; + std::cout << " where port = the device to use (default = first available port).\n\n"; + + std::cout << "Available ports:" << std::endl; + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); i++) { + std::cout << (*i)->getName(rtmidi::PortDescriptor::SESSION_PATH | + rtmidi::PortDescriptor::UNIQUE_NAME | + rtmidi::PortDescriptor::INCLUDE_API); + std::cout << "\t"; + std::cout << (*i)->getName() << std::endl; + } + exit( 0 ); +} + +int main( int argc, char *argv[] ) +{ + std::vector message; + int nBytes, i; + double stamp; + + + // RtMidiIn constructor + try { + RtMidiIn midiin; + + + rtmidi::PortList list = midiin.getPortList(); + + // Minimal command-line check. + if ( argc > 2 ) usage(list); + + rtmidi::Pointer port = 0; + // Check available ports vs. specified. + if ( argc == 2 ) { + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); i++) { + if (argv[1] == (*i)->getName(rtmidi::PortDescriptor::SESSION_PATH | + rtmidi::PortDescriptor::UNIQUE_NAME | + rtmidi::PortDescriptor::INCLUDE_API)) { + port = *i; + break; + } + } + } else { + port = list.front(); + } + if ( !port ) { + std::cout << "Invalid port specifier!\n"; + usage(list); + } + + try { + midiin.openPort( port ); + } + catch ( RtMidiError &error ) { + error.printMessage(); + return 1; + } + + // Don't ignore sysex, timing, or active sensing messages. + midiin.ignoreTypes( false, false, false ); + + // Install an interrupt handler function. + done = false; + (void) signal(SIGINT, finish); + + // Periodically check input queue. + std::cout << "Reading MIDI from port ... quit with Ctrl-C.\n"; + while ( !done ) { + stamp = midiin.getMessage( &message ); + nBytes = message.size(); + for ( i=0; i 0 ) + std::cout << "stamp = " << stamp << std::endl; + + // Sleep for 10 milliseconds. + SLEEP( 10 ); + } + } + catch ( RtMidiError &error ) { + error.printMessage(); + exit( EXIT_FAILURE ); + } + + return 0; +} From 7f2aadb66b51c66444fb057b9a5283ce166e0736 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Tue, 8 Apr 2014 21:15:55 +0200 Subject: [PATCH 023/210] Implement the missing functions of the proposed port selection API. Signed-off-by: Tobias Schlemmer --- RtMidi.cpp | 911 ++++++++++++++++++++++++++++------------------------- RtMidi.h | 60 ++-- 2 files changed, 528 insertions(+), 443 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 0b390d32..e9b73c46 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1157,7 +1157,7 @@ class AlsaSequencer { } } - AlsaSequencer(const std::string & name):seq(0) + AlsaSequencer(const std::string & n):seq(0),name(n) { if (locking) { pthread_mutexattr_t attr; @@ -1179,6 +1179,13 @@ class AlsaSequencer { } } + bool setName(const std::string & n) { + /* we don't want to rename the client after opening it. */ + if (seq) return false; + name = n; + return true; + } + std::string GetPortName(int client, int port, int flags) { init(); snd_seq_client_info_t *cinfo; @@ -1244,6 +1251,7 @@ class AlsaSequencer { } int getPortCapabilities(int client, int port) { + init(); snd_seq_port_info_t *pinfo; snd_seq_port_info_alloca( &pinfo ); { @@ -1350,6 +1358,7 @@ class AlsaSequencer { }; pthread_mutex_t mutex; snd_seq_t * seq; + std::string name; snd_seq_client_info_t * GetClient(int id) { @@ -1376,6 +1385,7 @@ class AlsaSequencer { Error::DRIVER_ERROR ); return; } + snd_seq_set_client_name( seq, name.c_str() ); } } }; @@ -1387,34 +1397,56 @@ struct AlsaPortDescriptor:public PortDescriptor, { MidiApi * api; static LockingAlsaSequencer seq; - AlsaPortDescriptor():api(0) + AlsaPortDescriptor(const std::string & name):api(0),clientName(name) { client = 0; port = 0; } - AlsaPortDescriptor(int c, int p):api(0) + AlsaPortDescriptor(int c, int p, const std::string & name):api(0),clientName(name) { client = c; port = p; + seq.setName(name); + } + AlsaPortDescriptor(snd_seq_addr_t & other, + const std::string & name):snd_seq_addr_t(other), + clientName(name) { + seq.setName(name); } ~AlsaPortDescriptor() {} - MidiApi * getAPI() { - return NULL; + MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) { + if (getCapabilities() & INPUT) + return new MidiInAlsa(clientName,queueSizeLimit); + else + return 0; + } + MidiOutApi * getOutputApi() { + if (getCapabilities() & OUTPUT) + return new MidiOutAlsa(clientName); + else + return 0; } std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) { return seq.GetPortName(client,port,flags); } + + const std::string & getClientName() { + return clientName; + } int getCapabilities() { + if (!client) return 0; return seq.getPortCapabilities(client,port); } - static PortList getPortList(int capabilities); + static PortList getPortList(int capabilities, const std::string & clientName); +protected: + std::string clientName; }; LockingAlsaSequencer AlsaPortDescriptor::seq; -PortList AlsaPortDescriptor :: getPortList(int capabilities) +PortList AlsaPortDescriptor :: getPortList(int capabilities, const std::string & clientName) { PortList list; snd_seq_client_info_t *cinfo; @@ -1449,7 +1481,7 @@ PortList AlsaPortDescriptor :: getPortList(int capabilities) != (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) continue; } - list.push_back(new AlsaPortDescriptor(client,snd_seq_port_info_get_port(pinfo))); + list.push_back(new AlsaPortDescriptor(client,snd_seq_port_info_get_port(pinfo),clientName)); } } return list; @@ -1467,13 +1499,19 @@ static void *alsaMidiHandler( void *ptr ); */ struct AlsaMidiData:public AlsaPortDescriptor { - AlsaMidiData():seq() { + /* + AlsaMidiData():seq() + { init(); - } - AlsaMidiData(const std::string &clientName):seq(clientName) { + } + */ + AlsaMidiData(const std::string &clientName):AlsaPortDescriptor(clientName), + seq(clientName) + { init(); } - ~AlsaMidiData() { + ~AlsaMidiData() + { if (local.client) deletePort(); } @@ -1785,7 +1823,8 @@ 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 ); } @@ -2076,13 +2115,25 @@ void MidiInAlsa :: openPort( const PortDescriptor & port, connected_ = true; } -Pointer MidiInAlsa :: getDescriptor() +Pointer MidiInAlsa :: getDescriptor(bool local) { - abort(); + AlsaMidiData *data = static_cast (apiData_); + if (local) { + if (data && data->local.client) { + return new AlsaPortDescriptor(data->local,data->getClientName()); + } + } else { + if (data && data->client) { + return new AlsaPortDescriptor(*data,data->getClientName()); + } + } + return NULL; } PortList MidiInAlsa :: getPortList(int capabilities) { - return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::INPUT); + AlsaMidiData *data = static_cast (apiData_); + return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::INPUT, + data->getClientName()); } @@ -2449,13 +2500,25 @@ void MidiOutAlsa :: openPort( const PortDescriptor & port, connected_ = true; } -Pointer MidiOutAlsa :: getDescriptor() +Pointer MidiOutAlsa :: getDescriptor(bool local) { - abort(); + AlsaMidiData *data = static_cast (apiData_); + if (local) { + if (data && data->local.client) { + return new AlsaPortDescriptor(data->local, data->getClientName()); + } + } else { + if (data && data->client) { + return new AlsaPortDescriptor(*data, data->getClientName()); + } + } + return NULL; } PortList MidiOutAlsa :: getPortList(int capabilities) { - return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT); + AlsaMidiData *data = static_cast (apiData_); + return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT, + data->getClientName()); } NAMSPACE_RTMIDI_END #endif // __LINUX_ALSA__ @@ -2482,504 +2545,504 @@ NAMSPACE_RTMIDI_END #define RT_SYSEX_BUFFER_SIZE 1024 #define RT_SYSEX_BUFFER_COUNT 4 -namespace rtmidi{ - // A structure to hold variables related to the CoreMIDI API - // implementation. - struct WinMidiData { - HMIDIIN inHandle; // Handle to Midi Input Device - HMIDIOUT outHandle; // Handle to Midi Output Device - DWORD lastTime; - MidiInApi::MidiMessage message; - LPMIDIHDR sysexBuffer[RT_SYSEX_BUFFER_COUNT]; - CRITICAL_SECTION _mutex; // [Patrice] see https://groups.google.com/forum/#!topic/mididev/6OUjHutMpEo - }; - - //*********************************************************************// - // API: Windows MM - // Class Definitions: MidiInWinMM - //*********************************************************************// - - static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, - UINT inputStatus, - DWORD_PTR instancePtr, - DWORD_PTR midiMessage, - DWORD timestamp ) - { - if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA && inputStatus != MIM_LONGERROR ) return; +NAMESPACE_RTMIDI_START +// A structure to hold variables related to the CoreMIDI API +// implementation. +struct WinMidiData { + HMIDIIN inHandle; // Handle to Midi Input Device + HMIDIOUT outHandle; // Handle to Midi Output Device + DWORD lastTime; + MidiInApi::MidiMessage message; + LPMIDIHDR sysexBuffer[RT_SYSEX_BUFFER_COUNT]; + CRITICAL_SECTION _mutex; // [Patrice] see https://groups.google.com/forum/#!topic/mididev/6OUjHutMpEo +}; - //MidiInApi::MidiInData *data = static_cast (instancePtr); - MidiInApi::MidiInData *data = (MidiInApi::MidiInData *)instancePtr; - WinMidiData *apiData = static_cast (data->apiData); +//*********************************************************************// +// API: Windows MM +// Class Definitions: MidiInWinMM +//*********************************************************************// - // Calculate time stamp. - if ( data->firstMessage == true ) { - apiData->message.timeStamp = 0.0; - data->firstMessage = false; +static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, + UINT inputStatus, + DWORD_PTR instancePtr, + DWORD_PTR midiMessage, + DWORD timestamp ) +{ + if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA && inputStatus != MIM_LONGERROR ) return; + + //MidiInApi::MidiInData *data = static_cast (instancePtr); + MidiInApi::MidiInData *data = (MidiInApi::MidiInData *)instancePtr; + WinMidiData *apiData = static_cast (data->apiData); + + // Calculate time stamp. + if ( data->firstMessage == true ) { + apiData->message.timeStamp = 0.0; + data->firstMessage = false; + } + else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001; + apiData->lastTime = timestamp; + + if ( inputStatus == MIM_DATA ) { // Channel or system message + + // Make sure the first byte is a status byte. + unsigned char status = (unsigned char) (midiMessage & 0x000000FF); + if ( !(status & 0x80) ) return; + + // Determine the number of bytes in the MIDI message. + unsigned short nBytes = 1; + if ( status < 0xC0 ) nBytes = 3; + else if ( status < 0xE0 ) nBytes = 2; + else if ( status < 0xF0 ) nBytes = 3; + else if ( status == 0xF1 ) { + if ( data->ignoreFlags & 0x02 ) return; + else nBytes = 2; + } + else if ( status == 0xF2 ) nBytes = 3; + else if ( status == 0xF3 ) nBytes = 2; + else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) { + // A MIDI timing tick message and we're ignoring it. + return; + } + else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { + // A MIDI active sensing message and we're ignoring it. + return; } - else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001; - apiData->lastTime = timestamp; - - if ( inputStatus == MIM_DATA ) { // Channel or system message - // Make sure the first byte is a status byte. - unsigned char status = (unsigned char) (midiMessage & 0x000000FF); - if ( !(status & 0x80) ) return; + // Copy bytes to our MIDI message. + unsigned char *ptr = (unsigned char *) &midiMessage; + for ( int i=0; imessage.bytes.push_back( *ptr++ ); + } + else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) + MIDIHDR *sysex = ( MIDIHDR *) midiMessage; + if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { + // Sysex message and we're not ignoring it + for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) + apiData->message.bytes.push_back( sysex->lpData[i] ); + } - // Determine the number of bytes in the MIDI message. - unsigned short nBytes = 1; - if ( status < 0xC0 ) nBytes = 3; - else if ( status < 0xE0 ) nBytes = 2; - else if ( status < 0xF0 ) nBytes = 3; - else if ( status == 0xF1 ) { - if ( data->ignoreFlags & 0x02 ) return; - else nBytes = 2; - } - else if ( status == 0xF2 ) nBytes = 3; - else if ( status == 0xF3 ) nBytes = 2; - else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) { - // A MIDI timing tick message and we're ignoring it. - return; - } - else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { - // A MIDI active sensing message and we're ignoring it. - return; - } + // The WinMM API requires that the sysex buffer be requeued after + // input of each sysex message. Even if we are ignoring sysex + // messages, we still need to requeue the buffer in case the user + // decides to not ignore sysex messages in the future. However, + // it seems that WinMM calls this function with an empty sysex + // buffer when an application closes and in this case, we should + // avoid requeueing it, else the computer suddenly reboots after + // one or two minutes. + if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { + //if ( sysex->dwBytesRecorded > 0 ) { + EnterCriticalSection( &(apiData->_mutex) ); + MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); + LeaveCriticalSection( &(apiData->_mutex) ); + if ( result != MMSYSERR_NOERROR ) + std::cerr << "\nMidiIn::midiInputCallback: error sending sysex to Midi device!!\n\n"; - // Copy bytes to our MIDI message. - unsigned char *ptr = (unsigned char *) &midiMessage; - for ( int i=0; imessage.bytes.push_back( *ptr++ ); + if ( data->ignoreFlags & 0x01 ) return; } - else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) - MIDIHDR *sysex = ( MIDIHDR *) midiMessage; - if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { - // Sysex message and we're not ignoring it - for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) - apiData->message.bytes.push_back( sysex->lpData[i] ); - } + else return; + } - // The WinMM API requires that the sysex buffer be requeued after - // input of each sysex message. Even if we are ignoring sysex - // messages, we still need to requeue the buffer in case the user - // decides to not ignore sysex messages in the future. However, - // it seems that WinMM calls this function with an empty sysex - // buffer when an application closes and in this case, we should - // avoid requeueing it, else the computer suddenly reboots after - // one or two minutes. - if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { - //if ( sysex->dwBytesRecorded > 0 ) { - EnterCriticalSection( &(apiData->_mutex) ); - MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); - LeaveCriticalSection( &(apiData->_mutex) ); - if ( result != MMSYSERR_NOERROR ) - std::cerr << "\nMidiIn::midiInputCallback: error sending sysex to Midi device!!\n\n"; - - if ( data->ignoreFlags & 0x01 ) return; - } - else return; + if ( data->usingCallback ) { + MidiCallback callback = (MidiCallback) data->userCallback; + callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = apiData->message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; } + else + std::cerr << "\nMidiIn: message queue limit reached!!\n\n"; + } - if ( data->usingCallback ) { - MidiCallback callback = (MidiCallback) data->userCallback; - callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = apiData->message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else - std::cerr << "\nMidiIn: message queue limit reached!!\n\n"; - } + // Clear the vector for the next input message. + apiData->message.bytes.clear(); +} - // Clear the vector for the next input message. - apiData->message.bytes.clear(); - } +MidiInWinMM :: MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) +{ + initialize( clientName ); +} - MidiInWinMM :: MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) - { - initialize( clientName ); - } +MidiInWinMM :: ~MidiInWinMM() +{ + // Close a connection if it exists. + closePort(); - MidiInWinMM :: ~MidiInWinMM() - { - // Close a connection if it exists. - closePort(); + WinMidiData *data = static_cast (apiData_); + DeleteCriticalSection( &(data->_mutex) ); - WinMidiData *data = static_cast (apiData_); - DeleteCriticalSection( &(data->_mutex) ); + // Cleanup. + delete data; +} - // Cleanup. - delete data; +void MidiInWinMM :: initialize( const std::string& /*clientName*/ ) +{ + // We'll issue a warning here if no devices are available but not + // throw an error since the user can plugin something later. + unsigned int nDevices = midiInGetNumDevs(); + if ( nDevices == 0 ) { + errorString_ = "MidiInWinMM::initialize: no MIDI input devices currently available."; + error( Error::WARNING, errorString_ ); } - void MidiInWinMM :: initialize( const std::string& /*clientName*/ ) - { - // We'll issue a warning here if no devices are available but not - // throw an error since the user can plugin something later. - unsigned int nDevices = midiInGetNumDevs(); - if ( nDevices == 0 ) { - errorString_ = "MidiInWinMM::initialize: no MIDI input devices currently available."; - error( Error::WARNING, errorString_ ); - } + // Save our api-specific connection information. + WinMidiData *data = (WinMidiData *) new WinMidiData; + apiData_ = (void *) data; + inputData_.apiData = (void *) data; + data->message.bytes.clear(); // needs to be empty for first input message - // Save our api-specific connection information. - WinMidiData *data = (WinMidiData *) new WinMidiData; - apiData_ = (void *) data; - inputData_.apiData = (void *) data; - data->message.bytes.clear(); // needs to be empty for first input message + if ( !InitializeCriticalSectionAndSpinCount(&(data->_mutex), 0x00000400) ) { + errorString_ = "MidiInWinMM::initialize: InitializeCriticalSectionAndSpinCount failed."; + error( Error::WARNING, errorString_ ); + } +} - if ( !InitializeCriticalSectionAndSpinCount(&(data->_mutex), 0x00000400) ) { - errorString_ = "MidiInWinMM::initialize: InitializeCriticalSectionAndSpinCount failed."; - error( Error::WARNING, errorString_ ); - } +void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) +{ + if ( connected_ ) { + errorString_ = "MidiInWinMM::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; } - void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) - { - if ( connected_ ) { - errorString_ = "MidiInWinMM::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); - return; - } + unsigned int nDevices = midiInGetNumDevs(); + if (nDevices == 0) { + errorString_ = "MidiInWinMM::openPort: no MIDI input sources found!"; + error( Error::NO_DEVICES_FOUND, errorString_ ); + return; + } - unsigned int nDevices = midiInGetNumDevs(); - if (nDevices == 0) { - errorString_ = "MidiInWinMM::openPort: no MIDI input sources found!"; - error( Error::NO_DEVICES_FOUND, errorString_ ); - return; - } + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiInWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::INVALID_PARAMETER, errorString_ ); + return; + } + + WinMidiData *data = static_cast (apiData_); + MMRESULT result = midiInOpen( &data->inHandle, + portNumber, + (DWORD_PTR)&midiInputCallback, + (DWORD_PTR)&inputData_, + CALLBACK_FUNCTION ); + if ( result != MMSYSERR_NOERROR ) { + errorString_ = "MidiInWinMM::openPort: error creating Windows MM MIDI input port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiInWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::INVALID_PARAMETER, errorString_ ); + // Allocate and init the sysex buffers. + for ( int i=0; isysexBuffer[i] = (MIDIHDR*) new char[ sizeof(MIDIHDR) ]; + data->sysexBuffer[i]->lpData = new char[ RT_SYSEX_BUFFER_SIZE ]; + data->sysexBuffer[i]->dwBufferLength = RT_SYSEX_BUFFER_SIZE; + data->sysexBuffer[i]->dwUser = i; // We use the dwUser parameter as buffer indicator + data->sysexBuffer[i]->dwFlags = 0; + + result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (PrepareHeader)."; + error( Error::DRIVER_ERROR, errorString_ ); return; } - WinMidiData *data = static_cast (apiData_); - MMRESULT result = midiInOpen( &data->inHandle, - portNumber, - (DWORD_PTR)&midiInputCallback, - (DWORD_PTR)&inputData_, - CALLBACK_FUNCTION ); + // Register the buffer. + result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); if ( result != MMSYSERR_NOERROR ) { - errorString_ = "MidiInWinMM::openPort: error creating Windows MM MIDI input port."; + midiInClose( data->inHandle ); + errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (AddBuffer)."; error( Error::DRIVER_ERROR, errorString_ ); return; } + } - // Allocate and init the sysex buffers. - for ( int i=0; isysexBuffer[i] = (MIDIHDR*) new char[ sizeof(MIDIHDR) ]; - data->sysexBuffer[i]->lpData = new char[ RT_SYSEX_BUFFER_SIZE ]; - data->sysexBuffer[i]->dwBufferLength = RT_SYSEX_BUFFER_SIZE; - data->sysexBuffer[i]->dwUser = i; // We use the dwUser parameter as buffer indicator - data->sysexBuffer[i]->dwFlags = 0; + result = midiInStart( data->inHandle ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } - result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (PrepareHeader)."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } + connected_ = true; +} + +void MidiInWinMM :: openVirtualPort( std::string /*portName*/ ) +{ + // This function cannot be implemented for the Windows MM MIDI API. + errorString_ = "MidiInWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; + error( Error::WARNING, errorString_ ); +} - // Register the buffer. - result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); +void MidiInWinMM :: closePort( void ) +{ + if ( connected_ ) { + WinMidiData *data = static_cast (apiData_); + EnterCriticalSection( &(data->_mutex) ); + midiInReset( data->inHandle ); + midiInStop( data->inHandle ); + + for ( int i=0; iinHandle, data->sysexBuffer[i], sizeof(MIDIHDR)); + delete [] data->sysexBuffer[i]->lpData; + delete [] data->sysexBuffer[i]; if ( result != MMSYSERR_NOERROR ) { midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (AddBuffer)."; + errorString_ = "MidiInWinMM::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader)."; error( Error::DRIVER_ERROR, errorString_ ); return; } } - result = midiInStart( data->inHandle ); - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - connected_ = true; + midiInClose( data->inHandle ); + connected_ = false; + LeaveCriticalSection( &(data->_mutex) ); } +} - void MidiInWinMM :: openVirtualPort( std::string /*portName*/ ) - { - // This function cannot be implemented for the Windows MM MIDI API. - errorString_ = "MidiInWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; +unsigned int MidiInWinMM :: getPortCount() +{ + return midiInGetNumDevs(); +} + +std::string MidiInWinMM :: getPortName( unsigned int portNumber ) +{ + std::string stringName; + unsigned int nDevices = midiInGetNumDevs(); + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiInWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); error( Error::WARNING, errorString_ ); + return stringName; } - void MidiInWinMM :: closePort( void ) - { - if ( connected_ ) { - WinMidiData *data = static_cast (apiData_); - EnterCriticalSection( &(data->_mutex) ); - midiInReset( data->inHandle ); - midiInStop( data->inHandle ); - - for ( int i=0; iinHandle, data->sysexBuffer[i], sizeof(MIDIHDR)); - delete [] data->sysexBuffer[i]->lpData; - delete [] data->sysexBuffer[i]; - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader)."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - } + MIDIINCAPS deviceCaps; + midiInGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIINCAPS)); - midiInClose( data->inHandle ); - connected_ = false; - LeaveCriticalSection( &(data->_mutex) ); - } - } +#if defined( UNICODE ) || defined( _UNICODE ) + int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; + stringName.assign( length, 0 ); + length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); +#else + stringName = std::string( deviceCaps.szPname ); +#endif - unsigned int MidiInWinMM :: getPortCount() - { - return midiInGetNumDevs(); - } + // 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 + std::ostringstream os; + os << " "; + os << portNumber; + stringName += os.str(); - std::string MidiInWinMM :: getPortName( unsigned int portNumber ) - { - std::string stringName; - unsigned int nDevices = midiInGetNumDevs(); - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiInWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::WARNING, errorString_ ); - return stringName; - } + return stringName; +} - MIDIINCAPS deviceCaps; - midiInGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIINCAPS)); +//*********************************************************************// +// API: Windows MM +// Class Definitions: MidiOutWinMM +//*********************************************************************// -#if defined( UNICODE ) || defined( _UNICODE ) - int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; - stringName.assign( length, 0 ); - length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); -#else - stringName = std::string( deviceCaps.szPname ); -#endif +MidiOutWinMM :: MidiOutWinMM( const std::string clientName ) : MidiOutApi() +{ + initialize( clientName ); +} - // 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 - std::ostringstream os; - os << " "; - os << portNumber; - stringName += os.str(); +MidiOutWinMM :: ~MidiOutWinMM() +{ + // Close a connection if it exists. + closePort(); - return stringName; + // Cleanup. + WinMidiData *data = static_cast (apiData_); + delete data; +} + +void MidiOutWinMM :: initialize( const std::string& /*clientName*/ ) +{ + // We'll issue a warning here if no devices are available but not + // throw an error since the user can plug something in later. + unsigned int nDevices = midiOutGetNumDevs(); + if ( nDevices == 0 ) { + errorString_ = "MidiOutWinMM::initialize: no MIDI output devices currently available."; + error( Error::WARNING, errorString_ ); } - //*********************************************************************// - // API: Windows MM - // Class Definitions: MidiOutWinMM - //*********************************************************************// + // Save our api-specific connection information. + WinMidiData *data = (WinMidiData *) new WinMidiData; + apiData_ = (void *) data; +} - MidiOutWinMM :: MidiOutWinMM( const std::string clientName ) : MidiOutApi() - { - initialize( clientName ); +unsigned int MidiOutWinMM :: getPortCount() +{ + return midiOutGetNumDevs(); +} + +std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) +{ + std::string stringName; + unsigned int nDevices = midiOutGetNumDevs(); + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiOutWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::WARNING, errorString_ ); + return stringName; } - MidiOutWinMM :: ~MidiOutWinMM() - { - // Close a connection if it exists. - closePort(); + MIDIOUTCAPS deviceCaps; + midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS)); - // Cleanup. - WinMidiData *data = static_cast (apiData_); - delete data; +#if defined( UNICODE ) || defined( _UNICODE ) + int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; + stringName.assign( length, 0 ); + length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); +#else + stringName = std::string( deviceCaps.szPname ); +#endif + + return stringName; +} + +void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) +{ + if ( connected_ ) { + errorString_ = "MidiOutWinMM::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; } - void MidiOutWinMM :: initialize( const std::string& /*clientName*/ ) - { - // We'll issue a warning here if no devices are available but not - // throw an error since the user can plug something in later. - unsigned int nDevices = midiOutGetNumDevs(); - if ( nDevices == 0 ) { - errorString_ = "MidiOutWinMM::initialize: no MIDI output devices currently available."; - error( Error::WARNING, errorString_ ); - } + unsigned int nDevices = midiOutGetNumDevs(); + if (nDevices < 1) { + errorString_ = "MidiOutWinMM::openPort: no MIDI output destinations found!"; + error( Error::NO_DEVICES_FOUND, errorString_ ); + return; + } - // Save our api-specific connection information. - WinMidiData *data = (WinMidiData *) new WinMidiData; - apiData_ = (void *) data; + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiOutWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + errorString_ = ost.str(); + error( Error::INVALID_PARAMETER, errorString_ ); + return; } - unsigned int MidiOutWinMM :: getPortCount() - { - return midiOutGetNumDevs(); + WinMidiData *data = static_cast (apiData_); + MMRESULT result = midiOutOpen( &data->outHandle, + portNumber, + (DWORD)NULL, + (DWORD)NULL, + CALLBACK_NULL ); + if ( result != MMSYSERR_NOERROR ) { + errorString_ = "MidiOutWinMM::openPort: error creating Windows MM MIDI output port."; + error( Error::DRIVER_ERROR, errorString_ ); + return; } - std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) - { - std::string stringName; - unsigned int nDevices = midiOutGetNumDevs(); - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiOutWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::WARNING, errorString_ ); - return stringName; - } + connected_ = true; +} - MIDIOUTCAPS deviceCaps; - midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS)); +void MidiOutWinMM :: closePort( void ) +{ + if ( connected_ ) { + WinMidiData *data = static_cast (apiData_); + midiOutReset( data->outHandle ); + midiOutClose( data->outHandle ); + connected_ = false; + } +} -#if defined( UNICODE ) || defined( _UNICODE ) - int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; - stringName.assign( length, 0 ); - length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); -#else - stringName = std::string( deviceCaps.szPname ); -#endif +void MidiOutWinMM :: openVirtualPort( std::string /*portName*/ ) +{ + // This function cannot be implemented for the Windows MM MIDI API. + errorString_ = "MidiOutWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; + error( Error::WARNING, errorString_ ); +} - return stringName; +void MidiOutWinMM :: sendMessage( std::vector *message ) +{ + if ( !connected_ ) return; + + unsigned int nBytes = static_cast(message->size()); + if ( nBytes == 0 ) { + errorString_ = "MidiOutWinMM::sendMessage: message argument is empty!"; + error( Error::WARNING, errorString_ ); + return; } - void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) - { - if ( connected_ ) { - errorString_ = "MidiOutWinMM::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); - return; - } + MMRESULT result; + WinMidiData *data = static_cast (apiData_); + if ( message->at(0) == 0xF0 ) { // Sysex message - unsigned int nDevices = midiOutGetNumDevs(); - if (nDevices < 1) { - errorString_ = "MidiOutWinMM::openPort: no MIDI output destinations found!"; - error( Error::NO_DEVICES_FOUND, errorString_ ); + // Allocate buffer for sysex data. + char *buffer = (char *) malloc( nBytes ); + if ( buffer == NULL ) { + errorString_ = "MidiOutWinMM::sendMessage: error allocating sysex message memory!"; + error( Error::MEMORY_ERROR, errorString_ ); return; } - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiOutWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::INVALID_PARAMETER, errorString_ ); - return; - } + // Copy data to buffer. + for ( unsigned int i=0; iat(i); - WinMidiData *data = static_cast (apiData_); - MMRESULT result = midiOutOpen( &data->outHandle, - portNumber, - (DWORD)NULL, - (DWORD)NULL, - CALLBACK_NULL ); + // Create and prepare MIDIHDR structure. + MIDIHDR sysex; + sysex.lpData = (LPSTR) buffer; + sysex.dwBufferLength = nBytes; + sysex.dwFlags = 0; + result = midiOutPrepareHeader( data->outHandle, &sysex, sizeof(MIDIHDR) ); if ( result != MMSYSERR_NOERROR ) { - errorString_ = "MidiOutWinMM::openPort: error creating Windows MM MIDI output port."; + free( buffer ); + errorString_ = "MidiOutWinMM::sendMessage: error preparing sysex header."; error( Error::DRIVER_ERROR, errorString_ ); return; } - connected_ = true; - } - - void MidiOutWinMM :: closePort( void ) - { - if ( connected_ ) { - WinMidiData *data = static_cast (apiData_); - midiOutReset( data->outHandle ); - midiOutClose( data->outHandle ); - connected_ = false; + // Send the message. + result = midiOutLongMsg( data->outHandle, &sysex, sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + free( buffer ); + errorString_ = "MidiOutWinMM::sendMessage: error sending sysex message."; + error( Error::DRIVER_ERROR, errorString_ ); + return; } - } - void MidiOutWinMM :: openVirtualPort( std::string /*portName*/ ) - { - // This function cannot be implemented for the Windows MM MIDI API. - errorString_ = "MidiOutWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; - error( Error::WARNING, errorString_ ); + // Unprepare the buffer and MIDIHDR. + while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof (MIDIHDR) ) ) Sleep( 1 ); + free( buffer ); } + else { // Channel or system message. - void MidiOutWinMM :: sendMessage( std::vector *message ) - { - if ( !connected_ ) return; - - unsigned int nBytes = static_cast(message->size()); - if ( nBytes == 0 ) { - errorString_ = "MidiOutWinMM::sendMessage: message argument is empty!"; + // Make sure the message size isn't too big. + if ( nBytes > 3 ) { + errorString_ = "MidiOutWinMM::sendMessage: message size is greater than 3 bytes (and not sysex)!"; error( Error::WARNING, errorString_ ); return; } - MMRESULT result; - WinMidiData *data = static_cast (apiData_); - if ( message->at(0) == 0xF0 ) { // Sysex message - - // Allocate buffer for sysex data. - char *buffer = (char *) malloc( nBytes ); - if ( buffer == NULL ) { - errorString_ = "MidiOutWinMM::sendMessage: error allocating sysex message memory!"; - error( Error::MEMORY_ERROR, errorString_ ); - return; - } - - // Copy data to buffer. - for ( unsigned int i=0; iat(i); - - // Create and prepare MIDIHDR structure. - MIDIHDR sysex; - sysex.lpData = (LPSTR) buffer; - sysex.dwBufferLength = nBytes; - sysex.dwFlags = 0; - result = midiOutPrepareHeader( data->outHandle, &sysex, sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - free( buffer ); - errorString_ = "MidiOutWinMM::sendMessage: error preparing sysex header."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Send the message. - result = midiOutLongMsg( data->outHandle, &sysex, sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - free( buffer ); - errorString_ = "MidiOutWinMM::sendMessage: error sending sysex message."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - - // Unprepare the buffer and MIDIHDR. - while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof (MIDIHDR) ) ) Sleep( 1 ); - free( buffer ); + // Pack MIDI bytes into double word. + DWORD packet; + unsigned char *ptr = (unsigned char *) &packet; + for ( unsigned int i=0; iat(i); + ++ptr; } - else { // Channel or system message. - // Make sure the message size isn't too big. - if ( nBytes > 3 ) { - errorString_ = "MidiOutWinMM::sendMessage: message size is greater than 3 bytes (and not sysex)!"; - error( Error::WARNING, errorString_ ); - return; - } - - // Pack MIDI bytes into double word. - DWORD packet; - unsigned char *ptr = (unsigned char *) &packet; - for ( unsigned int i=0; iat(i); - ++ptr; - } - - // Send the message immediately. - result = midiOutShortMsg( data->outHandle, packet ); - if ( result != MMSYSERR_NOERROR ) { - errorString_ = "MidiOutWinMM::sendMessage: error sending MIDI message."; - error( Error::DRIVER_ERROR, errorString_ ); - } + // Send the message immediately. + result = midiOutShortMsg( data->outHandle, packet ); + if ( result != MMSYSERR_NOERROR ) { + errorString_ = "MidiOutWinMM::sendMessage: error sending MIDI message."; + error( Error::DRIVER_ERROR, errorString_ ); } } } +NAMESPACE_RTMIDI_END #endif // __WINDOWS_MM__ diff --git a/RtMidi.h b/RtMidi.h index ba465594..1ec42d3e 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -224,6 +224,8 @@ typedef std::shared_ptr Pointer; #endif class MidiApi; +class MidiInApi; +class MidiOutApi; struct PortDescriptor { //! Flags for formatting a string description of the port. @@ -284,13 +286,27 @@ struct PortDescriptor { */ virtual ~PortDescriptor() {}; - //! Get the MIDI api for the current port. + //! Get the MIDI input api for the current port. /*! This is the only information RtMidi needs to know: Which - * API should handle this object. + * API should handle this object. This can be used to get + * an API which can send data to the given port. * - * \return API that can handle this object. + * \param queueSizeLimit The limit of the midi queue. This parameter is handled by + * the constructor of the backend API. + * + * \return API that can use this object to connect to an input port or 0 + * if no input API can be created. */ - virtual MidiApi * getAPI() = 0; + virtual MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) = 0; + + //! Get the MIDI output api for the current port. + /*! This is the only information RtMidi needs to know: Which + * API should handle this object. This can be used to get + * an API which can receive data from the given port. + * + * \return API that can use this object to connect to an output port. + */ + virtual MidiOutApi * getOutputApi() = 0; //! Return the port name /*! @@ -380,8 +396,14 @@ class MidiApi openPort(*p, portName); } - //! Pure virtual function to return a port descirptor if the port is open - virtual Pointer getDescriptor() = 0; + //! Pure virtual function to return a port descriptor if the port is open + /*! This function returns a port descriptor that can be used to open another port + either to the connected port or – if the backend supports it – the connecting port. + \param local The parameter local defines whether the function returns a descriptor to + the virtual port (true) or the remote port (false). The function returns 0 if the + port cannot be determined (e.g. if the port is not connected or the backend dosen't support it). + */ + virtual Pointer getDescriptor(bool local=false) = 0; //! Pure virtual function to return a list of all available ports of the current API. /*! @@ -465,7 +487,7 @@ class MidiInApi : public MidiApi MidiInApi( unsigned int queueSizeLimit ); virtual ~MidiInApi( void ); - void setCallback( MidiCallback callback, void *userData ); + void setCallback( MidiCallback callback, void *userData = 0 ); void cancelCallback( void ); virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); RTMIDI_DEPRECATED(double getMessage( std::vector *message )) @@ -644,9 +666,9 @@ class Midi { } //! Pure virtual function to return a port descirptor if the port is open - Pointer getDescriptor() + Pointer getDescriptor(bool local=false) { - if (rtapi_) return rtapi_->getDescriptor(); + if (rtapi_) return rtapi_->getDescriptor(local); return 0; } @@ -996,7 +1018,7 @@ class MidiInCore: public MidiInApi void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); - Pointer getDescriptor(); + Pointer getDescriptor(bool local=false); PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); @@ -1015,7 +1037,7 @@ class MidiOutCore: public MidiOutApi void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); - Pointer getDescriptor(); + Pointer getDescriptor(bool local=false); PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); @@ -1039,7 +1061,7 @@ class MidiInJack: public MidiInApi void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); - Pointer getDescriptor(); + Pointer getDescriptor(bool local=false); PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); @@ -1061,7 +1083,7 @@ class MidiOutJack: public MidiOutApi void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); - Pointer getDescriptor(); + Pointer getDescriptor(bool local=false); PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); @@ -1088,7 +1110,7 @@ class MidiInAlsa: public MidiInApi void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); - Pointer getDescriptor(); + Pointer getDescriptor(bool local=false); PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); @@ -1107,7 +1129,7 @@ class MidiOutAlsa: public MidiOutApi void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); - Pointer getDescriptor(); + Pointer getDescriptor(bool local=false); PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); @@ -1131,7 +1153,7 @@ class MidiInWinMM: public MidiInApi void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); - Pointer getDescriptor(); + Pointer getDescriptor(bool local=false); PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); @@ -1150,7 +1172,7 @@ class MidiOutWinMM: public MidiOutApi void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); - Pointer getDescriptor(); + Pointer getDescriptor(bool local=false); PortList getPortList(int capabilities); void closePort( void ); unsigned int getPortCount( void ); @@ -1177,7 +1199,7 @@ class MidiInDummy: public MidiInApi void openPort( unsigned int /*portNumber*/, const & std::string /*portName*/ ) {} void openVirtualPort( const std::string /*portName*/ ) {} void openPort( const PortDescriptor & port, const & std::string portName) {} - Pointer getDescriptor() { return 0; } + Pointer getDescriptor(bool local=false) { return 0; } PortList getPortList(int capabilities) { return PortList(); } void closePort( void ) {} unsigned int getPortCount( void ) { return 0; } @@ -1198,7 +1220,7 @@ class MidiOutDummy: public MidiOutApi void openPort( unsigned int /*portNumber*/, const & std::string /*portName*/ ) {} void openVirtualPort( const std::string /*portName*/ ) {} void openPort( const PortDescriptor & port, const & std::string portName) {} - Pointer getDescriptor() { return 0; } + Pointer getDescriptor(bool local=false) { return 0; } PortList getPortList(int capabilities) { return PortList(); } void closePort( void ) {} unsigned int getPortCount( void ) { return 0; } From c314e85205f7a2b0b2928760a466ebea1e63fc1c Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Tue, 8 Apr 2014 21:20:30 +0200 Subject: [PATCH 024/210] Provide a test case that uses virtual ports to test communication with virtual ports. --- tests/Makefile.in | 5 +- tests/cmidiin.cpp | 2 +- tests/loopback.cpp | 189 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 tests/loopback.cpp diff --git a/tests/Makefile.in b/tests/Makefile.in index bea71da1..bc8a728a 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -1,7 +1,7 @@ ### Do not edit -- Generated by 'configure --with-whatever' from Makefile.in ### RtMidi tests Makefile - for various flavors of unix -PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest midiprobe2 cmidiin2 qmidiin2 midiout2 +PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest midiprobe2 cmidiin2 qmidiin2 midiout2 loopback RM = /bin/rm SRC_PATH = .. INCLUDE = .. @@ -48,6 +48,9 @@ cmidiin2 : cmidiin2.cpp $(OBJECTS) sysextest : sysextest.cpp $(OBJECTS) $(CC) $(CFLAGS) $(DEFS) -o sysextest sysextest.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) +loopback : loopback.cpp $(OBJECTS) + $(CC) $(CFLAGS) $(DEFS) -o loopback loopback.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) + clean : $(RM) -f $(OBJECT_PATH)/*.o $(RM) -f $(PROGRAMS) *.exe diff --git a/tests/cmidiin.cpp b/tests/cmidiin.cpp index be78dbbd..49e48edb 100644 --- a/tests/cmidiin.cpp +++ b/tests/cmidiin.cpp @@ -19,7 +19,7 @@ void usage( void ) { exit( 0 ); } -void mycallback( double deltatime, std::vector< unsigned char > *message, void */*userData*/ ) +void mycallback( double deltatime, std::vector< unsigned char > *message, void * /* userData */ ) { unsigned int nBytes = message->size(); for ( unsigned int i=0; i +#include +#include "RtMidi.h" + +// Platform-dependent sleep routines. +#if defined(__WINDOWS_MM__) +#include +#define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) +#else // Unix variants +#include +#define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) +#endif + + +/* Here, we store the expected output. Timing is not tested */ +std::vector virtualinstring; +const char * virtualinstringgoal = + "\xc0\x5\xf1\x3c\xb0\x7\x64\x90\x40\x5a\x80\x40\x28\xb0\x7\x28\xf0\x43\x4\x3\x2\xf7"; +std::vector instring; +const char * instringgoal = + "\xc0\x6\xf1\x3d\xb0\x8\x64\x90\x41\x5a\x80\x41\x28\xb0\x8\x28\xf0\x43\x4\x3\x3\xf7"; + +void mycallback1( double deltatime, std::vector< unsigned char > *message, void * /* userData */ ) +{ + unsigned int nBytes = message->size(); + for ( unsigned int i=0; iat(i)); + // std::cout << "\\x" << std::hex << (int)message->at(i) << std::flush; + } + /* if ( nBytes > 0 ) + std::cout << "stamp = " << deltatime << std::endl; + */ +} + +void mycallback2( double deltatime, std::vector< unsigned char > *message, void * /* userData */ ) +{ + unsigned int nBytes = message->size(); + for ( unsigned int i=0; iat(i)); + // std::cout << "\\x" << std::hex << (int)message->at(i); + } + /* + if ( nBytes > 0 ) + std::cout << "stamp = " << deltatime << std::endl; + */ +} + + + +int main( int argc, char */*argv*/[] ) +{ + + std::vector message; + + try { + + // RtMidiIn constructor + RtMidiIn virtualin; + // RtMidiIn constructor + RtMidiOut virtualout; + + virtualin.openVirtualPort("RtMidi Test Virtual In"); + virtualout.openVirtualPort("RtMidi Test Virtual Out"); + + rtmidi::Pointer indescriptor + = virtualin.getDescriptor(true); + + rtmidi::Pointer outdescriptor + = virtualout.getDescriptor(true); + + { // avoid problems with wrong destruction order + /* use smart pointers to handle deletion */ + rtmidi::Pointer midiin = outdescriptor->getInputApi(); + if (!midiin) abort(); + rtmidi::Pointer midiout = indescriptor->getOutputApi(); + if (!midiout) abort(); + + + + midiin->openPort(outdescriptor); + midiout->openPort(indescriptor); + + + // Set our callback function. This should be done immediately after + // opening the port to avoid having incoming messages written to the + // queue instead of sent to the callback function. + midiin->setCallback( &mycallback1 ); + virtualin.setCallback( &mycallback2 ); + + // Don't ignore sysex, timing, or active sensing messages. + // Don't ignore sysex, timing, or active sensing messages. + midiin->ignoreTypes( false, false, false ); + virtualin.ignoreTypes( false, false, false ); + + SLEEP( 5000 ); + + // Send out a series of MIDI messages. + + // Program change: 192, 5 + message.push_back( 192 ); + message.push_back( 5 ); + midiout->sendMessage( &message ); + message[1] = 6; + virtualout.sendMessage(&message); + + SLEEP( 500 ); + + message[0] = 0xF1; + message[1] = 60; + midiout->sendMessage( &message ); + message[1] = 61; + virtualout.sendMessage(&message); + + // Control Change: 176, 7, 100 (volume) + message[0] = 176; + message[1] = 7; + message.push_back( 100 ); + midiout->sendMessage( &message ); + message[1] = 8; + virtualout.sendMessage ( &message ); + + // Note On: 144, 64, 90 + message[0] = 144; + message[1] = 64; + message[2] = 90; + midiout->sendMessage( &message ); + message[1] = 65; + virtualout.sendMessage( &message ); + + SLEEP( 500 ); + + // Note Off: 128, 64, 40 + message[0] = 128; + message[1] = 64; + message[2] = 40; + midiout->sendMessage( &message ); + message[1] = 65; + virtualout.sendMessage( &message ); + + SLEEP( 500 ); + + // Control Change: 176, 7, 40 + message[0] = 176; + message[1] = 7; + message[2] = 40; + midiout->sendMessage( &message ); + message[1] = 8; + virtualout.sendMessage( &message ); + + SLEEP( 500 ); + + // Sysex: 240, 67, 4, 3, 2, 247 + message[0] = 240; + message[1] = 67; + message[2] = 4; + message.push_back( 3 ); + message.push_back( 2 ); + message.push_back( 247 ); + midiout->sendMessage( &message ); + message[4] = 3; + virtualout.sendMessage( &message ); + + SLEEP( 500 ); + } + const unsigned char * goal = reinterpret_cast(instringgoal); + size_t i; + for (i = 0 ; i < instring.size() && goal[i] ; i++) + if (instring[i] != goal[i]) abort(); + if (i != instring.size()) abort(); + goal = reinterpret_cast(virtualinstringgoal); + for (i = 0 ; i < virtualinstring.size() && goal[i] ; i++) + if (virtualinstring[i] != goal[i]) abort(); + if (i != virtualinstring.size()) abort(); + + } catch ( RtMidiError &error ) { + error.printMessage(); + } +} From ab08fd55bd022884752bf636e6481e17bda7a885 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 13 Apr 2014 22:20:19 +0200 Subject: [PATCH 025/210] Implement new port selection API for JACK --- RtMidi.cpp | 701 ++++++++++++++++++++++++++++++++++++++++++++++----- RtMidi.h | 4 +- configure.ac | 14 + 3 files changed, 649 insertions(+), 70 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index e9b73c46..18fbab5e 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -38,6 +38,7 @@ #include "RtMidi.h" #include +#include NAMSPACE_RTMIDI_START //*********************************************************************// @@ -3065,15 +3066,431 @@ NAMESPACE_RTMIDI_END NAMSPACE_RTMIDI_START -struct JackMidiData { - jack_client_t *client; - jack_port_t *port; +struct JackMidiData; +static int jackProcessIn( jack_nframes_t nframes, void *arg ); +static int jackProcessOut( jack_nframes_t nframes, void *arg ); + +template +class JackSequencer { +public: + JackSequencer():client(0),name(),data(0) + { + if (locking) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); + } + } + + JackSequencer(const std::string & n, bool startqueue, JackMidiData * d):client(0),name(n),data(d) + { + if (locking) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); + } + init(client,startqueue); + } + + ~JackSequencer() + { + { + scoped_lock lock (mutex); + if (client) + jack_client_close (client); + } + if (locking) { + pthread_mutex_destroy(&mutex); + } + } + + bool setName(const std::string & n) { + /* we don't want to rename the client after opening it. */ + if (client) return false; + name = n; + return true; + } + + const char ** getPortList(unsigned long flags) { + init(); + return jack_get_ports(client, + NULL, + "midi", + flags); + } + + jack_port_t * getPort(const char * name) { + init(); + return jack_port_by_name(client,name); + } + + std::string getPortName(jack_port_t * port, int flags) { + init(); + int naming = flags & PortDescriptor::NAMING_MASK; + + std::ostringstream os; + switch (naming) { + case PortDescriptor::SESSION_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "JACK:"; +#if __UNIX_JACK_HAS_UUID__ + os << "UUID:" << std::hex << jack_port_uuid(port); +#else + os << jack_port_name(port); +#endif + break; + case PortDescriptor::STORAGE_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "JACK:"; + os << jack_port_name(port); + break; + case PortDescriptor::LONG_NAME: + os << jack_port_name(port); + if (flags & PortDescriptor::INCLUDE_API) + os << " (JACK)"; + break; + case PortDescriptor::SHORT_NAME: + default: + os << jack_port_short_name(port); + if (flags & PortDescriptor::INCLUDE_API) + os << " (JACK)"; + break; + } + return os.str(); + } + + int getPortCapabilities(jack_port_t * port) { + if (!port) return 0; + const char * type = jack_port_type(port); + if (strcmp(type,JACK_DEFAULT_MIDI_TYPE)) return 0; + int flags = jack_port_flags(port); + int retval = 0; + /* a JACK input port is capable of handling output to it and vice versa */ + if (flags & JackPortIsInput) + retval |= PortDescriptor::OUTPUT; + if (flags & JackPortIsOutput) + retval |= PortDescriptor::INPUT; + + return retval; + } + +#if 0 + int getNextClient(snd_seq_client_info_t * cinfo ) { + init(); + scoped_lock lock (mutex); + return snd_seq_query_next_client (client, cinfo); + } + int getNextPort(snd_seq_port_info_t * pinfo ) { + init(); + scoped_lock lock (mutex); + return snd_seq_query_next_port (client, pinfo); + } +#endif + + jack_port_t * createPort (const std::string & portName, unsigned long portOptions) { + init(); + scoped_lock lock (mutex); + return jack_port_register(client, + portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, + portOptions, + 0); + } + + void deletePort(jack_port_t * port) { + init(); + scoped_lock lock (mutex); + jack_port_unregister( client, port ); + } + + void connectPorts(jack_port_t * from, + jack_port_t * to) + { + init(); + jack_connect( client, + jack_port_name( from ), + jack_port_name( to ) ); + } + + void closePort(jack_port_t * from, + jack_port_t * to) + { + init(); + jack_disconnect( client, + jack_port_name( from ), + jack_port_name( to ) ); + } + +#if 0 + void startQueue(int queue_id) { + init(); + scoped_lock lock(mutex); + snd_seq_start_queue( client, queue_id, NULL ); + snd_seq_drain_output( client ); + } +#endif + + /*! Use JackSequencer like a C pointer. + \note This function breaks the design to control thread safety + by the selection of the \ref locking parameter to the class. + It should be removed as soon as possible in order ensure the + thread policy that has been intended by creating this class. + */ + operator jack_client_t * () + { + return client; + } +protected: + struct scoped_lock { + pthread_mutex_t * mutex; + scoped_lock(pthread_mutex_t & m): mutex(&m) + { + if (locking) + pthread_mutex_lock(mutex); + } + ~scoped_lock() + { + if (locking) + pthread_mutex_unlock(mutex); + } + }; + pthread_mutex_t mutex; + jack_client_t * client; + std::string name; + JackMidiData * data; + +#if 0 + snd_seq_client_info_t * GetClient(int id) { + init(); + snd_seq_client_info_t * cinfo; + scoped_lock lock(mutex); + snd_seq_get_any_client_info(client,id,cinfo); + return cinfo; + } +#endif + + void init() + { + init (client,false); + } + + void init(jack_client_t * &c, bool isoutput) + { + if (c) return; + { + scoped_lock lock(mutex); + if (( client = jack_client_open( name.c_str(), + JackNoStartServer, + NULL )) == 0) { + throw Error("JackSequencer::init: Could not connect to JACK server. Is it runnig?", + Error::WARNING); + return; + } + + if (isoutput && data) { + jack_set_process_callback( client, jackProcessOut, data ); + } else if (data) + jack_set_process_callback( client, jackProcessIn, data ); + jack_activate( client ); + } + } +}; +typedef JackSequencer<1> LockingJackSequencer; +typedef JackSequencer<0> NonLockingJackSequencer; + +struct JackPortDescriptor:public PortDescriptor +{ + MidiApi * api; + static LockingJackSequencer seq; + JackPortDescriptor(const std::string & name):api(0),clientName(name) + { + port = 0; + } + JackPortDescriptor(const char * portname, const std::string & name):api(0),clientName(name) + { + port = seq.getPort(portname); + seq.setName(name); + } + JackPortDescriptor(jack_port_t * other, + const std::string & name):api(0), + clientName(name) + { + port = other; + seq.setName(name); + } + JackPortDescriptor(JackPortDescriptor & other, + const std::string & name):api(0), + clientName(name) + { + port = other.port; + seq.setName(name); + } + ~JackPortDescriptor() + { + } + MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) { + if (getCapabilities() & INPUT) + return new MidiInJack(clientName,queueSizeLimit); + else + return 0; + } + MidiOutApi * getOutputApi() { + if (getCapabilities() & OUTPUT) + return new MidiOutJack(clientName); + else + return 0; + } + + + std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) { + return seq.getPortName(port,flags); + } + + const std::string & getClientName() { + return clientName; + } + int getCapabilities() { + return seq.getPortCapabilities(port); + } + static PortList getPortList(int capabilities, const std::string & clientName); + + operator jack_port_t * () const { return port; } + +protected: + std::string clientName; + jack_port_t * port; + + friend struct JackMidiData; +}; + +LockingJackSequencer JackPortDescriptor::seq; + + + +PortList JackPortDescriptor :: getPortList(int capabilities, const std::string & clientName) +{ + PortList list; + unsigned long flags = 0; + + if (capabilities & INPUT) { + flags |= JackPortIsOutput; + } + if (capabilities & OUTPUT) { + flags |= JackPortIsInput; + } + const char ** ports = seq.getPortList(flags); + if (!ports) return list; + for (const char ** port = ports; *port; port++) { + list.push_back(new JackPortDescriptor(*port, clientName)); + } + jack_free(ports); + return list; +} + +/*! A structure to hold variables related to the JACK API + implementation. + + \note After all sequencer handling is covered by the \ref + JackSequencer class, we should make seq to be a pointer in order + to allow a common client implementation. +*/ + +struct JackMidiData:public JackPortDescriptor { + jack_port_t * local; jack_ringbuffer_t *buffSize; jack_ringbuffer_t *buffMessage; jack_time_t lastTime; MidiInApi :: MidiInData *rtMidiIn; + NonLockingJackSequencer seq; + + /* + JackMidiData():seq() + { + init(); + } + */ + JackMidiData(const std::string &clientName, + MidiInApi :: MidiInData &inputData_):JackPortDescriptor(clientName), + local(0), + buffSize(0), + buffMessage(0), + lastTime(0), + rtMidiIn(&inputData_), + seq(clientName,false,this) + { + } + + /** + * Create output midi data. + * + * \param clientName + * + * \return + */ + JackMidiData(const std::string &clientName):JackPortDescriptor(clientName), + local(0), + buffSize(jack_ringbuffer_create( JACK_RINGBUFFER_SIZE )), + buffMessage(jack_ringbuffer_create( JACK_RINGBUFFER_SIZE )), + lastTime(0), + rtMidiIn(), + seq(clientName,true,this) + {} + + + ~JackMidiData() + { + if (local) + deletePort(); + if (buffSize) + jack_ringbuffer_free( buffSize ); + if (buffMessage) + jack_ringbuffer_free( buffMessage ); + } + + + + + void setRemote(jack_port_t * remote) { + port = remote; + } + + void connectPorts(jack_port_t * from, + jack_port_t * to) { + seq.connectPorts(from, to); + } + + int openPort(unsigned long jackCapabilities, + const std::string & portName) { + local = seq.createPort(portName, jackCapabilities); + if (!local) { + api->error( Error::DRIVER_ERROR, + "MidiInJack::openPort: JACK error opening port subscription." ); + return -99; + } + return 0; + } + + void deletePort() { + seq.deletePort(local); + local = 0; + } + + void closePort(bool output_is_remote) { + if (output_is_remote) { + seq.closePort( local, port ); + } else { + seq.closePort( port, local ); + } + port = 0; + } + + operator jack_port_t * () const { return port; } }; + + //*********************************************************************// // API: JACK // Class Definitions: MidiInJack @@ -3087,8 +3504,8 @@ static int jackProcessIn( jack_nframes_t nframes, void *arg ) jack_time_t time; // Is port created? - if ( jData->port == NULL ) return 0; - void *buff = jack_port_get_buffer( jData->port, nframes ); + if ( jData->local == NULL ) return 0; + void *buff = jack_port_get_buffer( jData->local, nframes ); // We have midi events in buffer int evCount = jack_midi_get_event_count( buff ); @@ -3139,25 +3556,22 @@ MidiInJack :: MidiInJack( const std::string clientName, unsigned int queueSizeLi void MidiInJack :: initialize( const std::string& clientName ) { - JackMidiData *data = new JackMidiData; + JackMidiData *data = new JackMidiData(clientName,inputData_); apiData_ = (void *) data; - - data->rtMidiIn = &inputData_; - data->port = NULL; - data->client = NULL; this->clientName = clientName; - - connect(); } +#if 0 void MidiInJack :: connect() { + abort(); + // this should be unnecessary JackMidiData *data = static_cast (apiData_); - if ( data->client ) + if ( data->local ) return; // Initialize JACK client - if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { + if (( data->local = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { errorString_ = "MidiInJack::initialize: JACK server not running?"; error( Error::WARNING, errorString_ ); return; @@ -3166,29 +3580,32 @@ void MidiInJack :: connect() jack_set_process_callback( data->client, jackProcessIn, data ); jack_activate( data->client ); } +#endif MidiInJack :: ~MidiInJack() { JackMidiData *data = static_cast (apiData_); closePort(); +#if 0 if ( data->client ) jack_client_close( data->client ); +#endif delete data; } -void MidiInJack :: openPort( unsigned int portNumber, const std::string portName ) +void MidiInJack :: openPort( unsigned int portNumber, const std::string & portName ) { JackMidiData *data = static_cast (apiData_); - connect(); + // connect(); // Creating new port - if ( data->port == NULL) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); + if ( data->local == NULL) + data->local = jack_port_register( data->seq, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); - if ( data->port == NULL) { + if ( data->local == NULL) { errorString_ = "MidiInJack::openPort: JACK error creating port"; error( Error::DRIVER_ERROR, errorString_ ); return; @@ -3196,41 +3613,114 @@ void MidiInJack :: openPort( unsigned int portNumber, const std::string portName // Connecting to the output std::string name = getPortName( portNumber ); - jack_connect( data->client, name.c_str(), jack_port_name( data->port ) ); + jack_connect( data->seq, name.c_str(), jack_port_name( data->local ) ); } void MidiInJack :: openVirtualPort( const std::string portName ) { JackMidiData *data = static_cast (apiData_); + // connect(); + if ( data->local == NULL ) + data->local = jack_port_register( data->seq, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); + + if ( data->local == NULL ) { + errorString_ = "MidiInJack::openVirtualPort: JACK error creating virtual port"; + error( Error::DRIVER_ERROR, errorString_ ); + } +} + +void MidiInJack :: openPort( const PortDescriptor & p, + const std::string & portName ) +{ + JackMidiData *data = static_cast (apiData_); + const JackPortDescriptor * port = dynamic_cast(&p); + + if ( !data ) { + errorString_ = "MidiInAlsa::openPort: Internal error: data has not been allocated!"; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } +#if 0 + if ( connected_ ) { + errorString_ = "MidiInAlsa::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } +#endif + if (!port) { + errorString_ = "MidiInAlsa::openPort: an invalid (i.e. non-ALSA) port descriptor has been passed to openPort!"; + error( Error::WARNING, errorString_ ); + return; + } + + if (!data->local) + data->openPort (JackPortIsInput, + portName); + data->setRemote(*port); + data->connectPorts(*port,data->local); + +#if 0 + connect(); - if ( data->port == NULL ) + + // Creating new port + if ( data->port == NULL) data->port = jack_port_register( data->client, portName.c_str(), JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); - if ( data->port == NULL ) { - errorString_ = "MidiInJack::openVirtualPort: JACK error creating virtual port"; + if ( data->port == NULL) { + errorString_ = "MidiInJack::openPort: JACK error creating port"; error( Error::DRIVER_ERROR, errorString_ ); + return; } + + // Connecting to the output + std::string name = getPortName( portNumber ); + jack_connect( data->client, name.c_str(), jack_port_name( data->port ) ); +#endif +} + +Pointer MidiInJack :: getDescriptor(bool local) +{ + JackMidiData *data = static_cast (apiData_); + if (local) { + if (data && data->local) { + return new JackPortDescriptor(data->local,data->getClientName()); + } + } else { + if (data && *data) { + return new JackPortDescriptor(*data,data->getClientName()); + } + } + return NULL; +} + +PortList MidiInJack :: getPortList(int capabilities) +{ + JackMidiData *data = static_cast (apiData_); + return JackPortDescriptor::getPortList(capabilities | PortDescriptor::INPUT, + data->getClientName()); } unsigned int MidiInJack :: getPortCount() { int count = 0; + // connect(); JackMidiData *data = static_cast (apiData_); - connect(); - if ( !data->client ) + if ( !(data->seq) ) return 0; // List of available ports - const char **ports = jack_get_ports( data->client, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); + const char **ports = jack_get_ports( data->seq, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); if ( ports == NULL ) return 0; while ( ports[count] != NULL ) count++; free( ports ); - + return count; } @@ -3239,10 +3729,10 @@ std::string MidiInJack :: getPortName( unsigned int portNumber ) JackMidiData *data = static_cast (apiData_); std::string retStr(""); - connect(); + // connect(); // List of available ports - const char **ports = jack_get_ports( data->client, NULL, + const char **ports = jack_get_ports( data->seq, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); // Check port validity @@ -3268,9 +3758,9 @@ void MidiInJack :: closePort() { JackMidiData *data = static_cast (apiData_); - if ( data->port == NULL ) return; - jack_port_unregister( data->client, data->port ); - data->port = NULL; + if ( data->local == NULL ) return; + jack_port_unregister( data->seq, data->local ); + data->local = NULL; } //*********************************************************************// @@ -3286,9 +3776,9 @@ static int jackProcessOut( jack_nframes_t nframes, void *arg ) int space; // Is port created? - if ( data->port == NULL ) return 0; + if ( data->local == NULL ) return 0; - void *buff = jack_port_get_buffer( data->port, nframes ); + void *buff = jack_port_get_buffer( data->local, nframes ); jack_midi_clear_buffer( buff ); while ( jack_ringbuffer_read_space( data->buffSize ) > 0 ) { @@ -3308,24 +3798,23 @@ MidiOutJack :: MidiOutJack( const std::string clientName ) : MidiOutApi() void MidiOutJack :: initialize( const std::string& clientName ) { - JackMidiData *data = new JackMidiData; + JackMidiData *data = new JackMidiData(clientName); apiData_ = (void *) data; - - data->port = NULL; - data->client = NULL; this->clientName = clientName; - connect(); + // connect(); } void MidiOutJack :: connect() { + abort(); +#if 0 JackMidiData *data = static_cast (apiData_); - if ( data->client ) + if ( data->seq ) return; // Initialize JACK client - if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { + if (( data->seq = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { errorString_ = "MidiOutJack::initialize: JACK server not running?"; error( Error::WARNING, errorString_ ); return; @@ -3335,6 +3824,7 @@ void MidiOutJack :: connect() data->buffSize = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); data->buffMessage = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); jack_activate( data->client ); +#endif } MidiOutJack :: ~MidiOutJack() @@ -3342,28 +3832,30 @@ MidiOutJack :: ~MidiOutJack() JackMidiData *data = static_cast (apiData_); closePort(); - if ( data->client ) { +#if 0 + if ( data->seq ) { // Cleanup jack_client_close( data->client ); jack_ringbuffer_free( data->buffSize ); jack_ringbuffer_free( data->buffMessage ); } +#endif delete data; } -void MidiOutJack :: openPort( unsigned int portNumber, const std::string portName ) +void MidiOutJack :: openPort( unsigned int portNumber, const std::string & portName ) { JackMidiData *data = static_cast (apiData_); - connect(); + // connect(); // Creating new port - if ( data->port == NULL ) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); + if ( data->local == NULL ) + data->local = jack_port_register( data->seq, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); - if ( data->port == NULL ) { + if ( data->local == NULL ) { errorString_ = "MidiOutJack::openPort: JACK error creating port"; error( Error::DRIVER_ERROR, errorString_ ); return; @@ -3371,42 +3863,115 @@ void MidiOutJack :: openPort( unsigned int portNumber, const std::string portNam // Connecting to the output std::string name = getPortName( portNumber ); - jack_connect( data->client, jack_port_name( data->port ), name.c_str() ); + jack_connect( data->seq, jack_port_name( data->local ), name.c_str() ); } void MidiOutJack :: openVirtualPort( const std::string portName ) { JackMidiData *data = static_cast (apiData_); + // connect(); + if ( data->local == NULL ) + data->local = jack_port_register( data->seq, portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); + + if ( data->local == NULL ) { + errorString_ = "MidiOutJack::openVirtualPort: JACK error creating virtual port"; + error( Error::DRIVER_ERROR, errorString_ ); + } +} + +void MidiOutJack :: openPort( const PortDescriptor & p, + const std::string & portName ) +{ + JackMidiData *data = static_cast (apiData_); + const JackPortDescriptor * port = dynamic_cast(&p); + + if ( !data ) { + errorString_ = "MidiInAlsa::openPort: Internal error: data has not been allocated!"; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } +#if 0 + if ( connected_ ) { + errorString_ = "MidiInAlsa::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } +#endif + if (!port) { + errorString_ = "MidiInAlsa::openPort: an invalid (i.e. non-ALSA) port descriptor has been passed to openPort!"; + error( Error::WARNING, errorString_ ); + return; + } + + if (!data->local) + data->openPort (JackPortIsOutput, + portName); + data->setRemote(*port); + data->connectPorts(data->local,*port); + +#if 0 + connect(); - if ( data->port == NULL ) + + // Creating new port + if ( data->port == NULL) data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); - if ( data->port == NULL ) { - errorString_ = "MidiOutJack::openVirtualPort: JACK error creating virtual port"; + if ( data->port == NULL) { + errorString_ = "MidiOutJack::openPort: JACK error creating port"; error( Error::DRIVER_ERROR, errorString_ ); + return; } + + // Connecting to the output + std::string name = getPortName( portNumber ); + jack_connect( data->client, name.c_str(), jack_port_name( data->port ) ); +#endif +} + +Pointer MidiOutJack :: getDescriptor(bool local) +{ + JackMidiData *data = static_cast (apiData_); + if (local) { + if (data && data->local) { + return new JackPortDescriptor(data->local,data->getClientName()); + } + } else { + if (data && *data) { + return new JackPortDescriptor(*data,data->getClientName()); + } + } + return NULL; +} + +PortList MidiOutJack :: getPortList(int capabilities) +{ + JackMidiData *data = static_cast (apiData_); + return JackPortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT, + data->getClientName()); } unsigned int MidiOutJack :: getPortCount() { int count = 0; JackMidiData *data = static_cast (apiData_); - connect(); - if ( !data->client ) + // connect(); + if ( !data->seq ) return 0; // List of available ports - const char **ports = jack_get_ports( data->client, NULL, + const char **ports = jack_get_ports( data->seq, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); if ( ports == NULL ) return 0; while ( ports[count] != NULL ) count++; - + free( ports ); - + return count; } @@ -3415,10 +3980,10 @@ std::string MidiOutJack :: getPortName( unsigned int portNumber ) JackMidiData *data = static_cast (apiData_); std::string retStr(""); - connect(); + // connect(); // List of available ports - const char **ports = jack_get_ports( data->client, NULL, + const char **ports = jack_get_ports( data->seq, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); // Check port validity @@ -3444,19 +4009,19 @@ void MidiOutJack :: closePort() { JackMidiData *data = static_cast (apiData_); - if ( data->port == NULL ) return; - jack_port_unregister( data->client, data->port ); - data->port = NULL; + if ( data->local == NULL ) return; + jack_port_unregister( data->seq, data->local ); + data->local = NULL; } -void MidiOutJack :: sendMessage( std::vector *message ) +void MidiOutJack :: sendMessage( std::vector &message ) { - int nBytes = message->size(); + int nBytes = message.size(); JackMidiData *data = static_cast (apiData_); // Write full message to buffer - jack_ringbuffer_write( data->buffMessage, ( const char * ) &( *message )[0], - message->size() ); + jack_ringbuffer_write( data->buffMessage, ( const char * ) &( message[0] ), + message.size() ); jack_ringbuffer_write( data->buffSize, ( char * ) &nBytes, sizeof( nBytes ) ); } NAMSPACE_RTMIDI_END diff --git a/RtMidi.h b/RtMidi.h index 1ec42d3e..7756071c 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -1057,7 +1057,7 @@ class MidiInJack: public MidiInApi public: MidiInJack( const std::string clientName, unsigned int queueSizeLimit ); ~MidiInJack( void ); - ApiType getCurrentApi( void ) { return UNIX_JACK; }; + ApiType getCurrentApi( void ) throw() { return UNIX_JACK; }; void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); @@ -1079,7 +1079,7 @@ class MidiOutJack: public MidiOutApi public: MidiOutJack( const std::string clientName ); ~MidiOutJack( void ); - ApiType getCurrentApi( void ) { return UNIX_JACK; }; + ApiType getCurrentApi( void ) throw() { return UNIX_JACK; }; void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); diff --git a/configure.ac b/configure.ac index f4f497aa..e0361195 100644 --- a/configure.ac +++ b/configure.ac @@ -68,6 +68,13 @@ case $host in api="$api -D__UNIX_JACK__" AC_MSG_RESULT(using JACK) AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], ) + AC_LANG_PUSH(C++) + AC_TRY_COMPILE([ +#include + ],[ +return jack_port_uuid(NULL); + ],api="$api -D__UNIX_JACK_HAS_UUID__") + AC_LANG_POP(C++) # Look for ALSA flag AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA sequencer API support (linux only)], [ @@ -92,6 +99,13 @@ case $host in api="$api -D__UNIX_JACK__" AC_MSG_RESULT(using JACK) AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], ) + AC_LANG_PUSH(C++) + AC_TRY_COMPILE([ +#include + ],[ +return jack_port_uuid(NULL); + ],api="$api -D__UNIX_JACK_HAS_UUID__") + AC_LANG_POP(C++) # Look for Core flag AC_ARG_WITH(core, [ --with-core = choose CoreMidi API support (mac only)], [ From df6cb652768aef2df58ea0c42cddf72fd7d42898 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 13 Apr 2014 22:09:07 +0200 Subject: [PATCH 026/210] Fix checking for the length of the gool. --- tests/loopback.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/tests/loopback.cpp b/tests/loopback.cpp index 9ce6464d..2ddefd92 100644 --- a/tests/loopback.cpp +++ b/tests/loopback.cpp @@ -31,6 +31,13 @@ std::vector instring; const char * instringgoal = "\xc0\x6\xf1\x3d\xb0\x8\x64\x90\x41\x5a\x80\x41\x28\xb0\x8\x28\xf0\x43\x4\x3\x3\xf7"; +inline size_t getlength(const char * messages) { + size_t retval = 0; + const unsigned char * c = reinterpret_cast(messages); + while (*(c++) != 0xf7) retval++; + return ++retval; +} + void mycallback1( double deltatime, std::vector< unsigned char > *message, void * /* userData */ ) { unsigned int nBytes = message->size(); @@ -175,12 +182,24 @@ int main( int argc, char */*argv*/[] ) } const unsigned char * goal = reinterpret_cast(instringgoal); size_t i; - for (i = 0 ; i < instring.size() && goal[i] ; i++) + std::cout << "Virtual output -> input:" << std::endl; + if (instring.size() != getlength(instringgoal)) abort(); + for (i = 0 ; i < instring.size() && goal[i] ; i++){ + std::cout << " " << std::hex << (int) instring[i]; + std::cout << "/" << std::hex << (int) goal[i] << std::flush; if (instring[i] != goal[i]) abort(); + } + std::cout << std::endl; if (i != instring.size()) abort(); goal = reinterpret_cast(virtualinstringgoal); - for (i = 0 ; i < virtualinstring.size() && goal[i] ; i++) + std::cout << "Output -> virtual input:" << std::endl; + if (instring.size() != getlength(virtualinstringgoal)) abort(); + for (i = 0 ; i < virtualinstring.size() && goal[i] ; i++) { + std::cout << " " << std::hex << (int) virtualinstring[i]; + std::cout << "/" << std::hex << (int) goal[i] << std::flush; if (virtualinstring[i] != goal[i]) abort(); + } + std::cout << std::endl; if (i != virtualinstring.size()) abort(); } catch ( RtMidiError &error ) { From 996d4eacc61977b4c2f48b0712e40bad5bf65bf9 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 13 Apr 2014 22:19:08 +0200 Subject: [PATCH 027/210] Really show output ports to the user in midiout2. --- tests/midiout2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/midiout2.cpp b/tests/midiout2.cpp index 5d09b97d..bf45a266 100644 --- a/tests/midiout2.cpp +++ b/tests/midiout2.cpp @@ -121,7 +121,7 @@ bool chooseMidiPort( RtMidiOut &midi ) } std::string portName; - rtmidi::PortList list = midi.getPortList(rtmidi::PortDescriptor::INPUT); + rtmidi::PortList list = midi.getPortList(rtmidi::PortDescriptor::OUTPUT); if ( list.empty() ) { std::cout << "No output ports available!" << std::endl; return false; From 4a0af7e50be417ab32f6f46563966448043d1597 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 13 Apr 2014 23:14:00 +0200 Subject: [PATCH 028/210] Flush the output queue when a JACK client connection is going to be closed. --- RtMidi.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 18fbab5e..22844e66 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -3098,8 +3098,11 @@ class JackSequencer { { { scoped_lock lock (mutex); - if (client) + if (client) { + jack_deactivate (client); + // the latter doesn't flush the queue jack_client_close (client); + } } if (locking) { pthread_mutex_destroy(&mutex); From b404c3205c078c38922a25b8fd0dbb5f7d73ccab Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 13 Apr 2014 23:15:11 +0200 Subject: [PATCH 029/210] Update midiout2 provides a virtual output port (not input port) ;-) --- tests/midiout2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/midiout2.cpp b/tests/midiout2.cpp index bf45a266..068e7cb2 100644 --- a/tests/midiout2.cpp +++ b/tests/midiout2.cpp @@ -108,7 +108,7 @@ int main( int /* argc*/, char */*argv*/[] ) bool chooseMidiPort( RtMidiOut &midi ) { - std::cout << "\nWould you like to open a virtual input port? [y/N] "; + std::cout << "\nWould you like to open a virtual output port? [y/N] "; std::string keyHit; std::getline( std::cin, keyHit ); From 3f505b96792bc77ecadbb25306bd80ae1f2e95e3 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 26 Apr 2014 10:36:50 +0200 Subject: [PATCH 030/210] Emulate the new port selection API for WinMM. WinMM does not support a good port selection scheme. At least wine seems to ensure reliable port ids. --- RtMidi.cpp | 575 +++++++++++++++++++++++++++++++++++++++++++-- RtMidi.h | 7 +- tests/midiout2.cpp | 1 + tests/qmidiin2.cpp | 8 +- 4 files changed, 571 insertions(+), 20 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 22844e66..edb4c2be 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -2547,9 +2547,431 @@ NAMSPACE_RTMIDI_END #define RT_SYSEX_BUFFER_SIZE 1024 #define RT_SYSEX_BUFFER_COUNT 4 NAMESPACE_RTMIDI_START -// A structure to hold variables related to the CoreMIDI API -// implementation. -struct WinMidiData { + +/* some header defines UNIQUE_NAME as a macro */ +#ifdef UNIQUE_NAME +#undef UNIQUE_NAME +#endif +/*! An abstraction layer for the ALSA sequencer layer. It provides + the following functionality: + - dynamic allocation of the sequencer + - optionallay avoid concurrent access to the ALSA sequencer, + which is not thread proof. This feature is controlled by + the parameter \ref locking. +*/ + +template +class WinMMSequencer { +public: + WinMMSequencer():mutex(0),name() + { + if (locking) { +#if 0 + // use mthreads instead + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); +#endif + } + } + + WinMMSequencer(const std::string & n):name(n) + { + if (locking) { +#if 0 + // use mthreads instead + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); +#endif + } + init(); + { + scoped_lock lock(mutex); + } + } + + ~WinMMSequencer() + { + if (locking) { +#if 0 + // use mthreads instead + pthread_mutex_destroy(&mutex); +#endif + } + } + + bool setName(const std::string & n) { + /* we don't want to rename the client after opening it. */ + name = n; + return true; + } + + std::string getPortName(int port, bool is_input, int flags) { + init(); + int naming = flags & PortDescriptor::NAMING_MASK; + std::string name; + + unsigned int nDevices = is_input?midiInGetNumDevs() + : midiOutGetNumDevs(); + if ( port >= nDevices ) { + std::ostringstream ost; + std::cerr << port << "<" << nDevices << std::endl; + throw Error("WinMMSequencer::getPortName: the 'port' argument is invalid.", + Error::WARNING); + } + + if (is_input) { + MIDIINCAPS deviceCaps; + midiInGetDevCaps( port, &deviceCaps, sizeof(MIDIINCAPS)); + +#if defined( UNICODE ) || defined( _UNICODE ) + int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; + name.assign( length, 0 ); + length = WideCharToMultiByte(CP_UTF8, + 0, + deviceCaps.szPname, + static_cast(wcslen(deviceCaps.szPname)), + &name[0], + length, + NULL, + NULL); +#else + name = deviceCaps.szPname; +#endif + } else { + MIDIOUTCAPS deviceCaps; + midiOutGetDevCaps( port, &deviceCaps, sizeof(MIDIOUTCAPS)); + +#if defined( UNICODE ) || defined( _UNICODE ) + int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; + name.assign( length, 0 ); + length = WideCharToMultiByte(CP_UTF8, + 0, + deviceCaps.szPname, + static_cast(wcslen(deviceCaps.szPname)), + &name[0], + length, + NULL, + NULL); +#else + name = deviceCaps.szPname; +#endif + + } + + + std::ostringstream os; + switch (naming) { + case PortDescriptor::SESSION_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "WinMM:"; + os << port << ":" << name.c_str(); + break; + case PortDescriptor::STORAGE_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "WinMM:"; + os << name.c_str(); + if (flags & PortDescriptor::UNIQUE_NAME) + os << ";" << port; + break; + case PortDescriptor::LONG_NAME: + case PortDescriptor::SHORT_NAME: + default: + os << name.c_str(); + if (flags & PortDescriptor::UNIQUE_NAME) { + os << " "; + os << port; + } + if (flags & PortDescriptor::INCLUDE_API) + os << " (WinMM)"; + + break; + } + return os.str(); + } + +#if 0 + int getPortCapabilities(int client, int port) { + init(); + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + { + scoped_lock lock (mutex); + snd_seq_get_any_port_info(seq,client,port,pinfo); + } + unsigned int caps = snd_seq_port_info_get_capability(pinfo); + int retval = (caps & (SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ))? + PortDescriptor::INPUT:0; + if (caps & (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) + retval |= PortDescriptor::OUTPUT; + return retval; + } + + int getNextClient(snd_seq_client_info_t * cinfo ) { + init(); + scoped_lock lock (mutex); + return snd_seq_query_next_client (seq, cinfo); + } + int getNextPort(snd_seq_port_info_t * pinfo ) { + init(); + scoped_lock lock (mutex); + return snd_seq_query_next_port (seq, pinfo); + } + + int createPort (snd_seq_port_info_t *pinfo) { + init(); + scoped_lock lock (mutex); + return snd_seq_create_port(seq, pinfo); + } + + void deletePort(int port) { + init(); + scoped_lock lock (mutex); + snd_seq_delete_port( seq, port ); + } + + snd_seq_port_subscribe_t * connectPorts(const snd_seq_addr_t & from, + const snd_seq_addr_t & to, + bool real_time) { + init(); + snd_seq_port_subscribe_t *subscription; + + if (snd_seq_port_subscribe_malloc( &subscription ) < 0) { + throw Error("MidiInWinMM::openPort: WINMM error allocation port subscription.", + Error::DRIVER_ERROR ); + return 0; + } + snd_seq_port_subscribe_set_sender(subscription, &from); + snd_seq_port_subscribe_set_dest(subscription, &to); + if (real_time) { + snd_seq_port_subscribe_set_time_update(subscription, 1); + snd_seq_port_subscribe_set_time_real(subscription, 1); + } + { + scoped_lock lock (mutex); + if ( snd_seq_subscribe_port(seq, subscription) ) { + snd_seq_port_subscribe_free( subscription ); + subscription = 0; + throw Error("MidiInWinMM::openPort: WINMM error making port connection.", + Error::DRIVER_ERROR); + return 0; + } + } + return subscription; + } + + void closePort(snd_seq_port_subscribe_t * subscription ) { + init(); + scoped_lock lock(mutex); + snd_seq_unsubscribe_port( seq, subscription ); + } + + void startQueue(int queue_id) { + init(); + scoped_lock lock(mutex); + snd_seq_start_queue( seq, queue_id, NULL ); + snd_seq_drain_output( seq ); + } + + /*! Use WinMMSequencer like a C pointer. + \note This function breaks the design to control thread safety + by the selection of the \ref locking parameter to the class. + It should be removed as soon as possible in order ensure the + thread policy that has been intended by creating this class. + */ + operator snd_seq_t * () + { + return seq; + } +#endif +protected: + struct scoped_lock { + // pthread_mutex_t * mutex; + scoped_lock(unsigned int &) + { +#if 0 + if (locking) + pthread_mutex_lock(mutex); +#endif + } + ~scoped_lock() + { +#if 0 + if (locking) + pthread_mutex_unlock(mutex); +#endif + } + }; + // to keep the API simple + int mutex; + std::string name; + +#if 0 + snd_seq_client_info_t * GetClient(int id) { + init(); + snd_seq_client_info_t * cinfo; + scoped_lock lock(mutex); + snd_seq_get_any_client_info(seq,id,cinfo); + return cinfo; + } +#endif + + void init() + { + // init (seq); + } + +#if 0 + void init(snd_seq_t * &s) + { + if (s) return; + { + scoped_lock lock(mutex); + int result = snd_seq_open(&s, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); + if ( result < 0 ) { + throw Error( "MidiInWinMM::initialize: error creating WINMM sequencer client object.", + Error::DRIVER_ERROR ); + return; + } + snd_seq_set_client_name( seq, name.c_str() ); + } + } +#endif +}; +// typedef WinMMSequencer<1> LockingWinMMSequencer; +typedef WinMMSequencer<0> NonLockingWinMMSequencer; + +struct WinMMPortDescriptor:public PortDescriptor +{ + static NonLockingWinMMSequencer seq; + WinMMPortDescriptor(const std::string & cname):name(),port(0),clientName(name) + { + } + WinMMPortDescriptor(unsigned int p, const std::string & pn, bool i_o, const std::string & n): + name(pn), + port(p), + is_input(i_o), + clientName(n) + { + } + ~WinMMPortDescriptor() {} + MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) { + if (is_input) + return new MidiInWinMM(clientName,queueSizeLimit); + else + return 0; + } + MidiOutApi * getOutputApi() { + if (!is_input) + return new MidiOutWinMM(clientName); + else + return 0; + } + std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) { + return seq.getPortName(port,is_input,flags); + } + + const std::string & getClientName() const { + return clientName; + } + int getCapabilities() const { + return is_input ? INPUT : OUTPUT; + } + + int getCapabilities() { + const WinMMPortDescriptor * self = this; + return self->getCapabilities(); + } + + bool is_valid() const { + if (is_input) { + if (midiInGetNumDevs() <= port) { + std::cerr << "In: " << midiInGetNumDevs() << "<=" << port << std::endl; + return false; + } + } else { + if (midiOutGetNumDevs() <= port) { + std::cerr << "Out: " << midiOutGetNumDevs() << "<=" << port << std::endl; + return false; + } + } + std::cerr << seq.getPortName(port,is_input,PortDescriptor::STORAGE_PATH) + << "==" << name << std::endl; + return seq.getPortName(port,is_input,PortDescriptor::STORAGE_PATH) + == name; + } + + void setRemote(const WinMMPortDescriptor * remote) { + port = remote->port; + name = remote->name; + is_input = remote->is_input; + } + + + unsigned int getPortNumber() const { return port; } + + static PortList getPortList(int capabilities, const std::string & clientName); +protected: + /* There is no perfect port descriptor available in this API. + We use the port number and issue an error if the port name has changed + between the creation of the port descriptor and opening the port. */ + std::string name; + unsigned int port; + bool is_input; + std::string clientName; +}; + +NonLockingWinMMSequencer WinMMPortDescriptor::seq; + + + +PortList WinMMPortDescriptor :: getPortList(int capabilities, const std::string & clientName) +{ + PortList list; + + if (capabilities & INPUT && capabilities & OUTPUT) return list; + + if (capabilities & INPUT) { + size_t n = midiInGetNumDevs(); + for (size_t i = 0 ; i < n ; i++) { + std::string name = seq.getPortName(i,true,PortDescriptor::STORAGE_PATH); + list.push_back(new WinMMPortDescriptor(i,name,true,clientName)); + } + } else { + size_t n = midiOutGetNumDevs(); + for (size_t i = 0 ; i < n ; i++) { + std::string name = seq.getPortName(i,false,PortDescriptor::STORAGE_PATH); + std::cout << name << std::endl; + list.push_back(new WinMMPortDescriptor(i,name,false,clientName)); + } + } + return list; +} + +static void *winMMMidiHandler( void *ptr ); + + +/*! A structure to hold variables related to the WINMM API + implementation. + + \note After all sequencer handling is covered by the \ref + WinMMSequencer class, we should make seq to be a pointer in order + to allow a common client implementation. +*/ + +struct WinMidiData:public WinMMPortDescriptor { + /* + WinMMMidiData():seq() + { + init(); + } + */ + WinMidiData(const std::string &clientName):WinMMPortDescriptor(clientName) {} + ~WinMidiData() {} + HMIDIIN inHandle; // Handle to Midi Input Device HMIDIOUT outHandle; // Handle to Midi Output Device DWORD lastTime; @@ -2558,6 +2980,7 @@ struct WinMidiData { CRITICAL_SECTION _mutex; // [Patrice] see https://groups.google.com/forum/#!topic/mididev/6OUjHutMpEo }; + //*********************************************************************// // API: Windows MM // Class Definitions: MidiInWinMM @@ -2679,7 +3102,7 @@ MidiInWinMM :: ~MidiInWinMM() delete data; } -void MidiInWinMM :: initialize( const std::string& /*clientName*/ ) +void MidiInWinMM :: initialize( const std::string& clientName ) { // We'll issue a warning here if no devices are available but not // throw an error since the user can plugin something later. @@ -2690,7 +3113,7 @@ void MidiInWinMM :: initialize( const std::string& /*clientName*/ ) } // Save our api-specific connection information. - WinMidiData *data = (WinMidiData *) new WinMidiData; + WinMidiData *data = (WinMidiData *) new WinMidiData(clientName); apiData_ = (void *) data; inputData_.apiData = (void *) data; data->message.bytes.clear(); // needs to be empty for first input message @@ -2701,7 +3124,7 @@ void MidiInWinMM :: initialize( const std::string& /*clientName*/ ) } } -void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) +void MidiInWinMM :: openPort( unsigned int portNumber, const std::string & /*portName*/ ) { if ( connected_ ) { errorString_ = "MidiInWinMM::openPort: a valid connection already exists!"; @@ -2780,6 +3203,67 @@ void MidiInWinMM :: openVirtualPort( std::string /*portName*/ ) error( Error::WARNING, errorString_ ); } +void MidiInWinMM :: openPort(const PortDescriptor & p, const std::string & portName) { + const WinMMPortDescriptor * port = dynamic_cast (&p); + if ( !port) { + error( Error::DRIVER_ERROR, + "MidiINWinMM::openPort: an invalid (i.e. non-WinMM) port descriptor has been passed to openPort!"); + return; + } + if ( connected_ ) { + errorString_ = "MidiInWinMM::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + if (port->getCapabilities() != PortDescriptor::INPUT) { + error( Error::DRIVER_ERROR, + "MidiINWinMM::openPort: the port descriptor cannot be used to open an input port."); + return; + } + + // there is a possible race condition between opening the port and + // reordering of ports so we must check whether we opened the right port. + openPort(port->getPortNumber(),portName); + if (!port->is_valid()) { + closePort(); + error (Error::DRIVER_ERROR, + "MidiINWinMM::openPort: some change in the arrangement of MIDI input ports invalidated the port descriptor."); + return; + } + connected_ = true; +} + +Pointer MidiInWinMM :: getDescriptor(bool local) +{ + if (local || !connected_) return 0; + WinMidiData *data = static_cast (apiData_); + if (!data) return 0; + UINT devid; + switch (midiInGetID(data->inHandle,&devid)) { + case MMSYSERR_INVALHANDLE: + error (Error::DRIVER_ERROR, + "MidiInWinMM::getDescriptor: The internal handle is invalid."); + return 0; + case MMSYSERR_NODRIVER: + error (Error::DRIVER_ERROR, + "MidiInWinMM::getDescriptor: The system has no driver for our handle :-(."); + return 0; + case MMSYSERR_NOMEM: + error (Error::DRIVER_ERROR, + "MidiInWinMM::getDescriptor: The system could not handle enough memory."); + return 0; + } + return new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); + +} + +PortList MidiInWinMM :: getPortList(int capabilities) +{ + WinMidiData *data = static_cast (apiData_); + if (!data) return PortList(); + return WinMMPortDescriptor::getPortList(PortDescriptor::INPUT,data->getClientName()); +} + void MidiInWinMM :: closePort( void ) { if ( connected_ ) { @@ -2865,7 +3349,7 @@ MidiOutWinMM :: ~MidiOutWinMM() delete data; } -void MidiOutWinMM :: initialize( const std::string& /*clientName*/ ) +void MidiOutWinMM :: initialize( const std::string& clientName ) { // We'll issue a warning here if no devices are available but not // throw an error since the user can plug something in later. @@ -2876,7 +3360,7 @@ void MidiOutWinMM :: initialize( const std::string& /*clientName*/ ) } // Save our api-specific connection information. - WinMidiData *data = (WinMidiData *) new WinMidiData; + WinMidiData *data = (WinMidiData *) new WinMidiData(clientName); apiData_ = (void *) data; } @@ -2911,7 +3395,7 @@ std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) return stringName; } -void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) +void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string & /*portName*/ ) { if ( connected_ ) { errorString_ = "MidiOutWinMM::openPort: a valid connection already exists!"; @@ -2966,11 +3450,74 @@ void MidiOutWinMM :: openVirtualPort( std::string /*portName*/ ) error( Error::WARNING, errorString_ ); } -void MidiOutWinMM :: sendMessage( std::vector *message ) + +void MidiOutWinMM :: openPort(const PortDescriptor & p, const std::string & portName) { + const WinMMPortDescriptor * port = dynamic_cast (&p); + if ( !port) { + error( Error::DRIVER_ERROR, + "MidiOUTWinMM::openPort: an invalid (i.e. non-WinMM) port descriptor has been passed to openPort!"); + return; + } + if ( connected_ ) { + errorString_ = "MidiOutWinMM::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + if (port->getCapabilities() != PortDescriptor::OUTPUT) { + error( Error::DRIVER_ERROR, + "MidiOUTWinMM::openPort: the port descriptor cannot be used to open an output port."); + return; + } + + // there is a possible race condition between opening the port and + // reordering of ports so we must check whether we opened the right port. + openPort(port->getPortNumber(),portName); + if (!port->is_valid()) { + closePort(); + error (Error::DRIVER_ERROR, + "MidiOUTWinMM::openPort: some change in the arrangement of MIDI input ports invalidated the port descriptor."); + return; + } + connected_ = true; +} + +Pointer MidiOutWinMM :: getDescriptor(bool local) +{ + if (local || !connected_) return 0; + WinMidiData *data = static_cast (apiData_); + if (!data) return 0; + UINT devid; + switch (midiOutGetID(data->outHandle,&devid)) { + case MMSYSERR_INVALHANDLE: + error (Error::DRIVER_ERROR, + "MidiOutWinMM::getDescriptor: The internal handle is invalid."); + return 0; + case MMSYSERR_NODRIVER: + error (Error::DRIVER_ERROR, + "MidiOutWinMM::getDescriptor: The system has no driver for our handle :-(."); + return 0; + case MMSYSERR_NOMEM: + error (Error::DRIVER_ERROR, + "MidiOutWinMM::getDescriptor: The system could not handle enough memory."); + return 0; + } + return new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); + +} + +PortList MidiOutWinMM :: getPortList(int capabilities) +{ + WinMidiData *data = static_cast (apiData_); + if (!data) return PortList(); + return WinMMPortDescriptor::getPortList(PortDescriptor::OUTPUT,data->getClientName()); +} + + +void MidiOutWinMM :: sendMessage( std::vector &message ) { if ( !connected_ ) return; - unsigned int nBytes = static_cast(message->size()); + unsigned int nBytes = static_cast(message.size()); if ( nBytes == 0 ) { errorString_ = "MidiOutWinMM::sendMessage: message argument is empty!"; error( Error::WARNING, errorString_ ); @@ -2979,7 +3526,7 @@ void MidiOutWinMM :: sendMessage( std::vector *message ) MMRESULT result; WinMidiData *data = static_cast (apiData_); - if ( message->at(0) == 0xF0 ) { // Sysex message + if ( message.at(0) == 0xF0 ) { // Sysex message // Allocate buffer for sysex data. char *buffer = (char *) malloc( nBytes ); @@ -2990,7 +3537,7 @@ void MidiOutWinMM :: sendMessage( std::vector *message ) } // Copy data to buffer. - for ( unsigned int i=0; iat(i); + for ( unsigned int i=0; i *message ) DWORD packet; unsigned char *ptr = (unsigned char *) &packet; for ( unsigned int i=0; iat(i); + *ptr = message.at(i); ++ptr; } diff --git a/RtMidi.h b/RtMidi.h index 7756071c..e7a5c914 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -258,7 +258,8 @@ struct PortDescriptor { UNIQUE_NAME = 0x10, /*!< Make all names uniqe. This is usually done by adding numbers to the end of the - string */ + string \note: use #undef UNIQUE_NAME + on windows in case of any errors */ INCLUDE_API = 0x20 /*!< Add a string describing the API at the beginning of the string. */ @@ -1149,7 +1150,7 @@ class MidiInWinMM: public MidiInApi public: MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ); ~MidiInWinMM( void ); - ApiType getCurrentApi( void ) { return WINDOWS_MM; }; + ApiType getCurrentApi( void ) throw() { return WINDOWS_MM; }; void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); @@ -1168,7 +1169,7 @@ class MidiOutWinMM: public MidiOutApi public: MidiOutWinMM( const std::string clientName ); ~MidiOutWinMM( void ); - ApiType getCurrentApi( void ) { return WINDOWS_MM; }; + ApiType getCurrentApi( void ) throw() { return WINDOWS_MM; }; void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); diff --git a/tests/midiout2.cpp b/tests/midiout2.cpp index 068e7cb2..8c8848c5 100644 --- a/tests/midiout2.cpp +++ b/tests/midiout2.cpp @@ -14,6 +14,7 @@ #if defined(__WINDOWS_MM__) #include #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) +#undef UNIQUE_NAME #else // Unix variants #include #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) diff --git a/tests/qmidiin2.cpp b/tests/qmidiin2.cpp index e3e1a996..a25777dc 100644 --- a/tests/qmidiin2.cpp +++ b/tests/qmidiin2.cpp @@ -16,6 +16,7 @@ #if defined(__WINDOWS_MM__) #include #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) +#undef UNIQUE_NAME #else // Unix variants #include #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) @@ -31,11 +32,12 @@ void usage( rtmidi::PortList list ) { std::cout << " where port = the device to use (default = first available port).\n\n"; std::cout << "Available ports:" << std::endl; + int flags = rtmidi::PortDescriptor::SESSION_PATH | + rtmidi::PortDescriptor::UNIQUE_NAME | + rtmidi::PortDescriptor::INCLUDE_API; for (rtmidi::PortList::iterator i = list.begin(); i != list.end(); i++) { - std::cout << (*i)->getName(rtmidi::PortDescriptor::SESSION_PATH | - rtmidi::PortDescriptor::UNIQUE_NAME | - rtmidi::PortDescriptor::INCLUDE_API); + std::cout << (*i)->getName(flags); std::cout << "\t"; std::cout << (*i)->getName() << std::endl; } From e930f0e5562265c2dde3ee67eee6e0cb95ce84e6 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Thu, 1 May 2014 22:00:55 +0200 Subject: [PATCH 031/210] Implement the new API for CoreMidi. --- RtMidi.cpp | 1313 +++++++++++++++++++++++++++++++++++++++++++++------- RtMidi.h | 4 +- 2 files changed, 1135 insertions(+), 182 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 22844e66..30fa2bbb 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -407,13 +407,984 @@ NAMSPACE_RTMIDI_END NAMSPACE_RTMIDI_START +/*! An abstraction layer for the CORE sequencer layer. It provides + the following functionality: + - dynamic allocation of the sequencer + - optionallay avoid concurrent access to the CORE sequencer, + which is not thread proof. This feature is controlled by + the parameter \ref locking. +*/ + +// This function was submitted by Douglas Casey Tucker and apparently +// derived largely from PortMidi. +// or copied from the Apple developer Q&A website +// https://developer.apple.com/library/mac/qa/qa1374/_index.html + +CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal ) +{ + CFMutableStringRef result = CFStringCreateMutable( NULL, 0 ); + CFStringRef str; + + // Begin with the endpoint's name. + str = NULL; + MIDIObjectGetStringProperty( endpoint, kMIDIPropertyName, &str ); + if ( str != NULL ) { + CFStringAppend( result, str ); + CFRelease( str ); + } + + MIDIEntityRef entity = 0; + MIDIEndpointGetEntity( endpoint, &entity ); + if ( entity == 0 ) + // probably virtual + return result; + + if ( CFStringGetLength( result ) == 0 ) { + // endpoint name has zero length -- try the entity + str = NULL; + MIDIObjectGetStringProperty( entity, kMIDIPropertyName, &str ); + if ( str != NULL ) { + CFStringAppend( result, str ); + CFRelease( str ); + } + } + // now consider the device's name + MIDIDeviceRef device = 0; + MIDIEntityGetDevice( entity, &device ); + if ( device == 0 ) + return result; + + str = NULL; + MIDIObjectGetStringProperty( device, kMIDIPropertyName, &str ); + if ( CFStringGetLength( result ) == 0 ) { + CFRelease( result ); + return str; + } + if ( str != NULL ) { + // if an external device has only one entity, throw away + // the endpoint name and just use the device name + if ( isExternal && MIDIDeviceGetNumberOfEntities( device ) < 2 ) { + CFRelease( result ); + return str; + } else { + if ( CFStringGetLength( str ) == 0 ) { + CFRelease( str ); + return result; + } + // does the entity name already start with the device name? + // (some drivers do this though they shouldn't) + // if so, do not prepend + if ( CFStringCompareWithOptions( result, /* endpoint name */ + str /* device name */, + CFRangeMake(0, CFStringGetLength( str ) ), 0 ) != kCFCompareEqualTo ) { + // prepend the device name to the entity name + if ( CFStringGetLength( result ) > 0 ) + CFStringInsert( result, 0, CFSTR(" ") ); + CFStringInsert( result, 0, str ); + } + CFRelease( str ); + } + } + return result; +} + +// This function was submitted by Douglas Casey Tucker and apparently +// derived largely from PortMidi. +// Nearly the same text can be found in the Apple Q&A qa1374: +// https://developer.apple.com/library/mac/qa/qa1374/_index.html +static CFStringRef ConnectedEndpointName( MIDIEndpointRef endpoint ) +{ + CFMutableStringRef result = CFStringCreateMutable( NULL, 0 ); + CFStringRef str; + OSStatus err; + int i; + + // Does the endpoint have connections? + CFDataRef connections = NULL; + int nConnected = 0; + bool anyStrings = false; + err = MIDIObjectGetDataProperty( endpoint, kMIDIPropertyConnectionUniqueID, &connections ); + if ( connections != NULL ) { + // It has connections, follow them + // Concatenate the names of all connected devices + nConnected = CFDataGetLength( connections ) / sizeof(MIDIUniqueID); + if ( nConnected ) { + const SInt32 *pid = (const SInt32 *)(CFDataGetBytePtr(connections)); + for ( i=0; i +class CoreSequencer { +public: + CoreSequencer():seq(0) + { + if (locking) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); + } + } + + CoreSequencer(const std::string & n):seq(0),name(n) + { + if (locking) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); + } + init(); + } + + ~CoreSequencer() + { + if (seq) { + scoped_lock lock(mutex); + MIDIClientDispose(seq); + seq = 0; + } + if (locking) { + pthread_mutex_destroy(&mutex); + } + } + + bool setName(const std::string & n) { + /* we don't want to rename the client after opening it. */ + if (seq) return false; + name = n; + return true; + } + + static std::string str(CFStringRef s) { + const char * cstr = + CFStringGetCStringPtr(s,kCFStringEncodingUTF8); + if (cstr) return cstr; + + CFIndex len = CFStringGetLength(s); + std::string retval; + retval.resize(CFStringGetMaximumSizeForEncoding(len, + kCFStringEncodingUTF8)+1); + CFStringGetBytes(s, + CFRangeMake(0, len), + kCFStringEncodingUTF8, + 0, + false, + reinterpret_cast(&retval[0]), + retval.size()-1, + &len); + retval.resize(len); + return retval; + } + + +#if 0 + // Obtain the name of an endpoint, following connections. + + // The result should be released by the caller. + + static CFStringRef CreateConnectedEndpointName(MIDIEndpointRef endpoint) + { + CFMutableStringRef result = CFStringCreateMutable(NULL, 0); + CFStringRef str; + OSStatus err; + + + // Does the endpoint have connections? + CFDataRef connections = NULL; + int nConnected = 0; + bool anyStrings = false; + err = MIDIObjectGetDataProperty(endpoint, kMIDIPropertyConnectionUniqueID, &connections); + if (connections != NULL) { + // It has connections, follow them + // Concatenate the names of all connected devices + nConnected = CFDataGetLength(connections) / sizeof(MIDIUniqueID); + + if (nConnected) { + const SInt32 *pid = reinterpret_cast(CFDataGetBytePtr(connections)); + for (int i = 0; i < nConnected; ++i, ++pid) { + MIDIUniqueID id = EndianS32_BtoN(*pid); + MIDIObjectRef connObject; + MIDIObjectType connObjectType; + err = MIDIObjectFindByUniqueID(id, &connObject, &connObjectType); + if (err == noErr) { + if (connObjectType == kMIDIObjectType_ExternalSource || + connObjectType == kMIDIObjectType_ExternalDestination) { + // Connected to an external device's endpoint (10.3 and later). + str = EndpointName(static_cast(connObject), true); + } else { + // Connected to an external device (10.2) (or something else, catch-all) + str = NULL; + MIDIObjectGetStringProperty(connObject, kMIDIPropertyName, &str); + } + + if (str != NULL) { + if (anyStrings) + CFStringAppend(result, CFSTR(", ")); + else anyStrings = true; + CFStringAppend(result, str); + CFRelease(str); + } + } + } + } + CFRelease(connections); + } + + + if (anyStrings) + return result; + else + CFRelease(result); + + // Here, either the endpoint had no connections, or we failed to obtain names for any of them. + return CreateEndpointName(endpoint, false); + } + + + + ////////////////////////////////////// + + // Obtain the name of an endpoint without regard for whether it has connections. + + // The result should be released by the caller. + + static CFStringRef CreateEndpointName(MIDIEndpointRef endpoint, bool isExternal) + { + CFMutableStringRef result = CFStringCreateMutable(NULL, 0); + CFStringRef str; + + // begin with the endpoint's name + str = NULL; + MIDIObjectGetStringProperty(endpoint, kMIDIPropertyName, &str); + if (str != NULL) { + CFStringAppend(result, str); + CFRelease(str); + } + + MIDIEntityRef entity = NULL; + MIDIEndpointGetEntity(endpoint, &entity); + if (entity == NULL) + // probably virtual + return result; + + if (CFStringGetLength(result) == 0) { + // endpoint name has zero length -- try the entity + str = NULL; + MIDIObjectGetStringProperty(entity, kMIDIPropertyName, &str); + if (str != NULL) { + CFStringAppend(result, str); + CFRelease(str); + } + } + + + + // now consider the device's name + MIDIDeviceRef device = NULL; + MIDIEntityGetDevice(entity, &device); + if (device == NULL) return result; + + str = NULL; + MIDIObjectGetStringProperty(device, kMIDIPropertyName, &str); + if (str != NULL) { + // if an external device has only one entity, throw away + // the endpoint name and just use the device name + if (isExternal && MIDIDeviceGetNumberOfEntities(device) < 2) { + CFRelease(result); + return str; + } else { + // does the entity name already start with the device name? + // (some drivers do this though they shouldn't) + // if so, do not prepend + + if (CFStringCompareWithOptions(str /* device name */, + result /* endpoint name */, + CFRangeMake(0, + CFStringGetLength(str)), + 0) + != kCFCompareEqualTo) { + // prepend the device name to the entity name + if (CFStringGetLength(result) > 0) + CFStringInsert(result, 0, CFSTR(" ")); + CFStringInsert(result, 0, str); + } + CFRelease(str); + } + } + + return result; + } +#endif + + static std::string getConnectionsString(MIDIEndpointRef port) + { + /* This function is derived from + CreateConnectedEndpointName at Apple Q&A */ + std::ostringstream result; + CFDataRef connections = NULL; + OSStatus err = MIDIObjectGetDataProperty(port, + kMIDIPropertyConnectionUniqueID, + &connections); + if (err != noErr) + return result.str(); + + if (!connections) + return result.str(); + CFIndex size = CFDataGetLength( connections ) / sizeof(MIDIUniqueID); + if (!size) { + CFRelease(connections); + return result.str(); + } + + CFStringRef strRef; + const SInt32 *pid + = reinterpret_cast(CFDataGetBytePtr(connections)); + bool anyStrings = false; + for (int i = 0; i < size; ++i, ++pid) { + MIDIUniqueID id = EndianS32_BtoN(*pid); + MIDIObjectRef connObject; + MIDIObjectType connObjectType; + err = MIDIObjectFindByUniqueID(id, &connObject, &connObjectType); + if (err != noErr) + continue; + + if (connObjectType == kMIDIObjectType_ExternalSource || + connObjectType == kMIDIObjectType_ExternalDestination) { + // Connected to an external + // device's endpoint + // (10.3 and later). + strRef = EndpointName(static_cast(connObject), + true); + } else { + // Connected to an external device + // (10.2) (or something else, catch-all) + strRef = NULL; + MIDIObjectGetStringProperty(connObject, + kMIDIPropertyName, &strRef); + } + + if (strRef != NULL) { + if (anyStrings) + result << ", "; + else anyStrings = true; + result << str(strRef); + CFRelease(strRef); + } + } + CFRelease(connections); + return result.str(); + } + + static std::string getPortName(MIDIEndpointRef port, int flags) { + std::string clientname; + std::string devicename; + std::string portname; + std::string entityname; + std::string externaldevicename; + std::string connections; + std::string recommendedname; + // bool isVirtual; + bool hasManyEndpoints = false; + CFStringRef nameRef; + MIDIObjectGetStringProperty(port, + kMIDIPropertyDisplayName, + &nameRef); + recommendedname = str(nameRef); + connections = getConnectionsString(port); + + MIDIObjectGetStringProperty(port, + kMIDIPropertyName, + &nameRef); + portname = str(nameRef); + CFRelease( nameRef ); + + MIDIEntityRef entity = NULL; + MIDIEndpointGetEntity(port, &entity); + // entity == NULL: probably virtual + if (entity != NULL) { + nameRef = NULL; + MIDIObjectGetStringProperty(entity, kMIDIPropertyName, &nameRef); + if (str != NULL) { + entityname = str(nameRef); + CFRelease(nameRef); + } + + // now consider the device's name + MIDIDeviceRef device = NULL; + MIDIEntityGetDevice(entity, &device); + if (device != NULL) { + hasManyEndpoints = MIDIDeviceGetNumberOfEntities(device) >= 2; + MIDIObjectGetStringProperty(device, + kMIDIPropertyName, + &nameRef); + devicename = str(nameRef); + CFRelease(nameRef); + } + // does the entity name already start with the device name? + // (some drivers do this though they shouldn't) + if (entityname.substr(0,devicename.length()) + == devicename) { + int start = devicename.length(); + while (isspace(entityname[start])) + start++; + entityname = entityname.substr(start); + } + } + + int naming = flags & PortDescriptor::NAMING_MASK; + + std::ostringstream os; + switch (naming) { + case PortDescriptor::SESSION_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "CORE:"; + os << port; + break; + case PortDescriptor::STORAGE_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "CORE:"; + os << clientname; + os << ":" << devicename; + os << ":" << portname; + os << ":" << entityname; + os << ":" << externaldevicename; + os << ":" << connections; + os << ":" << recommendedname; + if (flags & PortDescriptor::UNIQUE_NAME) + os << ";" << port; + break; + case PortDescriptor::LONG_NAME: + os << devicename; + if (hasManyEndpoints) { + if (!portname.empty()) { + os << ": "; + os << portname; + } else { + os << ": "; + os << entityname; + } + } + if (!connections.empty()) { + os << " ⇒ "; + os << connections; + } + if (flags & + (PortDescriptor::INCLUDE_API + | PortDescriptor::UNIQUE_NAME)) { + os << " ("; + if (flags & + PortDescriptor::INCLUDE_API) { + os << "CORE"; + if (flags & PortDescriptor::UNIQUE_NAME) + os << ":"; + } + if (flags & PortDescriptor::UNIQUE_NAME) { + os << port; + } + os << ")"; + } + break; + case PortDescriptor::SHORT_NAME: + default: + if (!recommendedname.empty()) { + os << recommendedname; + } else if (!connections.empty()) { + os << connections; + } else { + os << devicename; + if (hasManyEndpoints) { + if (!portname.empty()) { + os << portname; + } else { + os << entityname; + } + } + } + if (flags & + (PortDescriptor::INCLUDE_API + | PortDescriptor::UNIQUE_NAME)) { + os << " ("; + if (flags & + PortDescriptor::INCLUDE_API) { + os << "CORE"; + if (flags & PortDescriptor::UNIQUE_NAME) + os << ":"; + } + if (flags & PortDescriptor::UNIQUE_NAME) { + os << port; + } + os << ")"; + } + break; + } + return os.str(); + } + + int getPortCapabilities(MIDIEndpointRef port) { + int retval = 0; + MIDIEntityRef entity = 0; + OSStatus stat = + MIDIEndpointGetEntity(port,&entity); + if (stat == kMIDIObjectNotFound) { + // plan B for virtual ports + MIDIUniqueID uid; + stat = MIDIObjectGetIntegerProperty (port, + kMIDIPropertyUniqueID, + &uid); + if (stat != noErr) { + throw + Error("CoreSequencer::getPortCapabilties: \ +Could not get the UID of a midi endpoint.", + Error::DRIVER_ERROR); + return 0; + } + MIDIObjectRef obj; + MIDIObjectType type; + stat = MIDIObjectFindByUniqueID (uid, + &obj, + &type); + if (stat != noErr || obj != port) { + throw + Error("CoreSequencer::getPortCapabilties: \ +Could not get the endpoint back from UID of a midi endpoint.", + Error::DRIVER_ERROR); + return 0; + } + if (type == kMIDIObjectType_Source + || type == kMIDIObjectType_ExternalSource) + return PortDescriptor::INPUT; + else if (type == kMIDIObjectType_Destination + || type == kMIDIObjectType_ExternalDestination) + return PortDescriptor::OUTPUT; + else { + return 0; + } + + } else if (stat != noErr) { + throw + Error("CoreSequencer::getPortCapabilties: \ +Could not get the entity of a midi endpoint.", + Error::DRIVER_ERROR); + return 0; + } + /* Theoretically Mac OS X could silently use + the same endpoint reference for input and + output. We might benefit from this + behaviour. + \todo: Find a way to query the object + whether it can act as source or destination. + */ + ItemCount count = + MIDIEntityGetNumberOfDestinations(entity); + for (ItemCount i = 0; i < count ; i++) { + MIDIEndpointRef dest= + MIDIEntityGetDestination(entity,i); + if (dest == port) { + retval |= + PortDescriptor::OUTPUT; + break; + } + } + count = + MIDIEntityGetNumberOfSources(entity); + for (ItemCount i = 0; i < count ; i++) { + MIDIEndpointRef src= + MIDIEntityGetSource(entity,i); + if (src == port) { + retval |= + PortDescriptor::INPUT; + } + } + return retval; + } + +#if 0 + int getNextClient(snd_seq_client_info_t * cinfo ) { + init(); + scoped_lock lock (mutex); + return snd_seq_query_next_client (seq, cinfo); + } + int getNextPort(snd_seq_port_info_t * pinfo ) { + init(); + scoped_lock lock (mutex); + return snd_seq_query_next_port (seq, pinfo); + } +#endif + + MIDIPortRef createPort (std::string portName, + int flags, + MidiInApi::MidiInData * data = NULL) + { + init(); + scoped_lock lock (mutex); + MIDIPortRef port = 0; + OSStatus result; + switch (flags) { + case PortDescriptor::INPUT: + result = MIDIInputPortCreate(seq, + CFStringCreateWithCString( + NULL, + portName.c_str(), + kCFStringEncodingUTF8 ), + midiInputCallback, + (void *)data, + &port); + break; + case PortDescriptor::OUTPUT: + result + = MIDIOutputPortCreate(seq, + CFStringCreateWithCString( + NULL, + portName.c_str(), + kCFStringEncodingUTF8 ), + &port); + break; + default: + throw Error("CoreSequencer::createPort:\ + Error creating OS X MIDI port because of invalid port flags", + Error::DRIVER_ERROR); + } + if ( result != noErr ) { + throw Error( + "CoreSequencer::createPort:\ + error creating OS-X MIDI port.", + Error::DRIVER_ERROR); + } + return port; + } + + MIDIEndpointRef createVirtualPort (std::string portName, + int flags, + MidiInApi::MidiInData * data = NULL) + { + init(); + scoped_lock lock (mutex); + MIDIEndpointRef port = 0; + OSStatus result; + switch (flags) { + case PortDescriptor::INPUT: + result + = MIDIDestinationCreate(seq, + CFStringCreateWithCString( + NULL, + portName.c_str(), + kCFStringEncodingUTF8 ), + midiInputCallback, + (void *)data, + &port); + break; + case PortDescriptor::OUTPUT: + result + = MIDISourceCreate(seq, + CFStringCreateWithCString( + NULL, + portName.c_str(), + kCFStringEncodingUTF8 ), + &port); + break; + default: + throw Error(Error::DRIVER_ERROR, + "CoreSequencer::createVirtualPort:\ + Error creating OS X MIDI port because of invalid port flags"); + } + if ( result != noErr ) { + throw Error( Error::DRIVER_ERROR, + "CoreSequencer::createVirtualPort: error creating OS-X MIDI port." ); + } + return port; + } + +#if 0 + void deletePort(int port) { + init(); + scoped_lock lock (mutex); + snd_seq_delete_port( seq, port ); + } + + snd_seq_port_subscribe_t * connectPorts(const snd_seq_addr_t & from, + const snd_seq_addr_t & to, + bool real_time) { + init(); + snd_seq_port_subscribe_t *subscription; + + if (snd_seq_port_subscribe_malloc( &subscription ) < 0) { + throw Error("MidiInCore::openPort: CORE error allocation port subscription.", + Error::DRIVER_ERROR ); + return 0; + } + snd_seq_port_subscribe_set_sender(subscription, &from); + snd_seq_port_subscribe_set_dest(subscription, &to); + if (real_time) { + snd_seq_port_subscribe_set_time_update(subscription, 1); + snd_seq_port_subscribe_set_time_real(subscription, 1); + } + { + scoped_lock lock (mutex); + if ( snd_seq_subscribe_port(seq, subscription) ) { + snd_seq_port_subscribe_free( subscription ); + subscription = 0; + throw Error("MidiInCore::openPort: CORE error making port connection.", + Error::DRIVER_ERROR); + return 0; + } + } + return subscription; + } + + void closePort(snd_seq_port_subscribe_t * subscription ) { + init(); + scoped_lock lock(mutex); + snd_seq_unsubscribe_port( seq, subscription ); + } + + + void startQueue(int queue_id) { + init(); + scoped_lock lock(mutex); + snd_seq_start_queue( seq, queue_id, NULL ); + snd_seq_drain_output( seq ); + } +#endif + + /*! Use CoreSequencer like a C pointer. + \note This function breaks the design to control thread safety + by the selection of the \ref locking parameter to the class. + It should be removed as soon as possible in order ensure the + thread policy that has been intended by creating this class. + */ + operator MIDIClientRef () + { + return seq; + } +protected: + struct scoped_lock { + pthread_mutex_t * mutex; + scoped_lock(pthread_mutex_t & m): mutex(&m) + { + if (locking) + pthread_mutex_lock(mutex); + } + ~scoped_lock() + { + if (locking) + pthread_mutex_unlock(mutex); + } + }; + pthread_mutex_t mutex; + MIDIClientRef seq; + std::string name; + +#if 0 + snd_seq_client_info_t * GetClient(int id) { + init(); + snd_seq_client_info_t * cinfo; + scoped_lock lock(mutex); + snd_seq_get_any_client_info(seq,id,cinfo); + return cinfo; + } +#endif + + void init() + { + init (seq); + } + + void init(MIDIClientRef &s) + { + if (s) return; + { + scoped_lock lock(mutex); + OSStatus result = MIDIClientCreate( + CFStringCreateWithCString( NULL, + name.c_str(), + kCFStringEncodingUTF8), + NULL, NULL, &s ); + if ( result != noErr ) { + throw Error( + "CoreSequencer::initialize: \ +Error creating OS-X MIDI client object.", + Error::DRIVER_ERROR); + return; + } + } + } +}; +typedef CoreSequencer<1> LockingCoreSequencer; +typedef CoreSequencer<0> NonLockingCoreSequencer; + +struct CorePortDescriptor:public PortDescriptor { + CorePortDescriptor(const std::string & name):api(0), + clientName(name), + endpoint(0) + { + } + CorePortDescriptor(MIDIEndpointRef p, + const std::string & name):api(0), + clientName(name), + endpoint(p) + { + seq.setName(name); + } + CorePortDescriptor(CorePortDescriptor & + other):PortDescriptor(other), + api(other.api), + clientName(other.clientName), + endpoint(other.endpoint) + { + seq.setName(clientName); + } + ~CorePortDescriptor() {} + + MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) { + if (getCapabilities() & INPUT) + return new MidiInCore(clientName,queueSizeLimit); + else + return 0; + } + + MidiOutApi * getOutputApi() { + if (getCapabilities() & OUTPUT) + return new MidiOutCore(clientName); + else + return 0; + } + + void setEndpoint(MIDIEndpointRef e) + { + endpoint = e; + } + MIDIEndpointRef getEndpoint() const + { + return endpoint; + } + + std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) { + return seq.getPortName(endpoint,flags); + } + + const std::string & getClientName() { + return clientName; + } + int getCapabilities() { + if (!endpoint) return 0; + return seq.getPortCapabilities(endpoint); + } + static PortList getPortList(int capabilities, const std::string & clientName); +protected: + MidiApi * api; + static LockingCoreSequencer seq; + + std::string clientName; + MIDIEndpointRef endpoint; +}; + +LockingCoreSequencer CorePortDescriptor::seq; + + + +PortList CorePortDescriptor :: getPortList(int capabilities, const std::string & clientName) +{ + PortList list; + + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + int caps = capabilities & PortDescriptor::INOUTPUT; + bool unlimited = capabilities & PortDescriptor::UNLIMITED; + bool forceInput = PortDescriptor::INPUT & caps; + bool forceOutput = PortDescriptor::OUTPUT & caps; + bool allowOutput = forceOutput || !forceInput; + bool allowInput = forceInput || !forceOutput; + if (allowOutput) { + ItemCount count = + MIDIGetNumberOfDestinations(); + for (ItemCount i = 0 ; i < count; i++) { + MIDIEndpointRef destination = + MIDIGetDestination(i); + if ((seq.getPortCapabilities(destination) + & caps) == caps) + list.push_back(new CorePortDescriptor(destination, + clientName)); + } + // Combined sources and destinations + // should be both occur as destinations and as + // sources. So we have finished the search, here. + } else if (allowInput) { + ItemCount count = + MIDIGetNumberOfSources(); + for (ItemCount i = 0 ; i < count; i++) { + MIDIEndpointRef src = + MIDIGetSource(i); + if ((seq.getPortCapabilities(src) + & caps) == caps) + list.push_back(new CorePortDescriptor(src, + clientName)); + } + } + return list; +} + + // A structure to hold variables related to the CoreMIDI API // implementation. -struct CoreMidiData { - MIDIClientRef client; - MIDIPortRef port; - MIDIEndpointRef endpoint; - MIDIEndpointRef destinationId; +struct CoreMidiData:public CorePortDescriptor { + CoreMidiData(std::string clientname):CorePortDescriptor(clientname), + client(clientname), + localEndpoint(0), + localPort(0) {} + ~CoreMidiData() { + if (localEndpoint) + MIDIEndpointDispose(localEndpoint); + localEndpoint = 0; + } + + void openPort(const std::string & name, + int flags, + MidiInApi::MidiInData * data = NULL) { + localPort = client.createPort(name, flags, data); + } + + void setRemote(const CorePortDescriptor & remote) + { + setEndpoint(remote.getEndpoint()); + } + + NonLockingCoreSequencer client; + MIDIEndpointRef localEndpoint; + MIDIPortRef localPort; unsigned long long lastTime; MIDISysexSendRequest sysexreq; }; @@ -575,7 +1546,9 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void * } } -MidiInCore :: MidiInCore( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) +MidiInCore :: MidiInCore( const std::string clientName, + unsigned int queueSizeLimit ) : + MidiInApi( queueSizeLimit ) { initialize( clientName ); } @@ -587,31 +1560,19 @@ MidiInCore :: ~MidiInCore( void ) // Cleanup. CoreMidiData *data = static_cast (apiData_); - MIDIClientDispose( data->client ); - if ( data->endpoint ) MIDIEndpointDispose( data->endpoint ); delete data; } void MidiInCore :: initialize( const std::string& clientName ) { - // Set up our client. - MIDIClientRef client; - OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client ); - if ( result != noErr ) { - errorString_ = "MidiInCore::initialize: error creating OS-X MIDI client object."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - // Save our api-specific connection information. - CoreMidiData *data = (CoreMidiData *) new CoreMidiData; - data->client = client; - data->endpoint = 0; + CoreMidiData *data = (CoreMidiData *) new CoreMidiData(clientName); apiData_ = (void *) data; inputData_.apiData = (void *) data; } -void MidiInCore :: openPort( unsigned int portNumber, const std::string portName ) +void MidiInCore :: openPort( unsigned int portNumber, + const std::string & portName ) { if ( connected_ ) { errorString_ = "MidiInCore::openPort: a valid connection already exists!"; @@ -638,7 +1599,7 @@ void MidiInCore :: openPort( unsigned int portNumber, const std::string portName MIDIPortRef port; CoreMidiData *data = static_cast (apiData_); OSStatus result = MIDIInputPortCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), + CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingUTF8 ), midiInputCallback, (void *)&inputData_, &port ); if ( result != noErr ) { MIDIClientDispose( data->client ); @@ -668,7 +1629,8 @@ void MidiInCore :: openPort( unsigned int portNumber, const std::string portName } // Save our api-specific port information. - data->port = port; + data->localPort = port; + data->setEndpoint(endpoint); connected_ = true; } @@ -680,7 +1642,7 @@ void MidiInCore :: openVirtualPort( const std::string portName ) // Create a virtual MIDI input destination. MIDIEndpointRef endpoint; OSStatus result = MIDIDestinationCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), + CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingUTF8 ), midiInputCallback, (void *)&inputData_, &endpoint ); if ( result != noErr ) { errorString_ = "MidiInCore::openVirtualPort: error creating virtual OS-X MIDI destination."; @@ -689,146 +1651,91 @@ void MidiInCore :: openVirtualPort( const std::string portName ) } // Save our api-specific connection information. - data->endpoint = endpoint; + data->localEndpoint = endpoint; } -void MidiInCore :: closePort( void ) +void MidiInCore :: openPort( const PortDescriptor & port, + const std::string & portName) { - if ( connected_ ) { - CoreMidiData *data = static_cast (apiData_); - MIDIPortDispose( data->port ); - connected_ = false; + CoreMidiData *data = static_cast (apiData_); + const CorePortDescriptor * remote = dynamic_cast(&port); + + if ( !data ) { + errorString_ = "MidiInCore::openPort: Internal error: data has not been allocated!"; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + if ( connected_ || data -> localEndpoint) { + errorString_ = "MidiInCore::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + if (!remote) { + errorString_ = "MidiInCore::openPort: an invalid (i.e. non-CORE) port descriptor has been passed to openPort!"; + error( Error::WARNING, errorString_ ); + return; } -} -unsigned int MidiInCore :: getPortCount() -{ - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - return MIDIGetNumberOfSources(); + data->openPort (portName, + PortDescriptor::INPUT, + &inputData_); + data->setRemote(*remote); + OSStatus result = + MIDIPortConnectSource(data->localPort, + data->getEndpoint(), + NULL); + if ( result != noErr ) { + error(Error::DRIVER_ERROR, + "CoreSequencer::createPort:\ + error creating OS-X MIDI port."); + } + + connected_ = true; } -// This function was submitted by Douglas Casey Tucker and apparently -// derived largely from PortMidi. -CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal ) +Pointer MidiInCore :: getDescriptor(bool local) { - CFMutableStringRef result = CFStringCreateMutable( NULL, 0 ); - CFStringRef str; - - // Begin with the endpoint's name. - str = NULL; - MIDIObjectGetStringProperty( endpoint, kMIDIPropertyName, &str ); - if ( str != NULL ) { - CFStringAppend( result, str ); - CFRelease( str ); + CoreMidiData *data = static_cast + (apiData_); + if (!data) { + return NULL; } - - MIDIEntityRef entity = 0; - MIDIEndpointGetEntity( endpoint, &entity ); - if ( entity == 0 ) - // probably virtual - return result; - - if ( CFStringGetLength( result ) == 0 ) { - // endpoint name has zero length -- try the entity - str = NULL; - MIDIObjectGetStringProperty( entity, kMIDIPropertyName, &str ); - if ( str != NULL ) { - CFStringAppend( result, str ); - CFRelease( str ); + if (local) { + if (data && data->localEndpoint) { + return new + CorePortDescriptor(data->localEndpoint, + data->getClientName()); } - } - // now consider the device's name - MIDIDeviceRef device = 0; - MIDIEntityGetDevice( entity, &device ); - if ( device == 0 ) - return result; - - str = NULL; - MIDIObjectGetStringProperty( device, kMIDIPropertyName, &str ); - if ( CFStringGetLength( result ) == 0 ) { - CFRelease( result ); - return str; - } - if ( str != NULL ) { - // if an external device has only one entity, throw away - // the endpoint name and just use the device name - if ( isExternal && MIDIDeviceGetNumberOfEntities( device ) < 2 ) { - CFRelease( result ); - return str; - } else { - if ( CFStringGetLength( str ) == 0 ) { - CFRelease( str ); - return result; - } - // does the entity name already start with the device name? - // (some drivers do this though they shouldn't) - // if so, do not prepend - if ( CFStringCompareWithOptions( result, /* endpoint name */ - str /* device name */, - CFRangeMake(0, CFStringGetLength( str ) ), 0 ) != kCFCompareEqualTo ) { - // prepend the device name to the entity name - if ( CFStringGetLength( result ) > 0 ) - CFStringInsert( result, 0, CFSTR(" ") ); - CFStringInsert( result, 0, str ); - } - CFRelease( str ); + } else { + if (data->getEndpoint()) { + return new CorePortDescriptor(*data); } } - return result; + return NULL; } -// This function was submitted by Douglas Casey Tucker and apparently -// derived largely from PortMidi. -static CFStringRef ConnectedEndpointName( MIDIEndpointRef endpoint ) +PortList MidiInCore :: getPortList(int capabilities) { - CFMutableStringRef result = CFStringCreateMutable( NULL, 0 ); - CFStringRef str; - OSStatus err; - int i; + CoreMidiData *data = static_cast (apiData_); + return CorePortDescriptor::getPortList(capabilities | PortDescriptor::INPUT, + data->getClientName()); +} - // Does the endpoint have connections? - CFDataRef connections = NULL; - int nConnected = 0; - bool anyStrings = false; - err = MIDIObjectGetDataProperty( endpoint, kMIDIPropertyConnectionUniqueID, &connections ); - if ( connections != NULL ) { - // It has connections, follow them - // Concatenate the names of all connected devices - nConnected = CFDataGetLength( connections ) / sizeof(MIDIUniqueID); - if ( nConnected ) { - const SInt32 *pid = (const SInt32 *)(CFDataGetBytePtr(connections)); - for ( i=0; i (apiData_); + MIDIPortDispose( data->localPort ); + data->localPort = 0; + connected_ = false; } - if ( anyStrings ) - return result; +} - // Here, either the endpoint had no connections, or we failed to obtain names - return EndpointName( endpoint, false ); +unsigned int MidiInCore :: getPortCount() +{ + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + return MIDIGetNumberOfSources(); } std::string MidiInCore :: getPortName( unsigned int portNumber ) @@ -849,12 +1756,13 @@ std::string MidiInCore :: getPortName( unsigned int portNumber ) portRef = MIDIGetSource( portNumber ); nameRef = ConnectedEndpointName(portRef); - CFStringGetCString( nameRef, name, sizeof(name), CFStringGetSystemEncoding()); + CFStringGetCString( nameRef, name, sizeof(name), kCFStringEncodingUTF8); CFRelease( nameRef ); return stringName = name; } + //*********************************************************************// // API: OS-X // Class Definitions: MidiOutCore @@ -872,26 +1780,13 @@ MidiOutCore :: ~MidiOutCore( void ) // Cleanup. CoreMidiData *data = static_cast (apiData_); - MIDIClientDispose( data->client ); - if ( data->endpoint ) MIDIEndpointDispose( data->endpoint ); delete data; } void MidiOutCore :: initialize( const std::string& clientName ) { - // Set up our client. - MIDIClientRef client; - OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client ); - if ( result != noErr ) { - errorString_ = "MidiOutCore::initialize: error creating OS-X MIDI client object."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } - // Save our api-specific connection information. - CoreMidiData *data = (CoreMidiData *) new CoreMidiData; - data->client = client; - data->endpoint = 0; + CoreMidiData *data = (CoreMidiData *) new CoreMidiData(clientName); apiData_ = (void *) data; } @@ -919,13 +1814,14 @@ std::string MidiOutCore :: getPortName( unsigned int portNumber ) portRef = MIDIGetDestination( portNumber ); nameRef = ConnectedEndpointName(portRef); - CFStringGetCString( nameRef, name, sizeof(name), CFStringGetSystemEncoding()); + CFStringGetCString( nameRef, name, sizeof(name), kCFStringEncodingUTF8); CFRelease( nameRef ); return stringName = name; } -void MidiOutCore :: openPort( unsigned int portNumber, const std::string portName ) +void MidiOutCore :: openPort( unsigned int portNumber, + const std::string &portName ) { if ( connected_ ) { errorString_ = "MidiOutCore::openPort: a valid connection already exists!"; @@ -952,7 +1848,7 @@ void MidiOutCore :: openPort( unsigned int portNumber, const std::string portNam MIDIPortRef port; CoreMidiData *data = static_cast (apiData_); OSStatus result = MIDIOutputPortCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), + CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingUTF8 ), &port ); if ( result != noErr ) { MIDIClientDispose( data->client ); @@ -972,8 +1868,8 @@ void MidiOutCore :: openPort( unsigned int portNumber, const std::string portNam } // Save our api-specific connection information. - data->port = port; - data->destinationId = destination; + data->localPort = port; + data->setEndpoint(destination); connected_ = true; } @@ -981,7 +1877,7 @@ void MidiOutCore :: closePort( void ) { if ( connected_ ) { CoreMidiData *data = static_cast (apiData_); - MIDIPortDispose( data->port ); + MIDIPortDispose( data->localPort ); connected_ = false; } } @@ -990,7 +1886,7 @@ void MidiOutCore :: openVirtualPort( std::string portName ) { CoreMidiData *data = static_cast (apiData_); - if ( data->endpoint ) { + if ( data->localEndpoint ) { errorString_ = "MidiOutCore::openVirtualPort: a virtual output port already exists!"; error( Error::WARNING, errorString_ ); return; @@ -999,7 +1895,7 @@ void MidiOutCore :: openVirtualPort( std::string portName ) // Create a virtual MIDI output source. MIDIEndpointRef endpoint; OSStatus result = MIDISourceCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), + CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingUTF8 ), &endpoint ); if ( result != noErr ) { errorString_ = "MidiOutCore::initialize: error creating OS-X virtual MIDI source."; @@ -1008,9 +1904,66 @@ void MidiOutCore :: openVirtualPort( std::string portName ) } // Save our api-specific connection information. - data->endpoint = endpoint; + data->localEndpoint = endpoint; +} + +void MidiOutCore :: openPort( const PortDescriptor & port, + const std::string & portName) +{ + CoreMidiData *data = static_cast (apiData_); + const CorePortDescriptor * remote = dynamic_cast(&port); + + if ( !data ) { + errorString_ = "MidiOutCore::openPort: Internal error: data has not been allocated!"; + error( Error::DRIVER_ERROR, errorString_ ); + return; + } + if ( connected_ || data -> localEndpoint) { + errorString_ = "MidiOutCore::openPort: a valid connection already exists!"; + error( Error::WARNING, errorString_ ); + return; + } + if (!remote) { + errorString_ = "MidiOutCore::openPort: an invalid (i.e. non-CORE) port descriptor has been passed to openPort!"; + error( Error::WARNING, errorString_ ); + return; + } + + data->openPort (portName, + PortDescriptor::OUTPUT); + data->setRemote(*remote); + connected_ = true; +} + +Pointer MidiOutCore :: getDescriptor(bool local) +{ + CoreMidiData *data = static_cast + (apiData_); + if (!data) { + return NULL; + } + if (local) { + if (data && data->localEndpoint) { + return new + CorePortDescriptor(data->localEndpoint, + data->getClientName()); + } + } else { + if (data->getEndpoint()) { + return new CorePortDescriptor(*data); + } + } + return NULL; +} + +PortList MidiOutCore :: getPortList(int capabilities) +{ + CoreMidiData *data = static_cast (apiData_); + return CorePortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT, + data->getClientName()); } + // Not necessary if we don't treat sysex messages any differently than // normal messages ... see below. //static void sysexCompletionProc( MIDISysexSendRequest *sreq ) @@ -1018,13 +1971,13 @@ void MidiOutCore :: openVirtualPort( std::string portName ) // free( sreq ); //} -void MidiOutCore :: sendMessage( std::vector *message ) +void MidiOutCore :: sendMessage( std::vector &message ) { // We use the MIDISendSysex() function to asynchronously send sysex // messages. Otherwise, we use a single CoreMidi MIDIPacket. - unsigned int nBytes = message->size(); + unsigned int nBytes = message.size(); if ( nBytes == 0 ) { - errorString_ = "MidiOutCore::sendMessage: no data in message argument!"; + errorString_ = "MidiOutCore::sendMessage: no data in message argument!"; error( Error::WARNING, errorString_ ); return; } @@ -1040,7 +1993,7 @@ void MidiOutCore :: sendMessage( std::vector *message ) // messages through the normal mechanism. In addition, this avoids // the problem of virtual ports not receiving sysex messages. - if ( message->at(0) == 0xF0 ) { + if ( message.at(0) == 0xF0 ) { // Apple's fantastic API requires us to free the allocated data in // the completion callback but trashes the pointer and size before @@ -1053,7 +2006,7 @@ void MidiOutCore :: sendMessage( std::vector *message ) char * sysexBuffer = ((char *) newRequest) + sizeof(struct MIDISysexSendRequest); // Copy data to buffer. - for ( unsigned int i=0; iat(i); + for ( unsigned int i=0; idestination = data->destinationId; newRequest->data = (Byte *)sysexBuffer; @@ -1080,16 +2033,16 @@ void MidiOutCore :: sendMessage( std::vector *message ) MIDIPacketList packetList; MIDIPacket *packet = MIDIPacketListInit( &packetList ); - packet = MIDIPacketListAdd( &packetList, sizeof(packetList), packet, timeStamp, nBytes, (const Byte *) &message->at( 0 ) ); + packet = MIDIPacketListAdd( &packetList, sizeof(packetList), packet, timeStamp, nBytes, (const Byte *) &message.at( 0 ) ); if ( !packet ) { - errorString_ = "MidiOutCore::sendMessage: could not allocate packet list"; + errorString_ = "MidiOutCore::sendMessage: could not allocate packet list"; error( Error::DRIVER_ERROR, errorString_ ); return; } // Send to any destinations that may have connected to us. - if ( data->endpoint ) { - result = MIDIReceived( data->endpoint, &packetList ); + if ( data->localEndpoint ) { + result = MIDIReceived( data->localEndpoint, &packetList ); if ( result != noErr ) { errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; error( Error::WARNING, errorString_ ); @@ -1098,7 +2051,7 @@ void MidiOutCore :: sendMessage( std::vector *message ) // And send to an explicit destination port if we're connected. if ( connected_ ) { - result = MIDISend( data->port, data->destinationId, &packetList ); + result = MIDISend( data->localPort, data->getEndpoint(), &packetList ); if ( result != noErr ) { errorString_ = "MidiOutCore::sendMessage: error sending MIDI message to port."; error( Error::WARNING, errorString_ ); diff --git a/RtMidi.h b/RtMidi.h index 7756071c..c121399c 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -1014,7 +1014,7 @@ class MidiInCore: public MidiInApi public: MidiInCore( const std::string clientName, unsigned int queueSizeLimit ); ~MidiInCore( void ); - ApiType getCurrentApi( void ) { return MACOSX_CORE; }; + ApiType getCurrentApi( void ) throw() { return MACOSX_CORE; }; void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); @@ -1033,7 +1033,7 @@ class MidiOutCore: public MidiOutApi public: MidiOutCore( const std::string clientName ); ~MidiOutCore( void ); - ApiType getCurrentApi( void ) { return MACOSX_CORE; }; + ApiType getCurrentApi( void ) throw() { return MACOSX_CORE; }; void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); From 1c3fef8807fce144cf5e2956accdf0afaed4e0ec Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Thu, 1 May 2014 22:01:49 +0200 Subject: [PATCH 032/210] Fix destructors of some sequencer classes. --- RtMidi.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RtMidi.cpp b/RtMidi.cpp index 30fa2bbb..47bebbfc 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -2128,6 +2128,11 @@ class AlsaSequencer { ~AlsaSequencer() { + if (seq) { + scoped_lock lock(mutex); + snd_seq_close(seq); + seq = 0; + } if (locking) { pthread_mutex_destroy(&mutex); } @@ -4055,6 +4060,7 @@ class JackSequencer { jack_deactivate (client); // the latter doesn't flush the queue jack_client_close (client); + client = 0; } } if (locking) { From 1e124d4b4c749c5a1e5e4615574fe26cfc280388 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 2 May 2014 07:59:23 +0200 Subject: [PATCH 033/210] Fix getPortName(PortDescriptor) for Core MIDI. --- RtMidi.cpp | 89 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 25 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 47bebbfc..24c3d546 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -387,13 +387,31 @@ MidiOutApi :: ~MidiOutApi( void ) { } + +// trim from start +static inline std::string <rim(std::string &s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); + return s; +} + +// trim from end +static inline std::string &rtrim(std::string &s) { + s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); + return s; +} + +// trim from both ends +static inline std::string &trim(std::string &s) { + return ltrim(rtrim(s)); +} +NAMSPACE_RTMIDI_END + // *************************************************** // // // OS/API-specific methods. // // *************************************************** // -NAMSPACE_RTMIDI_END #if defined(__MACOSX_CORE__) // The CoreMIDI API is based on the use of a callback function for @@ -608,7 +626,7 @@ class CoreSequencer { retval.size()-1, &len); retval.resize(len); - return retval; + return trim(retval); } @@ -811,14 +829,15 @@ class CoreSequencer { } static std::string getPortName(MIDIEndpointRef port, int flags) { - std::string clientname; + // std::string clientname; std::string devicename; std::string portname; std::string entityname; - std::string externaldevicename; + // std::string externaldevicename; std::string connections; std::string recommendedname; // bool isVirtual; + bool hasManyEntities = false; bool hasManyEndpoints = false; CFStringRef nameRef; MIDIObjectGetStringProperty(port, @@ -843,12 +862,16 @@ class CoreSequencer { entityname = str(nameRef); CFRelease(nameRef); } + hasManyEndpoints = + MIDIEntityGetNumberOfSources(entity) >= 2 || + MIDIEntityGetNumberOfDestinations(entity) + >= 2; // now consider the device's name MIDIDeviceRef device = NULL; MIDIEntityGetDevice(entity, &device); if (device != NULL) { - hasManyEndpoints = MIDIDeviceGetNumberOfEntities(device) >= 2; + hasManyEntities = MIDIDeviceGetNumberOfEntities(device) >= 2; MIDIObjectGetStringProperty(device, kMIDIPropertyName, &nameRef); @@ -869,6 +892,7 @@ class CoreSequencer { int naming = flags & PortDescriptor::NAMING_MASK; std::ostringstream os; + bool needcolon; switch (naming) { case PortDescriptor::SESSION_PATH: if (flags & PortDescriptor::INCLUDE_API) @@ -878,25 +902,34 @@ class CoreSequencer { case PortDescriptor::STORAGE_PATH: if (flags & PortDescriptor::INCLUDE_API) os << "CORE:"; - os << clientname; - os << ":" << devicename; + // os << clientname; + os << devicename; os << ":" << portname; os << ":" << entityname; - os << ":" << externaldevicename; + // os << ":" << externaldevicename; os << ":" << connections; - os << ":" << recommendedname; + // os << ":" << recommendedname; if (flags & PortDescriptor::UNIQUE_NAME) os << ";" << port; break; case PortDescriptor::LONG_NAME: + needcolon = !devicename.empty(); os << devicename; - if (hasManyEndpoints) { - if (!portname.empty()) { - os << ": "; - os << portname; - } else { - os << ": "; + if (hasManyEndpoints || + hasManyEntities || + devicename.empty()) { + if (!entityname.empty()) { + if (needcolon) + os << ": "; os << entityname; + needcolon = true; + } + if ((hasManyEndpoints + || entityname.empty()) + && !portname.empty()) { + if (needcolon) + os << ": "; + os << portname; } } if (!connections.empty()) { @@ -923,18 +956,24 @@ class CoreSequencer { default: if (!recommendedname.empty()) { os << recommendedname; - } else if (!connections.empty()) { - os << connections; - } else { - os << devicename; - if (hasManyEndpoints) { - if (!portname.empty()) { - os << portname; - } else { - os << entityname; + } else + if (!connections.empty()) { + os << connections; + } else { + os << devicename; + if (hasManyEntities || + hasManyEndpoints || + devicename.empty()) { + if (!devicename.empty()) + os << " "; + if (!portname.empty()) { + os << portname; + } else if (!entityname.empty()) { + os << entityname; + } else + os << "???"; } } - } if (flags & (PortDescriptor::INCLUDE_API | PortDescriptor::UNIQUE_NAME)) { From 89c1a64a5dbb4823b9d80316721a88da6e58b03f Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 2 May 2014 08:00:10 +0200 Subject: [PATCH 034/210] Use "RtMidi virtual port" as default for virtual ports. --- RtMidi.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index c121399c..d18255ad 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -361,7 +361,7 @@ class MidiApi \param portName An optional name for the applicaction port that is used to connect to portId can be specified. */ - virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0; + virtual void openVirtualPort( const std::string portName = std::string( "RtMidi virtual port" ) ) = 0; //! Pure virtual function to open a MIDI connection given by enumeration number. /*! \param portNumber An optional port number greater than 0 @@ -619,7 +619,7 @@ class Midi { \param portName An optional name for the applicaction port that is used to connect to portId can be specified. */ - void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) + void openVirtualPort( const std::string portName = std::string( "RtMidi virtual port" ) ) { if (rtapi_) rtapi_->openVirtualPort(portName); } From 2f3c663e7dd76a275eca6dbadcf05fae493222f4 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 2 May 2014 08:00:49 +0200 Subject: [PATCH 035/210] Make everything dependent on RtMidi.h --- tests/Makefile.in | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Makefile.in b/tests/Makefile.in index bc8a728a..8498dfdd 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -21,6 +21,7 @@ LIBRARY = @LIBS@ all : $(PROGRAMS) +RtMidi.o: $(SRC_PATH)/RtMidi.cpp $(SRC_PATH)/RtMidi.h midiprobe : midiprobe.cpp $(OBJECTS) $(CC) $(CFLAGS) $(DEFS) -o midiprobe midiprobe.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) From e97632576a7a858f6e32685fe15b434935dfa59b Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 2 May 2014 08:01:45 +0200 Subject: [PATCH 036/210] Improve the identification of virtual ports using Core MIDI. --- tests/cmidiin2.cpp | 2 +- tests/midiout2.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cmidiin2.cpp b/tests/cmidiin2.cpp index 0d16eea9..cfd90942 100644 --- a/tests/cmidiin2.cpp +++ b/tests/cmidiin2.cpp @@ -71,7 +71,7 @@ bool chooseMidiPort( RtMidiIn &midi ) std::string keyHit; std::getline( std::cin, keyHit ); if ( keyHit == "y" ) { - midi.openVirtualPort(); + midi.openVirtualPort("RtMidi virtual input"); return true; } diff --git a/tests/midiout2.cpp b/tests/midiout2.cpp index 068e7cb2..af8a57a7 100644 --- a/tests/midiout2.cpp +++ b/tests/midiout2.cpp @@ -113,7 +113,7 @@ bool chooseMidiPort( RtMidiOut &midi ) std::string keyHit; std::getline( std::cin, keyHit ); if ( keyHit == "y" ) { - midi.openVirtualPort(); + midi.openVirtualPort("RtMidi virtual output"); std::cout << "Press return to start the transmission." << std::endl; std::getline( std::cin, keyHit ); From 2011265bb52500d1e5a20fbbbc4472bdfe9ada7a Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 4 May 2014 20:58:30 +0200 Subject: [PATCH 037/210] Convert tests for the port descriptor API to use the new API directly. --- tests/cmidiin2.cpp | 10 +++++----- tests/loopback.cpp | 10 +++++----- tests/midiout2.cpp | 13 +++++++------ tests/midiprobe2.cpp | 26 +++++++++++++------------- tests/qmidiin2.cpp | 8 ++++---- 5 files changed, 34 insertions(+), 33 deletions(-) diff --git a/tests/cmidiin2.cpp b/tests/cmidiin2.cpp index cfd90942..b24edd0a 100644 --- a/tests/cmidiin2.cpp +++ b/tests/cmidiin2.cpp @@ -31,7 +31,7 @@ void mycallback( double deltatime, std::vector< unsigned char > *message, void * // This function should be embedded in a try/catch block in case of // an exception. It offers the user a choice of MIDI ports to open. // It returns false if there are no ports available. -bool chooseMidiPort( RtMidiIn &rtmidi ); +bool chooseMidiPort( rtmidi::MidiIn &rtmidi ); int main( int argc, char */*argv*/[] ) { @@ -41,8 +41,8 @@ int main( int argc, char */*argv*/[] ) try { - // RtMidiIn constructor - RtMidiIn midiin; + // rtmidi::MidiIn constructor + rtmidi::MidiIn midiin; // Call function to select port. if ( chooseMidiPort( midiin ) == false ) return 0; @@ -59,12 +59,12 @@ int main( int argc, char */*argv*/[] ) char input; std::cin.get(input); - } catch ( RtMidiError &error ) { + } catch ( rtmidi::Error &error ) { error.printMessage(); } } -bool chooseMidiPort( RtMidiIn &midi ) +bool chooseMidiPort( rtmidi::MidiIn &midi ) { std::cout << "\nWould you like to open a virtual input port? [y/N] "; diff --git a/tests/loopback.cpp b/tests/loopback.cpp index 2ddefd92..62af2fd2 100644 --- a/tests/loopback.cpp +++ b/tests/loopback.cpp @@ -72,10 +72,10 @@ int main( int argc, char */*argv*/[] ) try { - // RtMidiIn constructor - RtMidiIn virtualin; - // RtMidiIn constructor - RtMidiOut virtualout; + // rtmidi::MidiIn constructor + rtmidi::MidiIn virtualin; + // rtmidi::MidiIn constructor + rtmidi::MidiOut virtualout; virtualin.openVirtualPort("RtMidi Test Virtual In"); virtualout.openVirtualPort("RtMidi Test Virtual Out"); @@ -202,7 +202,7 @@ int main( int argc, char */*argv*/[] ) std::cout << std::endl; if (i != virtualinstring.size()) abort(); - } catch ( RtMidiError &error ) { + } catch ( rtmidi::Error &error ) { error.printMessage(); } } diff --git a/tests/midiout2.cpp b/tests/midiout2.cpp index af8a57a7..6e45d53d 100644 --- a/tests/midiout2.cpp +++ b/tests/midiout2.cpp @@ -22,21 +22,22 @@ // This function should be embedded in a try/catch block in case of // an exception. It offers the user a choice of MIDI ports to open. // It returns false if there are no ports available. -bool chooseMidiPort( RtMidiOut &ortmidi ); +bool chooseMidiPort( rtmidi::MidiOut &ortmidi ); +//! The main program int main( int /* argc*/, char */*argv*/[] ) { std::vector message; - // RtMidiOut constructor + // rtmidi::MidiOut constructor try { - RtMidiOut midiout; + rtmidi::MidiOut midiout; // Call function to select port. try { if ( chooseMidiPort( midiout ) == false ) return 1; } - catch ( RtMidiError &error ) { + catch ( rtmidi::Error &error ) { error.printMessage(); return 2; } @@ -98,7 +99,7 @@ int main( int /* argc*/, char */*argv*/[] ) } - catch ( RtMidiError &error ) { + catch ( rtmidi::Error &error ) { error.printMessage(); exit( EXIT_FAILURE ); } @@ -106,7 +107,7 @@ int main( int /* argc*/, char */*argv*/[] ) return 0; } -bool chooseMidiPort( RtMidiOut &midi ) +bool chooseMidiPort( rtmidi::MidiOut &midi ) { std::cout << "\nWould you like to open a virtual output port? [y/N] "; diff --git a/tests/midiprobe2.cpp b/tests/midiprobe2.cpp index 9c599c9e..18052ba4 100644 --- a/tests/midiprobe2.cpp +++ b/tests/midiprobe2.cpp @@ -13,15 +13,15 @@ int main() { // Create an api map. std::map apiMap; - apiMap[RtMidi::MACOSX_CORE] = "OS-X CoreMidi"; - apiMap[RtMidi::WINDOWS_MM] = "Windows MultiMedia"; - apiMap[RtMidi::WINDOWS_KS] = "Windows Kernel Straming"; - apiMap[RtMidi::UNIX_JACK] = "Jack Client"; - apiMap[RtMidi::LINUX_ALSA] = "Linux ALSA"; - apiMap[RtMidi::RTMIDI_DUMMY] = "RtMidi Dummy"; + apiMap[rtmidi::MACOSX_CORE] = "OS-X CoreMidi"; + apiMap[rtmidi::WINDOWS_MM] = "Windows MultiMedia"; + apiMap[rtmidi::WINDOWS_KS] = "Windows Kernel Straming"; + apiMap[rtmidi::UNIX_JACK] = "Jack Client"; + apiMap[rtmidi::LINUX_ALSA] = "Linux ALSA"; + apiMap[rtmidi::RTMIDI_DUMMY] = "RtMidi Dummy"; - std::vector< RtMidi::Api > apis; - RtMidi :: getCompiledApi( apis ); + std::vector< rtmidi::ApiType > apis; + rtmidi::Midi :: getCompiledApi( apis ); std::cout << "\nCompiled APIs:\n"; for ( unsigned int i=0; i Date: Sun, 4 May 2014 20:59:29 +0200 Subject: [PATCH 038/210] Fix compilation on Linux as well as duplicate closing of the ALSA sequencer. --- RtMidi.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 24c3d546..a64ec026 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -39,6 +39,7 @@ #include "RtMidi.h" #include #include +#include NAMSPACE_RTMIDI_START //*********************************************************************// @@ -2849,7 +2850,6 @@ MidiInAlsa :: ~MidiInAlsa() #ifndef AVOID_TIMESTAMPING snd_seq_free_queue( data->seq, data->queue_id ); #endif - snd_seq_close( data->seq ); delete data; } @@ -3247,7 +3247,6 @@ MidiOutAlsa :: ~MidiOutAlsa() if ( data->local.client > 0 ) snd_seq_delete_port( data->seq, data->local.port ); if ( data->coder ) snd_midi_event_free( data->coder ); if ( data->buffer ) free( data->buffer ); - snd_seq_close( data->seq ); delete data; } From f9996df1c95116edf154e91f60dab5026665bece Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 4 May 2014 21:03:06 +0200 Subject: [PATCH 039/210] Add tests for the port descriptor API to the documentation as examples. --- doc/doxygen/Doxyfile | 4 ++-- doc/doxygen/header.html | 2 +- tests/cmidiin2.cpp | 9 ++++++--- tests/loopback.cpp | 7 ++++--- tests/midiout2.cpp | 12 ++++++++---- tests/midiprobe2.cpp | 10 ++++++---- tests/qmidiin2.cpp | 10 ++++++---- tests/sysextest.cpp | 8 ++++---- 8 files changed, 37 insertions(+), 25 deletions(-) diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index 29cc59a3..4f8489c5 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -669,7 +669,7 @@ WARN_LOGFILE = INPUT = tutorial.txt \ ../../RtMidi.h \ - ../../RtError.h + ../../tests # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -729,7 +729,7 @@ EXCLUDE_SYMBOLS = # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = +EXAMPLE_PATH = ../../tests # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp diff --git a/doc/doxygen/header.html b/doc/doxygen/header.html index 3b6d60ba..62a1f347 100644 --- a/doc/doxygen/header.html +++ b/doc/doxygen/header.html @@ -5,5 +5,5 @@
-Tutorial   Class/Enum List   File List   Compound Members  
+Tutorial   Examples   Class/Enum List   File List   Compound Members  
diff --git a/tests/cmidiin2.cpp b/tests/cmidiin2.cpp index b24edd0a..549b1316 100644 --- a/tests/cmidiin2.cpp +++ b/tests/cmidiin2.cpp @@ -1,9 +1,12 @@ //*****************************************// // cmidiin.cpp -// by Gary Scavone, 2003-2004. +// by Gary Scavone, 2003-2014. +// and Tobias Schlemmer 2014. // -// Simple program to test MIDI input and -// use of a user callback function. +/*! \example cmidiin2.cpp + Simple program to test MIDI input and + use of a user callback function. +*/ // //*****************************************// diff --git a/tests/loopback.cpp b/tests/loopback.cpp index 62af2fd2..5082f05c 100644 --- a/tests/loopback.cpp +++ b/tests/loopback.cpp @@ -4,9 +4,10 @@ // inspired by virtual-loopback-test-automated.js from the node-midi project. // donated to RtMidi. // -// Simple program to test MIDI input and -// output using a user callback function. -// +/*! \example loopback.cpp + Simple program to test MIDI input and + output in an internal loop using a user callback function. +*/ //*****************************************// #include diff --git a/tests/midiout2.cpp b/tests/midiout2.cpp index 6e45d53d..584faea9 100644 --- a/tests/midiout2.cpp +++ b/tests/midiout2.cpp @@ -1,10 +1,14 @@ //*****************************************// // midiout.cpp -// by Gary Scavone, 2003-2004. +// by Gary Scavone, 2003-2014. +// and Tobias Schlemmer 2014 // -// Simple program to test MIDI output. -// -//*****************************************// +/*! \example midiout2.cpp + Simple program to test MIDI output. +*/ +// *****************************************// + + #include #include diff --git a/tests/midiprobe2.cpp b/tests/midiprobe2.cpp index 18052ba4..85fc8633 100644 --- a/tests/midiprobe2.cpp +++ b/tests/midiprobe2.cpp @@ -1,8 +1,10 @@ -// midiprobe.cpp -// -// Simple program to check MIDI inputs and outputs. +/*! \example midiprobe2.cpp + + Simple program to check MIDI inputs and outputs. +*/ // -// by Gary Scavone, 2003-2012. +// by Gary Scavone, 2003-2014. +// and Tobias Schlemmer 2014 #include #include diff --git a/tests/qmidiin2.cpp b/tests/qmidiin2.cpp index acb62b6a..0e364ea9 100644 --- a/tests/qmidiin2.cpp +++ b/tests/qmidiin2.cpp @@ -1,10 +1,12 @@ //*****************************************// // qmidiin.cpp -// by Gary Scavone, 2003-2004. -// -// Simple program to test MIDI input and -// retrieval from the queue. +// by Gary Scavone, 2003-2014. +// and Tobias Schlemmer, 2014 // +/*! \example qmidiin2.cpp + Simple program to test MIDI input and + retrieval from the queue. +*/ //*****************************************// #include diff --git a/tests/sysextest.cpp b/tests/sysextest.cpp index 8402c74c..e2cf2a2b 100644 --- a/tests/sysextest.cpp +++ b/tests/sysextest.cpp @@ -1,9 +1,9 @@ //*****************************************// -// sysextest.cpp // by Gary Scavone, 2003-2005. -// -// Simple program to test MIDI sysex sending and receiving. -// +/*! \example sysextest.cpp + + program to test MIDI sysex sending and receiving. +*/ //*****************************************// #include From d551556dcef7dd31214bf6433769b16732363b79 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 4 May 2014 21:06:08 +0200 Subject: [PATCH 040/210] Update the documentation to reflect the port descriptor API. --- doc/doxygen/tutorial.txt | 429 +++++++++++++++++++++++---------------- 1 file changed, 250 insertions(+), 179 deletions(-) diff --git a/doc/doxygen/tutorial.txt b/doc/doxygen/tutorial.txt index aba7f3bd..3dd74207 100644 --- a/doc/doxygen/tutorial.txt +++ b/doc/doxygen/tutorial.txt @@ -2,32 +2,81 @@
\ref intro    \ref download    \ref start    \ref error    \ref probing    \ref output    \ref input    \ref virtual    \ref compiling    \ref debug    \ref multi    \ref apinotes    \ref acknowledge    \ref license
+\section warning Warning: + +This documentation refers to an API suggested to RtMidi (and available at GitHub). So far it is not officially accepted in the RtMidi distribution. + \section intro Introduction RtMidi is a set of C++ classes (RtMidiIn, RtMidiOut and API-specific classes) that provides a common API (Application Programming Interface) for realtime MIDI input/output across Linux (ALSA & JACK), Macintosh OS X (CoreMIDI & JACK), and Windows (Multimedia Library) operating systems. RtMidi significantly simplifies the process of interacting with computer MIDI hardware and software. It was designed with the following goals: - -
    -
  • object oriented C++ design
  • -
  • simple, common API across all supported platforms
  • -
  • only one header and one source file for easy inclusion in programming projects
  • -
  • MIDI device enumeration
  • -
+ - object oriented C++ design + - simple, common API across all supported platforms + - only one header and one source file for easy inclusion in programming projects + - MIDI device enumeration Where applicable, multiple API support can be compiled and a particular API specified when creating an RtAudio instance. MIDI input and output functionality are separated into two classes, RtMidiIn and RtMidiOut. Each class instance supports only a single MIDI connection. RtMidi does not provide timing functionality (i.e., output messages are sent immediately). Input messages are timestamped with delta times in seconds (via a \c double floating point type). MIDI data is passed to the user as raw bytes using an std::vector. +\section whatsnew3 What's New (Version 3.0) + + - The classes of RtMidi now reside in the namespace rtmidi. + - The beginning letters “Rt” are dropped from the names + - For easy adoption of the new interface wrappers for the old API are provided. + - The library uses backend provided port descriptors, now. This provides a more reliable port handling for changing environments (See below). + +The way MIDI devices are enumerated has changed. The old way, using the ordinal number of MIDI devices works only in cases where MIDI devices are not added or removed during the program session. When a virtual MIDI port or USB MIDI device is added or removed the ordinal number of each of the other devices may change. + +Suppose your computer has the following list of MIDI devices. + 1. MIDI loopback device + 2. Removable USB MIDI device + 3. Another MIDI device + 4. Software MIDI Synth + 5. A virtual MIDI port + +After the software obtained this list, your friend remembers that he +must catch the next bus and unplugs his removable USB MIDI device. +The software does not recognize this removal and keeps the above list, +while the system has a new one: + 1. MIDI loopback device + 2. Another MIDI device + 3. Software MIDI Synth + 4. A virtual MIDI port + +Somehow you told the software to use the Software MIDI Synth. The +program stores the number 4 as it obtained during enumeration of the +MIDI devices. Instead of playing the music using your sound card it +sends the music to a different port. + +While this behaviour is only annoying in interactive environments it +results in unpredictable behaviour if several ports are opened at +once. E.g. in the ALSA backend every opened port results in an +aditional newly created virtual port. + +In order to avoid such problems, most backends identify ports (except +WinMM) by different data structures. + +The current version introduces a new class \ref rtmidi::PortDescriptor +in order to hide this implementation detail from the user code. In +order to avoid the above problems these are retrieved at once using \ref rtmidi::Midi::getPortList. +This new feature also allows to retreive the port descriptor of an open device using +\ref rtmidi::Midi::getDescriptor. The latter can be used to obtain + + + \section whatsnew What's New (Version 2.1) A minor API change was made. The RtError class was renamed RtMidiError and embedded directly in RtMidi.h. Thus, all references to RtError should be renamed to RtMidiError and the RtError.h file should be deleted. The Windows Kernel Streaming support was removed because it was uncompilable and incomplete. \section download Download +The prerelease this documentation refers to: Download from the git repository + Latest Release (30 March 2014): Version 2.1.0 \section start Getting Started -The first thing that must be done when using RtMidi is to create an instance of the RtMidiIn or RtMidiOut subclasses. RtMidi is an abstract base class, which itself cannot be instantiated. Each default constructor attempts to establish any necessary "connections" with the underlying MIDI system. RtMidi uses C++ exceptions to report errors, necessitating try/catch blocks around many member functions. An RtMidiError can be thrown during instantiation in some circumstances. A warning message may also be reported if no MIDI devices are found during instantiation. The RtMidi classes have been designed to work with "hot pluggable" or virtual (software) MIDI devices, making it possible to connect to MIDI devices that may not have been present when the classes were instantiated. The following code example demonstrates default object construction and destruction: +The first thing that must be done when using RtMidi is to create an instance of the rtmidi::MidiIn or rtmidi::MidiOut subclasses. rtmidi::Midi is an abstract base class, which itself cannot be instantiated. Each default constructor attempts to establish any necessary "connections" with the underlying MIDI system. RtMidi uses C++ exceptions to report errors, necessitating try/catch blocks around many member functions. An rtmidi::Error can be thrown during instantiation in some circumstances. A warning message may also be reported if no MIDI devices are found during instantiation. The RtMidi classes have been designed to work with "hot pluggable" or virtual (software) MIDI devices, making it possible to connect to MIDI devices that may not have been present when the classes were instantiated. The following code example demonstrates default object construction and destruction: \code @@ -35,110 +84,124 @@ The first thing that must be done when using RtMidi is to create an instance of int main() { - RtMidiIn *midiin = 0; + rtmidi::MidiIn *midiin = 0; - // RtMidiIn constructor try { - midiin = new RtMidiIn(); - } - catch (RtMidiError &error) { - // Handle the exception here - error.printMessage(); - } + // MidiIn constructor + try { + midiin = new rtmidi::MidiIn(); + } + catch (rtmidi::Error &error) { + // Handle the exception here + error.printMessage(); + } - // Clean up - delete midiin; + /* put your code here */ + + // Clean up + delete midiin; + midiin = 0; + } catch (...) { + // avoid resource leaks in case of exceptions thrown by your code + delete midiin; + throw; + } } \endcode Obviously, this example doesn't demonstrate any of the real functionality of RtMidi. However, all uses of RtMidi must begin with construction and must end with class destruction. Further, it is necessary that all class methods that can throw a C++ exception be called within a try/catch block. +\note The outer try/catch block can be simplyfied if you create the MidiIn object on the stack as it is done in the following examples. + + + \section error Error Handling -RtMidi uses a C++ exception handler called RtMidiError, which is -declared and defined in RtMidi.h. The RtMidiError class is quite -simple but it does allow errors to be "caught" by RtMidiError::Type. -Many RtMidi methods can "throw" an RtMidiError, most typically if a +RtMidi uses a C++ exception handler called rtmidi::Error, which is +declared and defined in RtMidi.h. The rtmidi::Error class is quite +simple but it does allow errors to be "caught" by rtmidi::Error::Type. +Many RtMidi methods can "throw" an rtmidi::Error, most typically if a driver error occurs or an invalid function argument is specified. There are a number of cases within RtMidi where warning messages may be displayed but an exception is not thrown. A client error callback -function can be specified (via the RtMidi::setErrorCallback function) +function can be specified (via the rtmidi::Midi::setErrorCallback function) that is invoked when an error occurs. By default, error messages are not automatically displayed in RtMidi unless the preprocessor definition __RTMIDI_DEBUG__ is defined during compilation. Messages associated with caught exceptions can be displayed with, for example, -the RtMidiError::printMessage() function. +the rtmidi::Error::printMessage() function. \section probing Probing Ports -A client generally must query the available MIDI ports before deciding which to use. The following example outlines how this can be done. +A client generally must query the available MIDI ports before deciding which to use. The following example outlines how this can be done. A more sophisticated example demonstrating the API detection and the different naming schemes can be found in the \c tests subdirectory in the file \link midiprobe2.cpp \c midiprobe2.cpp \endlink. \code // midiprobe.cpp #include #include +#include #include "RtMidi.h" int main() { - RtMidiIn *midiin = 0; - RtMidiOut *midiout = 0; + // Create an api map. + std::map apiMap; + apiMap[RtMidi::MACOSX_CORE] = "OS-X CoreMidi"; + apiMap[RtMidi::WINDOWS_MM] = "Windows MultiMedia"; + apiMap[RtMidi::WINDOWS_KS] = "Windows Kernel Straming"; + apiMap[RtMidi::UNIX_JACK] = "Jack Client"; + apiMap[RtMidi::LINUX_ALSA] = "Linux ALSA"; + apiMap[RtMidi::RTMIDI_DUMMY] = "RtMidi Dummy"; - // RtMidiIn constructor - try { - midiin = new RtMidiIn(); - } - catch ( RtMidiError &error ) { - error.printMessage(); - exit( EXIT_FAILURE ); - } + std::vector< rtmidi::ApiType > apis; + rtmidi::Midi :: getCompiledApi( apis ); + + std::cout << "\nCompiled APIs:\n"; + for ( unsigned int i=0; igetPortCount(); - std::cout << "\nThere are " << nPorts << " MIDI input sources available.\n"; - std::string portName; - for ( unsigned int i=0; igetPortName(i); - } - catch ( RtMidiError &error ) { - error.printMessage(); - goto cleanup; - } - std::cout << " Input Port #" << i+1 << ": " << portName << '\n'; - } - // RtMidiOut constructor try { - midiout = new RtMidiOut(); - } - catch ( RtMidiError &error ) { - error.printMessage(); - exit( EXIT_FAILURE ); - } - // Check outputs. - nPorts = midiout->getPortCount(); - std::cout << "\nThere are " << nPorts << " MIDI output ports available.\n"; - for ( unsigned int i=0; igetPortName(i); + // rtmidi::MidiIn constructor ... exception possible + rtmidi::MidiIn midiin; + + std::cout << "\nCurrent input API: " << apiMap[ midiin.getCurrentApi() ] << std::endl; + + + rtmidi::PortList list = midiin.getPortList(); + // Check inputs. + std::cout << "\nThere are " << list.size() << " MIDI input sources available.\n"; + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); + i++) { + std::cout << " Input Port: " << (*i)->getName() << std::endl; } - catch (RtMidiError &error) { - error.printMessage(); - goto cleanup; + + std::cout << "**********************************************************************" << std::endl; + + // rtmidi::MidiOut constructor ... exception possible + rtmidi::MidiOut midiout; + + std::cout << "\nCurrent output API: " << apiMap[ midiout.getCurrentApi() ] << std::endl; + + list = midiout.getPortList(); + + // Check inputs. + std::cout << "\nThere are " << list.size() << " MIDI output sinks available.\n"; + + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); + i++) { + std::cout << " Output Port: " << (*i)->getName() << std::endl; } - std::cout << " Output Port #" << i+1 << ": " << portName << '\n'; - } - std::cout << '\n'; - // Clean up - cleanup: - delete midiin; - delete midiout; + } catch ( rtmidi::Error &error ) { + error.printMessage(); + } return 0; } @@ -146,9 +209,9 @@ int main() \section output MIDI Output -The RtMidiOut class provides simple functionality to immediately send messages over a MIDI connection. No timing functionality is provided. +The rtmidi::MidiOut class provides simple functionality to immediately send messages over a MIDI connection. No timing functionality is provided. -In the following example, we omit necessary error checking and details regarding OS-dependent sleep functions. For a complete example, see the \c midiout.cpp program in the \c tests directory. +In the following example, we omit necessary error checking and details regarding OS-dependent sleep functions. For a complete example, see the \link midiout2.cpp \c midiout2.cpp \endlink program in the \c tests directory. \code // midiout.cpp @@ -159,50 +222,51 @@ In the following example, we omit necessary error checking and details regarding int main() { - RtMidiOut *midiout = new RtMidiOut(); - std::vector message; - - // Check available ports. - unsigned int nPorts = midiout->getPortCount(); - if ( nPorts == 0 ) { - std::cout << "No ports available!\n"; - goto cleanup; - } - - // Open first available port. - midiout->openPort( 0 ); + try { + rtmidi::MidiOut midiout; + std::vector message; + + // Check available ports. + rtmidi::PortList list = midiout.getPortList(); + if (list.empty()) { + std::cerr << "No devices found." << std::endl; + exit(EXIT_FAILURE); + } - // Send out a series of MIDI messages. + // Open first available port. + midiout.openPort( list.front ); - // Program change: 192, 5 - message.push_back( 192 ); - message.push_back( 5 ); - midiout->sendMessage( &message ); + // Send out a series of MIDI messages. - // Control Change: 176, 7, 100 (volume) - message[0] = 176; - message[1] = 7; - message.push_back( 100 ); - midiout->sendMessage( &message ); + // Program change: 192, 5 + message.push_back( 192 ); + message.push_back( 5 ); + midiout.sendMessage( &message ); - // Note On: 144, 64, 90 - message[0] = 144; - message[1] = 64; - message[2] = 90; - midiout->sendMessage( &message ); + // Control Change: 176, 7, 100 (volume) + message[0] = 176; + message[1] = 7; + message.push_back( 100 ); + midiout.sendMessage( &message ); - SLEEP( 500 ); // Platform-dependent ... see example in tests directory. + // Note On: 144, 64, 90 + message[0] = 144; + message[1] = 64; + message[2] = 90; + midiout.sendMessage( &message ); - // Note Off: 128, 64, 40 - message[0] = 128; - message[1] = 64; - message[2] = 40; - midiout->sendMessage( &message ); + SLEEP( 500 ); // Platform-dependent ... see example in tests directory. - // Clean up - cleanup: - delete midiout; + // Note Off: 128, 64, 40 + message[0] = 128; + message[1] = 64; + message[2] = 40; + midiout.sendMessage( &message ); + } catch (rtmidi::Error & error) { + error.printMessage(); + exit(EXIT_FAILURE); + } return 0; } \endcode @@ -210,15 +274,15 @@ int main() \section input MIDI Input -The RtMidiIn class uses an internal callback function or thread to receive incoming MIDI messages from a port or device. These messages are then either queued and read by the user via calls to the RtMidiIn::getMessage() function or immediately passed to a user-specified callback function (which must be "registered" using the RtMidiIn::setCallback() function). We'll provide examples of both usages. +The rtmidi::MidiIn class uses an internal callback function or thread to receive incoming MIDI messages from a port or device. These messages are then either queued and read by the user via calls to the rtmidi::MidiIn::getMessage() function or immediately passed to a user-specified callback function (which must be "registered" using the rtmidi::MidiIn::setCallback() function). We'll provide examples of both usages. -The RtMidiIn class provides the RtMidiIn::ignoreTypes() function to specify that certain MIDI message types be ignored. By default, system exclusive, timing, and active sensing messages are ignored. +The rtmidi::MidiIn class provides the rtmidi::MidiIn::ignoreTypes() function to specify that certain MIDI message types be ignored. By default, system exclusive, timing, and active sensing messages are ignored. \subsection qmidiin Queued MIDI Input -The RtMidiIn::getMessage() function does not block. If a MIDI message is available in the queue, it is copied to the user-provided \c std::vector container. When no MIDI message is available, the function returns an empty container. The default maximum MIDI queue size is 1024 messages. This value may be modified with the RtMidiIn::setQueueSizeLimit() function. If the maximum queue size limit is reached, subsequent incoming MIDI messages are discarded until the queue size is reduced. +The rtmidi::MidiIn::getMessage() function does not block. If a MIDI message is available in the queue, it is copied to the user-provided \c std::vector container. When no MIDI message is available, the function returns an empty container. The default maximum MIDI queue size is 1024 messages. This value may be modified with the rtmidi::MidiIn::setQueueSizeLimit() function. If the maximum queue size limit is reached, subsequent incoming MIDI messages are discarded until the queue size is reduced. -In the following example, we omit some necessary error checking and details regarding OS-dependent sleep functions. For a more complete example, see the \c qmidiin.cpp program in the \c tests directory. +In the following example, we omit some necessary error checking and details regarding OS-dependent sleep functions. For a more complete example, see the \link qmidiin2.cpp \c qmidiin2.cpp \endlink program in the \c tests directory. \code // qmidiin.cpp @@ -233,51 +297,54 @@ static void finish(int ignore){ done = true; } int main() { - RtMidiIn *midiin = new RtMidiIn(); - std::vector message; - int nBytes, i; - double stamp; + try { + rtmidi::MidiIn midiin; + std::vector message; + int nBytes, i; + double stamp; + + // Check available ports. + rtmidi::PortList list = midiin.getPortList(); + if (list.empty()) { + std::cerr << "No devices found." << std::endl; + exit(EXIT_FAILURE); + } - // Check available ports. - unsigned int nPorts = midiin->getPortCount(); - if ( nPorts == 0 ) { - std::cout << "No ports available!\n"; - goto cleanup; - } - midiin->openPort( 0 ); - - // Don't ignore sysex, timing, or active sensing messages. - midiin->ignoreTypes( false, false, false ); - - // Install an interrupt handler function. - done = false; - (void) signal(SIGINT, finish); - - // Periodically check input queue. - std::cout << "Reading MIDI from port ... quit with Ctrl-C.\n"; - while ( !done ) { - stamp = midiin->getMessage( &message ); - nBytes = message.size(); - for ( i=0; i 0 ) - std::cout << "stamp = " << stamp << std::endl; - - // Sleep for 10 milliseconds ... platform-dependent. - SLEEP( 10 ); - } + // Open first available port. + midiin.openPort( list.front ); + + // Don't ignore sysex, timing, or active sensing messages. + midiin.ignoreTypes( false, false, false ); + + // Install an interrupt handler function. + done = false; + (void) signal(SIGINT, finish); + + // Periodically check input queue. + std::cout << "Reading MIDI from port ... quit with Ctrl-C.\n"; + while ( !done ) { + stamp = midiin.getMessage( &message ); + nBytes = message.size(); + for ( i=0; i 0 ) + std::cout << "stamp = " << stamp << std::endl; - // Clean up - cleanup: - delete midiin; + // Sleep for 10 milliseconds ... platform-dependent. + SLEEP( 10 ); + } + } catch (rtmidi::Error & error) { + error.printMessage(); + exit(EXIT_FAILURE); + } return 0; } \endcode \subsection cmidiin MIDI Input with User Callback -When set, a user-provided callback function will be invoked after the input of a complete MIDI message. It is possible to provide a pointer to user data that can be accessed in the callback function (not shown here). It is necessary to set the callback function immediately after opening the port to avoid having incoming messages written to the queue (which is not emptied when a callback function is set). If you are worried about this happening, you can check the queue using the RtMidi::getMessage() function to verify it is empty (after the callback function is set). +When set, a user-provided callback function will be invoked after the input of a complete MIDI message. It is possible to provide a pointer to user data that can be accessed in the callback function (not shown here). It is necessary to set the callback function immediately after opening the port to avoid having incoming messages written to the queue (which is not emptied when a callback function is set). If you are worried about this happening, you can check the queue using the rtmidi::Midi::getMessage() function to verify it is empty (after the callback function is set). In the following example, we omit some necessary error checking. For a more complete example, see the \c cmidiin.cpp program in the \c tests directory. @@ -299,40 +366,42 @@ void mycallback( double deltatime, std::vector< unsigned char > *message, void * int main() { - RtMidiIn *midiin = new RtMidiIn(); + try { + rtmidi::MidiIn midiin; // Check available ports. - unsigned int nPorts = midiin->getPortCount(); - if ( nPorts == 0 ) { - std::cout << "No ports available!\n"; - goto cleanup; - } - - midiin->openPort( 0 ); + rtmidi::PortList list = midiin.getPortList(); + if (list.empty()) { + std::cerr << "No ports available." << std::endl; + exit(EXIT_FAILURE); + } - // Set our callback function. This should be done immediately after - // opening the port to avoid having incoming messages written to the - // queue. - midiin->setCallback( &mycallback ); + // Open first available port. + midiin.openPort( list.front ); - // Don't ignore sysex, timing, or active sensing messages. - midiin->ignoreTypes( false, false, false ); + // Set our callback function. This should be done immediately after + // opening the port to avoid having incoming messages written to the + // queue. + midiin.setCallback( &mycallback ); - std::cout << "\nReading MIDI input ... press to quit.\n"; - char input; - std::cin.get(input); + // Don't ignore sysex, timing, or active sensing messages. + midiin.ignoreTypes( false, false, false ); - // Clean up - cleanup: - delete midiin; + std::cout << "\nReading MIDI input ... press to quit.\n"; + char input; + std::cin.get(input); + } catch (rtmidi::Error & error) { + error.printMessage(); + exit(EXIT_FAILURE); + } return 0; } \endcode \section virtual Virtual Ports -The Linux ALSA, Macintosh CoreMIDI and JACK APIs allow for the establishment of virtual input and output MIDI ports to which other software clients can connect. RtMidi incorporates this functionality with the RtMidiIn::openVirtualPort() and RtMidiOut::openVirtualPort() functions. Any messages sent with the RtMidiOut::sendMessage() function will also be transmitted through an open virtual output port. If a virtual input port is open and a user callback function is set, the callback function will be invoked when messages arrive via that port. If a callback function is not set, the user must poll the input queue to check whether messages have arrived. No notification is provided for the establishment of a client connection via a virtual port. +The Linux ALSA, Macintosh CoreMIDI and JACK APIs allow for the establishment of virtual input and output MIDI ports to which other software clients can connect. RtMidi incorporates this functionality with the rtmidi::MidiIn::openVirtualPort() and rtmidi::MidiOut::openVirtualPort() functions. Any messages sent with the rtmidi::MidiOut::sendMessage() function will also be transmitted through an open virtual output port. If a virtual input port is open and a user callback function is set, the callback function will be invoked when messages arrive via that port. If a callback function is not set, the user must poll the input queue to check whether messages have arrived. No notification is provided for the establishment of a client connection via a virtual port. \section compiling Compiling @@ -352,21 +421,21 @@ In order to compile RtMidi for a specific OS and API, it is necessary to supply ALSA Sequencer __LINUX_ALSA__ asound, pthread - g++ -Wall -D__LINUX_ALSA__ -o midiprobe midiprobe.cpp RtMidi.cpp -lasound -lpthread + g++ -Wall -D__LINUX_ALSA__ -o midiprobe midiprobe2.cpp RtMidi.cpp -lasound -lpthread Linux or Mac JACK MIDI __UNIX_JACK__ jack - g++ -Wall -D__UNIX_JACK__ -o midiprobe midiprobe.cpp RtMidi.cpp -ljack + g++ -Wall -D__UNIX_JACK__ -o midiprobe midiprobe2.cpp RtMidi.cpp -ljack Macintosh OS X CoreMIDI __MACOSX_CORE__ CoreMIDI, CoreAudio, CoreFoundation - g++ -Wall -D__MACOSX_CORE__ -o midiprobe midiprobe.cpp RtMidi.cpp -framework CoreMIDI -framework CoreAudio -framework CoreFoundation + g++ -Wall -D__MACOSX_CORE__ -o midiprobe midiprobe2.cpp RtMidi.cpp -framework CoreMIDI -framework CoreAudio -framework CoreFoundation Windows @@ -378,7 +447,7 @@ In order to compile RtMidi for a specific OS and API, it is necessary to supply

-The example compiler statements above could be used to compile the midiprobe.cpp example file, assuming that midiprobe.cpp, RtMidi.h and RtMidi.cpp all exist in the same directory. +The example compiler statements above could be used to compile the midiprobe2.cpp example file, assuming that midiprobe2.cpp, RtMidi.h and RtMidi.cpp all exist in the same directory. \section debug Debugging @@ -386,9 +455,9 @@ If you are having problems getting RtMidi to run on your system, try passing the \section multi Using Simultaneous Multiple APIs -Support for each MIDI API is encapsulated in specific MidiInApi or MidiOutApi subclasses, making it possible to compile and instantiate multiple API-specific subclasses on a given operating system. For example, one can compile both CoreMIDI and JACK support on the OS-X operating system by providing the appropriate preprocessor definitions for each. In a run-time situation, one might first attempt to determine whether any JACK ports are available. This can be done by specifying the api argument RtMidi::UNIX_JACK when attempting to create an instance of RtMidiIn or RtMidiOut. If no available ports are found, then an instance of RtMidi with the api argument RtMidi::MACOSX_CORE can be created. Alternately, if no api argument is specified, RtMidi will first look for JACK ports and if none are found, then CoreMIDI ports (in linux, the search order is JACK and then ALSA. In theory, it should also be possible to have separate instances of RtMidi open at the same time with different underlying API support, though this has not been tested. +Support for each MIDI API is encapsulated in specific MidiInApi or MidiOutApi subclasses, making it possible to compile and instantiate multiple API-specific subclasses on a given operating system. For example, one can compile both CoreMIDI and JACK support on the OS-X operating system by providing the appropriate preprocessor definitions for each. In a run-time situation, one might first attempt to determine whether any JACK ports are available. This can be done by specifying the api argument rtmidi::UNIX_JACK when attempting to create an instance of rtmidi::MidiIn or rtmidi::MidiOut. If no available ports are found, then an instance of rtmidi::Midi with the api argument rtmidi::MACOSX_CORE can be created. Alternately, if no api argument is specified, RtMidi will first look for JACK ports and if none are found, then CoreMIDI ports (in linux, the search order is JACK and then ALSA). In theory, it should also be possible to have separate instances of RtMidi open at the same time with different underlying API support, though this has not been tested. -The static function RtMidi::getCompiledApi() is provided to determine the available compiled API support. The function RtMidi::getCurrentApi() indicates the API selected for a given RtMidi instance. +The static function rtmidi::Midi::getCompiledApi() is provided to determine the available compiled API support. The function rtmidi::Midi::getCurrentApi() indicates the API selected for a given RtMidi instance. \section apinotes API Notes @@ -396,7 +465,7 @@ RtMidi is designed to provide a common API across the various supported operatin \subsection linux Linux: -RtMidi for Linux was developed using the Fedora distribution. Two different MIDI APIs are supported on Linux platforms: ALSA and JACK. A decision was made to not include support for the OSS API because the OSS API provides very limited functionality and because ALSA support is now incorporated in the Linux kernel. The ALSA sequencer and JACK APIs allows for virtual software input and output ports. +Two different MIDI APIs are supported on Linux platforms: ALSA and JACK. A decision was made to not include support for the OSS API because the OSS API provides very limited functionality and because ALSA support is now incorporated in the Linux kernel. The ALSA sequencer and JACK APIs allows for virtual software input and output ports. \subsection macosx Macintosh OS X (CoreAudio): @@ -408,7 +477,7 @@ The RtMidi JACK support can be compiled on Macintosh OS-X systems, as well as in The \c configure script provides support for the MinGW compiler. -The Windows Multimedia library MIDI calls used in RtMidi do not make use of streaming functionality. Incoming system exclusive messages read by RtMidiIn are limited to a length as defined by the preprocessor definition RT_SYSEX_BUFFER_SIZE (set in RtMidi.cpp). The default value is 1024. There is no such limit for outgoing sysex messages via RtMidiOut. +The Windows Multimedia library MIDI calls used in RtMidi do not make use of streaming functionality. Incoming system exclusive messages read by rtimidi::MidiIn are limited to a length as defined by the preprocessor definition RT_SYSEX_BUFFER_SIZE (set in RtMidi.cpp). The default value is 1024. There is no such limit for outgoing sysex messages via rtmidi::MidiOut. RtMidi was originally developed with Visual C++ version 6.0 but has been tested with Virtual Studio 2010. @@ -432,6 +501,7 @@ In years past, the following people provided bug fixes and improvements:

  • Martin Koegler (various fixes)
  • Immanuel Litzroth (OS-X sysex fix)
  • Jon McCormack (Snow Leopard updates)
  • +
  • Tobias Schlemmer (port descriptor API)
  • Axel Schmidt (client naming)
  • Alexander Svetalkin (JACK MIDI)
  • Casey Tucker (OS-X driver information, sysex sending)
  • @@ -469,3 +539,4 @@ In years past, the following people provided bug fixes and improvements: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + From 832b543fa5ec26becfd09a37d7e034c548e96012 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 11 May 2014 14:39:28 +0200 Subject: [PATCH 041/210] Depricate old API and rename RTMIDI_DUMMY to DUMMY (not in compatiblitiy enum) --- RtMidi.h | 1656 +++++++++++++++++++++--------------------- tests/midiprobe2.cpp | 2 +- 2 files changed, 837 insertions(+), 821 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index d18255ad..851829f9 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -68,13 +68,13 @@ NAMESPACE_RTMIDI_START //! MIDI API specifier arguments. enum ApiType { - UNSPECIFIED, /*!< Search for a working compiled API. */ - MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ - LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ - UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ - WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ - WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ - RTMIDI_DUMMY /*!< A compilable but non-functional API. */ + UNSPECIFIED, /*!< Search for a working compiled API. */ + MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ + LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ + UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ + WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ + WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ + DUMMY /*!< A compilable but non-functional API. */ }; //! User callback function type definition. @@ -100,42 +100,42 @@ typedef void (*MidiCallback)( double timeStamp, std::vector *mess class Error : public std::exception { public: - //! Defined Error types. - enum Type { - WARNING, /*!< A non-critical error. */ - DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ - UNSPECIFIED, /*!< The default, unspecified error type. */ - NO_DEVICES_FOUND, /*!< No devices found on system. */ - INVALID_DEVICE, /*!< An invalid device ID was specified. */ - MEMORY_ERROR, /*!< An error occured during memory allocation. */ - INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ - INVALID_USE, /*!< The function was called incorrectly. */ - DRIVER_ERROR, /*!< A system driver error occured. */ - SYSTEM_ERROR, /*!< A system error occured. */ - THREAD_ERROR /*!< A thread error occured. */ - }; - - //! The constructor. - Error( const std::string& message, Type type = Error::UNSPECIFIED ) throw() : message_(message), type_(type) {} - - //! The destructor. - virtual ~Error( void ) throw() {} - - //! Prints thrown error message to stderr. - virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } - - //! Returns the thrown error message type. - virtual const Type& getType(void) const throw() { return type_; } - - //! Returns the thrown error message string. - virtual const std::string& getMessage(void) const throw() { return message_; } - - //! Returns the thrown error message as a c-style string. - virtual const char* what( void ) const throw() { return message_.c_str(); } + //! Defined Error types. + enum Type { + WARNING, /*!< A non-critical error. */ + DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ + UNSPECIFIED, /*!< The default, unspecified error type. */ + NO_DEVICES_FOUND, /*!< No devices found on system. */ + INVALID_DEVICE, /*!< An invalid device ID was specified. */ + MEMORY_ERROR, /*!< An error occured during memory allocation. */ + INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ + INVALID_USE, /*!< The function was called incorrectly. */ + DRIVER_ERROR, /*!< A system driver error occured. */ + SYSTEM_ERROR, /*!< A system error occured. */ + THREAD_ERROR /*!< A thread error occured. */ + }; + + //! The constructor. + Error( const std::string& message, Type type = Error::UNSPECIFIED ) throw() : message_(message), type_(type) {} + + //! The destructor. + virtual ~Error( void ) throw() {} + + //! Prints thrown error message to stderr. + virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } + + //! Returns the thrown error message type. + virtual const Type& getType(void) const throw() { return type_; } + + //! Returns the thrown error message string. + virtual const std::string& getMessage(void) const throw() { return message_; } + + //! Returns the thrown error message as a c-style string. + virtual const char* what( void ) const throw() { return message_.c_str(); } protected: - std::string message_; - Type type_; + std::string message_; + Type type_; }; //! RtMidi error callback function prototype. @@ -223,785 +223,801 @@ template typedef std::shared_ptr Pointer; #endif -class MidiApi; -class MidiInApi; -class MidiOutApi; - -struct PortDescriptor { - //! Flags for formatting a string description of the port. - /*! These flags just mark the requirements that the string - should fulfil. An API may return the same string for - different requirements e.g. the same short and long - name. */ - enum NamingType { - SHORT_NAME =0, /*!< A short human readable name - depending on the API - e.g. “Ensoniq AudioPCI” */ - LONG_NAME, /*!< A complete human readable - name depending on the API - e.g. "Ensoniq AudioPCI: ES1371" */ - SESSION_PATH, /*!< A unique description that can - be used to identify the port - during runtime. It may be a - cryptic string. */ - STORAGE_PATH, /*!< A unique description that is - optimised for storage in - configuration files. This is a - more textual representation that - is more robust to small changes in - the surrounding environment than - \ref SESSION_PATH */ - NAMING_MASK = 0x0F, /*!< part of the flags - that is concerned with - naming. - */ - UNIQUE_NAME = 0x10, /*!< Make all names uniqe. This - is usually done by adding - numbers to the end of the - string */ - INCLUDE_API = 0x20 /*!< Add a string describing the - API at the beginning of the - string. */ - }; - - //! Flags describing the capabilities of a given port. - enum PortCapabilities { - INPUT = 1, /*!< Ports that can be read from. */ - OUTPUT = 2, /*!< Ports that can be written to. */ - INOUTPUT = 3, /*!< Ports that allow reading and writing (INPUT | OUTPUT) */ - UNLIMITED = 0x10 /*!< Some APIs can filter out certain ports which they consider - not to be useful. This flags supresses this behaviour and - selects all ports that are useable. */ - }; - - //! Default constructor. - /*! - * Derived classes should have a constructor. - */ - PortDescriptor() {}; - - //! A virtual destructor - /*! As we might have to destruct the object from the application code - * each port id must have a virtual destructor. - */ - virtual ~PortDescriptor() {}; - - //! Get the MIDI input api for the current port. - /*! This is the only information RtMidi needs to know: Which - * API should handle this object. This can be used to get - * an API which can send data to the given port. - * - * \param queueSizeLimit The limit of the midi queue. This parameter is handled by - * the constructor of the backend API. - * - * \return API that can use this object to connect to an input port or 0 - * if no input API can be created. - */ - virtual MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) = 0; - - //! Get the MIDI output api for the current port. - /*! This is the only information RtMidi needs to know: Which - * API should handle this object. This can be used to get - * an API which can receive data from the given port. - * - * \return API that can use this object to connect to an output port. - */ - virtual MidiOutApi * getOutputApi() = 0; - - //! Return the port name - /*! - * \param flags A description of the requirements of the returned name. - * \return A name that is formatted according to \ref flags. - * \sa NamingTypes - */ - virtual std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) = 0; - - //! Get capabilities - /*! \return a capabilities flag describing the capabilities of the port. - * \sa PortCapabilities - */ - virtual int getCapabilities() = 0; -}; - -//! A list of port descriptors. -/*! Port descriptors are stored as shared pointers. This avoids - unnecessary duplication of the data structure and handles automatic - deletion if all references have been removed. */ -typedef std::list > PortList; - - - -// **************************************************************** // -// -// MidiInApi / MidiOutApi class declarations. -// -// Subclasses of MidiInApi and MidiOutApi contain all API- and -// OS-specific code necessary to fully implement the RtMidi API. -// -// Note that MidiInApi and MidiOutApi are abstract base classes and -// cannot be explicitly instantiated. MidiIn and MidiOut will -// create instances of a MidiInApi or MidiOutApi subclass. -// -// **************************************************************** // - -class MidiApi -{ -public: - - MidiApi(); - virtual ~MidiApi(); - - //! Pure virtal function to create a virtual port, with optional name. - /*! - This function creates a virtual MIDI port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, any JACK, - and Linux ALSA APIs (the function returns an error for the other APIs). - - \param portName An optional name for the applicaction port that is - used to connect to portId can be specified. - */ - virtual void openVirtualPort( const std::string portName = std::string( "RtMidi virtual port" ) ) = 0; - - //! Pure virtual function to open a MIDI connection given by enumeration number. - /*! \param portNumber An optional port number greater than 0 - can be specified. Otherwise, the default or first port - found is opened. - - \param portName An optional name for the applicaction port - that will be generated to connect to portId can be - specified. - */ - virtual void openPort( unsigned int portNumber = 0, const std::string & portName = std::string( "RtMidi" ) ) = 0; - - //! Pure virtual function to open a MIDI connection given by a port descriptor. - /*! - \param port A port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - */ - virtual void openPort( const PortDescriptor & port, const std::string & portName = std::string( "RtMidi" ) ) = 0; - - //! Open a MIDI connection given by a port descriptor pointer. - /*! - \param port A pointer to a port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - \sa openPort(const PortDescriptor &,const std::string &); - */ - void openPort( Pointer p, const std::string & portName = std::string( "RtMidi" ) ) { - if (!p) { - errorString_ = "MidiApi::openPort: passed NULL pointer"; - error( Error::INVALID_PARAMETER, errorString_ ); - return; - } - openPort(*p, portName); - } - - //! Pure virtual function to return a port descriptor if the port is open - /*! This function returns a port descriptor that can be used to open another port - either to the connected port or – if the backend supports it – the connecting port. - \param local The parameter local defines whether the function returns a descriptor to - the virtual port (true) or the remote port (false). The function returns 0 if the - port cannot be determined (e.g. if the port is not connected or the backend dosen't support it). - */ - virtual Pointer getDescriptor(bool local=false) = 0; - - //! Pure virtual function to return a list of all available ports of the current API. - /*! - \param capabilities an optional parameter that describes which - capabilities the device typu - - \return This function returns a list of port descriptors. - - \note An input API may but need not necessarily report - output devices which cannot be used as input if - \ref 0 is passed as \ref capabilities parameter. - \sa PortDescriptor::PortCapabilitiers - */ - virtual PortList getPortList(int capabilities = 0) = 0; - - //! Pure virtual to return the number of available MIDI ports of the current API. - /*! - \return This function returns the number of MIDI ports of - the selected API. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortName - */ - virtual unsigned int getPortCount() = 0; - - //! Pure virtual function to return a string identifier for the specified MIDI port number. - /*! - \param portNumber Number of the device to be referred to. - \return The name of the port with the given Id is returned. - \retval An empty string is returned if an invalid port specifier is provided. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortCount() - */ - virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; - - //! Pure virtual function to close an open MIDI connection (if one exists). - virtual void closePort( void ) = 0; - - // ! A basic error reporting function for RtMidi classes. - // static void error( Error::Type type, std::string &errorString ); - - //! Pure virtual function to return whether a port is open or not. - /*! \retval true if a port is open and - \retval false if the port is not open (e.g. not opend or closed). - */ - bool isPortOpen() const { return connected_; } - - //! Pure virtual function to set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. - */ - virtual void setErrorCallback( ErrorCallback errorCallback = NULL ); - - - //! Returns the MIDI API specifier for the current instance of RtMidiIn. - virtual ApiType getCurrentApi( void ) throw() = 0; - - //! A basic error reporting function for RtMidi classes. - void error( Error::Type type, std::string errorString ); - -protected: - virtual void initialize( const std::string& clientName ) = 0; - - void *apiData_; - bool connected_; - std::string errorString_; - ErrorCallback errorCallback_; -}; - -class MidiInApi : public MidiApi -{ -public: - - MidiInApi( unsigned int queueSizeLimit ); - virtual ~MidiInApi( void ); - void setCallback( MidiCallback callback, void *userData = 0 ); - void cancelCallback( void ); - virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); - RTMIDI_DEPRECATED(double getMessage( std::vector *message )) - { - if (!message) { - errorString_ = "MidiInApi::getMessage: passed NULL pointer"; - error( Error::WARNING, errorString_ ); - } - return getMessage(*message); - } - double getMessage( std::vector &message ); - - // A MIDI structure used internally by the class to store incoming - // messages. Each message represents one and only one MIDI message. - struct MidiMessage { - std::vector bytes; - double timeStamp; - - // Default constructor. - MidiMessage() - :bytes(0), timeStamp(0.0) {} - }; - - struct MidiQueue { - unsigned int front; - unsigned int back; - unsigned int size; - unsigned int ringSize; - MidiMessage *ring; - - // Default constructor. - MidiQueue() - :front(0), back(0), size(0), ringSize(0) {} - }; - - // The RtMidiInData structure is used to pass private class data to - // the MIDI input handling function or thread. - struct MidiInData { - MidiQueue queue; - MidiMessage message; - unsigned char ignoreFlags; - bool doInput; - bool firstMessage; - void *apiData; - bool usingCallback; - MidiCallback userCallback; - void *userData; - bool continueSysex; - - // Default constructor. - MidiInData() - : ignoreFlags(7), doInput(false), firstMessage(true), - apiData(0), usingCallback(false), userCallback(0), userData(0), - continueSysex(false) {} - }; - -protected: - MidiInData inputData_; -}; - -class MidiOutApi : public MidiApi -{ -public: - - MidiOutApi( void ); - virtual ~MidiOutApi( void ); - RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) - { - if (!message) { - errorString_ = "MidiOutApi::sendMessage: no data in message argument!"; - error( Error::WARNING, errorString_ ); - } - sendMessage(*message); - } - virtual void sendMessage( std::vector &message ) = 0; -}; - - -/*! \class Midi - \brief A global class that implements basic backend API handling. - - This class enhances \ref MidiApi by some functionality to handle - backend API objects. It serves as base class for the public RtMidi - API. - - by Gary P. Scavone, 2003-2014. -*/ -/**********************************************************************/ -class Midi { -public: - typedef rtmidi::ApiType Api; - //! defined for compatibility - enum Api2 { - UNSPECIFIED = rtmidi::UNSPECIFIED, - MACOSX_CORE = rtmidi::MACOSX_CORE, - LINUX_ALSA = rtmidi::LINUX_ALSA, - UNIX_JACK = rtmidi::UNIX_JACK, - WINDOWS_MM = rtmidi::WINDOWS_MM, - WINDOWS_KS = rtmidi::WINDOWS_KS, - RTMIDI_DUMMY = rtmidi::RTMIDI_DUMMY - }; - - - //! A static function to determine the current RtMidi version. - static std::string getVersion( void ) throw(); - - //! A static function to determine the available compiled MIDI APIs. - /*! - The values returned in the std::vector can be compared against - the enumerated list values. Note that there can be more than one - API compiled for certain operating systems. - */ - static void getCompiledApi( std::vector &apis ) throw(); - - //! Returns the MIDI API specifier for the current instance of RtMidiIn. - ApiType getCurrentApi( void ) throw() - { - if (rtapi_) return rtapi_->getCurrentApi(); - else return rtmidi::UNSPECIFIED; - } - - //! Function to create a virtual port, with optional name. - /*! - This function creates a virtual MIDI port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, any JACK, - and Linux ALSA APIs (the function returns an error for the other APIs). - - \param portName An optional name for the applicaction port that is - used to connect to portId can be specified. - */ - void openVirtualPort( const std::string portName = std::string( "RtMidi virtual port" ) ) - { - if (rtapi_) rtapi_->openVirtualPort(portName); - } - - //! Pure virtual function to open a MIDI connection given by enumeration number. - /*! \param portNumber An optional port number greater than 0 - can be specified. Otherwise, the default or first port - found is opened. - - \param portName An optional name for the applicaction port - that will be generated to connect to portId can be - specified. - */ - void openPort( unsigned int portNumber = 0, - const std::string portName = std::string( "RtMidi" ) ) - { - if (rtapi_) rtapi_->openPort(portNumber,portName); - } - - //! Pure virtual function to open a MIDI connection given by a port descriptor. - /*! - \param port A port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - */ - void openPort( const PortDescriptor & port, - const std::string & portName = std::string( "RtMidi" ) ) - { - if (rtapi_) rtapi_->openPort(port,portName); - } - - //! Open a MIDI connection given by a port descriptor pointer. - /*! - \param port A pointer to a port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - \sa openPort(const PortDescriptor &,const std::string &); - */ - void openPort( Pointer p, - const std::string & portName = std::string( "RtMidi" ) ) { - if (!p) { - error( Error::INVALID_PARAMETER, "MidiApi::openPort: passed NULL pointer" ); - return; - } - openPort(*p, portName); - } - - //! Pure virtual function to return a port descirptor if the port is open - Pointer getDescriptor(bool local=false) - { - if (rtapi_) return rtapi_->getDescriptor(local); - return 0; - } - - //! Return a list of all available ports of the current API. - /*! - \param capabilities an optional parameter that - describes which capabilities the returned devices - must support. The returned devices may have - additional capabilities to those which have been - requested, but not less. - - \return This function returns a list of port descriptors. - - \note Each API will request additonal - capabilites. An output API will set always add \ref - PortDescriptor::OUTPUT to the mask while an input - device will always add \ref PortDescriptor::OUTPUT. - - \note An input API may but need not necessarily - report output devices which cannot be used as input - if \ref PortDescriptor::OUTPUT is passed as \ref - capabilities parameter. - */ - PortList getPortList(int capabilities = 0) - { - if (rtapi_) return rtapi_->getPortList(capabilities); - return PortList(); - } - - //! Pure virtual to return the number of available MIDI ports of the current API. - /*! - \return This function returns the number of MIDI ports of - the selected API. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortName - */ - unsigned int getPortCount() - { - if (rtapi_) return rtapi_->getPortCount(); - return 0; - } - - //! Pure virtual function to return a string identifier for the specified MIDI port number. - /*! - \param portNumber Number of the device to be referred to. - \return The name of the port with the given Id is returned. - \retval An empty string is returned if an invalid port specifier is provided. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortCount() - */ - std::string getPortName( unsigned int portNumber = 0 ) - { - if (rtapi_) return rtapi_->getPortName(portNumber); - return ""; - } - - //! Close an open MIDI connection (if one exists). - void closePort( void ) - { - if (rtapi_) rtapi_->closePort(); - } - - // ! A basic error reporting function for RtMidi classes. - // static void error( Error::Type type, std::string &errorString ); - - //! Pure virtual function to return whether a port is open or not. - /*! \retval true if a port is open and - \retval false if the port is not open (e.g. not opend or closed). - */ - bool isPortOpen( void ) const - { - if (rtapi_) return rtapi_->isPortOpen(); - return false; - } - - //! Pure virtual function to set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. - */ - void setErrorCallback( ErrorCallback errorCallback = NULL ) - { - if (rtapi_) rtapi_->setErrorCallback(errorCallback); - } - - //! A basic error reporting function for RtMidi classes. - void error( Error::Type type, std::string errorString ); -protected: - MidiApi *rtapi_; - - Midi():rtapi_(0) {} - ~Midi() - { - if (rtapi_) { - delete rtapi_; - rtapi_ = 0; - } - } -}; - -/**********************************************************************/ -/*! \class MidiIn - \brief A realtime MIDI input class. - - This class provides a common, platform-independent API for - realtime MIDI input. It allows access to a single MIDI input - port. Incoming MIDI messages are either saved to a queue for - retrieval using the getMessage() function or immediately passed to - a user-specified callback function. Create multiple instances of - this class to connect to more than one MIDI device at the same - time. With the OS-X and Linux ALSA 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-2014. -*/ -/**********************************************************************/ - -// **************************************************************** // -// -// MidiIn and MidiOut class declarations. -// -// MidiIn / MidiOut are "controllers" used to select an available -// MIDI input or output interface. They present common APIs for the -// user to call but all functionality is implemented by the classes -// MidiInApi, MidiOutApi and their subclasses. MidiIn and MidiOut -// each create an instance of a MidiInApi or MidiOutApi subclass based -// on the user's API choice. If no choice is made, they attempt to -// make a "logical" API selection. -// -// **************************************************************** // - -class MidiIn : public Midi -{ -public: - - - //! Default constructor that allows an optional api, client name and queue size. - /*! - An exception will be thrown if a MIDI system initialization - error occurs. The queue size defines the maximum number of - messages that can be held in the MIDI queue (when not using a - callback function). If the queue size limit is reached, - incoming messages will be ignored. - - If no API argument is specified and multiple API support has been - compiled, the default order of use is JACK, ALSA (Linux) and CORE, - JACK (OS-X). - - \param api An optional API id can be specified. - \param clientName An optional Client name can be specified. This - will be used to group the ports that are created - by the application. - \param queueSizeLimit An optional size of the MIDI input queue can be specified. - */ - MidiIn( ApiType api=rtmidi::UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Input Client"), - unsigned int queueSizeLimit = 100 ); - - //! If a MIDI connection is still open, it will be closed by the destructor. - ~MidiIn ( void ) throw(); - - //! Set a callback function to be invoked for incoming MIDI messages. - /*! - The callback function will be called whenever an incoming MIDI - message is received. While not absolutely necessary, it is best - to set the callback function before opening a MIDI port to avoid - leaving some messages in the queue. - - \param callback A callback function must be given. - \param userData Opitionally, a pointer to additional data can be - passed to the callback function whenever it is called. - */ - void setCallback( MidiCallback callback, void *userData = 0 ) - { - if (rtapi_) - static_cast(rtapi_)->setCallback(callback,userData); - } - - //! Cancel use of the current callback function (if one exists). - /*! - Subsequent incoming MIDI messages will be written to the queue - and can be retrieved with the \e getMessage function. - */ - void cancelCallback() - { - if (rtapi_) - static_cast(rtapi_)->cancelCallback(); - } - - //! Specify whether certain MIDI message types should be queued or ignored during input. - /*! - By default, MIDI timing and active sensing messages are ignored - during message input because of their relative high data rates. - MIDI sysex messages are ignored by default as well. Variable - values of "true" imply that the respective message type will be - ignored. - */ - void ignoreTypes( bool midiSysex = true, - bool midiTime = true, - bool midiSense = true ) - { - if (rtapi_) - static_cast(rtapi_)->ignoreTypes(midiSysex, midiTime, midiSense); - } - - //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. - /*! - This function returns immediately whether a new message is - available or not. A valid message is indicated by a non-zero - vector size. An exception is thrown if an error occurs during - message retrieval or an input connection was not previously - established. - */ - double getMessage( std::vector &message ) - { - if (rtapi_) - return static_cast(rtapi_)->getMessage(message); - std::string errorString_ = "MidiIn::getMessage: No valid API found."; - error( Error::WARNING, errorString_ ); - return 0.0; - } - - //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. - /*! - This function returns immediately whether a new message is - available or not. A valid message is indicated by a non-zero - vector size. An exception is thrown if an error occurs during - message retrieval or an input connection was not previously - established. - - \deprecated - */ - RTMIDI_DEPRECATED(double getMessage( std::vector *message )) - { - if (!message) { - error( Error::WARNING, - "MidiIn::getMessage: passed NULL pointer"); - } - if (rtapi_) - return static_cast(rtapi_)->getMessage(*message); - error( Error::WARNING, - "MidiIn::getMessage: No valid API found."); - return 0.0; - } - -protected: - void openMidiApi( ApiType api, const std::string clientName, unsigned int queueSizeLimit ); - -}; - -/**********************************************************************/ -/*! \class MidiOut - \brief A realtime MIDI output class. - - This class provides a common, platform-independent API for MIDI - output. It allows one to probe available MIDI output ports, to - connect to one such port, and to send MIDI bytes immediately over - the connection. Create multiple instances of this class to - connect to more than one MIDI device at the same time. With the - OS-X and Linux ALSA MIDI APIs, it is also possible to open a - virtual port to which other MIDI software clients can connect. - - by Gary P. Scavone, 2003-2014. -*/ -/**********************************************************************/ - -class MidiOut : public Midi -{ -public: - - //! Default constructor that allows an optional client name. - /*! - An exception will be thrown if a MIDI system initialization error occurs. - - If no API argument is specified and multiple API support has been - compiled, the default order of use is JACK, ALSA (Linux) and CORE, - JACK (OS-X). - */ - MidiOut( ApiType api=rtmidi::UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Output Client") ); - - //! The destructor closes any open MIDI connections. - ~MidiOut( void ) throw(); - - //! Immediately send a single message out an open MIDI output port. - /*! - An exception is thrown if an error occurs during output or an - output connection was not previously established. - - \deprecated - */ - RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) - { - if (!message) { - error( Error::WARNING, - "MidiOutApi::sendMessage: no data in message argument!"); - } - if (rtapi_) - static_cast(rtapi_)->sendMessage(*message); - else - error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); - } - - - //! Immediately send a single message out an open MIDI output port. - /*! - An exception is thrown if an error occurs during output or an - output connection was not previously established. - */ - void sendMessage( std::vector &message ) { - if (rtapi_) - static_cast(rtapi_)->sendMessage(message); - error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); - } -protected: - void openMidiApi( ApiType api, const std::string clientName ); -}; - - -// **************************************************************** // -// -// MidiInApi and MidiOutApi subclass prototypes. -// -// **************************************************************** // + class MidiApi; + class MidiInApi; + class MidiOutApi; + + struct PortDescriptor { + //! Flags for formatting a string description of the port. + /*! These flags just mark the requirements that the string + should fulfil. An API may return the same string for + different requirements e.g. the same short and long + name. */ + enum NamingType { + SHORT_NAME =0, /*!< A short human readable name + depending on the API + e.g. “Ensoniq AudioPCI” */ + LONG_NAME, /*!< A complete human readable + name depending on the API + e.g. "Ensoniq AudioPCI: ES1371" */ + SESSION_PATH, /*!< A unique description that can + be used to identify the port + during runtime. It may be a + cryptic string. */ + STORAGE_PATH, /*!< A unique description that is + optimised for storage in + configuration files. This is a + more textual representation that + is more robust to small changes in + the surrounding environment than + \ref SESSION_PATH */ + NAMING_MASK = 0x0F, /*!< part of the flags + that is concerned with + naming. + */ + UNIQUE_NAME = 0x10, /*!< Make all names uniqe. This + is usually done by adding + numbers to the end of the + string */ + INCLUDE_API = 0x20 /*!< Add a string describing the + API at the beginning of the + string. */ + }; + + //! Flags describing the capabilities of a given port. + enum PortCapabilities { + INPUT = 1, /*!< Ports that can be read from. */ + OUTPUT = 2, /*!< Ports that can be written to. */ + INOUTPUT = 3, /*!< Ports that allow reading and writing (INPUT | OUTPUT) */ + UNLIMITED = 0x10 /*!< Some APIs can filter out certain ports which they consider + not to be useful. This flags supresses this behaviour and + selects all ports that are useable. */ + }; + + //! Default constructor. + /*! + * Derived classes should have a constructor. + */ + PortDescriptor() {}; + + //! A virtual destructor + /*! As we might have to destruct the object from the application code + * each port id must have a virtual destructor. + */ + virtual ~PortDescriptor() {}; + + //! Get the MIDI input api for the current port. + /*! This is the only information RtMidi needs to know: Which + * API should handle this object. This can be used to get + * an API which can send data to the given port. + * + * \param queueSizeLimit The limit of the midi queue. This parameter is handled by + * the constructor of the backend API. + * + * \return API that can use this object to connect to an input port or 0 + * if no input API can be created. + */ + virtual MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) = 0; + + //! Get the MIDI output api for the current port. + /*! This is the only information RtMidi needs to know: Which + * API should handle this object. This can be used to get + * an API which can receive data from the given port. + * + * \return API that can use this object to connect to an output port. + */ + virtual MidiOutApi * getOutputApi() = 0; + + //! Return the port name + /*! + * \param flags A description of the requirements of the returned name. + * \return A name that is formatted according to \ref flags. + * \sa NamingTypes + */ + virtual std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) = 0; + + //! Get capabilities + /*! \return a capabilities flag describing the capabilities of the port. + * \sa PortCapabilities + */ + virtual int getCapabilities() = 0; + }; + + //! A list of port descriptors. + /*! Port descriptors are stored as shared pointers. This avoids + unnecessary duplication of the data structure and handles automatic + deletion if all references have been removed. */ + typedef std::list > PortList; + + + + // **************************************************************** // + // + // MidiInApi / MidiOutApi class declarations. + // + // Subclasses of MidiInApi and MidiOutApi contain all API- and + // OS-specific code necessary to fully implement the RtMidi API. + // + // Note that MidiInApi and MidiOutApi are abstract base classes and + // cannot be explicitly instantiated. MidiIn and MidiOut will + // create instances of a MidiInApi or MidiOutApi subclass. + // + // **************************************************************** // + + class MidiApi + { + public: + + MidiApi(); + virtual ~MidiApi(); + + //! Pure virtal function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + */ + virtual void openVirtualPort( const std::string portName = std::string( "RtMidi virtual port" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. + + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. + */ + virtual void openPort( unsigned int portNumber = 0, const std::string & portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + virtual void openPort( const PortDescriptor & port, const std::string & portName = std::string( "RtMidi" ) ) = 0; + + //! Open a MIDI connection given by a port descriptor pointer. + /*! + \param port A pointer to a port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + \sa openPort(const PortDescriptor &,const std::string &); + */ + void openPort( Pointer p, const std::string & portName = std::string( "RtMidi" ) ) { + if (!p) { + errorString_ = "MidiApi::openPort: passed NULL pointer"; + error( Error::INVALID_PARAMETER, errorString_ ); + return; + } + openPort(*p, portName); + } + + //! Pure virtual function to return a port descriptor if the port is open + /*! This function returns a port descriptor that can be used to open another port + either to the connected port or – if the backend supports it – the connecting port. + \param local The parameter local defines whether the function returns a descriptor to + the virtual port (true) or the remote port (false). The function returns 0 if the + port cannot be determined (e.g. if the port is not connected or the backend dosen't support it). + */ + virtual Pointer getDescriptor(bool local=false) = 0; + + //! Pure virtual function to return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that describes which + capabilities the device typu + + \return This function returns a list of port descriptors. + + \note An input API may but need not necessarily report + output devices which cannot be used as input if + \ref 0 is passed as \ref capabilities parameter. + \sa PortDescriptor::PortCapabilitiers + */ + virtual PortList getPortList(int capabilities = 0) = 0; + + //! Pure virtual to return the number of available MIDI ports of the current API. + /*! + \return This function returns the number of MIDI ports of + the selected API. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortName + */ + virtual unsigned int getPortCount() = 0; + + //! Pure virtual function to return a string identifier for the specified MIDI port number. + /*! + \param portNumber Number of the device to be referred to. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortCount() + */ + virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; + + //! Pure virtual function to close an open MIDI connection (if one exists). + virtual void closePort( void ) = 0; + + // ! A basic error reporting function for RtMidi classes. + // static void error( Error::Type type, std::string &errorString ); + + //! Pure virtual function to return whether a port is open or not. + /*! \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). + */ + bool isPortOpen() const { return connected_; } + + //! Pure virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + virtual void setErrorCallback( ErrorCallback errorCallback = NULL ); + + + //! Returns the MIDI API specifier for the current instance of RtMidiIn. + virtual ApiType getCurrentApi( void ) throw() = 0; + + //! A basic error reporting function for RtMidi classes. + void error( Error::Type type, std::string errorString ); + + protected: + virtual void initialize( const std::string& clientName ) = 0; + + void *apiData_; + bool connected_; + std::string errorString_; + ErrorCallback errorCallback_; + }; + + class MidiInApi : public MidiApi + { + public: + + MidiInApi( unsigned int queueSizeLimit ); + virtual ~MidiInApi( void ); + void setCallback( MidiCallback callback, void *userData = 0 ); + void cancelCallback( void ); + virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); + RTMIDI_DEPRECATED(double getMessage( std::vector *message )) + { + if (!message) { + errorString_ = "MidiInApi::getMessage: passed NULL pointer"; + error( Error::WARNING, errorString_ ); + } + return getMessage(*message); + } + double getMessage( std::vector &message ); + + // A MIDI structure used internally by the class to store incoming + // messages. Each message represents one and only one MIDI message. + struct MidiMessage { + std::vector bytes; + double timeStamp; + + // Default constructor. + MidiMessage() + :bytes(0), timeStamp(0.0) {} + }; + + struct MidiQueue { + unsigned int front; + unsigned int back; + unsigned int size; + unsigned int ringSize; + MidiMessage *ring; + + // Default constructor. + MidiQueue() + :front(0), back(0), size(0), ringSize(0) {} + }; + + // The RtMidiInData structure is used to pass private class data to + // the MIDI input handling function or thread. + struct MidiInData { + MidiQueue queue; + MidiMessage message; + unsigned char ignoreFlags; + bool doInput; + bool firstMessage; + void *apiData; + bool usingCallback; + MidiCallback userCallback; + void *userData; + bool continueSysex; + + // Default constructor. + MidiInData() + : ignoreFlags(7), doInput(false), firstMessage(true), + apiData(0), usingCallback(false), userCallback(0), userData(0), + continueSysex(false) {} + }; + + protected: + MidiInData inputData_; + }; + + class MidiOutApi : public MidiApi + { + public: + + MidiOutApi( void ); + virtual ~MidiOutApi( void ); + RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) + { + if (!message) { + errorString_ = "MidiOutApi::sendMessage: no data in message argument!"; + error( Error::WARNING, errorString_ ); + } + sendMessage(*message); + } + virtual void sendMessage( std::vector &message ) = 0; + }; + + + /*! \class Midi + \brief A global class that implements basic backend API handling. + + This class enhances \ref MidiApi by some functionality to handle + backend API objects. It serves as base class for the public RtMidi + API. + + by Gary P. Scavone, 2003-2014. + */ + /**********************************************************************/ + class Midi { + public: + typedef rtmidi::ApiType Api; + //! defined for compatibility + enum Api2 { + UNSPECIFIED = rtmidi::UNSPECIFIED, + MACOSX_CORE = rtmidi::MACOSX_CORE, + LINUX_ALSA = rtmidi::LINUX_ALSA, + UNIX_JACK = rtmidi::UNIX_JACK, + WINDOWS_MM = rtmidi::WINDOWS_MM, + WINDOWS_KS = rtmidi::WINDOWS_KS, + RTMIDI_DUMMY = rtmidi::DUMMY + }; + + + //! A static function to determine the current RtMidi version. + static std::string getVersion( void ) throw(); + + //! A static function to determine the available compiled MIDI APIs. + /*! + The values returned in the std::vector can be compared against + the enumerated list values. Note that there can be more than one + API compiled for certain operating systems. + */ + static void getCompiledApi( std::vector &apis ) throw(); + + //! A static function to determine the available compiled MIDI APIs. + /*! + The values returned in the std::vector can be compared against + the enumerated list values. Note that there can be more than one + API compiled for certain operating systems. + */ + static std::vector getCompiledApi( ) throw() { + std::vector apis; + getCompiledApi(apis); + return apis; + } + + //! Returns the MIDI API specifier for the current instance of RtMidiIn. + ApiType getCurrentApi( void ) throw() + { + if (rtapi_) return rtapi_->getCurrentApi(); + else return rtmidi::UNSPECIFIED; + } + + //! Function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + */ + void openVirtualPort( const std::string portName = std::string( "RtMidi virtual port" ) ) + { + if (rtapi_) rtapi_->openVirtualPort(portName); + } + + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. + + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. + + \deprecated + */ + RTMIDI_DEPRECATED(void openPort( unsigned int portNumber = 0, + const std::string portName = std::string( "RtMidi" ) )) + { + if (rtapi_) rtapi_->openPort(portNumber,portName); + } + + //! Pure virtual function to open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + void openPort( const PortDescriptor & port, + const std::string & portName = std::string( "RtMidi" ) ) + { + if (rtapi_) rtapi_->openPort(port,portName); + } + + //! Open a MIDI connection given by a port descriptor pointer. + /*! + \param port A pointer to a port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + \sa openPort(const PortDescriptor &,const std::string &); + */ + void openPort( Pointer p, + const std::string & portName = std::string( "RtMidi" ) ) { + if (!p) { + error( Error::INVALID_PARAMETER, "MidiApi::openPort: passed NULL pointer" ); + return; + } + openPort(*p, portName); + } + + //! Pure virtual function to return a port descirptor if the port is open + Pointer getDescriptor(bool local=false) + { + if (rtapi_) return rtapi_->getDescriptor(local); + return 0; + } + + //! Return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that + describes which capabilities the returned devices + must support. The returned devices may have + additional capabilities to those which have been + requested, but not less. + + \return This function returns a list of port descriptors. + + \note Each API will request additonal + capabilites. An output API will set always add \ref + PortDescriptor::OUTPUT to the mask while an input + device will always add \ref PortDescriptor::OUTPUT. + + \note An input API may but need not necessarily + report output devices which cannot be used as input + if \ref PortDescriptor::OUTPUT is passed as \ref + capabilities parameter. + */ + PortList getPortList(int capabilities = 0) + { + if (rtapi_) return rtapi_->getPortList(capabilities); + return PortList(); + } + + //! Pure virtual to return the number of available MIDI ports of the current API. + /*! + \return This function returns the number of MIDI ports of + the selected API. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortName + \deprecated + */ + RTMIDI_DEPRECATED(unsigned int getPortCount()) + { + if (rtapi_) return rtapi_->getPortCount(); + return 0; + } + + //! Pure virtual function to return a string identifier for the specified MIDI port number. + /*! + \param portNumber Number of the device to be referred to. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortCount() + \deprecated + */ + RTMIDI_DEPRECATED(std::string getPortName( unsigned int portNumber = 0 )) + { + if (rtapi_) return rtapi_->getPortName(portNumber); + return ""; + } + + //! Close an open MIDI connection (if one exists). + void closePort( void ) + { + if (rtapi_) rtapi_->closePort(); + } + + // ! A basic error reporting function for RtMidi classes. + // static void error( Error::Type type, std::string &errorString ); + + //! Pure virtual function to return whether a port is open or not. + /*! \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). + */ + bool isPortOpen( void ) const + { + if (rtapi_) return rtapi_->isPortOpen(); + return false; + } + + //! Pure virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + void setErrorCallback( ErrorCallback errorCallback = NULL ) + { + if (rtapi_) rtapi_->setErrorCallback(errorCallback); + } + + //! A basic error reporting function for RtMidi classes. + void error( Error::Type type, std::string errorString ); + protected: + MidiApi *rtapi_; + + Midi():rtapi_(0) {} + ~Midi() + { + if (rtapi_) { + delete rtapi_; + rtapi_ = 0; + } + } + }; + + /**********************************************************************/ + /*! \class MidiIn + \brief A realtime MIDI input class. + + This class provides a common, platform-independent API for + realtime MIDI input. It allows access to a single MIDI input + port. Incoming MIDI messages are either saved to a queue for + retrieval using the getMessage() function or immediately passed to + a user-specified callback function. Create multiple instances of + this class to connect to more than one MIDI device at the same + time. With the OS-X and Linux ALSA 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-2014. + */ + /**********************************************************************/ + + // **************************************************************** // + // + // MidiIn and MidiOut class declarations. + // + // MidiIn / MidiOut are "controllers" used to select an available + // MIDI input or output interface. They present common APIs for the + // user to call but all functionality is implemented by the classes + // MidiInApi, MidiOutApi and their subclasses. MidiIn and MidiOut + // each create an instance of a MidiInApi or MidiOutApi subclass based + // on the user's API choice. If no choice is made, they attempt to + // make a "logical" API selection. + // + // **************************************************************** // + + class MidiIn : public Midi + { + public: + + + //! Default constructor that allows an optional api, client name and queue size. + /*! + An exception will be thrown if a MIDI system initialization + error occurs. The queue size defines the maximum number of + messages that can be held in the MIDI queue (when not using a + callback function). If the queue size limit is reached, + incoming messages will be ignored. + + If no API argument is specified and multiple API support has been + compiled, the default order of use is JACK, ALSA (Linux) and CORE, + JACK (OS-X). + + \param api An optional API id can be specified. + \param clientName An optional Client name can be specified. This + will be used to group the ports that are created + by the application. + \param queueSizeLimit An optional size of the MIDI input queue can be specified. + */ + MidiIn( ApiType api=rtmidi::UNSPECIFIED, + const std::string clientName = std::string( "RtMidi Input Client"), + unsigned int queueSizeLimit = 100 ); + + //! If a MIDI connection is still open, it will be closed by the destructor. + ~MidiIn ( void ) throw(); + + //! Set a callback function to be invoked for incoming MIDI messages. + /*! + The callback function will be called whenever an incoming MIDI + message is received. While not absolutely necessary, it is best + to set the callback function before opening a MIDI port to avoid + leaving some messages in the queue. + + \param callback A callback function must be given. + \param userData Opitionally, a pointer to additional data can be + passed to the callback function whenever it is called. + */ + void setCallback( MidiCallback callback, void *userData = 0 ) + { + if (rtapi_) + static_cast(rtapi_)->setCallback(callback,userData); + } + + //! Cancel use of the current callback function (if one exists). + /*! + Subsequent incoming MIDI messages will be written to the queue + and can be retrieved with the \e getMessage function. + */ + void cancelCallback() + { + if (rtapi_) + static_cast(rtapi_)->cancelCallback(); + } + + //! Specify whether certain MIDI message types should be queued or ignored during input. + /*! + By default, MIDI timing and active sensing messages are ignored + during message input because of their relative high data rates. + MIDI sysex messages are ignored by default as well. Variable + values of "true" imply that the respective message type will be + ignored. + */ + void ignoreTypes( bool midiSysex = true, + bool midiTime = true, + bool midiSense = true ) + { + if (rtapi_) + static_cast(rtapi_)->ignoreTypes(midiSysex, midiTime, midiSense); + } + + //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. + /*! + This function returns immediately whether a new message is + available or not. A valid message is indicated by a non-zero + vector size. An exception is thrown if an error occurs during + message retrieval or an input connection was not previously + established. + */ + double getMessage( std::vector &message ) + { + if (rtapi_) + return static_cast(rtapi_)->getMessage(message); + std::string errorString_ = "MidiIn::getMessage: No valid API found."; + error( Error::WARNING, errorString_ ); + return 0.0; + } + + //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. + /*! + This function returns immediately whether a new message is + available or not. A valid message is indicated by a non-zero + vector size. An exception is thrown if an error occurs during + message retrieval or an input connection was not previously + established. + + \deprecated + */ + RTMIDI_DEPRECATED(double getMessage( std::vector *message )) + { + if (!message) { + error( Error::WARNING, + "MidiIn::getMessage: passed NULL pointer"); + } + if (rtapi_) + return static_cast(rtapi_)->getMessage(*message); + error( Error::WARNING, + "MidiIn::getMessage: No valid API found."); + return 0.0; + } + + protected: + void openMidiApi( ApiType api, const std::string clientName, unsigned int queueSizeLimit ); + + }; + + /**********************************************************************/ + /*! \class MidiOut + \brief A realtime MIDI output class. + + This class provides a common, platform-independent API for MIDI + output. It allows one to probe available MIDI output ports, to + connect to one such port, and to send MIDI bytes immediately over + the connection. Create multiple instances of this class to + connect to more than one MIDI device at the same time. With the + OS-X and Linux ALSA MIDI APIs, it is also possible to open a + virtual port to which other MIDI software clients can connect. + + by Gary P. Scavone, 2003-2014. + */ + /**********************************************************************/ + + class MidiOut : public Midi + { + public: + + //! Default constructor that allows an optional client name. + /*! + An exception will be thrown if a MIDI system initialization error occurs. + + If no API argument is specified and multiple API support has been + compiled, the default order of use is JACK, ALSA (Linux) and CORE, + JACK (OS-X). + */ + MidiOut( ApiType api=rtmidi::UNSPECIFIED, + const std::string clientName = std::string( "RtMidi Output Client") ); + + //! The destructor closes any open MIDI connections. + ~MidiOut( void ) throw(); + + //! Immediately send a single message out an open MIDI output port. + /*! + An exception is thrown if an error occurs during output or an + output connection was not previously established. + + \deprecated + */ + RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) + { + if (!message) { + error( Error::WARNING, + "MidiOutApi::sendMessage: no data in message argument!"); + } + if (rtapi_) + static_cast(rtapi_)->sendMessage(*message); + else + error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); + } + + + //! Immediately send a single message out an open MIDI output port. + /*! + An exception is thrown if an error occurs during output or an + output connection was not previously established. + */ + void sendMessage( std::vector &message ) { + if (rtapi_) + static_cast(rtapi_)->sendMessage(message); + error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); + } + protected: + void openMidiApi( ApiType api, const std::string clientName ); + }; + + + // **************************************************************** // + // + // MidiInApi and MidiOutApi subclass prototypes. + // + // **************************************************************** // #if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__) #define __RTMIDI_DUMMY__ diff --git a/tests/midiprobe2.cpp b/tests/midiprobe2.cpp index 85fc8633..f5b9386b 100644 --- a/tests/midiprobe2.cpp +++ b/tests/midiprobe2.cpp @@ -20,7 +20,7 @@ int main() apiMap[rtmidi::WINDOWS_KS] = "Windows Kernel Straming"; apiMap[rtmidi::UNIX_JACK] = "Jack Client"; apiMap[rtmidi::LINUX_ALSA] = "Linux ALSA"; - apiMap[rtmidi::RTMIDI_DUMMY] = "RtMidi Dummy"; + apiMap[rtmidi::DUMMY] = "RtMidi Dummy"; std::vector< rtmidi::ApiType > apis; rtmidi::Midi :: getCompiledApi( apis ); From 0d5b881640561351e1d9c375225157d6a63ad59f Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 8 Aug 2018 15:38:31 +0200 Subject: [PATCH 042/210] Some whitespace fixes # Conflicts: # RtMidi.cpp --- RtMidi.cpp | 35 +- RtMidi.h | 1672 ++++++++++++++++++++++++++-------------------------- 2 files changed, 853 insertions(+), 854 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index a64ec026..3d33114c 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -41,7 +41,7 @@ #include #include -NAMSPACE_RTMIDI_START +NAMESPACE_RTMIDI_START //*********************************************************************// // Midi Definitions //*********************************************************************// @@ -405,7 +405,7 @@ static inline std::string &rtrim(std::string &s) { static inline std::string &trim(std::string &s) { return ltrim(rtrim(s)); } -NAMSPACE_RTMIDI_END +NAMESPACE_RTMIDI_END // *************************************************** // // @@ -425,7 +425,7 @@ NAMSPACE_RTMIDI_END #include -NAMSPACE_RTMIDI_START +NAMESPACE_RTMIDI_START /*! An abstraction layer for the CORE sequencer layer. It provides the following functionality: - dynamic allocation of the sequencer @@ -1310,14 +1310,14 @@ struct CorePortDescriptor:public PortDescriptor { } ~CorePortDescriptor() {} - MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) { + MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) const { if (getCapabilities() & INPUT) return new MidiInCore(clientName,queueSizeLimit); else return 0; } - MidiOutApi * getOutputApi() { + MidiOutApi * getOutputApi() const { if (getCapabilities() & OUTPUT) return new MidiOutCore(clientName); else @@ -1340,7 +1340,7 @@ struct CorePortDescriptor:public PortDescriptor { const std::string & getClientName() { return clientName; } - int getCapabilities() { + int getCapabilities() const { if (!endpoint) return 0; return seq.getPortCapabilities(endpoint); } @@ -2098,7 +2098,7 @@ void MidiOutCore :: sendMessage( std::vector &message ) } } } -NAMSPACE_RTMIDI_END +NAMESPACE_RTMIDI_END #endif // __MACOSX_CORE__ @@ -2127,7 +2127,7 @@ NAMSPACE_RTMIDI_END // ALSA header file. #include -NAMSPACE_RTMIDI_START +NAMESPACE_RTMIDI_START struct AlsaMidiData; /*! An abstraction layer for the ALSA sequencer layer. It provides @@ -2413,13 +2413,13 @@ struct AlsaPortDescriptor:public PortDescriptor, seq.setName(name); } ~AlsaPortDescriptor() {} - MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) { + MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) const { if (getCapabilities() & INPUT) return new MidiInAlsa(clientName,queueSizeLimit); else return 0; } - MidiOutApi * getOutputApi() { + MidiOutApi * getOutputApi() const { if (getCapabilities() & OUTPUT) return new MidiOutAlsa(clientName); else @@ -2432,7 +2432,7 @@ struct AlsaPortDescriptor:public PortDescriptor, const std::string & getClientName() { return clientName; } - int getCapabilities() { + int getCapabilities() const { if (!client) return 0; return seq.getPortCapabilities(client,port); } @@ -2444,7 +2444,6 @@ struct AlsaPortDescriptor:public PortDescriptor, LockingAlsaSequencer AlsaPortDescriptor::seq; - PortList AlsaPortDescriptor :: getPortList(int capabilities, const std::string & clientName) { PortList list; @@ -3517,7 +3516,7 @@ PortList MidiOutAlsa :: getPortList(int capabilities) return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT, data->getClientName()); } -NAMSPACE_RTMIDI_END +NAMESPACE_RTMIDI_END #endif // __LINUX_ALSA__ @@ -4060,7 +4059,7 @@ NAMESPACE_RTMIDI_END #define JACK_RINGBUFFER_SIZE 16384 // Default size for ringbuffer -NAMSPACE_RTMIDI_START +NAMESPACE_RTMIDI_START struct JackMidiData; static int jackProcessIn( jack_nframes_t nframes, void *arg ); @@ -4330,13 +4329,13 @@ struct JackPortDescriptor:public PortDescriptor ~JackPortDescriptor() { } - MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) { + MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) const { if (getCapabilities() & INPUT) return new MidiInJack(clientName,queueSizeLimit); else return 0; } - MidiOutApi * getOutputApi() { + MidiOutApi * getOutputApi() const { if (getCapabilities() & OUTPUT) return new MidiOutJack(clientName); else @@ -4351,7 +4350,7 @@ struct JackPortDescriptor:public PortDescriptor const std::string & getClientName() { return clientName; } - int getCapabilities() { + int getCapabilities() const { return seq.getPortCapabilities(port); } static PortList getPortList(int capabilities, const std::string & clientName); @@ -5024,6 +5023,6 @@ void MidiOutJack :: sendMessage( std::vector &message ) message.size() ); jack_ringbuffer_write( data->buffSize, ( char * ) &nBytes, sizeof( nBytes ) ); } -NAMSPACE_RTMIDI_END +NAMESPACE_RTMIDI_END #endif // __UNIX_JACK__ diff --git a/RtMidi.h b/RtMidi.h index 851829f9..9d1981f3 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -68,13 +68,13 @@ NAMESPACE_RTMIDI_START //! MIDI API specifier arguments. enum ApiType { - UNSPECIFIED, /*!< Search for a working compiled API. */ - MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ - LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ - UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ - WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ - WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ - DUMMY /*!< A compilable but non-functional API. */ + UNSPECIFIED, /*!< Search for a working compiled API. */ + MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ + LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ + UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ + WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ + WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ + DUMMY /*!< A compilable but non-functional API. */ }; //! User callback function type definition. @@ -100,42 +100,42 @@ typedef void (*MidiCallback)( double timeStamp, std::vector *mess class Error : public std::exception { public: - //! Defined Error types. - enum Type { - WARNING, /*!< A non-critical error. */ - DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ - UNSPECIFIED, /*!< The default, unspecified error type. */ - NO_DEVICES_FOUND, /*!< No devices found on system. */ - INVALID_DEVICE, /*!< An invalid device ID was specified. */ - MEMORY_ERROR, /*!< An error occured during memory allocation. */ - INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ - INVALID_USE, /*!< The function was called incorrectly. */ - DRIVER_ERROR, /*!< A system driver error occured. */ - SYSTEM_ERROR, /*!< A system error occured. */ - THREAD_ERROR /*!< A thread error occured. */ - }; - - //! The constructor. - Error( const std::string& message, Type type = Error::UNSPECIFIED ) throw() : message_(message), type_(type) {} - - //! The destructor. - virtual ~Error( void ) throw() {} - - //! Prints thrown error message to stderr. - virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } - - //! Returns the thrown error message type. - virtual const Type& getType(void) const throw() { return type_; } - - //! Returns the thrown error message string. - virtual const std::string& getMessage(void) const throw() { return message_; } - - //! Returns the thrown error message as a c-style string. - virtual const char* what( void ) const throw() { return message_.c_str(); } + //! Defined Error types. + enum Type { + WARNING, /*!< A non-critical error. */ + DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ + UNSPECIFIED, /*!< The default, unspecified error type. */ + NO_DEVICES_FOUND, /*!< No devices found on system. */ + INVALID_DEVICE, /*!< An invalid device ID was specified. */ + MEMORY_ERROR, /*!< An error occured during memory allocation. */ + INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ + INVALID_USE, /*!< The function was called incorrectly. */ + DRIVER_ERROR, /*!< A system driver error occured. */ + SYSTEM_ERROR, /*!< A system error occured. */ + THREAD_ERROR /*!< A thread error occured. */ + }; + + //! The constructor. + Error( const std::string& message, Type type = Error::UNSPECIFIED ) throw() : message_(message), type_(type) {} + + //! The destructor. + virtual ~Error( void ) throw() {} + + //! Prints thrown error message to stderr. + virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } + + //! Returns the thrown error message type. + virtual const Type& getType(void) const throw() { return type_; } + + //! Returns the thrown error message string. + virtual const std::string& getMessage(void) const throw() { return message_; } + + //! Returns the thrown error message as a c-style string. + virtual const char* what( void ) const throw() { return message_.c_str(); } protected: - std::string message_; - Type type_; + std::string message_; + Type type_; }; //! RtMidi error callback function prototype. @@ -223,801 +223,801 @@ template typedef std::shared_ptr Pointer; #endif - class MidiApi; - class MidiInApi; - class MidiOutApi; - - struct PortDescriptor { - //! Flags for formatting a string description of the port. - /*! These flags just mark the requirements that the string - should fulfil. An API may return the same string for - different requirements e.g. the same short and long - name. */ - enum NamingType { - SHORT_NAME =0, /*!< A short human readable name - depending on the API - e.g. “Ensoniq AudioPCI” */ - LONG_NAME, /*!< A complete human readable - name depending on the API - e.g. "Ensoniq AudioPCI: ES1371" */ - SESSION_PATH, /*!< A unique description that can - be used to identify the port - during runtime. It may be a - cryptic string. */ - STORAGE_PATH, /*!< A unique description that is - optimised for storage in - configuration files. This is a - more textual representation that - is more robust to small changes in - the surrounding environment than - \ref SESSION_PATH */ - NAMING_MASK = 0x0F, /*!< part of the flags - that is concerned with - naming. - */ - UNIQUE_NAME = 0x10, /*!< Make all names uniqe. This - is usually done by adding - numbers to the end of the - string */ - INCLUDE_API = 0x20 /*!< Add a string describing the - API at the beginning of the - string. */ - }; - - //! Flags describing the capabilities of a given port. - enum PortCapabilities { - INPUT = 1, /*!< Ports that can be read from. */ - OUTPUT = 2, /*!< Ports that can be written to. */ - INOUTPUT = 3, /*!< Ports that allow reading and writing (INPUT | OUTPUT) */ - UNLIMITED = 0x10 /*!< Some APIs can filter out certain ports which they consider - not to be useful. This flags supresses this behaviour and - selects all ports that are useable. */ - }; - - //! Default constructor. - /*! - * Derived classes should have a constructor. - */ - PortDescriptor() {}; - - //! A virtual destructor - /*! As we might have to destruct the object from the application code - * each port id must have a virtual destructor. - */ - virtual ~PortDescriptor() {}; - - //! Get the MIDI input api for the current port. - /*! This is the only information RtMidi needs to know: Which - * API should handle this object. This can be used to get - * an API which can send data to the given port. - * - * \param queueSizeLimit The limit of the midi queue. This parameter is handled by - * the constructor of the backend API. - * - * \return API that can use this object to connect to an input port or 0 - * if no input API can be created. - */ - virtual MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) = 0; - - //! Get the MIDI output api for the current port. - /*! This is the only information RtMidi needs to know: Which - * API should handle this object. This can be used to get - * an API which can receive data from the given port. - * - * \return API that can use this object to connect to an output port. - */ - virtual MidiOutApi * getOutputApi() = 0; - - //! Return the port name - /*! - * \param flags A description of the requirements of the returned name. - * \return A name that is formatted according to \ref flags. - * \sa NamingTypes - */ - virtual std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) = 0; - - //! Get capabilities - /*! \return a capabilities flag describing the capabilities of the port. - * \sa PortCapabilities - */ - virtual int getCapabilities() = 0; - }; - - //! A list of port descriptors. - /*! Port descriptors are stored as shared pointers. This avoids - unnecessary duplication of the data structure and handles automatic - deletion if all references have been removed. */ - typedef std::list > PortList; - - - - // **************************************************************** // - // - // MidiInApi / MidiOutApi class declarations. - // - // Subclasses of MidiInApi and MidiOutApi contain all API- and - // OS-specific code necessary to fully implement the RtMidi API. - // - // Note that MidiInApi and MidiOutApi are abstract base classes and - // cannot be explicitly instantiated. MidiIn and MidiOut will - // create instances of a MidiInApi or MidiOutApi subclass. - // - // **************************************************************** // - - class MidiApi - { - public: - - MidiApi(); - virtual ~MidiApi(); - - //! Pure virtal function to create a virtual port, with optional name. - /*! - This function creates a virtual MIDI port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, any JACK, - and Linux ALSA APIs (the function returns an error for the other APIs). - - \param portName An optional name for the applicaction port that is - used to connect to portId can be specified. - */ - virtual void openVirtualPort( const std::string portName = std::string( "RtMidi virtual port" ) ) = 0; - - //! Pure virtual function to open a MIDI connection given by enumeration number. - /*! \param portNumber An optional port number greater than 0 - can be specified. Otherwise, the default or first port - found is opened. - - \param portName An optional name for the applicaction port - that will be generated to connect to portId can be - specified. - */ - virtual void openPort( unsigned int portNumber = 0, const std::string & portName = std::string( "RtMidi" ) ) = 0; - - //! Pure virtual function to open a MIDI connection given by a port descriptor. - /*! - \param port A port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - */ - virtual void openPort( const PortDescriptor & port, const std::string & portName = std::string( "RtMidi" ) ) = 0; - - //! Open a MIDI connection given by a port descriptor pointer. - /*! - \param port A pointer to a port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - \sa openPort(const PortDescriptor &,const std::string &); - */ - void openPort( Pointer p, const std::string & portName = std::string( "RtMidi" ) ) { - if (!p) { - errorString_ = "MidiApi::openPort: passed NULL pointer"; - error( Error::INVALID_PARAMETER, errorString_ ); - return; - } - openPort(*p, portName); - } - - //! Pure virtual function to return a port descriptor if the port is open - /*! This function returns a port descriptor that can be used to open another port - either to the connected port or – if the backend supports it – the connecting port. - \param local The parameter local defines whether the function returns a descriptor to - the virtual port (true) or the remote port (false). The function returns 0 if the - port cannot be determined (e.g. if the port is not connected or the backend dosen't support it). - */ - virtual Pointer getDescriptor(bool local=false) = 0; - - //! Pure virtual function to return a list of all available ports of the current API. - /*! - \param capabilities an optional parameter that describes which - capabilities the device typu - - \return This function returns a list of port descriptors. - - \note An input API may but need not necessarily report - output devices which cannot be used as input if - \ref 0 is passed as \ref capabilities parameter. - \sa PortDescriptor::PortCapabilitiers - */ - virtual PortList getPortList(int capabilities = 0) = 0; - - //! Pure virtual to return the number of available MIDI ports of the current API. - /*! - \return This function returns the number of MIDI ports of - the selected API. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortName - */ - virtual unsigned int getPortCount() = 0; - - //! Pure virtual function to return a string identifier for the specified MIDI port number. - /*! - \param portNumber Number of the device to be referred to. - \return The name of the port with the given Id is returned. - \retval An empty string is returned if an invalid port specifier is provided. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortCount() - */ - virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; - - //! Pure virtual function to close an open MIDI connection (if one exists). - virtual void closePort( void ) = 0; - - // ! A basic error reporting function for RtMidi classes. - // static void error( Error::Type type, std::string &errorString ); - - //! Pure virtual function to return whether a port is open or not. - /*! \retval true if a port is open and - \retval false if the port is not open (e.g. not opend or closed). - */ - bool isPortOpen() const { return connected_; } - - //! Pure virtual function to set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. - */ - virtual void setErrorCallback( ErrorCallback errorCallback = NULL ); - - - //! Returns the MIDI API specifier for the current instance of RtMidiIn. - virtual ApiType getCurrentApi( void ) throw() = 0; - - //! A basic error reporting function for RtMidi classes. - void error( Error::Type type, std::string errorString ); - - protected: - virtual void initialize( const std::string& clientName ) = 0; - - void *apiData_; - bool connected_; - std::string errorString_; - ErrorCallback errorCallback_; - }; - - class MidiInApi : public MidiApi - { - public: - - MidiInApi( unsigned int queueSizeLimit ); - virtual ~MidiInApi( void ); - void setCallback( MidiCallback callback, void *userData = 0 ); - void cancelCallback( void ); - virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); - RTMIDI_DEPRECATED(double getMessage( std::vector *message )) - { - if (!message) { - errorString_ = "MidiInApi::getMessage: passed NULL pointer"; - error( Error::WARNING, errorString_ ); - } - return getMessage(*message); - } - double getMessage( std::vector &message ); - - // A MIDI structure used internally by the class to store incoming - // messages. Each message represents one and only one MIDI message. - struct MidiMessage { - std::vector bytes; - double timeStamp; - - // Default constructor. - MidiMessage() - :bytes(0), timeStamp(0.0) {} - }; - - struct MidiQueue { - unsigned int front; - unsigned int back; - unsigned int size; - unsigned int ringSize; - MidiMessage *ring; - - // Default constructor. - MidiQueue() - :front(0), back(0), size(0), ringSize(0) {} - }; - - // The RtMidiInData structure is used to pass private class data to - // the MIDI input handling function or thread. - struct MidiInData { - MidiQueue queue; - MidiMessage message; - unsigned char ignoreFlags; - bool doInput; - bool firstMessage; - void *apiData; - bool usingCallback; - MidiCallback userCallback; - void *userData; - bool continueSysex; - - // Default constructor. - MidiInData() - : ignoreFlags(7), doInput(false), firstMessage(true), - apiData(0), usingCallback(false), userCallback(0), userData(0), - continueSysex(false) {} - }; - - protected: - MidiInData inputData_; - }; - - class MidiOutApi : public MidiApi - { - public: - - MidiOutApi( void ); - virtual ~MidiOutApi( void ); - RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) - { - if (!message) { - errorString_ = "MidiOutApi::sendMessage: no data in message argument!"; - error( Error::WARNING, errorString_ ); - } - sendMessage(*message); - } - virtual void sendMessage( std::vector &message ) = 0; - }; - - - /*! \class Midi - \brief A global class that implements basic backend API handling. - - This class enhances \ref MidiApi by some functionality to handle - backend API objects. It serves as base class for the public RtMidi - API. - - by Gary P. Scavone, 2003-2014. - */ - /**********************************************************************/ - class Midi { - public: - typedef rtmidi::ApiType Api; - //! defined for compatibility - enum Api2 { - UNSPECIFIED = rtmidi::UNSPECIFIED, - MACOSX_CORE = rtmidi::MACOSX_CORE, - LINUX_ALSA = rtmidi::LINUX_ALSA, - UNIX_JACK = rtmidi::UNIX_JACK, - WINDOWS_MM = rtmidi::WINDOWS_MM, - WINDOWS_KS = rtmidi::WINDOWS_KS, - RTMIDI_DUMMY = rtmidi::DUMMY - }; - - - //! A static function to determine the current RtMidi version. - static std::string getVersion( void ) throw(); - - //! A static function to determine the available compiled MIDI APIs. - /*! - The values returned in the std::vector can be compared against - the enumerated list values. Note that there can be more than one - API compiled for certain operating systems. - */ - static void getCompiledApi( std::vector &apis ) throw(); - - //! A static function to determine the available compiled MIDI APIs. - /*! - The values returned in the std::vector can be compared against - the enumerated list values. Note that there can be more than one - API compiled for certain operating systems. - */ - static std::vector getCompiledApi( ) throw() { - std::vector apis; - getCompiledApi(apis); - return apis; - } - - //! Returns the MIDI API specifier for the current instance of RtMidiIn. - ApiType getCurrentApi( void ) throw() - { - if (rtapi_) return rtapi_->getCurrentApi(); - else return rtmidi::UNSPECIFIED; - } - - //! Function to create a virtual port, with optional name. - /*! - This function creates a virtual MIDI port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, any JACK, - and Linux ALSA APIs (the function returns an error for the other APIs). - - \param portName An optional name for the applicaction port that is - used to connect to portId can be specified. - */ - void openVirtualPort( const std::string portName = std::string( "RtMidi virtual port" ) ) - { - if (rtapi_) rtapi_->openVirtualPort(portName); - } - - //! Pure virtual function to open a MIDI connection given by enumeration number. - /*! \param portNumber An optional port number greater than 0 - can be specified. Otherwise, the default or first port - found is opened. - - \param portName An optional name for the applicaction port - that will be generated to connect to portId can be - specified. - - \deprecated - */ - RTMIDI_DEPRECATED(void openPort( unsigned int portNumber = 0, - const std::string portName = std::string( "RtMidi" ) )) - { - if (rtapi_) rtapi_->openPort(portNumber,portName); - } - - //! Pure virtual function to open a MIDI connection given by a port descriptor. - /*! - \param port A port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - */ - void openPort( const PortDescriptor & port, - const std::string & portName = std::string( "RtMidi" ) ) - { - if (rtapi_) rtapi_->openPort(port,portName); - } - - //! Open a MIDI connection given by a port descriptor pointer. - /*! - \param port A pointer to a port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - \sa openPort(const PortDescriptor &,const std::string &); - */ - void openPort( Pointer p, - const std::string & portName = std::string( "RtMidi" ) ) { - if (!p) { - error( Error::INVALID_PARAMETER, "MidiApi::openPort: passed NULL pointer" ); - return; - } - openPort(*p, portName); - } - - //! Pure virtual function to return a port descirptor if the port is open - Pointer getDescriptor(bool local=false) - { - if (rtapi_) return rtapi_->getDescriptor(local); - return 0; - } - - //! Return a list of all available ports of the current API. - /*! - \param capabilities an optional parameter that - describes which capabilities the returned devices - must support. The returned devices may have - additional capabilities to those which have been - requested, but not less. - - \return This function returns a list of port descriptors. - - \note Each API will request additonal - capabilites. An output API will set always add \ref - PortDescriptor::OUTPUT to the mask while an input - device will always add \ref PortDescriptor::OUTPUT. - - \note An input API may but need not necessarily - report output devices which cannot be used as input - if \ref PortDescriptor::OUTPUT is passed as \ref - capabilities parameter. - */ - PortList getPortList(int capabilities = 0) - { - if (rtapi_) return rtapi_->getPortList(capabilities); - return PortList(); - } - - //! Pure virtual to return the number of available MIDI ports of the current API. - /*! - \return This function returns the number of MIDI ports of - the selected API. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortName - \deprecated - */ - RTMIDI_DEPRECATED(unsigned int getPortCount()) - { - if (rtapi_) return rtapi_->getPortCount(); - return 0; - } - - //! Pure virtual function to return a string identifier for the specified MIDI port number. - /*! - \param portNumber Number of the device to be referred to. - \return The name of the port with the given Id is returned. - \retval An empty string is returned if an invalid port specifier is provided. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortCount() - \deprecated - */ - RTMIDI_DEPRECATED(std::string getPortName( unsigned int portNumber = 0 )) - { - if (rtapi_) return rtapi_->getPortName(portNumber); - return ""; - } - - //! Close an open MIDI connection (if one exists). - void closePort( void ) - { - if (rtapi_) rtapi_->closePort(); - } - - // ! A basic error reporting function for RtMidi classes. - // static void error( Error::Type type, std::string &errorString ); - - //! Pure virtual function to return whether a port is open or not. - /*! \retval true if a port is open and - \retval false if the port is not open (e.g. not opend or closed). - */ - bool isPortOpen( void ) const - { - if (rtapi_) return rtapi_->isPortOpen(); - return false; - } - - //! Pure virtual function to set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. - */ - void setErrorCallback( ErrorCallback errorCallback = NULL ) - { - if (rtapi_) rtapi_->setErrorCallback(errorCallback); - } - - //! A basic error reporting function for RtMidi classes. - void error( Error::Type type, std::string errorString ); - protected: - MidiApi *rtapi_; - - Midi():rtapi_(0) {} - ~Midi() - { - if (rtapi_) { - delete rtapi_; - rtapi_ = 0; - } - } - }; - - /**********************************************************************/ - /*! \class MidiIn - \brief A realtime MIDI input class. - - This class provides a common, platform-independent API for - realtime MIDI input. It allows access to a single MIDI input - port. Incoming MIDI messages are either saved to a queue for - retrieval using the getMessage() function or immediately passed to - a user-specified callback function. Create multiple instances of - this class to connect to more than one MIDI device at the same - time. With the OS-X and Linux ALSA 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-2014. - */ - /**********************************************************************/ - - // **************************************************************** // - // - // MidiIn and MidiOut class declarations. - // - // MidiIn / MidiOut are "controllers" used to select an available - // MIDI input or output interface. They present common APIs for the - // user to call but all functionality is implemented by the classes - // MidiInApi, MidiOutApi and their subclasses. MidiIn and MidiOut - // each create an instance of a MidiInApi or MidiOutApi subclass based - // on the user's API choice. If no choice is made, they attempt to - // make a "logical" API selection. - // - // **************************************************************** // - - class MidiIn : public Midi - { - public: - - - //! Default constructor that allows an optional api, client name and queue size. - /*! - An exception will be thrown if a MIDI system initialization - error occurs. The queue size defines the maximum number of - messages that can be held in the MIDI queue (when not using a - callback function). If the queue size limit is reached, - incoming messages will be ignored. - - If no API argument is specified and multiple API support has been - compiled, the default order of use is JACK, ALSA (Linux) and CORE, - JACK (OS-X). - - \param api An optional API id can be specified. - \param clientName An optional Client name can be specified. This - will be used to group the ports that are created - by the application. - \param queueSizeLimit An optional size of the MIDI input queue can be specified. - */ - MidiIn( ApiType api=rtmidi::UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Input Client"), - unsigned int queueSizeLimit = 100 ); - - //! If a MIDI connection is still open, it will be closed by the destructor. - ~MidiIn ( void ) throw(); - - //! Set a callback function to be invoked for incoming MIDI messages. - /*! - The callback function will be called whenever an incoming MIDI - message is received. While not absolutely necessary, it is best - to set the callback function before opening a MIDI port to avoid - leaving some messages in the queue. - - \param callback A callback function must be given. - \param userData Opitionally, a pointer to additional data can be - passed to the callback function whenever it is called. - */ - void setCallback( MidiCallback callback, void *userData = 0 ) - { - if (rtapi_) - static_cast(rtapi_)->setCallback(callback,userData); - } - - //! Cancel use of the current callback function (if one exists). - /*! - Subsequent incoming MIDI messages will be written to the queue - and can be retrieved with the \e getMessage function. - */ - void cancelCallback() - { - if (rtapi_) - static_cast(rtapi_)->cancelCallback(); - } - - //! Specify whether certain MIDI message types should be queued or ignored during input. - /*! - By default, MIDI timing and active sensing messages are ignored - during message input because of their relative high data rates. - MIDI sysex messages are ignored by default as well. Variable - values of "true" imply that the respective message type will be - ignored. - */ - void ignoreTypes( bool midiSysex = true, - bool midiTime = true, - bool midiSense = true ) - { - if (rtapi_) - static_cast(rtapi_)->ignoreTypes(midiSysex, midiTime, midiSense); - } - - //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. - /*! - This function returns immediately whether a new message is - available or not. A valid message is indicated by a non-zero - vector size. An exception is thrown if an error occurs during - message retrieval or an input connection was not previously - established. - */ - double getMessage( std::vector &message ) - { - if (rtapi_) - return static_cast(rtapi_)->getMessage(message); - std::string errorString_ = "MidiIn::getMessage: No valid API found."; - error( Error::WARNING, errorString_ ); - return 0.0; - } - - //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. - /*! - This function returns immediately whether a new message is - available or not. A valid message is indicated by a non-zero - vector size. An exception is thrown if an error occurs during - message retrieval or an input connection was not previously - established. - - \deprecated - */ - RTMIDI_DEPRECATED(double getMessage( std::vector *message )) - { - if (!message) { - error( Error::WARNING, - "MidiIn::getMessage: passed NULL pointer"); - } - if (rtapi_) - return static_cast(rtapi_)->getMessage(*message); - error( Error::WARNING, - "MidiIn::getMessage: No valid API found."); - return 0.0; - } - - protected: - void openMidiApi( ApiType api, const std::string clientName, unsigned int queueSizeLimit ); - - }; - - /**********************************************************************/ - /*! \class MidiOut - \brief A realtime MIDI output class. - - This class provides a common, platform-independent API for MIDI - output. It allows one to probe available MIDI output ports, to - connect to one such port, and to send MIDI bytes immediately over - the connection. Create multiple instances of this class to - connect to more than one MIDI device at the same time. With the - OS-X and Linux ALSA MIDI APIs, it is also possible to open a - virtual port to which other MIDI software clients can connect. - - by Gary P. Scavone, 2003-2014. - */ - /**********************************************************************/ - - class MidiOut : public Midi - { - public: - - //! Default constructor that allows an optional client name. - /*! - An exception will be thrown if a MIDI system initialization error occurs. - - If no API argument is specified and multiple API support has been - compiled, the default order of use is JACK, ALSA (Linux) and CORE, - JACK (OS-X). - */ - MidiOut( ApiType api=rtmidi::UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Output Client") ); - - //! The destructor closes any open MIDI connections. - ~MidiOut( void ) throw(); - - //! Immediately send a single message out an open MIDI output port. - /*! - An exception is thrown if an error occurs during output or an - output connection was not previously established. - - \deprecated - */ - RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) - { - if (!message) { - error( Error::WARNING, - "MidiOutApi::sendMessage: no data in message argument!"); - } - if (rtapi_) - static_cast(rtapi_)->sendMessage(*message); - else - error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); - } - - - //! Immediately send a single message out an open MIDI output port. - /*! - An exception is thrown if an error occurs during output or an - output connection was not previously established. - */ - void sendMessage( std::vector &message ) { - if (rtapi_) - static_cast(rtapi_)->sendMessage(message); - error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); - } - protected: - void openMidiApi( ApiType api, const std::string clientName ); - }; - - - // **************************************************************** // - // - // MidiInApi and MidiOutApi subclass prototypes. - // - // **************************************************************** // +class MidiApi; +class MidiInApi; +class MidiOutApi; + +struct PortDescriptor { + //! Flags for formatting a string description of the port. + /*! These flags just mark the requirements that the string + should fulfil. An API may return the same string for + different requirements e.g. the same short and long + name. */ + enum NamingType { + SHORT_NAME =0, /*!< A short human readable name + depending on the API + e.g. “Ensoniq AudioPCI” */ + LONG_NAME, /*!< A complete human readable + name depending on the API + e.g. "Ensoniq AudioPCI: ES1371" */ + SESSION_PATH, /*!< A unique description that can + be used to identify the port + during runtime. It may be a + cryptic string. */ + STORAGE_PATH, /*!< A unique description that is + optimised for storage in + configuration files. This is a + more textual representation that + is more robust to small changes in + the surrounding environment than + \ref SESSION_PATH */ + NAMING_MASK = 0x0F, /*!< part of the flags + that is concerned with + naming. + */ + UNIQUE_NAME = 0x10, /*!< Make all names uniqe. This + is usually done by adding + numbers to the end of the + string */ + INCLUDE_API = 0x20 /*!< Add a string describing the + API at the beginning of the + string. */ + }; + + //! Flags describing the capabilities of a given port. + enum PortCapabilities { + INPUT = 1, /*!< Ports that can be read from. */ + OUTPUT = 2, /*!< Ports that can be written to. */ + INOUTPUT = 3, /*!< Ports that allow reading and writing (INPUT | OUTPUT) */ + UNLIMITED = 0x10 /*!< Some APIs can filter out certain ports which they consider + not to be useful. This flags supresses this behaviour and + selects all ports that are useable. */ + }; + + //! Default constructor. + /*! + * Derived classes should have a constructor. + */ + PortDescriptor() {}; + + //! A virtual destructor + /*! As we might have to destruct the object from the application code + * each port id must have a virtual destructor. + */ + virtual ~PortDescriptor() {}; + + //! Get the MIDI input api for the current port. + /*! This is the only information RtMidi needs to know: Which + * API should handle this object. This can be used to get + * an API which can send data to the given port. + * + * \param queueSizeLimit The limit of the midi queue. This parameter is handled by + * the constructor of the backend API. + * + * \return API that can use this object to connect to an input port or 0 + * if no input API can be created. + */ + virtual MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) const = 0; + + //! Get the MIDI output api for the current port. + /*! This is the only information RtMidi needs to know: Which + * API should handle this object. This can be used to get + * an API which can receive data from the given port. + * + * \return API that can use this object to connect to an output port. + */ + virtual MidiOutApi * getOutputApi() const = 0; + + //! Return the port name + /*! + * \param flags A description of the requirements of the returned name. + * \return A name that is formatted according to \ref flags. + * \sa NamingTypes + */ + virtual std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) = 0; + + //! Get capabilities + /*! \return a capabilities flag describing the capabilities of the port. + * \sa PortCapabilities + */ + virtual int getCapabilities() const = 0; +}; + +//! A list of port descriptors. +/*! Port descriptors are stored as shared pointers. This avoids + unnecessary duplication of the data structure and handles automatic + deletion if all references have been removed. */ +typedef std::list > PortList; + + + +// **************************************************************** // +// +// MidiInApi / MidiOutApi class declarations. +// +// Subclasses of MidiInApi and MidiOutApi contain all API- and +// OS-specific code necessary to fully implement the RtMidi API. +// +// Note that MidiInApi and MidiOutApi are abstract base classes and +// cannot be explicitly instantiated. MidiIn and MidiOut will +// create instances of a MidiInApi or MidiOutApi subclass. +// +// **************************************************************** // + +class MidiApi +{ +public: + + MidiApi(); + virtual ~MidiApi(); + + //! Pure virtal function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + */ + virtual void openVirtualPort( const std::string portName = std::string( "RtMidi virtual port" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. + + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. + */ + virtual void openPort( unsigned int portNumber = 0, const std::string & portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + virtual void openPort( const PortDescriptor & port, const std::string & portName = std::string( "RtMidi" ) ) = 0; + + //! Open a MIDI connection given by a port descriptor pointer. + /*! + \param port A pointer to a port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + \sa openPort(const PortDescriptor &,const std::string &); + */ + void openPort( Pointer p, const std::string & portName = std::string( "RtMidi" ) ) { + if (!p) { + errorString_ = "MidiApi::openPort: passed NULL pointer"; + error( Error::INVALID_PARAMETER, errorString_ ); + return; + } + openPort(*p, portName); + } + + //! Pure virtual function to return a port descriptor if the port is open + /*! This function returns a port descriptor that can be used to open another port + either to the connected port or – if the backend supports it – the connecting port. + \param local The parameter local defines whether the function returns a descriptor to + the virtual port (true) or the remote port (false). The function returns 0 if the + port cannot be determined (e.g. if the port is not connected or the backend dosen't support it). + */ + virtual Pointer getDescriptor(bool local=false) = 0; + + //! Pure virtual function to return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that describes which + capabilities the device typu + + \return This function returns a list of port descriptors. + + \note An input API may but need not necessarily report + output devices which cannot be used as input if + \ref 0 is passed as \ref capabilities parameter. + \sa PortDescriptor::PortCapabilitiers + */ + virtual PortList getPortList(int capabilities = 0) = 0; + + //! Pure virtual to return the number of available MIDI ports of the current API. + /*! + \return This function returns the number of MIDI ports of + the selected API. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortName + */ + virtual unsigned int getPortCount() = 0; + + //! Pure virtual function to return a string identifier for the specified MIDI port number. + /*! + \param portNumber Number of the device to be referred to. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortCount() + */ + virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; + + //! Pure virtual function to close an open MIDI connection (if one exists). + virtual void closePort( void ) = 0; + + // ! A basic error reporting function for RtMidi classes. + // static void error( Error::Type type, std::string &errorString ); + + //! Pure virtual function to return whether a port is open or not. + /*! \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). + */ + bool isPortOpen() const { return connected_; } + + //! Pure virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + virtual void setErrorCallback( ErrorCallback errorCallback = NULL ); + + + //! Returns the MIDI API specifier for the current instance of RtMidiIn. + virtual ApiType getCurrentApi( void ) throw() = 0; + + //! A basic error reporting function for RtMidi classes. + void error( Error::Type type, std::string errorString ); + +protected: + virtual void initialize( const std::string& clientName ) = 0; + + void *apiData_; + bool connected_; + std::string errorString_; + ErrorCallback errorCallback_; +}; + +class MidiInApi : public MidiApi +{ +public: + + MidiInApi( unsigned int queueSizeLimit ); + virtual ~MidiInApi( void ); + void setCallback( MidiCallback callback, void *userData = 0 ); + void cancelCallback( void ); + virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); + RTMIDI_DEPRECATED(double getMessage( std::vector *message )) + { + if (!message) { + errorString_ = "MidiInApi::getMessage: passed NULL pointer"; + error( Error::WARNING, errorString_ ); + } + return getMessage(*message); + } + double getMessage( std::vector &message ); + + // A MIDI structure used internally by the class to store incoming + // messages. Each message represents one and only one MIDI message. + struct MidiMessage { + std::vector bytes; + double timeStamp; + + // Default constructor. + MidiMessage() + :bytes(0), timeStamp(0.0) {} + }; + + struct MidiQueue { + unsigned int front; + unsigned int back; + unsigned int size; + unsigned int ringSize; + MidiMessage *ring; + + // Default constructor. + MidiQueue() + :front(0), back(0), size(0), ringSize(0) {} + }; + + // The RtMidiInData structure is used to pass private class data to + // the MIDI input handling function or thread. + struct MidiInData { + MidiQueue queue; + MidiMessage message; + unsigned char ignoreFlags; + bool doInput; + bool firstMessage; + void *apiData; + bool usingCallback; + MidiCallback userCallback; + void *userData; + bool continueSysex; + + // Default constructor. + MidiInData() + : ignoreFlags(7), doInput(false), firstMessage(true), + apiData(0), usingCallback(false), userCallback(0), userData(0), + continueSysex(false) {} + }; + +protected: + MidiInData inputData_; +}; + +class MidiOutApi : public MidiApi +{ +public: + + MidiOutApi( void ); + virtual ~MidiOutApi( void ); + RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) + { + if (!message) { + errorString_ = "MidiOutApi::sendMessage: no data in message argument!"; + error( Error::WARNING, errorString_ ); + } + sendMessage(*message); + } + virtual void sendMessage( std::vector &message ) = 0; +}; + + +/*! \class Midi + \brief A global class that implements basic backend API handling. + + This class enhances \ref MidiApi by some functionality to handle + backend API objects. It serves as base class for the public RtMidi + API. + + by Gary P. Scavone, 2003-2014. +*/ +/**********************************************************************/ +class Midi { +public: + typedef rtmidi::ApiType Api; + //! defined for compatibility + enum Api2 { + UNSPECIFIED = rtmidi::UNSPECIFIED, + MACOSX_CORE = rtmidi::MACOSX_CORE, + LINUX_ALSA = rtmidi::LINUX_ALSA, + UNIX_JACK = rtmidi::UNIX_JACK, + WINDOWS_MM = rtmidi::WINDOWS_MM, + WINDOWS_KS = rtmidi::WINDOWS_KS, + RTMIDI_DUMMY = rtmidi::DUMMY + }; + + + //! A static function to determine the current RtMidi version. + static std::string getVersion( void ) throw(); + + //! A static function to determine the available compiled MIDI APIs. + /*! + The values returned in the std::vector can be compared against + the enumerated list values. Note that there can be more than one + API compiled for certain operating systems. + */ + static void getCompiledApi( std::vector &apis ) throw(); + + //! A static function to determine the available compiled MIDI APIs. + /*! + The values returned in the std::vector can be compared against + the enumerated list values. Note that there can be more than one + API compiled for certain operating systems. + */ + static std::vector getCompiledApi( ) throw() { + std::vector apis; + getCompiledApi(apis); + return apis; + } + + //! Returns the MIDI API specifier for the current instance of RtMidiIn. + ApiType getCurrentApi( void ) throw() + { + if (rtapi_) return rtapi_->getCurrentApi(); + else return rtmidi::UNSPECIFIED; + } + + //! Function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + */ + void openVirtualPort( const std::string portName = std::string( "RtMidi virtual port" ) ) + { + if (rtapi_) rtapi_->openVirtualPort(portName); + } + + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. + + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. + + \deprecated + */ + RTMIDI_DEPRECATED(void openPort( unsigned int portNumber = 0, + const std::string portName = std::string( "RtMidi" ) )) + { + if (rtapi_) rtapi_->openPort(portNumber,portName); + } + + //! Pure virtual function to open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + void openPort( const PortDescriptor & port, + const std::string & portName = std::string( "RtMidi" ) ) + { + if (rtapi_) rtapi_->openPort(port,portName); + } + + //! Open a MIDI connection given by a port descriptor pointer. + /*! + \param port A pointer to a port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + \sa openPort(const PortDescriptor &,const std::string &); + */ + void openPort( Pointer p, + const std::string & portName = std::string( "RtMidi" ) ) { + if (!p) { + error( Error::INVALID_PARAMETER, "MidiApi::openPort: passed NULL pointer" ); + return; + } + openPort(*p, portName); + } + + //! Pure virtual function to return a port descirptor if the port is open + Pointer getDescriptor(bool local=false) + { + if (rtapi_) return rtapi_->getDescriptor(local); + return 0; + } + + //! Return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that + describes which capabilities the returned devices + must support. The returned devices may have + additional capabilities to those which have been + requested, but not less. + + \return This function returns a list of port descriptors. + + \note Each API will request additonal + capabilites. An output API will set always add \ref + PortDescriptor::OUTPUT to the mask while an input + device will always add \ref PortDescriptor::OUTPUT. + + \note An input API may but need not necessarily + report output devices which cannot be used as input + if \ref PortDescriptor::OUTPUT is passed as \ref + capabilities parameter. + */ + PortList getPortList(int capabilities = 0) + { + if (rtapi_) return rtapi_->getPortList(capabilities); + return PortList(); + } + + //! Pure virtual to return the number of available MIDI ports of the current API. + /*! + \return This function returns the number of MIDI ports of + the selected API. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortName + \deprecated + */ + RTMIDI_DEPRECATED(unsigned int getPortCount()) + { + if (rtapi_) return rtapi_->getPortCount(); + return 0; + } + + //! Pure virtual function to return a string identifier for the specified MIDI port number. + /*! + \param portNumber Number of the device to be referred to. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortCount() + \deprecated + */ + RTMIDI_DEPRECATED(std::string getPortName( unsigned int portNumber = 0 )) + { + if (rtapi_) return rtapi_->getPortName(portNumber); + return ""; + } + + //! Close an open MIDI connection (if one exists). + void closePort( void ) + { + if (rtapi_) rtapi_->closePort(); + } + + // ! A basic error reporting function for RtMidi classes. + // static void error( Error::Type type, std::string &errorString ); + + //! Pure virtual function to return whether a port is open or not. + /*! \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). + */ + bool isPortOpen( void ) const + { + if (rtapi_) return rtapi_->isPortOpen(); + return false; + } + + //! Pure virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + void setErrorCallback( ErrorCallback errorCallback = NULL ) + { + if (rtapi_) rtapi_->setErrorCallback(errorCallback); + } + + //! A basic error reporting function for RtMidi classes. + void error( Error::Type type, std::string errorString ); +protected: + MidiApi *rtapi_; + + Midi():rtapi_(0) {} + ~Midi() + { + if (rtapi_) { + delete rtapi_; + rtapi_ = 0; + } + } +}; + +/**********************************************************************/ +/*! \class MidiIn + \brief A realtime MIDI input class. + + This class provides a common, platform-independent API for + realtime MIDI input. It allows access to a single MIDI input + port. Incoming MIDI messages are either saved to a queue for + retrieval using the getMessage() function or immediately passed to + a user-specified callback function. Create multiple instances of + this class to connect to more than one MIDI device at the same + time. With the OS-X and Linux ALSA 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-2014. +*/ +/**********************************************************************/ + +// **************************************************************** // +// +// MidiIn and MidiOut class declarations. +// +// MidiIn / MidiOut are "controllers" used to select an available +// MIDI input or output interface. They present common APIs for the +// user to call but all functionality is implemented by the classes +// MidiInApi, MidiOutApi and their subclasses. MidiIn and MidiOut +// each create an instance of a MidiInApi or MidiOutApi subclass based +// on the user's API choice. If no choice is made, they attempt to +// make a "logical" API selection. +// +// **************************************************************** // + +class MidiIn : public Midi +{ +public: + + + //! Default constructor that allows an optional api, client name and queue size. + /*! + An exception will be thrown if a MIDI system initialization + error occurs. The queue size defines the maximum number of + messages that can be held in the MIDI queue (when not using a + callback function). If the queue size limit is reached, + incoming messages will be ignored. + + If no API argument is specified and multiple API support has been + compiled, the default order of use is JACK, ALSA (Linux) and CORE, + JACK (OS-X). + + \param api An optional API id can be specified. + \param clientName An optional Client name can be specified. This + will be used to group the ports that are created + by the application. + \param queueSizeLimit An optional size of the MIDI input queue can be specified. + */ + MidiIn( ApiType api=rtmidi::UNSPECIFIED, + const std::string clientName = std::string( "RtMidi Input Client"), + unsigned int queueSizeLimit = 100 ); + + //! If a MIDI connection is still open, it will be closed by the destructor. + ~MidiIn ( void ) throw(); + + //! Set a callback function to be invoked for incoming MIDI messages. + /*! + The callback function will be called whenever an incoming MIDI + message is received. While not absolutely necessary, it is best + to set the callback function before opening a MIDI port to avoid + leaving some messages in the queue. + + \param callback A callback function must be given. + \param userData Opitionally, a pointer to additional data can be + passed to the callback function whenever it is called. + */ + void setCallback( MidiCallback callback, void *userData = 0 ) + { + if (rtapi_) + static_cast(rtapi_)->setCallback(callback,userData); + } + + //! Cancel use of the current callback function (if one exists). + /*! + Subsequent incoming MIDI messages will be written to the queue + and can be retrieved with the \e getMessage function. + */ + void cancelCallback() + { + if (rtapi_) + static_cast(rtapi_)->cancelCallback(); + } + + //! Specify whether certain MIDI message types should be queued or ignored during input. + /*! + By default, MIDI timing and active sensing messages are ignored + during message input because of their relative high data rates. + MIDI sysex messages are ignored by default as well. Variable + values of "true" imply that the respective message type will be + ignored. + */ + void ignoreTypes( bool midiSysex = true, + bool midiTime = true, + bool midiSense = true ) + { + if (rtapi_) + static_cast(rtapi_)->ignoreTypes(midiSysex, midiTime, midiSense); + } + + //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. + /*! + This function returns immediately whether a new message is + available or not. A valid message is indicated by a non-zero + vector size. An exception is thrown if an error occurs during + message retrieval or an input connection was not previously + established. + */ + double getMessage( std::vector &message ) + { + if (rtapi_) + return static_cast(rtapi_)->getMessage(message); + std::string errorString_ = "MidiIn::getMessage: No valid API found."; + error( Error::WARNING, errorString_ ); + return 0.0; + } + + //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. + /*! + This function returns immediately whether a new message is + available or not. A valid message is indicated by a non-zero + vector size. An exception is thrown if an error occurs during + message retrieval or an input connection was not previously + established. + + \deprecated + */ + RTMIDI_DEPRECATED(double getMessage( std::vector *message )) + { + if (!message) { + error( Error::WARNING, + "MidiIn::getMessage: passed NULL pointer"); + } + if (rtapi_) + return static_cast(rtapi_)->getMessage(*message); + error( Error::WARNING, + "MidiIn::getMessage: No valid API found."); + return 0.0; + } + +protected: + void openMidiApi( ApiType api, const std::string clientName, unsigned int queueSizeLimit ); + +}; + +/**********************************************************************/ +/*! \class MidiOut + \brief A realtime MIDI output class. + + This class provides a common, platform-independent API for MIDI + output. It allows one to probe available MIDI output ports, to + connect to one such port, and to send MIDI bytes immediately over + the connection. Create multiple instances of this class to + connect to more than one MIDI device at the same time. With the + OS-X and Linux ALSA MIDI APIs, it is also possible to open a + virtual port to which other MIDI software clients can connect. + + by Gary P. Scavone, 2003-2014. +*/ +/**********************************************************************/ + +class MidiOut : public Midi +{ +public: + + //! Default constructor that allows an optional client name. + /*! + An exception will be thrown if a MIDI system initialization error occurs. + + If no API argument is specified and multiple API support has been + compiled, the default order of use is JACK, ALSA (Linux) and CORE, + JACK (OS-X). + */ + MidiOut( ApiType api=rtmidi::UNSPECIFIED, + const std::string clientName = std::string( "RtMidi Output Client") ); + + //! The destructor closes any open MIDI connections. + ~MidiOut( void ) throw(); + + //! Immediately send a single message out an open MIDI output port. + /*! + An exception is thrown if an error occurs during output or an + output connection was not previously established. + + \deprecated + */ + RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) + { + if (!message) { + error( Error::WARNING, + "MidiOutApi::sendMessage: no data in message argument!"); + } + if (rtapi_) + static_cast(rtapi_)->sendMessage(*message); + else + error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); + } + + + //! Immediately send a single message out an open MIDI output port. + /*! + An exception is thrown if an error occurs during output or an + output connection was not previously established. + */ + void sendMessage( std::vector &message ) { + if (rtapi_) + static_cast(rtapi_)->sendMessage(message); + error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); + } +protected: + void openMidiApi( ApiType api, const std::string clientName ); +}; + + +// **************************************************************** // +// +// MidiInApi and MidiOutApi subclass prototypes. +// +// **************************************************************** // #if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__) #define __RTMIDI_DUMMY__ From f3a9fc64535cf721755eeabf6041e6f36a28b0f6 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 May 2014 17:37:50 +0200 Subject: [PATCH 043/210] Fix conflict in the makefile. --- Makefile.in | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Makefile.in b/Makefile.in index 4d8dabfd..48ab3bd0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -9,13 +9,8 @@ OBJECTS = RtMidi.o LIBNAME = librtmidi STATIC = $(LIBNAME).a SHARED = @sharedlib@ -<<<<<<< HEAD -RELEASE = 2.1.0 -MAJOR = 2 -======= RELEASE = 3.0.0 MAJOR = 3 ->>>>>>> Bump library version. LIBRARIES = $(STATIC) $(SHARED) CC = @CXX@ From ce3339cc62c51a8ad1b97235648c4e6413694e52 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 May 2014 17:40:42 +0200 Subject: [PATCH 044/210] Allow to enumerate all MIDI ports from all APIs. --- RtMidi.cpp | 44 ++++++++++++- RtMidi.h | 143 ++++++++++++++++++++++++++++++---------- tests/Makefile.in | 7 +- tests/midiout2.cpp | 12 +++- tests/midiprobe-all.cpp | 122 ++++++++++++++++++++++++++++++++++ tests/midiprobe2.cpp | 1 + 6 files changed, 291 insertions(+), 38 deletions(-) create mode 100644 tests/midiprobe-all.cpp diff --git a/RtMidi.cpp b/RtMidi.cpp index 3d33114c..84bde320 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -140,9 +140,29 @@ void MidiIn :: openMidiApi( ApiType api, const std::string clientName, unsigned #endif } +MidiApiList MidiIn::queryApis; + MidiIn :: MidiIn( ApiType api, const std::string clientName, unsigned int queueSizeLimit ) - : Midi() + : Midi(&queryApis) { + if ( api == rtmidi::ALL_API) { + if (!queryApis.empty()) { + rtapi_ = NULL; + return; + } + + std::vector< ApiType > apis; + getCompiledApi( apis ); + for ( unsigned int i=0; i apis; + getCompiledApi( apis ); + for ( unsigned int i=0; i &message ) = 0; }; +typedef Pointer MidiApiPtr; +typedef std::list MidiApiList; /*! \class Midi \brief A global class that implements basic backend API handling. @@ -634,6 +653,9 @@ class Midi { void openVirtualPort( const std::string portName = std::string( "RtMidi virtual port" ) ) { if (rtapi_) rtapi_->openVirtualPort(portName); + else { + error(Error::INVALID_DEVICE,"Midi::OpenVirtualPort: No valid API selected"); + } } //! Pure virtual function to open a MIDI connection given by enumeration number. @@ -653,31 +675,6 @@ class Midi { if (rtapi_) rtapi_->openPort(portNumber,portName); } - //! Pure virtual function to open a MIDI connection given by a port descriptor. - /*! - \param port A port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - */ - void openPort( const PortDescriptor & port, - const std::string & portName = std::string( "RtMidi" ) ) - { - if (rtapi_) rtapi_->openPort(port,portName); - } - - //! Open a MIDI connection given by a port descriptor pointer. - /*! - \param port A pointer to a port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - \sa openPort(const PortDescriptor &,const std::string &); - */ - void openPort( Pointer p, - const std::string & portName = std::string( "RtMidi" ) ) { - if (!p) { - error( Error::INVALID_PARAMETER, "MidiApi::openPort: passed NULL pointer" ); - return; - } - openPort(*p, portName); - } //! Pure virtual function to return a port descirptor if the port is open Pointer getDescriptor(bool local=false) @@ -709,6 +706,16 @@ class Midi { PortList getPortList(int capabilities = 0) { if (rtapi_) return rtapi_->getPortList(capabilities); + if (list && !list->empty()) { + PortList retval; + for (MidiApiList::iterator i = list->begin(); + i != list->end(); + ++i) { + PortList tmp = (*i)->getPortList(capabilities); + retval.splice(retval.end(), tmp); + } + return retval; + } return PortList(); } @@ -782,8 +789,9 @@ class Midi { void error( Error::Type type, std::string errorString ); protected: MidiApi *rtapi_; + MidiApiList * list; - Midi():rtapi_(0) {} + Midi(MidiApiList * l):rtapi_(0),list(l) {} ~Midi() { if (rtapi_) { @@ -855,6 +863,43 @@ class MidiIn : public Midi //! If a MIDI connection is still open, it will be closed by the destructor. ~MidiIn ( void ) throw(); + using Midi::openPort; + + //! Open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + void openPort( const PortDescriptor & port, + const std::string & portName = std::string( "RtMidi" ) ) + { + if (!rtapi_) rtapi_ = port.getInputApi(); + if (rtapi_) rtapi_->openPort(port,portName); + } + + + //! Open a MIDI connection given by a port descriptor pointer. + /*! + \param port A pointer to a port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + \sa openPort(const PortDescriptor &,const std::string &); + */ + void openPort( Pointer p, + const std::string & portName = std::string( "RtMidi" ) ) { + if (!p) { + error( Error::INVALID_PARAMETER, "MidiApi::openPort: passed NULL pointer" ); + return; + } + openPort(*p, portName); + } + + //! Pure virtual function to return a port descirptor if the port is open + Pointer getDescriptor(bool local=false) + { + if (rtapi_) return rtapi_->getDescriptor(local); + return 0; + } + //! Set a callback function to be invoked for incoming MIDI messages. /*! The callback function will be called whenever an incoming MIDI @@ -940,6 +985,7 @@ class MidiIn : public Midi } protected: + static MidiApiList queryApis; void openMidiApi( ApiType api, const std::string clientName, unsigned int queueSizeLimit ); }; @@ -978,6 +1024,36 @@ class MidiOut : public Midi //! The destructor closes any open MIDI connections. ~MidiOut( void ) throw(); + using Midi::openPort; + + //! Open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + void openPort( const PortDescriptor & port, + const std::string & portName = std::string( "RtMidi" ) ) + { + if (!rtapi_) rtapi_ = port.getOutputApi(); + if (rtapi_) rtapi_->openPort(port,portName); + } + + //! Open a MIDI connection given by a port descriptor pointer. + /*! + \param port A pointer to a port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + \sa openPort(const PortDescriptor &,const std::string &); + */ + void openPort( Pointer p, + const std::string & portName = std::string( "RtMidi" ) ) { + if (!p) { + error( Error::INVALID_PARAMETER, "MidiApi::openPort: passed NULL pointer" ); + return; + } + openPort(*p, portName); + } + + //! Immediately send a single message out an open MIDI output port. /*! An exception is thrown if an error occurs during output or an @@ -1009,6 +1085,7 @@ class MidiOut : public Midi error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); } protected: + static MidiApiList queryApis; void openMidiApi( ApiType api, const std::string clientName ); }; diff --git a/tests/Makefile.in b/tests/Makefile.in index 8498dfdd..42625888 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -1,7 +1,7 @@ ### Do not edit -- Generated by 'configure --with-whatever' from Makefile.in ### RtMidi tests Makefile - for various flavors of unix -PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest midiprobe2 cmidiin2 qmidiin2 midiout2 loopback +PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest midiprobe2 midiprobe-all cmidiin2 qmidiin2 midiout2 loopback RM = /bin/rm SRC_PATH = .. INCLUDE = .. @@ -13,7 +13,7 @@ OBJECTS = RtMidi.o CC = @CXX@ DEFS = @CPPFLAGS@ CFLAGS = @CXXFLAGS@ -CFLAGS += -I$(INCLUDE) -I$(INCLUDE)/include +CFLAGS += -I$(INCLUDE) LIBRARY = @LIBS@ %.o : $(SRC_PATH)/%.cpp @@ -28,6 +28,9 @@ midiprobe : midiprobe.cpp $(OBJECTS) midiprobe2 : midiprobe2.cpp $(OBJECTS) $(CC) $(CFLAGS) $(DEFS) -o midiprobe2 midiprobe2.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) +midiprobe-all : midiprobe-all.cpp $(OBJECTS) + $(CC) $(CFLAGS) $(DEFS) -o midiprobe-all midiprobe-all.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) + midiout : midiout.cpp $(OBJECTS) $(CC) $(CFLAGS) $(DEFS) -o midiout midiout.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) diff --git a/tests/midiout2.cpp b/tests/midiout2.cpp index 584faea9..7e964d1a 100644 --- a/tests/midiout2.cpp +++ b/tests/midiout2.cpp @@ -26,16 +26,24 @@ // This function should be embedded in a try/catch block in case of // an exception. It offers the user a choice of MIDI ports to open. // It returns false if there are no ports available. -bool chooseMidiPort( rtmidi::MidiOut &ortmidi ); +bool chooseMidiPort( rtmidi::MidiOut &midi ); //! The main program int main( int /* argc*/, char */*argv*/[] ) { std::vector message; + std::cout << "\nWould you like to check all output ports? [Y/n] "; + + std::string keyHit; + std::getline( std::cin, keyHit ); + rtmidi::ApiType type = rtmidi::ALL_API; + if ( keyHit == "n" ) { + type = rtmidi::UNSPECIFIED; + } // rtmidi::MidiOut constructor try { - rtmidi::MidiOut midiout; + rtmidi::MidiOut midiout(type); // Call function to select port. try { diff --git a/tests/midiprobe-all.cpp b/tests/midiprobe-all.cpp new file mode 100644 index 00000000..ba24e5aa --- /dev/null +++ b/tests/midiprobe-all.cpp @@ -0,0 +1,122 @@ +// midiprobe.cpp +// +// Simple program to check MIDI inputs and outputs. +// +// by Gary Scavone, 2003-2012. + +#include +#include +#include +#include "RtMidi.h" + +int main() +{ + // Create an api map. + + std::vector< RtMidi::Api > apis; + rtmidi::Midi :: getCompiledApi( apis ); + + std::cout << "\nCompiled APIs:\n"; + for ( unsigned int i=0; igetName() << std::endl; + for (int j = 0 ; j < 4 ; j++ ) { + std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME) << std::endl; + std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME + | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << std::endl; + } + std::cout << std::endl; + } + + std::cout << "**********************************************************************" << std::endl; + + // RtMidiOut constructor ... exception possible + rtmidi::MidiOut midiout (rtmidi::ALL_API); + list = midiout.getPortList(); + + std::cout << "\nCurrent output API: " << rtmidi::getApiName(midiout.getCurrentApi()) << std::endl; + + // Check inputs. + std::cout << "\nThere are " << list.size() << " MIDI output sinks available.\n"; + + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); + i++) { + std::cout << " Output Port: " << (*i)->getName() << std::endl; + for (int j = 0 ; j < 4 ; j++ ) { + std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME) << std::endl; + std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME + | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << std::endl; + } + std::cout << std::endl; + } + + std::cout << "**********************************************************************" << std::endl; + std::cout << "* entering unlimited mode *" << std::endl; + std::cout << "**********************************************************************" << std::endl; + + list = midiin.getPortList(rtmidi::PortDescriptor::UNLIMITED); + // Check inputs. + std::cout << "\nThere are " << list.size() << " MIDI input sources available in unlimited mode.\n"; + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); + i++) { + std::cout << " Input Port: " << (*i)->getName() << std::endl; + for (int j = 0 ; j < 4 ; j++ ) { + std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME) << std::endl; + std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME + | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << std::endl; + } + std::cout << std::endl; + } + + std::cout << "**********************************************************************" << std::endl; + list = midiout.getPortList(rtmidi::PortDescriptor::UNLIMITED); + + // Check inputs. + std::cout << "\nThere are " << list.size() << " MIDI output sinks available in unlimited mode.\n"; + + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); + i++) { + std::cout << " Output Port: " << (*i)->getName() << std::endl; + for (int j = 0 ; j < 4 ; j++ ) { + std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME) << std::endl; + std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME + | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << std::endl; + } + std::cout << std::endl; + } + + } catch ( rtmidi::Error &error ) { + error.printMessage(); + } + + return 0; +} diff --git a/tests/midiprobe2.cpp b/tests/midiprobe2.cpp index f5b9386b..a0c8c260 100644 --- a/tests/midiprobe2.cpp +++ b/tests/midiprobe2.cpp @@ -21,6 +21,7 @@ int main() apiMap[rtmidi::UNIX_JACK] = "Jack Client"; apiMap[rtmidi::LINUX_ALSA] = "Linux ALSA"; apiMap[rtmidi::DUMMY] = "RtMidi Dummy"; + apiMap[rtmidi::ALL_API] = "All RtMidi APIs"; std::vector< rtmidi::ApiType > apis; rtmidi::Midi :: getCompiledApi( apis ); From f90014e7fe47569564f66a4e836bcebc792995a4 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 May 2014 17:44:40 +0200 Subject: [PATCH 045/210] Add configure options to enable runtime pointer and thread checks. Modern versions of gcc and clang can compile files in a way that they can detect bad access to memory as use after free or array overflow when it happens, which improves the debugging of such errors. --- configure.ac | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/configure.ac b/configure.ac index e0361195..a1ca1d82 100644 --- a/configure.ac +++ b/configure.ac @@ -46,6 +46,74 @@ fi CXXFLAGS="$CXXFLAGS $cxxflag" +AC_ARG_ENABLE(address-sanitizer, + AS_HELP_STRING([--enable-address-sanitizer],[Enable gcc/clang address santizer]), + [AS_IF(test "$enableval" = yes, + + AC_LANG_PUSH(C++) + for flag in -fsanitize=address -fno-omit-frame-pointer -fno-common + do + tmpcxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $flag" + AC_MSG_CHECKING([whether $CXX supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CXXFLAGS="$tmpcxxflags" + AC_MSG_RESULT([no])]) + AC_LANG_PUSH(C) + tmpcflags="$CFLAGS" + CFLAGS="$CFLAGS $flag" + AC_MSG_CHECKING([whether $CC supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CFLAGS="$tmpcflags" + AC_MSG_RESULT([no])]) + AC_LANG_POP(C) + done + AC_LANG_POP(C++) + ) + ] +) + +AC_ARG_ENABLE(thread-sanitizer, + AS_HELP_STRING([--enable-thread-sanitizer],[Enable gcc/clang thread santizer]), + [AS_IF(test "$enableval" = yes, + AC_LANG_PUSH(C++) + for flag in -fsanitize=thread -fno-omit-frame-pointer -fno-common -fPIC + do + tmpcxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $flag" + AC_MSG_CHECKING([whether $CXX supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CXXFLAGS="$tmpcxxflags" + AC_MSG_RESULT([no])]) + AC_LANG_PUSH(C) + tmpcflags="$CFLAGS" + CFLAGS="$CFLAGS $flag" + AC_MSG_CHECKING([whether $CC supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CFLAGS="$tmpcflags" + AC_MSG_RESULT([no])]) + AC_LANG_POP(C) + done + for flag in -pie + do + tmpldflags="$LDFLAGS" + LDFLAGS="$LDFLAGS $flag" + AC_MSG_CHECKING([whether $LD supports $flag]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [LDFLAGS="$tmpldflags" + AC_MSG_RESULT([no])]) + done + AC_LANG_POP(C++) + ) + ] +) + + # Checks for package options and external software AC_CANONICAL_HOST From 23aa1e78e82cc3e133f7b718616b7a545aefdbe7 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 May 2014 17:46:57 +0200 Subject: [PATCH 046/210] Partly fix an issue of the JACK backend that loses data and may cause segmentation faults. --- RtMidi.cpp | 139 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 104 insertions(+), 35 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 84bde320..799e1bdd 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1844,7 +1844,6 @@ std::string MidiInCore :: getPortName( unsigned int portNumber ) return stringName = name; } - //*********************************************************************// // API: OS-X // Class Definitions: MidiOutCore @@ -4439,12 +4438,30 @@ PortList JackPortDescriptor :: getPortList(int capabilities, const std::string & */ struct JackMidiData:public JackPortDescriptor { + /* signal the JACK process what to do next */ + volatile enum { + RUNNING, /*!< keep the client open, flag is owned by the controlling process */ + CLOSING, /*!< close the current port */ + DELETING /*!< Delete the client after delivering the contents of the ring buffer */ + } stateflags; + /*! response/state from the JACK thread. See \ref jackProcessOut for details */ + volatile enum { + OPEN, + CLOSING2, + CLOSED, + DELETING2, + DELETING3 + /* DELETED is useless as this doesn't exist anymore */ + } state_response; + jack_port_t * local; jack_ringbuffer_t *buffSize; jack_ringbuffer_t *buffMessage; jack_time_t lastTime; MidiInApi :: MidiInData *rtMidiIn; - NonLockingJackSequencer seq; + /*! Sequencer object: This must be deleted _before_ the MIDI data to avoid + segmentation faults while queued data is still in the ring buffer. */ + NonLockingJackSequencer * seq; /* JackMidiData():seq() @@ -4454,12 +4471,13 @@ struct JackMidiData:public JackPortDescriptor { */ JackMidiData(const std::string &clientName, MidiInApi :: MidiInData &inputData_):JackPortDescriptor(clientName), + stateflags(RUNNING), local(0), buffSize(0), buffMessage(0), lastTime(0), rtMidiIn(&inputData_), - seq(clientName,false,this) + seq(new NonLockingJackSequencer(clientName,false,this)) { } @@ -4471,12 +4489,13 @@ struct JackMidiData:public JackPortDescriptor { * \return */ JackMidiData(const std::string &clientName):JackPortDescriptor(clientName), + stateflags(RUNNING), local(0), buffSize(jack_ringbuffer_create( JACK_RINGBUFFER_SIZE )), buffMessage(jack_ringbuffer_create( JACK_RINGBUFFER_SIZE )), lastTime(0), rtMidiIn(), - seq(clientName,true,this) + seq(new NonLockingJackSequencer(clientName,true,this)) {} @@ -4484,6 +4503,8 @@ struct JackMidiData:public JackPortDescriptor { { if (local) deletePort(); + if (seq) + delete seq; if (buffSize) jack_ringbuffer_free( buffSize ); if (buffMessage) @@ -4499,12 +4520,12 @@ struct JackMidiData:public JackPortDescriptor { void connectPorts(jack_port_t * from, jack_port_t * to) { - seq.connectPorts(from, to); + seq->connectPorts(from, to); } int openPort(unsigned long jackCapabilities, const std::string & portName) { - local = seq.createPort(portName, jackCapabilities); + local = seq->createPort(portName, jackCapabilities); if (!local) { api->error( Error::DRIVER_ERROR, "MidiInJack::openPort: JACK error opening port subscription." ); @@ -4514,15 +4535,15 @@ struct JackMidiData:public JackPortDescriptor { } void deletePort() { - seq.deletePort(local); + seq->deletePort(local); local = 0; } void closePort(bool output_is_remote) { if (output_is_remote) { - seq.closePort( local, port ); + seq->closePort( local, port ); } else { - seq.closePort( port, local ); + seq->closePort( port, local ); } port = 0; } @@ -4632,6 +4653,7 @@ MidiInJack :: ~MidiInJack() if ( data->client ) jack_client_close( data->client ); #endif + /* immediately shut down the JACK client */ delete data; } @@ -4643,7 +4665,7 @@ void MidiInJack :: openPort( unsigned int portNumber, const std::string & portNa // Creating new port if ( data->local == NULL) - data->local = jack_port_register( data->seq, portName.c_str(), + data->local = jack_port_register( *(data->seq), portName.c_str(), JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); if ( data->local == NULL) { @@ -4654,7 +4676,7 @@ void MidiInJack :: openPort( unsigned int portNumber, const std::string & portNa // Connecting to the output std::string name = getPortName( portNumber ); - jack_connect( data->seq, name.c_str(), jack_port_name( data->local ) ); + jack_connect( *(data->seq), name.c_str(), jack_port_name( data->local ) ); } void MidiInJack :: openVirtualPort( const std::string portName ) @@ -4663,7 +4685,7 @@ void MidiInJack :: openVirtualPort( const std::string portName ) // connect(); if ( data->local == NULL ) - data->local = jack_port_register( data->seq, portName.c_str(), + data->local = jack_port_register( *(data->seq), portName.c_str(), JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); if ( data->local == NULL ) { @@ -4750,11 +4772,11 @@ unsigned int MidiInJack :: getPortCount() int count = 0; // connect(); JackMidiData *data = static_cast (apiData_); - if ( !(data->seq) ) + if ( !(*(data->seq)) ) return 0; // List of available ports - const char **ports = jack_get_ports( data->seq, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); + const char **ports = jack_get_ports( *(data->seq), NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); if ( ports == NULL ) return 0; while ( ports[count] != NULL ) @@ -4773,8 +4795,8 @@ std::string MidiInJack :: getPortName( unsigned int portNumber ) // connect(); // List of available ports - const char **ports = jack_get_ports( data->seq, NULL, - JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); + const char **ports = jack_get_ports(* (data->seq), NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); // Check port validity if ( ports == NULL ) { @@ -4800,7 +4822,7 @@ void MidiInJack :: closePort() JackMidiData *data = static_cast (apiData_); if ( data->local == NULL ) return; - jack_port_unregister( data->seq, data->local ); + jack_port_unregister( *(data->seq), data->local ); data->local = NULL; } @@ -4815,6 +4837,7 @@ static int jackProcessOut( jack_nframes_t nframes, void *arg ) JackMidiData *data = (JackMidiData *) arg; jack_midi_data_t *midiData; int space; + bool mayclose = false; // Is port created? if ( data->local == NULL ) return 0; @@ -4827,6 +4850,48 @@ static int jackProcessOut( jack_nframes_t nframes, void *arg ) midiData = jack_midi_event_reserve( buff, 0, space ); jack_ringbuffer_read( data->buffMessage, (char *) midiData, (size_t) space ); + mayclose = true; + } + + if (!mayclose) + return 0; + + switch (data->stateflags) { + case JackMidiData::RUNNING: break; + case JackMidiData::CLOSING: + if (data->state_response != JackMidiData::CLOSING2) { + /* output the transferred data */ + data->state_response = JackMidiData::CLOSING2; + return 0; + } + if ( data->local == NULL ) break; + jack_port_unregister( *(data->seq), data->local ); + data->local = NULL; + data->state_response = JackMidiData::CLOSED; + break; + + case JackMidiData::DELETING: +#if defined(__RTMIDI_DEBUG__) + std::cerr << "deleting port" << std::endl; +#endif + if (data->state_response != JackMidiData::DELETING2) { + data->state_response = JackMidiData::DELETING2; + /* output the transferred data */ + return 0; + } + + if (data->local != NULL && data->state_response != JackMidiData::DELETING2) { + data->stateflags = JackMidiData::CLOSING; + jack_port_unregister( *(data->seq), data->local ); + data->local = NULL; + data->state_response = JackMidiData::DELETING2; + return 0; + } + delete data; +#if defined(__RTMIDI_DEBUG__) + std::cerr << "deleted port" << std::endl; +#endif + break; } return 0; @@ -4851,11 +4916,11 @@ void MidiOutJack :: connect() abort(); #if 0 JackMidiData *data = static_cast (apiData_); - if ( data->seq ) + if ( *(data->seq) ) return; // Initialize JACK client - if (( data->seq = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { + if (( *(data->seq) = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { errorString_ = "MidiOutJack::initialize: JACK server not running?"; error( Error::WARNING, errorString_ ); return; @@ -4871,10 +4936,10 @@ void MidiOutJack :: connect() MidiOutJack :: ~MidiOutJack() { JackMidiData *data = static_cast (apiData_); - closePort(); + // closePort(); #if 0 - if ( data->seq ) { + if ( *(data->seq) ) { // Cleanup jack_client_close( data->client ); jack_ringbuffer_free( data->buffSize ); @@ -4882,7 +4947,7 @@ MidiOutJack :: ~MidiOutJack() } #endif - delete data; + data->stateflags = JackMidiData::DELETING; } void MidiOutJack :: openPort( unsigned int portNumber, const std::string & portName ) @@ -4893,7 +4958,7 @@ void MidiOutJack :: openPort( unsigned int portNumber, const std::string & portN // Creating new port if ( data->local == NULL ) - data->local = jack_port_register( data->seq, portName.c_str(), + data->local = jack_port_register( *(data->seq), portName.c_str(), JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); if ( data->local == NULL ) { @@ -4904,7 +4969,7 @@ void MidiOutJack :: openPort( unsigned int portNumber, const std::string & portN // Connecting to the output std::string name = getPortName( portNumber ); - jack_connect( data->seq, jack_port_name( data->local ), name.c_str() ); + jack_connect( *(data->seq), jack_port_name( data->local ), name.c_str() ); } void MidiOutJack :: openVirtualPort( const std::string portName ) @@ -4913,7 +4978,7 @@ void MidiOutJack :: openVirtualPort( const std::string portName ) // connect(); if ( data->local == NULL ) - data->local = jack_port_register( data->seq, portName.c_str(), + data->local = jack_port_register( *(data->seq), portName.c_str(), JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); if ( data->local == NULL ) { @@ -4972,7 +5037,6 @@ void MidiOutJack :: openPort( const PortDescriptor & p, jack_connect( data->client, name.c_str(), jack_port_name( data->port ) ); #endif } - Pointer MidiOutJack :: getDescriptor(bool local) { JackMidiData *data = static_cast (apiData_); @@ -5000,19 +5064,19 @@ unsigned int MidiOutJack :: getPortCount() int count = 0; JackMidiData *data = static_cast (apiData_); // connect(); - if ( !data->seq ) + if ( !*(data->seq) ) return 0; // List of available ports - const char **ports = jack_get_ports( data->seq, NULL, - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); + const char **ports = jack_get_ports(* (data->seq), NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); if ( ports == NULL ) return 0; while ( ports[count] != NULL ) count++; free( ports ); - + return count; } @@ -5024,8 +5088,8 @@ std::string MidiOutJack :: getPortName( unsigned int portNumber ) // connect(); // List of available ports - const char **ports = jack_get_ports( data->seq, NULL, - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); + const char **ports = jack_get_ports(*(data->seq), NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); // Check port validity if ( ports == NULL) { @@ -5048,11 +5112,16 @@ std::string MidiOutJack :: getPortName( unsigned int portNumber ) void MidiOutJack :: closePort() { +#if defined(__RTMIDI_DEBUG__) + std::cerr << "Closing Port" << std::endl; +#endif JackMidiData *data = static_cast (apiData_); - if ( data->local == NULL ) return; - jack_port_unregister( data->seq, data->local ); - data->local = NULL; + if ( data->local == NULL || data->state_response == JackMidiData::CLOSED ) return; + data -> stateflags = JackMidiData::CLOSING; +#if defined(__RTMIDI_DEBUG__) + std::cerr << "Closed Port" << std::endl; +#endif } void MidiOutJack :: sendMessage( std::vector &message ) From 228c91cbe3aaf1acbbb4ad366232af2affb32ec4 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 May 2014 18:13:24 +0200 Subject: [PATCH 047/210] Close the JACK independently from sending data. The client may be unable to get a write buffer for some reason. --- RtMidi.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 799e1bdd..9e3cabef 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -4837,7 +4837,6 @@ static int jackProcessOut( jack_nframes_t nframes, void *arg ) JackMidiData *data = (JackMidiData *) arg; jack_midi_data_t *midiData; int space; - bool mayclose = false; // Is port created? if ( data->local == NULL ) return 0; @@ -4850,12 +4849,8 @@ static int jackProcessOut( jack_nframes_t nframes, void *arg ) midiData = jack_midi_event_reserve( buff, 0, space ); jack_ringbuffer_read( data->buffMessage, (char *) midiData, (size_t) space ); - mayclose = true; } - if (!mayclose) - return 0; - switch (data->stateflags) { case JackMidiData::RUNNING: break; case JackMidiData::CLOSING: From a6edc5db471905ce4b49676571156c3c7df1e6e9 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 May 2014 18:13:59 +0200 Subject: [PATCH 048/210] Check whether the JACK write buffer exists before sending MIDI data. --- RtMidi.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 9e3cabef..1f454c1e 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -4842,13 +4842,15 @@ static int jackProcessOut( jack_nframes_t nframes, void *arg ) if ( data->local == NULL ) return 0; void *buff = jack_port_get_buffer( data->local, nframes ); - jack_midi_clear_buffer( buff ); + if (buff != NULL) { + jack_midi_clear_buffer( buff ); - while ( jack_ringbuffer_read_space( data->buffSize ) > 0 ) { - jack_ringbuffer_read( data->buffSize, (char *) &space, (size_t) sizeof(space) ); - midiData = jack_midi_event_reserve( buff, 0, space ); + while ( jack_ringbuffer_read_space( data->buffSize ) > 0 ) { + jack_ringbuffer_read( data->buffSize, (char *) &space, (size_t) sizeof(space) ); + midiData = jack_midi_event_reserve( buff, 0, space ); - jack_ringbuffer_read( data->buffMessage, (char *) midiData, (size_t) space ); + jack_ringbuffer_read( data->buffMessage, (char *) midiData, (size_t) space ); + } } switch (data->stateflags) { From 6c60ef5bd32a81f2a6d120dbbeedca0712e38e90 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 May 2014 15:10:45 +0200 Subject: [PATCH 049/210] Store API parameters for later usage and allow to choose the order of API detection. Both changes are needed to provide virtual ports from the all API seclection. --- RtMidi.cpp | 107 +++++++++++++++++++++++++++++++++++++---------------- RtMidi.h | 41 ++++++++++++++++---- 2 files changed, 110 insertions(+), 38 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 1f454c1e..45f9a5af 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -50,29 +50,48 @@ std::string Midi :: getVersion( void ) throw() return std::string( RTMIDI_VERSION ); } -void Midi :: getCompiledApi( std::vector &apis ) throw() +void Midi :: getCompiledApi( std::vector &apis, bool preferSystem ) throw() { apis.clear(); // The order here will control the order of RtMidi's API search in // the constructor. + + if (!preferSystem) { + // first check software and network backends +#if defined(__UNIX_JACK__) + apis.push_back( rtmidi::UNIX_JACK ); +#endif + } + + // check OS provided backends #if defined(__MACOSX_CORE__) apis.push_back( rtmidi::MACOSX_CORE ); #endif #if defined(__LINUX_ALSA__) apis.push_back( rtmidi::LINUX_ALSA ); #endif -#if defined(__UNIX_JACK__) - apis.push_back( rtmidi::UNIX_JACK ); -#endif #if defined(__WINDOWS_MM__) apis.push_back( rtmidi::WINDOWS_MM ); #endif + + if (preferSystem) { + // if we prefer OS provided backends, + // we should add the software backends, here. +#if defined(__UNIX_JACK__) + apis.push_back( rtmidi::UNIX_JACK ); +#endif + } + + // DUMMY is a no-backend class so we add it at + // the very end. #if defined(__RTMIDI_DUMMY__) apis.push_back( rtmidi::RTMIDI_DUMMY ); #endif } + + void Midi :: error( Error::Type type, std::string errorString ) { #if 0 @@ -112,38 +131,53 @@ void Midi :: error( Error::Type type, std::string errorString ) // MidiIn Definitions //*********************************************************************// -void MidiIn :: openMidiApi( ApiType api, const std::string clientName, unsigned int queueSizeLimit ) +void MidiIn :: openMidiApi( ApiType api ) { if ( rtapi_ ) delete rtapi_; rtapi_ = 0; + switch (api) { + case rtmidi::UNIX_JACK: #if defined(__UNIX_JACK__) - if ( api == rtmidi::UNIX_JACK ) rtapi_ = new MidiInJack( clientName, queueSizeLimit ); #endif + break; + case rtmidi::LINUX_ALSA: #if defined(__LINUX_ALSA__) - if ( api == rtmidi::LINUX_ALSA ) rtapi_ = new MidiInAlsa( clientName, queueSizeLimit ); #endif + break; + case rtmidi::WINDOWS_MM: #if defined(__WINDOWS_MM__) - if ( api == rtmidi::WINDOWS_MM ) rtapi_ = new MidiInWinMM( clientName, queueSizeLimit ); #endif + break; + case rtmidi::MACOSX_CORE: #if defined(__MACOSX_CORE__) - if ( api == rtmidi::MACOSX_CORE ) rtapi_ = new MidiInCore( clientName, queueSizeLimit ); #endif + break; + case rtmidi::DUMMY: #if defined(__RTMIDI_DUMMY__) - if ( api == rtmidi::RTMIDI_DUMMY ) rtapi_ = new MidiInDummy( clientName, queueSizeLimit ); #endif + break; + case rtmidi::ALL_API: + case rtmidi::UNSPECIFIED: + default: + break; + } } MidiApiList MidiIn::queryApis; -MidiIn :: MidiIn( ApiType api, const std::string clientName, unsigned int queueSizeLimit ) - : Midi(&queryApis) +MidiIn :: MidiIn( ApiType api, + const std::string clientName, + unsigned int queueSize, + bool pfsystem ) + : Midi(&queryApis,pfsystem,clientName), + queueSizeLimit(queueSize) { if ( api == rtmidi::ALL_API) { if (!queryApis.empty()) { @@ -154,7 +188,7 @@ MidiIn :: MidiIn( ApiType api, const std::string clientName, unsigned int queueS std::vector< ApiType > apis; getCompiledApi( apis ); for ( unsigned int i=0; i apis; getCompiledApi( apis ); for ( unsigned int i=0; igetPortCount() ) break; } @@ -201,39 +235,50 @@ MidiIn :: ~MidiIn() throw() // MidiOut Definitions //*********************************************************************// -void MidiOut :: openMidiApi( ApiType api, const std::string clientName ) +void MidiOut :: openMidiApi( ApiType api ) { if ( rtapi_ ) delete rtapi_; rtapi_ = 0; + switch (api) { + case rtmidi::UNIX_JACK: #if defined(__UNIX_JACK__) - if ( api == rtmidi::UNIX_JACK ) - rtapi_ = new MidiOutJack( clientName ); + rtapi_ = new MidiOutJack( clientName ); #endif + break; + case rtmidi::LINUX_ALSA: #if defined(__LINUX_ALSA__) - if ( api == rtmidi::LINUX_ALSA ) - rtapi_ = new MidiOutAlsa( clientName ); + rtapi_ = new MidiOutAlsa( clientName ); #endif + break; + case rtmidi::WINDOWS_MM: #if defined(__WINDOWS_MM__) - if ( api == rtmidi::WINDOWS_MM ) - rtapi_ = new MidiOutWinMM( clientName ); + rtapi_ = new MidiOutWinMM( clientName ); #endif + break; + case rtmidi::MACOSX_CORE: #if defined(__MACOSX_CORE__) - if ( api == rtmidi::MACOSX_CORE ) - rtapi_ = new MidiOutCore( clientName ); + rtapi_ = new MidiOutCore( clientName ); #endif + break; + case rtmidi::DUMMY: #if defined(__RTMIDI_DUMMY__) - if ( api == rtmidi::RTMIDI_DUMMY ) - rtapi_ = new MidiOutDummy( clientName ); + rtapi_ = new MidiOutDummy( clientName ); #endif + break; + case rtmidi::UNSPECIFIED: + case rtmidi::ALL_API: + default: + break; + } } MidiApiList MidiOut::queryApis; -MidiOut :: MidiOut( ApiType api, const std::string clientName ) - : Midi(&queryApis) +MidiOut :: MidiOut( ApiType api, const std::string clientName, bool pfsystem ) + : Midi(&queryApis, pfsystem, clientName) { if ( api == rtmidi::ALL_API) { if (!queryApis.empty()) { @@ -244,7 +289,7 @@ MidiOut :: MidiOut( ApiType api, const std::string clientName ) std::vector< ApiType > apis; getCompiledApi( apis ); for ( unsigned int i=0; i apis; getCompiledApi( apis ); for ( unsigned int i=0; igetPortCount() ) break; } diff --git a/RtMidi.h b/RtMidi.h index c794f61f..6703341c 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -618,8 +618,16 @@ class Midi { The values returned in the std::vector can be compared against the enumerated list values. Note that there can be more than one API compiled for certain operating systems. + + \param apis A vector apis must be provided for the + return value. All data in this vector will be + deleted prior to filling in the API data. + + \param preferSystem An opitonal boolean parameter + may be provided that tells wheter system or software + APIs shall be prefered. Passing \c true will prefer OS provided APIs */ - static void getCompiledApi( std::vector &apis ) throw(); + static void getCompiledApi( std::vector &apis, bool preferSystem = true ) throw(); //! A static function to determine the available compiled MIDI APIs. /*! @@ -790,9 +798,15 @@ class Midi { protected: MidiApi *rtapi_; MidiApiList * list; + bool preferSystem; + std::string clientName; - Midi(MidiApiList * l):rtapi_(0),list(l) {} - ~Midi() + Midi(MidiApiList * l, + bool pfsystem, + const std::string & name):rtapi_(0), + list(l), + preferSystem(pfsystem), + clientName(name) {} { if (rtapi_) { delete rtapi_; @@ -855,10 +869,20 @@ class MidiIn : public Midi will be used to group the ports that are created by the application. \param queueSizeLimit An optional size of the MIDI input queue can be specified. + + \param pfsystem An optional boolean parameter can be + provided to indicate the API preferences of the user + code. If RtMidi is requested to autoselect a backend + this parameter tells which backend should be tried + first. If it is \c true the backend will prefer OS + provieded APIs (WinMM, ALSA, Core MIDI) over other + APIs (JACK). If \c false, the order will be vice + versa. */ MidiIn( ApiType api=rtmidi::UNSPECIFIED, const std::string clientName = std::string( "RtMidi Input Client"), - unsigned int queueSizeLimit = 100 ); + unsigned int queueSizeLimit = 100, + bool pfsystem = true); //! If a MIDI connection is still open, it will be closed by the destructor. ~MidiIn ( void ) throw(); @@ -986,7 +1010,8 @@ class MidiIn : public Midi protected: static MidiApiList queryApis; - void openMidiApi( ApiType api, const std::string clientName, unsigned int queueSizeLimit ); + int queueSizeLimit; + void openMidiApi( ApiType api ); }; @@ -1019,7 +1044,8 @@ class MidiOut : public Midi JACK (OS-X). */ MidiOut( ApiType api=rtmidi::UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Output Client") ); + const std::string clientName = std::string( "RtMidi Output Client"), + bool pfsystem = true); //! The destructor closes any open MIDI connections. ~MidiOut( void ) throw(); @@ -1086,7 +1112,7 @@ class MidiOut : public Midi } protected: static MidiApiList queryApis; - void openMidiApi( ApiType api, const std::string clientName ); + void openMidiApi( ApiType api ); }; @@ -1096,6 +1122,7 @@ class MidiOut : public Midi // // **************************************************************** // + #if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__) #define __RTMIDI_DUMMY__ #endif From 1a0e931d5471d795d48b857ece437c909a27ae25 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 May 2014 15:12:30 +0200 Subject: [PATCH 050/210] Implement virtual ports for rtmidi::ALL_API --- RtMidi.h | 117 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 100 insertions(+), 17 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index 6703341c..65f34f7d 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -368,6 +368,14 @@ class MidiApi MidiApi(); virtual ~MidiApi(); + //! Return whether the API supports virtual ports + /*! + \retval true The funcion returns true if the API supports virtual ports. + \retval false The funcion returns false if the API doesn't support virtual ports. + \sa openVirtualPort + */ + virtual bool hasVirtualPorts() const = 0; + //! Pure virtal function to create a virtual port, with optional name. /*! This function creates a virtual MIDI port to which other @@ -377,6 +385,8 @@ class MidiApi \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + + \sa hasVirtualPorts */ virtual void openVirtualPort( const std::string portName = std::string( "RtMidi virtual port" ) ) = 0; @@ -648,23 +658,9 @@ class Midi { else return rtmidi::UNSPECIFIED; } - //! Function to create a virtual port, with optional name. - /*! - This function creates a virtual MIDI port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, any JACK, - and Linux ALSA APIs (the function returns an error for the other APIs). - - \param portName An optional name for the applicaction port that is - used to connect to portId can be specified. - */ - void openVirtualPort( const std::string portName = std::string( "RtMidi virtual port" ) ) - { - if (rtapi_) rtapi_->openVirtualPort(portName); - else { - error(Error::INVALID_DEVICE,"Midi::OpenVirtualPort: No valid API selected"); - } - } + //! Compatibilty function for older code + virtual + RTMIDI_DEPRECATED(void openVirtualPort( const std::string portName = std::string( "RtMidi virtual port" ) )) = 0; //! Pure virtual function to open a MIDI connection given by enumeration number. /*! \param portNumber An optional port number greater than 0 @@ -807,6 +803,7 @@ class Midi { list(l), preferSystem(pfsystem), clientName(name) {} + virtual ~Midi() { if (rtapi_) { delete rtapi_; @@ -917,6 +914,36 @@ class MidiIn : public Midi openPort(*p, portName); } + //! Function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the application port that is + used to connect to portId can be specified. + */ + void openVirtualPort( const std::string portName = std::string( "RtMidi virtual input port" ) ) + { + if (!rtapi_ && list && !list->empty()) { + Pointer api = list->front(); + + std::vector< ApiType > apis; + getCompiledApi( apis ); + for (size_t i = 0 ; i < apis.size() ; i++) { + openMidiApi( apis[0] ); + if (rtapi_ && rtapi_->hasVirtualPorts()) break; + } + } + + if (rtapi_) rtapi_->openVirtualPort(portName); + else { + error(Error::INVALID_DEVICE,"MidiIn::openVirtualPort: No valid API selected"); + } + } + + //! Pure virtual function to return a port descirptor if the port is open Pointer getDescriptor(bool local=false) { @@ -1042,6 +1069,21 @@ class MidiOut : public Midi If no API argument is specified and multiple API support has been compiled, the default order of use is JACK, ALSA (Linux) and CORE, JACK (OS-X). + + \param api An optional API id can be specified. + \param clientName An optional Client name can be specified. This + will be used to group the ports that are created + by the application. + \param queueSizeLimit An optional size of the MIDI input queue can be specified. + + \param pfsystem An optional boolean parameter can be + provided to indicate the API preferences of the user + code. If RtMidi is requested to autoselect a backend + this parameter tells which backend should be tried + first. If it is \c true the backend will prefer OS + provieded APIs (WinMM, ALSA, Core MIDI) over other + APIs (JACK). If \c false, the order will be vice + versa. */ MidiOut( ApiType api=rtmidi::UNSPECIFIED, const std::string clientName = std::string( "RtMidi Output Client"), @@ -1080,6 +1122,37 @@ class MidiOut : public Midi } + //! Function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + */ + void openVirtualPort( const std::string portName = std::string( "RtMidi virtual output port" ) ) + { + if (!rtapi_ && list && !list->empty()) { + Pointer api = list->front(); + + std::vector< ApiType > apis; + getCompiledApi( apis ); + for (size_t i = 0 ; i < apis.size() ; i++) { + openMidiApi( apis[0] ); + if (rtapi_ && rtapi_->hasVirtualPorts()) break; + } + } + + if (rtapi_) rtapi_->openVirtualPort(portName); + else { + error(Error::INVALID_DEVICE,"MidiOut::openVirtualPort: No valid API selected"); + } + } + + + //! Immediately send a single message out an open MIDI output port. /*! An exception is thrown if an error occurs during output or an @@ -1135,6 +1208,7 @@ class MidiInCore: public MidiInApi MidiInCore( const std::string clientName, unsigned int queueSizeLimit ); ~MidiInCore( void ); ApiType getCurrentApi( void ) throw() { return MACOSX_CORE; }; + bool hasVirtualPorts() const { return true; } void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); @@ -1154,6 +1228,7 @@ class MidiOutCore: public MidiOutApi MidiOutCore( const std::string clientName ); ~MidiOutCore( void ); ApiType getCurrentApi( void ) throw() { return MACOSX_CORE; }; + bool hasVirtualPorts() const { return true; } void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); @@ -1178,6 +1253,7 @@ class MidiInJack: public MidiInApi MidiInJack( const std::string clientName, unsigned int queueSizeLimit ); ~MidiInJack( void ); ApiType getCurrentApi( void ) throw() { return UNIX_JACK; }; + bool hasVirtualPorts() const { return true; } void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); @@ -1200,6 +1276,7 @@ class MidiOutJack: public MidiOutApi MidiOutJack( const std::string clientName ); ~MidiOutJack( void ); ApiType getCurrentApi( void ) throw() { return UNIX_JACK; }; + bool hasVirtualPorts() const { return true; } void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); @@ -1227,6 +1304,7 @@ class MidiInAlsa: public MidiInApi MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit ); ~MidiInAlsa( void ); ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; + bool hasVirtualPorts() const { return true; } void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); @@ -1246,6 +1324,7 @@ class MidiOutAlsa: public MidiOutApi MidiOutAlsa( const std::string clientName ); ~MidiOutAlsa( void ); ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; + bool hasVirtualPorts() const { return true; } void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); @@ -1270,6 +1349,7 @@ class MidiInWinMM: public MidiInApi MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ); ~MidiInWinMM( void ); ApiType getCurrentApi( void ) { return WINDOWS_MM; }; + bool hasVirtualPorts() const { return false; } void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); @@ -1289,6 +1369,7 @@ class MidiOutWinMM: public MidiOutApi MidiOutWinMM( const std::string clientName ); ~MidiOutWinMM( void ); ApiType getCurrentApi( void ) { return WINDOWS_MM; }; + bool hasVirtualPorts() const { return false; } void openPort( unsigned int portNumber, const std::string & portName ); void openVirtualPort( const std::string portName ); void openPort( const PortDescriptor & port, const std::string & portName); @@ -1316,6 +1397,7 @@ class MidiInDummy: public MidiInApi error( Error::WARNING, errorString_ ); } ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } + bool hasVirtualPorts() const { return false; } void openPort( unsigned int /*portNumber*/, const & std::string /*portName*/ ) {} void openVirtualPort( const std::string /*portName*/ ) {} void openPort( const PortDescriptor & port, const & std::string portName) {} @@ -1337,6 +1419,7 @@ class MidiOutDummy: public MidiOutApi error( Error::WARNING, errorString_ ); } ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } + bool hasVirtualPorts() const { return false; } void openPort( unsigned int /*portNumber*/, const & std::string /*portName*/ ) {} void openVirtualPort( const std::string /*portName*/ ) {} void openPort( const PortDescriptor & port, const & std::string portName) {} From b61b6b8341c797a39d6310ec893973a74ed263bd Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 May 2014 15:14:47 +0200 Subject: [PATCH 051/210] Update input tests/examples for rtmidi::ALL_API. --- tests/cmidiin2.cpp | 153 ++++++++++++++++++++++----------------------- tests/qmidiin2.cpp | 11 ++-- 2 files changed, 83 insertions(+), 81 deletions(-) diff --git a/tests/cmidiin2.cpp b/tests/cmidiin2.cpp index 549b1316..9bd0bb93 100644 --- a/tests/cmidiin2.cpp +++ b/tests/cmidiin2.cpp @@ -14,21 +14,13 @@ #include #include "RtMidi.h" -void usage( void ) { - // Error function in case of incorrect command-line - // argument specifications. - std::cout << "\nuseage: cmidiin2 \n"; - std::cout << " where port = the device to use (default = 0).\n\n"; - exit( 0 ); -} - void mycallback( double deltatime, std::vector< unsigned char > *message, void * /* userData */ ) { - unsigned int nBytes = message->size(); - for ( unsigned int i=0; i 0 ) - std::cout << "stamp = " << deltatime << std::endl; + unsigned int nBytes = message->size(); + for ( unsigned int i=0; i 0 ) + std::cout << "stamp = " << deltatime << std::endl; } // This function should be embedded in a try/catch block in case of @@ -36,81 +28,88 @@ void mycallback( double deltatime, std::vector< unsigned char > *message, void * // It returns false if there are no ports available. bool chooseMidiPort( rtmidi::MidiIn &rtmidi ); -int main( int argc, char */*argv*/[] ) +int main( int /* argc */, char */*argv*/[] ) { - // Minimal command-line check. - if ( argc > 2 ) usage(); + std::vector message; + std::cout << "\nWould you like to check all output ports? [Y/n] "; + + std::string keyHit; + std::getline( std::cin, keyHit ); + rtmidi::ApiType type = rtmidi::ALL_API; + if ( keyHit == "n" ) { + type = rtmidi::UNSPECIFIED; + } - try { + try { - // rtmidi::MidiIn constructor - rtmidi::MidiIn midiin; + // rtmidi::MidiIn constructor + rtmidi::MidiIn midiin(type); - // Call function to select port. - if ( chooseMidiPort( midiin ) == false ) return 0; + // Call function to select port. + if ( chooseMidiPort( midiin ) == false ) return 0; - // Set our callback function. This should be done immediately after - // opening the port to avoid having incoming messages written to the - // queue instead of sent to the callback function. - midiin.setCallback( &mycallback ); + // Set our callback function. This should be done immediately after + // opening the port to avoid having incoming messages written to the + // queue instead of sent to the callback function. + midiin.setCallback( &mycallback ); - // Don't ignore sysex, timing, or active sensing messages. - midiin.ignoreTypes( false, false, false ); + // Don't ignore sysex, timing, or active sensing messages. + midiin.ignoreTypes( false, false, false ); - std::cout << "\nReading MIDI input ... press to quit.\n"; - char input; - std::cin.get(input); + std::cout << "\nReading MIDI input ... press to quit.\n"; + char input; + std::cin.get(input); - } catch ( rtmidi::Error &error ) { - error.printMessage(); - } + } catch ( rtmidi::Error &error ) { + error.printMessage(); + } } bool chooseMidiPort( rtmidi::MidiIn &midi ) { - std::cout << "\nWould you like to open a virtual input port? [y/N] "; - - std::string keyHit; - std::getline( std::cin, keyHit ); - if ( keyHit == "y" ) { - midi.openVirtualPort("RtMidi virtual input"); - return true; - } - - std::string portName; - rtmidi::PortList list = midi.getPortList(rtmidi::PortDescriptor::INPUT); - if ( list.empty() ) { - std::cout << "No input ports available!" << std::endl; - return false; - } - - rtmidi::Pointer selected = list.front(); - if ( list.size() == 1 ) { - std::cout << "\nOpening " << selected->getName() << std::endl; - } else { - int nr; - std::vector > pointers(list.size()); - // copy the data into a structure that is used by the user interface. - std::copy(list.begin(),list.end(),pointers.begin()); - for (nr = 0 ; nr < (int)pointers.size(); nr++) { - portName = pointers[nr]->getName(rtmidi::PortDescriptor::LONG_NAME - | rtmidi::PortDescriptor::UNIQUE_NAME - | rtmidi::PortDescriptor::INCLUDE_API); - std::cout << " Input port #" << nr << ": " << portName << '\n'; - } - - do { - std::cout << "\nChoose a port number: "; - std::cin >> nr; - } while ( nr >= (int)pointers.size() ); - std::getline( std::cin, keyHit ); // used to clear out stdin - selected = pointers[nr]; - } - - /* The midi setup might have changed meanwhile. - Our portlist is under our control. So we enumerate this list. */ - // midi.openPort( i ); - midi.openPort(selected); - return true; + std::cout << "\nWould you like to open a virtual input port? [y/N] "; + + std::string keyHit; + std::getline( std::cin, keyHit ); + if ( keyHit == "y" ) { + midi.openVirtualPort("RtMidi virtual input"); + return true; + } + + std::string portName; + rtmidi::PortList list = midi.getPortList(rtmidi::PortDescriptor::INPUT); + if ( list.empty() ) { + std::cout << "No input ports available!" << std::endl; + return false; + } + + rtmidi::Pointer selected = list.front(); + if ( list.size() == 1 ) { + std::cout << "\nOpening " << selected->getName() << std::endl; + } else { + int nr; + std::vector > pointers(list.size()); + // copy the data into a structure that is used by the user interface. + std::copy(list.begin(),list.end(),pointers.begin()); + for (nr = 0 ; nr < (int)pointers.size(); nr++) { + portName = pointers[nr]->getName(rtmidi::PortDescriptor::LONG_NAME + | rtmidi::PortDescriptor::UNIQUE_NAME + | rtmidi::PortDescriptor::INCLUDE_API); + std::cout << " Input port #" << nr << ": " << portName << '\n'; + } + + do { + std::cout << "\nChoose a port number: "; + std::cin >> nr; + } while ( nr >= (int)pointers.size() ); + std::getline( std::cin, keyHit ); // used to clear out stdin + selected = pointers[nr]; + } + + /* The midi setup might have changed meanwhile. + Our portlist is under our control. So we enumerate this list. */ + // midi.openPort( i ); + midi.openPort(selected); + return true; } diff --git a/tests/qmidiin2.cpp b/tests/qmidiin2.cpp index 0e364ea9..b32d78be 100644 --- a/tests/qmidiin2.cpp +++ b/tests/qmidiin2.cpp @@ -17,7 +17,7 @@ // Platform-dependent sleep routines. #if defined(__WINDOWS_MM__) #include -#define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) +#define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) #else // Unix variants #include #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) @@ -35,9 +35,11 @@ void usage( rtmidi::PortList list ) { std::cout << "Available ports:" << std::endl; for (rtmidi::PortList::iterator i = list.begin(); i != list.end(); i++) { - std::cout << (*i)->getName(rtmidi::PortDescriptor::SESSION_PATH | + std::cout << "\"" + << (*i)->getName(rtmidi::PortDescriptor::SESSION_PATH | rtmidi::PortDescriptor::UNIQUE_NAME | - rtmidi::PortDescriptor::INCLUDE_API); + rtmidi::PortDescriptor::INCLUDE_API) + << "\""; std::cout << "\t"; std::cout << (*i)->getName() << std::endl; } @@ -53,11 +55,12 @@ int main( int argc, char *argv[] ) // rtmidi::MidiIn constructor try { - rtmidi::MidiIn midiin; + rtmidi::MidiIn midiin(rtmidi::ALL_API); rtmidi::PortList list = midiin.getPortList(); + // Minimal command-line check. if ( argc > 2 ) usage(list); From f5725fc84432e7bbf3c2544c7649ef06ab7ac74c Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 May 2014 15:15:54 +0200 Subject: [PATCH 052/210] Update the documentation to reflect the last changes to RtMidi --- doc/doxygen/tutorial.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/doxygen/tutorial.txt b/doc/doxygen/tutorial.txt index 3dd74207..1911ca60 100644 --- a/doc/doxygen/tutorial.txt +++ b/doc/doxygen/tutorial.txt @@ -455,17 +455,21 @@ If you are having problems getting RtMidi to run on your system, try passing the \section multi Using Simultaneous Multiple APIs -Support for each MIDI API is encapsulated in specific MidiInApi or MidiOutApi subclasses, making it possible to compile and instantiate multiple API-specific subclasses on a given operating system. For example, one can compile both CoreMIDI and JACK support on the OS-X operating system by providing the appropriate preprocessor definitions for each. In a run-time situation, one might first attempt to determine whether any JACK ports are available. This can be done by specifying the api argument rtmidi::UNIX_JACK when attempting to create an instance of rtmidi::MidiIn or rtmidi::MidiOut. If no available ports are found, then an instance of rtmidi::Midi with the api argument rtmidi::MACOSX_CORE can be created. Alternately, if no api argument is specified, RtMidi will first look for JACK ports and if none are found, then CoreMIDI ports (in linux, the search order is JACK and then ALSA). In theory, it should also be possible to have separate instances of RtMidi open at the same time with different underlying API support, though this has not been tested. +Support for each MIDI API is encapsulated in specific \ref rtmidi::MidiInApi or \ref rtmidi::MidiOutApi subclasses, making it possible to compile and instantiate multiple API-specific subclasses on a given operating system. For example, one can compile both CoreMIDI and JACK support on the OS-X operating system by providing the appropriate preprocessor definitions for each. In a run-time situation, one might first attempt to determine whether any JACK ports are available. This can be done by specifying the api argument rtmidi::UNIX_JACK when attempting to create an instance of rtmidi::MidiIn or rtmidi::MidiOut. If no available ports are found, then an instance of rtmidi::Midi with the api argument rtmidi::MACOSX_CORE can be created. Alternately, if no api argument is specified, RtMidi will first look for OS provided ports and if none are found, then software demons (currently JACK) ports (in linux, the search order is ALSA and then JACK). + +It is also possible to use all compiled backends simultaneously by passing the special api argument rtmidi::ALL_API to the constructor. In that case rtmidi::midi::getPortList will return a list of all port descriptors from all backends that are available. On the other hand rtmidi::midi::openVirtualPort will open only one port on the first API that is tested in the automatic port selecton as described above. The static function rtmidi::Midi::getCompiledApi() is provided to determine the available compiled API support. The function rtmidi::Midi::getCurrentApi() indicates the API selected for a given RtMidi instance. +\note It is recommended to avoid the atomatic API selection for virtual ports. In most cases it is a better option to let the end user choose the API for this port or simply generate an array of ports, each with a different backend API. + \section apinotes API Notes RtMidi is designed to provide a common API across the various supported operating systems and audio libraries. Despite that, some issues should be mentioned with regard to each. \subsection linux Linux: -Two different MIDI APIs are supported on Linux platforms: ALSA and JACK. A decision was made to not include support for the OSS API because the OSS API provides very limited functionality and because ALSA support is now incorporated in the Linux kernel. The ALSA sequencer and JACK APIs allows for virtual software input and output ports. +Two different MIDI APIs are supported on Linux platforms: ALSA and JACK. A decision was made to not include support for the OSS API because the OSS API provides very limited functionality and because ALSA support is incorporated in the Linux kernel. The ALSA sequencer and JACK APIs allows for virtual software input and output ports. \subsection macosx Macintosh OS X (CoreAudio): From af535ed9e228eacff561821f8f51be677bb2b7e1 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 28 May 2014 20:27:36 +0200 Subject: [PATCH 053/210] Fix some errors found by Gary. This patch has been tested both with g++ 4.1 and 4.4. --- RtMidi.cpp | 28 ++++++++++++++-------------- tests/loopback.cpp | 6 +++--- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 45f9a5af..3ee17c31 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -940,13 +940,13 @@ class CoreSequencer { portname = str(nameRef); CFRelease( nameRef ); - MIDIEntityRef entity = NULL; + MIDIEntityRef entity = 0; MIDIEndpointGetEntity(port, &entity); // entity == NULL: probably virtual - if (entity != NULL) { + if (entity != 0) { nameRef = NULL; MIDIObjectGetStringProperty(entity, kMIDIPropertyName, &nameRef); - if (str != NULL) { + if (nameRef != NULL) { entityname = str(nameRef); CFRelease(nameRef); } @@ -956,9 +956,9 @@ class CoreSequencer { >= 2; // now consider the device's name - MIDIDeviceRef device = NULL; + MIDIDeviceRef device = 0; MIDIEntityGetDevice(entity, &device); - if (device != NULL) { + if (device != 0) { hasManyEntities = MIDIDeviceGetNumberOfEntities(device) >= 2; MIDIObjectGetStringProperty(device, kMIDIPropertyName, @@ -1245,13 +1245,13 @@ Could not get the entity of a midi endpoint.", &port); break; default: - throw Error(Error::DRIVER_ERROR, - "CoreSequencer::createVirtualPort:\ - Error creating OS X MIDI port because of invalid port flags"); + throw Error("CoreSequencer::createVirtualPort:\ + Error creating OS X MIDI port because of invalid port flags", + Error::DRIVER_ERROR); } if ( result != noErr ) { - throw Error( Error::DRIVER_ERROR, - "CoreSequencer::createVirtualPort: error creating OS-X MIDI port." ); + throw Error( "CoreSequencer::createVirtualPort: error creating OS-X MIDI port.", + Error::DRIVER_ERROR); } return port; } @@ -1450,7 +1450,7 @@ PortList CorePortDescriptor :: getPortList(int capabilities, const std::string & CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); int caps = capabilities & PortDescriptor::INOUTPUT; - bool unlimited = capabilities & PortDescriptor::UNLIMITED; + // bool unlimited = capabilities & PortDescriptor::UNLIMITED; bool forceInput = PortDescriptor::INPUT & caps; bool forceOutput = PortDescriptor::OUTPUT & caps; bool allowOutput = forceOutput || !forceInput; @@ -1549,7 +1549,7 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void * if ( nBytes == 0 ) continue; // Calculate time stamp. - + if ( data->firstMessage ) { message.timeStamp = 0.0; data->firstMessage = false; @@ -1569,7 +1569,7 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void * apiData->lastTime = AudioGetCurrentHostTime(); } //std::cout << "TimeStamp = " << packet->timeStamp << std::endl; - + iByte = 0; if ( continueSysex ) { // We have a continuing, segmented sysex message. @@ -1599,7 +1599,7 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void * std::cerr << "\nMidiInCore: message queue limit reached!!\n\n"; } message.bytes.clear(); - } + } } } else { diff --git a/tests/loopback.cpp b/tests/loopback.cpp index 5082f05c..c8446174 100644 --- a/tests/loopback.cpp +++ b/tests/loopback.cpp @@ -39,7 +39,7 @@ inline size_t getlength(const char * messages) { return ++retval; } -void mycallback1( double deltatime, std::vector< unsigned char > *message, void * /* userData */ ) +void mycallback1( double /* deltatime */, std::vector< unsigned char > *message, void * /* userData */ ) { unsigned int nBytes = message->size(); for ( unsigned int i=0; i *message, void */ } -void mycallback2( double deltatime, std::vector< unsigned char > *message, void * /* userData */ ) +void mycallback2( double /* deltatime */, std::vector< unsigned char > *message, void * /* userData */ ) { unsigned int nBytes = message->size(); for ( unsigned int i=0; i *message, void -int main( int argc, char */*argv*/[] ) +int main( int /* argc */, char * /*argv*/[] ) { std::vector message; From e3374cfb10f0fbfdb57629662c9475ae16d9c6c0 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Thu, 29 May 2014 18:00:11 +0200 Subject: [PATCH 054/210] make PortDescriptor a class (it was partly a struct). --- RtMidi.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RtMidi.h b/RtMidi.h index 65f34f7d..31b98927 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -244,7 +244,8 @@ class MidiApi; class MidiInApi; class MidiOutApi; -struct PortDescriptor { +class PortDescriptor { +public: //! Flags for formatting a string description of the port. /*! These flags just mark the requirements that the string should fulfil. An API may return the same string for From 14a3c8ff8069a9ef6d5b9111f67933b4883ec707 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 7 Jun 2014 21:36:18 +0200 Subject: [PATCH 055/210] Use automake for tests and provide some limited test cases. --- Makefile.am | 1 + configure.ac | 9 +++++++ tests/Makefile.am | 39 +++++++++++++++++++++++++++ tests/Makefile.in | 68 ----------------------------------------------- 4 files changed, 49 insertions(+), 68 deletions(-) create mode 100644 tests/Makefile.am delete mode 100644 tests/Makefile.in diff --git a/Makefile.am b/Makefile.am index 4851619d..88c162b7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,4 @@ +SUBDIRS = . tests lib_LTLIBRARIES = %D%/librtmidi.la %C%_librtmidi_la_LDFLAGS = -no-undefined %C%_librtmidi_la_SOURCES = \ diff --git a/configure.ac b/configure.ac index d47e76ba..1eb07dcd 100644 --- a/configure.ac +++ b/configure.ac @@ -135,9 +135,11 @@ esac AC_SUBST( api, [""] ) AC_SUBST( req, [""] ) AC_MSG_CHECKING(for MIDI API) +have_virtual_devices=no case $host in *-*-linux*) AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (mac and linux only)], [ + have_virtual_devices=yes api="$api -D__UNIX_JACK__" AC_MSG_RESULT(using JACK) AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], ) @@ -151,6 +153,7 @@ return jack_port_uuid(NULL); # Look for ALSA flag AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA sequencer API support (linux only)], [ + have_virtual_devices=yes api="$api -D__LINUX_ALSA__" req="$req alsa" AC_MSG_RESULT(using ALSA) @@ -160,6 +163,7 @@ return jack_port_uuid(NULL); AC_MSG_RESULT(using ALSA) AC_SUBST( api, [-D__LINUX_ALSA__] ) req="$req alsa" + have_virtual_devices=yes AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(ALSA sequencer support requires the asound library!)) fi @@ -169,6 +173,7 @@ return jack_port_uuid(NULL); *-apple*) AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (mac and linux only)], [ + have_virtual_devices=yes api="$api -D__UNIX_JACK__" AC_MSG_RESULT(using JACK) AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], ) @@ -182,6 +187,7 @@ return jack_port_uuid(NULL); # Look for Core flag AC_ARG_WITH(core, [ --with-core = choose CoreMidi API support (mac only)], [ + have_virtual_devices=yes api="$api -D__MACOSX_CORE__" AC_MSG_RESULT(using CoreMidi) AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, [], [AC_MSG_ERROR(CoreMIDI header files not found!)] ) @@ -189,6 +195,7 @@ return jack_port_uuid(NULL); # If no api flags specified, use CoreMidi if [test "$api" == ""; ] then + have_virtual_devices=yes AC_SUBST( api, [-D__MACOSX_CORE__] ) AC_MSG_RESULT(using CoreMidi) AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, @@ -227,6 +234,8 @@ return jack_port_uuid(NULL); AC_MSG_ERROR(Unknown system type for MIDI support!) ;; esac +AM_CONDITIONAL(HAVE_VIRTUAL_DEVICES,test "$have_virtual_devices" == yes) + CPPFLAGS="$CPPFLAGS $api" diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 00000000..a6effbce --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,39 @@ +### RtMidi tests Makefile - for various flavors of unix +AM_CPPFLAGS = -I$(top_srcdir) +LDADD = -L$(top_builddir) -lrtmidi @LIBS@ + +noinst_PROGRAMS = \ + midiprobe \ + midiout \ + qmidiin \ + cmidiin \ + sysextest \ + midiprobe2 \ + midiprobe-all \ + cmidiin2 \ + qmidiin2 \ + midiout2 \ + loopback + +TESTS = \ + midiprobe \ + midiprobe2 \ + midiprobe-all + +if HAVE_VIRTUAL_DEVICES +TESTS += loopback +endif + + + +midiprobe_SOURCES = midiprobe.cpp +midiout_SOURCES = midiout.cpp +qmidiin_SOURCES = qmidiin.cpp +cmidiin_SOURCES = cmidiin.cpp +sysextest_SOURCES = sysextest.cpp +midiprobe2_SOURCES = midiprobe2.cpp +midiprobe_all_SOURCES = midiprobe-all.cpp +cmidiin2_SOURCES = cmidiin2.cpp +qmidiin2_SOURCES = qmidiin2.cpp +midiout2_SOURCES = midiout2.cpp +loopback_SOURCES = loopback.cpp diff --git a/tests/Makefile.in b/tests/Makefile.in deleted file mode 100644 index cb2ed60f..00000000 --- a/tests/Makefile.in +++ /dev/null @@ -1,68 +0,0 @@ -### Do not edit -- Generated by 'configure --with-whatever' from Makefile.in -### RtMidi tests Makefile - for various flavors of unix - -PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest midiprobe2 midiprobe-all cmidiin2 qmidiin2 midiout2 loopback -RM = /bin/rm -SRC_PATH = .. -INCLUDE = @top_srcdir@ -OBJECT_PATH = @object_path@ -vpath %.o $(OBJECT_PATH) - -OBJECTS = @top_builddir@/RtMidi.o - -CC = @CXX@ -DEFS = @CPPFLAGS@ -CFLAGS = @CXXFLAGS@ -CFLAGS += -I$(INCLUDE) -LIBRARY = @LIBS@ - -%.o : $(SRC_PATH)/%.cpp - $(CC) $(CFLAGS) $(DEFS) -c $(<) -o $(OBJECT_PATH)/$@ - -all : $(PROGRAMS) - -#RtMidi.o: $(SRC_PATH)/RtMidi.cpp $(SRC_PATH)/RtMidi.h -midiprobe : @srcdir@/midiprobe.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o midiprobe $^ $(LIBRARY) - -midiprobe2 : @srcdir@/midiprobe2.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o midiprobe2 $^ $(LIBRARY) - -midiprobe-all : @srcdir@/midiprobe-all.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o midiprobe-all $^ $(LIBRARY) - -midiout : @srcdir@/midiout.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o midiout $^ $(LIBRARY) - -midiout2 : @srcdir@/midiout2.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o midiout2 $^ $(LIBRARY) - -qmidiin : @srcdir@/qmidiin.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o qmidiin $^ $(LIBRARY) - -qmidiin2 : @srcdir@/qmidiin2.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o qmidiin2 $^ $(LIBRARY) - -cmidiin : @srcdir@/cmidiin.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o cmidiin $^ $(LIBRARY) - -cmidiin2 : @srcdir@/cmidiin2.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o cmidiin2 $^ $(LIBRARY) - -sysextest : @srcdir@/sysextest.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o sysextest $^ $(LIBRARY) - -loopback : @srcdir@/loopback.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o loopback $^ $(LIBRARY) - -clean : - $(RM) -f $(OBJECT_PATH)/*.o - $(RM) -f $(PROGRAMS) *.exe - $(RM) -f *~ - $(RM) -fR *.dSYM - -distclean: clean - $(RM) -f Makefile - -strip : - strip $(PROGRAMS) From 87b23adbef5cfcb1768482e72727d3d5a2bf96d6 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 8 Jun 2014 16:01:22 +0200 Subject: [PATCH 056/210] Fix compilation on Windows. --- RtMidi.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 76094370..87efcd8e 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -3938,13 +3938,13 @@ struct WinMMPortDescriptor:public PortDescriptor { } ~WinMMPortDescriptor() {} - MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) { + MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) const { if (is_input) return new MidiInWinMM(clientName,queueSizeLimit); else return 0; } - MidiOutApi * getOutputApi() { + MidiOutApi * getOutputApi() const { if (!is_input) return new MidiOutWinMM(clientName); else @@ -4330,7 +4330,7 @@ Pointer MidiInWinMM :: getDescriptor(bool local) return 0; case MMSYSERR_NOMEM: error (Error::DRIVER_ERROR, - "MidiInWinMM::getDescriptor: The system could not handle enough memory."); + "MidiInWinMM::getDescriptor: The system could not provide enough memory."); return 0; } return new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); @@ -4344,6 +4344,7 @@ PortList MidiInWinMM :: getPortList(int capabilities) return WinMMPortDescriptor::getPortList(PortDescriptor::INPUT,data->getClientName()); } + void MidiInWinMM :: closePort( void ) { if ( connected_ ) { From f1393459f5ba964e3cce941f7c67b2b31577b834 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 8 Jun 2014 17:11:03 +0200 Subject: [PATCH 057/210] Fix some compilation warnings in the WinMM code. --- RtMidi.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 87efcd8e..6f1e9728 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -3696,7 +3696,7 @@ class WinMMSequencer { unsigned int nDevices = is_input?midiInGetNumDevs() : midiOutGetNumDevs(); - if ( port >= nDevices ) { + if ( port < 0 || (unsigned int)port >= nDevices ) { std::ostringstream ost; std::cerr << port << "<" << nDevices << std::endl; throw Error("WinMMSequencer::getPortName: the 'port' argument is invalid.", @@ -3927,7 +3927,7 @@ typedef WinMMSequencer<0> NonLockingWinMMSequencer; struct WinMMPortDescriptor:public PortDescriptor { static NonLockingWinMMSequencer seq; - WinMMPortDescriptor(const std::string & cname):name(),port(0),clientName(name) + WinMMPortDescriptor(const std::string & /*cname*/):name(),port(0),clientName(name) { } WinMMPortDescriptor(unsigned int p, const std::string & pn, bool i_o, const std::string & n): @@ -4031,8 +4031,6 @@ PortList WinMMPortDescriptor :: getPortList(int capabilities, const std::string return list; } -static void *winMMMidiHandler( void *ptr ); - /*! A structure to hold variables related to the WINMM API implementation. From ce531f680a2d0d363131dbc2410eec74b6d6f8a3 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 8 Jun 2014 17:14:26 +0200 Subject: [PATCH 058/210] getPortList returns an empty set if the requirements cannot be met. It's up to the developers to deal with this case, anyway. --- RtMidi.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 6f1e9728..1a3e0fe9 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -4338,7 +4338,7 @@ Pointer MidiInWinMM :: getDescriptor(bool local) PortList MidiInWinMM :: getPortList(int capabilities) { WinMidiData *data = static_cast (apiData_); - if (!data) return PortList(); + if (!data || capabilities != PortDescriptor::INPUT) return PortList(); return WinMMPortDescriptor::getPortList(PortDescriptor::INPUT,data->getClientName()); } @@ -4587,7 +4587,7 @@ Pointer MidiOutWinMM :: getDescriptor(bool local) PortList MidiOutWinMM :: getPortList(int capabilities) { WinMidiData *data = static_cast (apiData_); - if (!data) return PortList(); + if (!data || capabilities != PortDescriptor::OUTPUT) return PortList(); return WinMMPortDescriptor::getPortList(PortDescriptor::OUTPUT,data->getClientName()); } From e17a725b40a14de44e9b25c13f251c3f4c7c198c Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 7 Jun 2014 19:31:37 +0200 Subject: [PATCH 059/210] End-user friendly error messages. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch changes the way error messages are handled: • source code locations are stored separately in the exception. This allows a GUI to prevent confusion of the end user while maintaining the ability to debug RtMidi. • all strings are marked with gettext_noopt so that it is easy to extract them. • if RtMidi is compiled with gettext support, gettext is called in the constructor of the error message. Drawbacks: This approach still doesn't support to use correct plural forms. However, this limitation can be easily circumvented by adding a parameter for the translated text. Benefits: All calls to gettext are bundled in the library part of RtMidi. This may prevent confusion that can occur when libraries like wxWidgets come into play, which provide their own gettext implementation. Missing parts: automatic initialisation of libintl. --- RtMidi.cpp | 771 +++++++++++++++++++++++++++++------------------------ RtMidi.h | 98 +++++-- 2 files changed, 490 insertions(+), 379 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 3ee17c31..17258388 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -42,6 +42,55 @@ #include NAMESPACE_RTMIDI_START + +//! The constructor. +Error::Error( const char * message, + Type type, + const char * class_name, + const char * function_name, + const char * file_name, + int line_number, ...) throw():exception(), + classname(class_name), + function(function_name), + file(file_name), + line(line_number), + type_(type) +{ +#ifdef RTMIDI_GETTEXT + message = gettext(message); +#endif + std::va_list args; + va_start(args,line_number); + size_t length; + length = vsnprintf(NULL,0,message,args); + if (length > 0) { + message_.resize(length+1); + std::vsnprintf(&(message_[0]),length,message,args); + message_.resize(length); + } else { + const char * fmt = gettext_noopt("Error formatting the error string:\n'%s'\nFound in %s::%s at \n%s:%d"); +#ifdef RTMIDI_GETTEXT + fmt = gettext(fmt); +#endif + + length = snprintf(NULL,0,fmt,message,class_name,function_name,file_name,line); + if (length > 0) { + message_.resize(length+1); + snprintf(&(message_[0]),length,fmt,message,class_name,function_name,file_name,line); + message_.resize(length); + } else { + const char * msg + = gettext_noopt("Error: could not format the error message"); +#ifdef RTMIDI_GETTEXT + msg = gettext(msg); +#endif + message_ = msg; + } + } + va_end(args); + +} + //*********************************************************************// // Midi Definitions //*********************************************************************// @@ -92,8 +141,9 @@ void Midi :: getCompiledApi( std::vector &apis, bool preferSystem ) thr -void Midi :: error( Error::Type type, std::string errorString ) +void Midi :: error(Error e) { + #if 0 if ( errorCallback_ ) { static bool firstErrorOccured = false; @@ -102,25 +152,26 @@ void Midi :: error( Error::Type type, std::string errorString ) return; firstErrorOccured = true; - const std::string errorMessage = errorString; + std::ostringstream s; + e.printMessage(s); - errorCallback_( type, errorMessage ); + errorCallback_( type, s.str() ); firstErrorOccured = false; return; } #endif - if ( type == Error::WARNING ) { - std::cerr << '\n' << errorString << "\n\n"; + if ( e.getType() == Error::WARNING ) { + e.printMessage(); } - else if ( type == Error::DEBUG_WARNING ) { + else if ( e.getType() == Error::DEBUG_WARNING ) { #if defined(__RTMIDI_DEBUG__) - std::cerr << '\n' << errorString << "\n\n"; + e.printMessage(); #endif } else { - std::cerr << '\n' << errorString << "\n\n"; - throw Error( errorString, type ); + e.printMessage(); + throw e; } } @@ -130,7 +181,7 @@ void Midi :: error( Error::Type type, std::string errorString ) //*********************************************************************// // MidiIn Definitions //*********************************************************************// - +#define RTMIDI_CLASSNAME "MidiIn" void MidiIn :: openMidiApi( ApiType api ) { if ( rtapi_ ) @@ -218,28 +269,28 @@ MidiIn :: MidiIn( ApiType api, if ( rtapi_ ) return; - // It should not be possible to get here because the preprocessor - // definition __RTMIDI_DUMMY__ is automatically defined if no - // API-specific definitions are passed to the compiler. But just in - // case something weird happens, we'll throw an error. - std::string errorText = "MidiIn: no compiled API support found ... critical error!!"; - throw( Error( errorText, Error::UNSPECIFIED ) ); + // We may reach this point if the only API is JACK, + // but no JACK devices are found. + throw( RTMIDI_ERROR( gettext_noopt("No compiled API support found."), + Error::UNSPECIFIED ) ); } MidiIn :: ~MidiIn() throw() { } +#undef RTMIDI_CLASSNAME //*********************************************************************// // MidiOut Definitions //*********************************************************************// -void MidiOut :: openMidiApi( ApiType api ) -{ - if ( rtapi_ ) - delete rtapi_; - rtapi_ = 0; +#define RTMIDI_CLASSNAME "MidiOut" + void MidiOut :: openMidiApi( ApiType api ) + { + if ( rtapi_ ) + delete rtapi_; + rtapi_ = 0; switch (api) { case rtmidi::UNIX_JACK: @@ -319,17 +370,16 @@ MidiOut :: MidiOut( ApiType api, const std::string clientName, bool pfsystem ) if ( rtapi_ ) return; - // It should not be possible to get here because the preprocessor - // definition __RTMIDI_DUMMY__ is automatically defined if no - // API-specific definitions are passed to the compiler. But just in - // case something weird happens, we'll thrown an error. - std::string errorText = "MidiOut: no compiled API support found ... critical error!!"; - throw( Error( errorText, Error::UNSPECIFIED ) ); + // We may reach this point, e.g. if JACK is the only + // compiled API, but no JACK devices are found. + throw( RTMIDI_ERROR(gettext_noopt("No compiled API support found."), + Error::UNSPECIFIED ) ); } MidiOut :: ~MidiOut() throw() { } +#undef RTMIDI_CLASSNAME //*********************************************************************// // Common MidiApi Definitions @@ -349,7 +399,7 @@ void MidiApi :: setErrorCallback( ErrorCallback errorCallback ) errorCallback_ = errorCallback; } -void MidiApi :: error( Error::Type type, std::string errorString ) +void MidiApi :: error(Error e) { if ( errorCallback_ ) { static bool firstErrorOccured = false; @@ -358,24 +408,25 @@ void MidiApi :: error( Error::Type type, std::string errorString ) return; firstErrorOccured = true; - const std::string errorMessage = errorString; + std::ostringstream s; + e.printMessage(s); - errorCallback_( type, errorMessage ); + errorCallback_( e.getType(), s.str() ); firstErrorOccured = false; return; } - if ( type == Error::WARNING ) { - std::cerr << '\n' << errorString << "\n\n"; + if ( e.getType() == Error::WARNING ) { + e.printMessage(); } - else if ( type == Error::DEBUG_WARNING ) { + else if ( e.getType() == Error::DEBUG_WARNING ) { #if defined(__RTMIDI_DEBUG__) - std::cerr << '\n' << errorString << "\n\n"; + e.printMessage(); #endif } else { - std::cerr << '\n' << errorString << "\n\n"; - throw Error( errorString, type ); + e.printMessage(); + throw e; } } @@ -383,6 +434,7 @@ void MidiApi :: error( Error::Type type, std::string errorString ) // Common MidiInApi Definitions //*********************************************************************// +#define RTMIDI_CLASSNAME "MidiInApi" MidiInApi :: MidiInApi( unsigned int queueSizeLimit ) : MidiApi() { @@ -401,16 +453,17 @@ MidiInApi :: ~MidiInApi( void ) void MidiInApi :: setCallback( MidiCallback callback, void *userData ) { if ( inputData_.usingCallback ) { - errorString_ = "MidiInApi::setCallback: a callback function is already set!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("A callback function is already set."), + Error::WARNING)); return; } if ( !callback ) { - errorString_ = "MidiIn::setCallback: callback function value is invalid!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("The callback function value is invalid."), + Error::WARNING)); return; } + inputData_.userCallback = callback; inputData_.userData = userData; @@ -420,8 +473,8 @@ void MidiInApi :: setCallback( MidiCallback callback, void *userData ) void MidiInApi :: cancelCallback() { if ( !inputData_.usingCallback ) { - errorString_ = "MidiIn::cancelCallback: no callback function was set!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("No callback function was set."), + Error::WARNING)); return; } @@ -443,8 +496,8 @@ double MidiInApi :: getMessage( std::vector &message ) message.clear(); if ( inputData_.usingCallback ) { - errorString_ = "MidiIn::getMessage: a user callback is currently set for this port."; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("A user callback is currently set for this port."), + Error::WARNING)); return 0.0; } @@ -461,11 +514,13 @@ double MidiInApi :: getMessage( std::vector &message ) return deltaTime; } +#undef RTMIDI_CLASSNAME //*********************************************************************// // Common MidiOutApi Definitions //*********************************************************************// +#define RTMIDI_CLASSNAME "MidiOutApi" MidiOutApi :: MidiOutApi( void ) : MidiApi() { @@ -474,6 +529,7 @@ MidiOutApi :: MidiOutApi( void ) MidiOutApi :: ~MidiOutApi( void ) { } +#undef RTMIDI_CLASSNAME // trim from start @@ -1095,9 +1151,8 @@ class CoreSequencer { &uid); if (stat != noErr) { throw - Error("CoreSequencer::getPortCapabilties: \ -Could not get the UID of a midi endpoint.", - Error::DRIVER_ERROR); + RTMIDI_ERROR(gettext_noopt("Could not get the UID of a midi endpoint."), + Error::DRIVER_ERROR); return 0; } MIDIObjectRef obj; @@ -1107,9 +1162,8 @@ Could not get the UID of a midi endpoint.", &type); if (stat != noErr || obj != port) { throw - Error("CoreSequencer::getPortCapabilties: \ -Could not get the endpoint back from UID of a midi endpoint.", - Error::DRIVER_ERROR); + RTMIDI_ERROR(gettext_noopt("Could not get the endpoint back from UID of a midi endpoint."), + Error::DRIVER_ERROR); return 0; } if (type == kMIDIObjectType_Source @@ -1124,9 +1178,8 @@ Could not get the endpoint back from UID of a midi endpoint.", } else if (stat != noErr) { throw - Error("CoreSequencer::getPortCapabilties: \ -Could not get the entity of a midi endpoint.", - Error::DRIVER_ERROR); + RTMIDI_ERROR(gettext_noopt("Could not get the entity of a midi endpoint."), + Error::DRIVER_ERROR); return 0; } /* Theoretically Mac OS X could silently use @@ -1202,15 +1255,12 @@ Could not get the entity of a midi endpoint.", &port); break; default: - throw Error("CoreSequencer::createPort:\ - Error creating OS X MIDI port because of invalid port flags", - Error::DRIVER_ERROR); + throw RTMIDI_ERROR(gettext_noopt("Error creating OS X MIDI port because of invalid port flags"), + Error::DRIVER_ERROR); } if ( result != noErr ) { - throw Error( - "CoreSequencer::createPort:\ - error creating OS-X MIDI port.", - Error::DRIVER_ERROR); + throw RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI port."), + Error::DRIVER_ERROR); } return port; } @@ -1245,13 +1295,12 @@ Could not get the entity of a midi endpoint.", &port); break; default: - throw Error("CoreSequencer::createVirtualPort:\ - Error creating OS X MIDI port because of invalid port flags", - Error::DRIVER_ERROR); + throw RTMIDI_ERROR(gettext_noopt("Error creating OS X MIDI port because of invalid port flags"), + Error::DRIVER_ERROR); } if ( result != noErr ) { - throw Error( "CoreSequencer::createVirtualPort: error creating OS-X MIDI port.", - Error::DRIVER_ERROR); + throw RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI port."), + Error::DRIVER_ERROR); } return port; } @@ -1270,8 +1319,8 @@ Could not get the entity of a midi endpoint.", snd_seq_port_subscribe_t *subscription; if (snd_seq_port_subscribe_malloc( &subscription ) < 0) { - throw Error("MidiInCore::openPort: CORE error allocation port subscription.", - Error::DRIVER_ERROR ); + throw RTMIDI_ERROR(gettext_noopt("CORE error allocation port subscription."), + Error::DRIVER_ERROR ); return 0; } snd_seq_port_subscribe_set_sender(subscription, &from); @@ -1285,8 +1334,8 @@ Could not get the entity of a midi endpoint.", if ( snd_seq_subscribe_port(seq, subscription) ) { snd_seq_port_subscribe_free( subscription ); subscription = 0; - throw Error("MidiInCore::openPort: CORE error making port connection.", - Error::DRIVER_ERROR); + throw RTMIDI_ERROR(gettext_noopt("CORE error making port connection."), + Error::DRIVER_ERROR); return 0; } } @@ -1362,10 +1411,8 @@ Could not get the entity of a midi endpoint.", kCFStringEncodingUTF8), NULL, NULL, &s ); if ( result != noErr ) { - throw Error( - "CoreSequencer::initialize: \ -Error creating OS-X MIDI client object.", - Error::DRIVER_ERROR); + throw RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI client object."), + Error::DRIVER_ERROR); return; } } @@ -1698,62 +1745,63 @@ void MidiInCore :: initialize( const std::string& clientName ) inputData_.apiData = (void *) data; } -void MidiInCore :: openPort( unsigned int portNumber, - const std::string & portName ) -{ - if ( connected_ ) { - errorString_ = "MidiInCore::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); - return; - } + void MidiInCore :: openPort( unsigned int portNumber, + const std::string & portName ) + { + if ( connected_ ) { + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING)); + return; + } - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - unsigned int nSrc = MIDIGetNumberOfSources(); - if (nSrc < 1) { - errorString_ = "MidiInCore::openPort: no MIDI input sources found!"; - error( Error::NO_DEVICES_FOUND, errorString_ ); - return; - } + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + unsigned int nSrc = MIDIGetNumberOfSources(); + if (nSrc < 1) { + error(RTMIDI_ERROR(gettext_noopt("No MIDI input sources found."), + Error::NO_DEVICES_FOUND)); + return; + } - if ( portNumber >= nSrc ) { - std::ostringstream ost; - ost << "MidiInCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::INVALID_PARAMETER, errorString_ ); - return; - } + if ( portNumber >= nSrc ) { + std::ostringstream ost; + ost << ""; + errorString_ = ost.str(); + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::INVALID_PARAMETER, portNumber) ); + return; + } - MIDIPortRef port; - CoreMidiData *data = static_cast (apiData_); - OSStatus result = MIDIInputPortCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingUTF8 ), - midiInputCallback, (void *)&inputData_, &port ); - if ( result != noErr ) { - MIDIClientDispose( data->client ); - errorString_ = "MidiInCore::openPort: error creating OS-X MIDI input port."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } + MIDIPortRef port; + CoreMidiData *data = static_cast (apiData_); + OSStatus result = MIDIInputPortCreate( data->client, + CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingUTF8 ), + midiInputCallback, (void *)&inputData_, &port ); + if ( result != noErr ) { + MIDIClientDispose( data->client ); + error(RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI input port."), + Error::DRIVER_ERROR, errorString_ )); + return; + } - // Get the desired input source identifier. - MIDIEndpointRef endpoint = MIDIGetSource( portNumber ); - if ( endpoint == 0 ) { - MIDIPortDispose( port ); - MIDIClientDispose( data->client ); - errorString_ = "MidiInCore::openPort: error getting MIDI input source reference."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } + // Get the desired input source identifier. + MIDIEndpointRef endpoint = MIDIGetSource( portNumber ); + if ( endpoint == 0 ) { + MIDIPortDispose( port ); + MIDIClientDispose( data->client ); + error(RTMIDI_ERROR(gettext_noopt("Error getting MIDI input source reference."), + Error::DRIVER_ERROR) ); + return; + } - // Make the connection. - result = MIDIPortConnectSource( port, endpoint, NULL ); - if ( result != noErr ) { - MIDIPortDispose( port ); - MIDIClientDispose( data->client ); - errorString_ = "MidiInCore::openPort: error connecting OS-X MIDI input port."; - error( Error::DRIVER_ERROR, errorString_ ); - return; - } + // Make the connection. + result = MIDIPortConnectSource( port, endpoint, NULL ); + if ( result != noErr ) { + MIDIPortDispose( port ); + MIDIClientDispose( data->client ); + error(RTMIDI_ERROR(gettext_noopt("Error connecting OS-X MIDI input port."), + Error::DRIVER_ERROR) ); + return; + } // Save our api-specific port information. data->localPort = port; @@ -1772,8 +1820,8 @@ void MidiInCore :: openVirtualPort( const std::string portName ) CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingUTF8 ), midiInputCallback, (void *)&inputData_, &endpoint ); if ( result != noErr ) { - errorString_ = "MidiInCore::openVirtualPort: error creating virtual OS-X MIDI destination."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error creating virtual OS-X MIDI destination."), + Error::DRIVER_ERROR) ); return; } @@ -1788,18 +1836,18 @@ void MidiInCore :: openPort( const PortDescriptor & port, const CorePortDescriptor * remote = dynamic_cast(&port); if ( !data ) { - errorString_ = "MidiInCore::openPort: Internal error: data has not been allocated!"; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Internal error: data has not been allocated."), + Error::DRIVER_ERROR) ); return; } if ( connected_ || data -> localEndpoint) { - errorString_ = "MidiInCore::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); return; } if (!remote) { - errorString_ = "MidiInCore::openPort: an invalid (i.e. non-CORE) port descriptor has been passed to openPort!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("An invalid (i.e. non-CORE) port descriptor has been passed to openPort."), + Error::WARNING) ); return; } @@ -1812,9 +1860,8 @@ void MidiInCore :: openPort( const PortDescriptor & port, data->getEndpoint(), NULL); if ( result != noErr ) { - error(Error::DRIVER_ERROR, - "CoreSequencer::createPort:\ - error creating OS-X MIDI port."); + error(RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI port."), + Error::DRIVER_ERROR)); } connected_ = true; @@ -1875,9 +1922,10 @@ std::string MidiInCore :: getPortName( unsigned int portNumber ) CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); if ( portNumber >= MIDIGetNumberOfSources() ) { std::ostringstream ost; - ost << "MidiInCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + ost << "MidiInCore::getPortName: "; errorString_ = ost.str(); - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::WARNING, portNumber)); return stringName; } @@ -1931,10 +1979,8 @@ std::string MidiOutCore :: getPortName( unsigned int portNumber ) std::string stringName; CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); if ( portNumber >= MIDIGetNumberOfDestinations() ) { - std::ostringstream ost; - ost << "MidiOutCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::WARNING, portNumber) ); return stringName; } @@ -1950,24 +1996,25 @@ void MidiOutCore :: openPort( unsigned int portNumber, const std::string &portName ) { if ( connected_ ) { - errorString_ = "MidiOutCore::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); return; } CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); unsigned int nDest = MIDIGetNumberOfDestinations(); if (nDest < 1) { - errorString_ = "MidiOutCore::openPort: no MIDI output destinations found!"; - error( Error::NO_DEVICES_FOUND, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("No MIDI output destinations found."), + Error::NO_DEVICES_FOUND) ); return; } if ( portNumber >= nDest ) { std::ostringstream ost; - ost << "MidiOutCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + ost << "MidiOutCore::openPort: "; errorString_ = ost.str(); - error( Error::INVALID_PARAMETER, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::INVALID_PARAMETER, portNumber) ); return; } @@ -1978,8 +2025,8 @@ void MidiOutCore :: openPort( unsigned int portNumber, &port ); if ( result != noErr ) { MIDIClientDispose( data->client ); - errorString_ = "MidiOutCore::openPort: error creating OS-X MIDI output port."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI output port."), + Error::DRIVER_ERROR) ); return; } @@ -1988,8 +2035,8 @@ void MidiOutCore :: openPort( unsigned int portNumber, if ( destination == 0 ) { MIDIPortDispose( port ); MIDIClientDispose( data->client ); - errorString_ = "MidiOutCore::openPort: error getting MIDI output destination reference."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error getting MIDI output destination reference."), + Error::DRIVER_ERROR) ); return; } @@ -2013,8 +2060,8 @@ void MidiOutCore :: openVirtualPort( std::string portName ) CoreMidiData *data = static_cast (apiData_); if ( data->localEndpoint ) { - errorString_ = "MidiOutCore::openVirtualPort: a virtual output port already exists!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("A virtual output port already exists."), + Error::WARNING) ); return; } @@ -2024,8 +2071,8 @@ void MidiOutCore :: openVirtualPort( std::string portName ) CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingUTF8 ), &endpoint ); if ( result != noErr ) { - errorString_ = "MidiOutCore::initialize: error creating OS-X virtual MIDI source."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error creating OS-X virtual MIDI source."), + Error::DRIVER_ERROR) ); return; } @@ -2040,18 +2087,18 @@ void MidiOutCore :: openPort( const PortDescriptor & port, const CorePortDescriptor * remote = dynamic_cast(&port); if ( !data ) { - errorString_ = "MidiOutCore::openPort: Internal error: data has not been allocated!"; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Internal error: data has not been allocated."), + Error::DRIVER_ERROR) ); return; } if ( connected_ || data -> localEndpoint) { - errorString_ = "MidiOutCore::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists"), + Error::WARNING) ); return; } if (!remote) { - errorString_ = "MidiOutCore::openPort: an invalid (i.e. non-CORE) port descriptor has been passed to openPort!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("An invalid (i.e. non-CORE) port descriptor has been passed to openPort."), + Error::WARNING) ); return; } @@ -2103,8 +2150,8 @@ void MidiOutCore :: sendMessage( std::vector &message ) // messages. Otherwise, we use a single CoreMidi MIDIPacket. unsigned int nBytes = message.size(); if ( nBytes == 0 ) { - errorString_ = "MidiOutCore::sendMessage: no data in message argument!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("No data in message argument."), + Error::WARNING)); return; } @@ -2144,15 +2191,17 @@ void MidiOutCore :: sendMessage( std::vector &message ) result = MIDISendSysex(newRequest); if ( result != noErr ) { free( newRequest ); - errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; - error( Error::WARNING, errorString_ ); + errorString_ = "MidiOutCore::sendMessage: "; + error(RTMIDI_ERROR(gettext_noopt("Error sending MIDI to virtual destinations."), + Error::WARNING, errorString_ ); return; } return; } else if ( nBytes > 3 ) { errorString_ = "MidiOutCore::sendMessage: message format problem ... not sysex but > 3 bytes?"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt(""), + Error::WARNING, errorString_ ); return; } */ @@ -2161,8 +2210,8 @@ void MidiOutCore :: sendMessage( std::vector &message ) MIDIPacket *packet = MIDIPacketListInit( &packetList ); packet = MIDIPacketListAdd( &packetList, sizeof(packetList), packet, timeStamp, nBytes, (const Byte *) &message.at( 0 ) ); if ( !packet ) { - errorString_ = "MidiOutCore::sendMessage: could not allocate packet list"; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Could not allocate packet list."), + Error::DRIVER_ERROR) ); return; } @@ -2170,8 +2219,8 @@ void MidiOutCore :: sendMessage( std::vector &message ) if ( data->localEndpoint ) { result = MIDIReceived( data->localEndpoint, &packetList ); if ( result != noErr ) { - errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error sending MIDI to virtual destinations."), + Error::WARNING) ); } } @@ -2179,8 +2228,8 @@ void MidiOutCore :: sendMessage( std::vector &message ) if ( connected_ ) { result = MIDISend( data->localPort, data->getEndpoint(), &packetList ); if ( result != noErr ) { - errorString_ = "MidiOutCore::sendMessage: error sending MIDI message to port."; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error sending MIDI message to port."), + Error::WARNING) ); } } } @@ -2224,6 +2273,7 @@ struct AlsaMidiData; the parameter \ref locking. */ +#define RTMIDI_CLASSNAME "AlsaSequencer" template class AlsaSequencer { public: @@ -2381,8 +2431,8 @@ class AlsaSequencer { snd_seq_port_subscribe_t *subscription; if (snd_seq_port_subscribe_malloc( &subscription ) < 0) { - throw Error("MidiInAlsa::openPort: ALSA error allocation port subscription.", - Error::DRIVER_ERROR ); + throw RTMIDI_ERROR(gettext_noopt("Error allocating ALSA port subscription."), + Error::DRIVER_ERROR ); return 0; } snd_seq_port_subscribe_set_sender(subscription, &from); @@ -2396,8 +2446,8 @@ class AlsaSequencer { if ( snd_seq_subscribe_port(seq, subscription) ) { snd_seq_port_subscribe_free( subscription ); subscription = 0; - throw Error("MidiInAlsa::openPort: ALSA error making port connection.", - Error::DRIVER_ERROR); + throw RTMIDI_ERROR(gettext_noopt("Error making ALSA port connection."), + Error::DRIVER_ERROR); return 0; } } @@ -2466,17 +2516,19 @@ class AlsaSequencer { scoped_lock lock(mutex); int result = snd_seq_open(&s, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); if ( result < 0 ) { - throw Error( "MidiInAlsa::initialize: error creating ALSA sequencer client object.", - Error::DRIVER_ERROR ); + throw RTMIDI_ERROR(gettext_noopt("Error creating ALSA sequencer client object."), + Error::DRIVER_ERROR ); return; } snd_seq_set_client_name( seq, name.c_str() ); } } }; +#undef RTMIDI_CLASSNAME typedef AlsaSequencer<1> LockingAlsaSequencer; typedef AlsaSequencer<0> NonLockingAlsaSequencer; +#define RTMIDI_CLASSNAME "AlsaPortDescriptor" struct AlsaPortDescriptor:public PortDescriptor, public snd_seq_addr_t { @@ -2530,6 +2582,7 @@ struct AlsaPortDescriptor:public PortDescriptor, LockingAlsaSequencer AlsaPortDescriptor::seq; + PortList AlsaPortDescriptor :: getPortList(int capabilities, const std::string & clientName) { PortList list; @@ -2570,6 +2623,7 @@ PortList AlsaPortDescriptor :: getPortList(int capabilities, const std::string & } return list; } +#undef RTMIDI_CLASSNAME static void *alsaMidiHandler( void *ptr ); @@ -2581,6 +2635,7 @@ static void *alsaMidiHandler( void *ptr ); AlsaSequencer class, we should make seq to be a pointer in order to allow a common client implementation. */ +#define RTMIDI_CLASSNAME "AlsaMidiData" struct AlsaMidiData:public AlsaPortDescriptor { /* @@ -2614,7 +2669,7 @@ struct AlsaMidiData:public AlsaPortDescriptor { } snd_seq_addr_t local; /*!< Our port and client id. If client = 0 (default) this means we didn't aquire a port so far. */ NonLockingAlsaSequencer seq; - // unsigned int portNum; + // unsigned int portNum; snd_seq_port_subscribe_t *subscription; snd_midi_event_t *coder; unsigned int bufferSize; @@ -2638,8 +2693,8 @@ struct AlsaMidiData:public AlsaPortDescriptor { int openPort(int alsaCapabilities, const std::string & portName) { if (subscription) { - api->error( Error::DRIVER_ERROR, - "MidiInAlsa::openPort: ALSA error allocation port subscription." ); + api->error( RTMIDI_ERROR(gettext_noopt("Error while trying to allocate ALSA port subscription."), + Error::DRIVER_ERROR )); return -99; } @@ -2663,8 +2718,8 @@ struct AlsaMidiData:public AlsaPortDescriptor { int createok = seq.createPort(pinfo); if ( createok < 0 ) { - api->error( Error::DRIVER_ERROR, - "MidiInAlsa::openPort: ALSA error creating input port." ); + api->error(RTMIDI_ERROR("ALSA error while creating input port.", + Error::DRIVER_ERROR)); return createok; } @@ -2700,13 +2755,14 @@ struct AlsaMidiData:public AlsaPortDescriptor { pthread_attr_destroy(&attr); if ( err ) { closePort(); - api->error( Error::THREAD_ERROR, - "MidiInAlsa::openPort: error starting MIDI input thread!" ); + api->error(RTMIDI_ERROR(gettext_noopt("Error starting MIDI input thread!"), + Error::THREAD_ERROR)); return false; } return true; } }; +#undef RTMIDI_CLASSNAME #define PORT_TYPE( pinfo, bits ) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits)) @@ -2907,6 +2963,7 @@ static void *alsaMidiHandler( void *ptr ) return 0; } +#define RTMIDI_CLASSNAME "MidiInAlsa" MidiInAlsa :: MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { @@ -2946,8 +3003,8 @@ void MidiInAlsa :: initialize( const std::string& clientName ) snd_seq_t *seq; int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); if ( result < 0 ) { - errorString_ = "MidiInAlsa::initialize: error creating ALSA sequencer client object."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error creating ALSA sequencer client object."), + Error::DRIVER_ERROR)); return; } #endif @@ -2964,8 +3021,8 @@ void MidiInAlsa :: initialize( const std::string& clientName ) inputData_.apiData = (void *) data; if ( pipe(data->trigger_fds) == -1 ) { - errorString_ = "MidiInAlsa::initialize: error creating pipe objects."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error creating pipe objects."), + Error::DRIVER_ERROR) ); return; } @@ -3044,23 +3101,23 @@ std::string MidiInAlsa :: getPortName( unsigned int portNumber ) } // If we get here, we didn't find a match. - errorString_ = "MidiInAlsa::getPortName: error looking for port name!"; - error( Error::WARNING, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("Error looking for port name."), + Error::WARNING) ); return stringName; } void MidiInAlsa :: openPort( unsigned int portNumber, const std::string & portName ) { if ( connected_ ) { - errorString_ = "MidiInAlsa::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); return; } unsigned int nSrc = this->getPortCount(); if ( nSrc < 1 ) { - errorString_ = "MidiInAlsa::openPort: no MIDI input sources found!"; - error( Error::NO_DEVICES_FOUND, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("No MIDI input sources found."), + Error::NO_DEVICES_FOUND )); return; } @@ -3069,9 +3126,9 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string & portNa AlsaMidiData *data = static_cast (apiData_); if ( portInfo( data->seq, src_pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) == 0 ) { std::ostringstream ost; - ost << "MidiInAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::INVALID_PARAMETER, errorString_ ); + error( RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::INVALID_PARAMETER, + portNumber) ); return; } @@ -3100,8 +3157,8 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string & portNa int createok = snd_seq_create_port(data->seq, pinfo); if ( createok < 0 ) { - errorString_ = "MidiInAlsa::openPort: ALSA error creating input port."; - error( Error::DRIVER_ERROR, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("Error creating ALSA input port."), + Error::DRIVER_ERROR)); return; } data->local.port = snd_seq_port_info_get_port(pinfo); @@ -3113,8 +3170,8 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string & portNa if ( !data->subscription ) { // Make subscription if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { - errorString_ = "MidiInAlsa::openPort: ALSA error allocation port subscription."; - error( Error::DRIVER_ERROR, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("Error allocating ALSA port subscription."), + Error::DRIVER_ERROR) ); return; } snd_seq_port_subscribe_set_sender(data->subscription, &sender); @@ -3122,8 +3179,8 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string & portNa if ( snd_seq_subscribe_port(data->seq, data->subscription) ) { snd_seq_port_subscribe_free( data->subscription ); data->subscription = 0; - errorString_ = "MidiInAlsa::openPort: ALSA error making port connection."; - error( Error::DRIVER_ERROR, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("Error making ALSA port connection."), + Error::DRIVER_ERROR) ); return; } } @@ -3148,8 +3205,8 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string & portNa snd_seq_port_subscribe_free( data->subscription ); data->subscription = 0; inputData_.doInput = false; - errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!"; - error( Error::THREAD_ERROR, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("Error starting MIDI input thread!"), + Error::THREAD_ERROR) ); return; } } @@ -3164,23 +3221,23 @@ void MidiInAlsa :: openPort( const PortDescriptor & port, const AlsaPortDescriptor * remote = dynamic_cast(&port); if ( !data ) { - errorString_ = "MidiInAlsa::openPort: Internal error: data has not been allocated!"; - error( Error::DRIVER_ERROR, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("Internal error: data has not been allocated."), + Error::DRIVER_ERROR) ); return; } if ( connected_ ) { - errorString_ = "MidiInAlsa::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); return; } if (data->subscription) { - error( Error::DRIVER_ERROR, - "MidiInAlsa::openPort: ALSA error allocation port subscription." ); + error( RTMIDI_ERROR(gettext_noopt("Error while allocating ALSA port subscription."), + Error::DRIVER_ERROR)); return; } if (!remote) { - errorString_ = "MidiInAlsa::openPort: an invalid (i.e. non-ALSA) port descriptor has been passed to openPort!"; - error( Error::WARNING, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("An invalid (i.e. non-ALSA) port descriptor has been passed to openPort."), + Error::WARNING) ); return; } @@ -3243,8 +3300,9 @@ void MidiInAlsa :: openVirtualPort( std::string portName ) int createok = snd_seq_create_port(data->seq, pinfo); if ( createok < 0 ) { - errorString_ = "MidiInAlsa::openVirtualPort: ALSA error creating virtual port."; - error( Error::DRIVER_ERROR, errorString_ ); + errorString_ = "MidiInAlsa::openVirtualPort: "; + error( RTMIDI_ERROR(gettext_noopt("Error creating ALSA virtual port."), + Error::DRIVER_ERROR) ); return; } data->local.port = snd_seq_port_info_get_port(pinfo); @@ -3277,8 +3335,8 @@ void MidiInAlsa :: openVirtualPort( std::string portName ) data->subscription = 0; } inputData_.doInput = false; - errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!"; - error( Error::THREAD_ERROR, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("Error starting MIDI input thread!"), + Error::THREAD_ERROR) ); return; } } @@ -3311,12 +3369,14 @@ void MidiInAlsa :: closePort( void ) pthread_join( data->thread, NULL ); } } +#undef RTMIDI_CLASSNAME //*********************************************************************// // API: LINUX ALSA // Class Definitions: MidiOutAlsa //*********************************************************************// +#define RTMIDI_CLASSNAME "MidiOutAlsa" MidiOutAlsa :: MidiOutAlsa( const std::string clientName ) : MidiOutApi() { initialize( clientName ); @@ -3343,7 +3403,8 @@ void MidiOutAlsa :: initialize( const std::string& clientName ) int result1 = snd_seq_open( &seq, "default", SND_SEQ_OPEN_OUTPUT, SND_SEQ_NONBLOCK ); if ( result1 < 0 ) { errorString_ = "MidiOutAlsa::initialize: error creating ALSA sequencer client object."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt(""), + Error::DRIVER_ERROR, errorString_ )); return; } @@ -3359,15 +3420,15 @@ void MidiOutAlsa :: initialize( const std::string& clientName ) int result = snd_midi_event_new( data->bufferSize, &data->coder ); if ( result < 0 ) { delete data; - errorString_ = "MidiOutAlsa::initialize: error initializing MIDI event parser!\n\n"; - error( Error::DRIVER_ERROR, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("Error initializing MIDI event parser."), + Error::DRIVER_ERROR) ); return; } data->buffer = (unsigned char *) malloc( data->bufferSize ); if ( data->buffer == NULL ) { delete data; - errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n"; - error( Error::MEMORY_ERROR, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("Error allocating buffer memory."), + Error::MEMORY_ERROR) ); return; } snd_midi_event_init( data->coder ); @@ -3406,23 +3467,25 @@ std::string MidiOutAlsa :: getPortName( unsigned int portNumber ) } // If we get here, we didn't find a match. - errorString_ = "MidiOutAlsa::getPortName: error looking for port name!"; - error( Error::WARNING, errorString_ ); + errorString_ = "MidiOutAlsa::getPortName: "; + error( RTMIDI_ERROR(gettext_noopt("Error looking for port name."), + Error::WARNING) ); return stringName; } void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string & portName ) { if ( connected_ ) { - errorString_ = "MidiOutAlsa::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); return; } unsigned int nSrc = this->getPortCount(); if (nSrc < 1) { - errorString_ = "MidiOutAlsa::openPort: no MIDI output sources found!"; - error( Error::NO_DEVICES_FOUND, errorString_ ); + errorString_ = "MidiOutAlsa::openPort: !"; + error(RTMIDI_ERROR(gettext_noopt("No MIDI output sources found."), + Error::NO_DEVICES_FOUND) ); return; } @@ -3431,9 +3494,10 @@ void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string & portN AlsaMidiData *data = static_cast (apiData_); if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) == 0 ) { std::ostringstream ost; - ost << "MidiOutAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + ost << "MidiOutAlsa::openPort: "; errorString_ = ost.str(); - error( Error::INVALID_PARAMETER, errorString_ ); + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::INVALID_PARAMETER, portNumber) ); return; } @@ -3446,8 +3510,9 @@ void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string & portN SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); if ( port < 0 ) { - errorString_ = "MidiOutAlsa::openPort: ALSA error creating output port."; - error( Error::DRIVER_ERROR, errorString_ ); + errorString_ = "MidiOutAlsa::openPort: "; + error(RTMIDI_ERROR(gettext_noopt("Error creating ALSA output port."), + Error::DRIVER_ERROR)); return; } @@ -3457,8 +3522,8 @@ void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string & portN // Make subscription if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { snd_seq_port_subscribe_free( data->subscription ); - errorString_ = "MidiOutAlsa::openPort: error allocating port subscription."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error allocating port subscription."), + Error::DRIVER_ERROR) ); return; } snd_seq_port_subscribe_set_sender(data->subscription, data); @@ -3467,8 +3532,8 @@ void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string & portN snd_seq_port_subscribe_set_time_real(data->subscription, 1); if ( snd_seq_subscribe_port(data->seq, data->subscription) ) { snd_seq_port_subscribe_free( data->subscription ); - errorString_ = "MidiOutAlsa::openPort: ALSA error making port connection."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error making ALSA port connection."), + Error::DRIVER_ERROR) ); return; } @@ -3494,8 +3559,8 @@ void MidiOutAlsa :: openVirtualPort( std::string portName ) SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); if ( port < 0 ) { - errorString_ = "MidiOutAlsa::openVirtualPort: ALSA error creating virtual port."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error creating ALSA virtual port."), + Error::DRIVER_ERROR) ); } data->local.port = port; data->local.client = snd_seq_client_id(data->seq); @@ -3511,15 +3576,15 @@ void MidiOutAlsa :: sendMessage( std::vector &message ) data->bufferSize = nBytes; result = snd_midi_event_resize_buffer ( data->coder, nBytes); if ( result != 0 ) { - errorString_ = "MidiOutAlsa::sendMessage: ALSA error resizing MIDI event buffer."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("ALSA error resizing MIDI event buffer."), + Error::DRIVER_ERROR) ); return; } free (data->buffer); data->buffer = (unsigned char *) malloc( data->bufferSize ); if ( data->buffer == NULL ) { - errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n"; - error( Error::MEMORY_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error allocating buffer memory."), + Error::MEMORY_ERROR) ); return; } } @@ -3532,16 +3597,16 @@ void MidiOutAlsa :: sendMessage( std::vector &message ) for ( unsigned int i=0; ibuffer[i] = message.at(i); result = snd_midi_event_encode( data->coder, data->buffer, (long)nBytes, &ev ); if ( result < (int)nBytes ) { - errorString_ = "MidiOutAlsa::sendMessage: event parsing error!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Event parsing error."), + Error::WARNING) ); return; } // Send the event. result = snd_seq_event_output(data->seq, &ev); if ( result < 0 ) { - errorString_ = "MidiOutAlsa::sendMessage: error sending MIDI message to port."; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error sending MIDI message to port."), + Error::WARNING) ); return; } snd_seq_drain_output(data->seq); @@ -3554,23 +3619,23 @@ void MidiOutAlsa :: openPort( const PortDescriptor & port, const AlsaPortDescriptor * remote = dynamic_cast(&port); if ( !data ) { - errorString_ = "MidiOutAlsa::openPort: Internal error: data has not been allocated!"; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Internal error: data has not been allocated."), + Error::DRIVER_ERROR) ); return; } if ( connected_ ) { - errorString_ = "MidiOutAlsa::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); return; } if (data->subscription) { - error( Error::DRIVER_ERROR, - "MidiOutAlsa::openPort: ALSA error allocation port subscription." ); + error(RTMIDI_ERROR(gettext_noopt("ALSA error allocation port subscription."), + Error::DRIVER_ERROR) ); return; } if (!remote) { - errorString_ = "MidiOutAlsa::openPort: an invalid (i.e. non-ALSA) port descriptor has been passed to openPort!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("An invalid (i.e. non-ALSA) port descriptor has been passed to openPort."), + Error::WARNING) ); return; } @@ -3766,8 +3831,8 @@ void MidiInWinMM :: initialize( const std::string& /*clientName*/ ) // throw an error since the user can plugin something later. unsigned int nDevices = midiInGetNumDevs(); if ( nDevices == 0 ) { - errorString_ = "MidiInWinMM::initialize: no MIDI input devices currently available."; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("No MIDI input devices currently available."), + Error::WARNING) ); } // Save our api-specific connection information. @@ -3777,31 +3842,32 @@ void MidiInWinMM :: initialize( const std::string& /*clientName*/ ) data->message.bytes.clear(); // needs to be empty for first input message if ( !InitializeCriticalSectionAndSpinCount(&(data->_mutex), 0x00000400) ) { - errorString_ = "MidiInWinMM::initialize: InitializeCriticalSectionAndSpinCount failed."; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("InitializeCriticalSectionAndSpinCount failed."), + Error::WARNING) ); } } void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) { if ( connected_ ) { - errorString_ = "MidiInWinMM::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); return; } unsigned int nDevices = midiInGetNumDevs(); if (nDevices == 0) { - errorString_ = "MidiInWinMM::openPort: no MIDI input sources found!"; - error( Error::NO_DEVICES_FOUND, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("No MIDI input sources found."), + Error::NO_DEVICES_FOUND) ); return; } if ( portNumber >= nDevices ) { std::ostringstream ost; - ost << "MidiInWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + ost << "MidiInWinMM::openPort: "; errorString_ = ost.str(); - error( Error::INVALID_PARAMETER, errorString_ ); + error(RTMIDI_ERROR1(gettext_noopt("the 'portNumber' argument (%d) is invalid."), + Error::INVALID_PARAMETER, portNumber) ); return; } @@ -3812,8 +3878,8 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portN (DWORD_PTR)&inputData_, CALLBACK_FUNCTION ); if ( result != MMSYSERR_NOERROR ) { - errorString_ = "MidiInWinMM::openPort: error creating Windows MM MIDI input port."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error creating Windows MM MIDI input port."), + Error::DRIVER_ERROR) ); return; } @@ -3828,8 +3894,8 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portN result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); if ( result != MMSYSERR_NOERROR ) { midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (PrepareHeader)."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error starting Windows MM MIDI input port (PrepareHeader)."), + Error::DRIVER_ERROR )); return; } @@ -3837,8 +3903,8 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portN result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); if ( result != MMSYSERR_NOERROR ) { midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (AddBuffer)."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error starting Windows MM MIDI input port (AddBuffer)."), + Error::DRIVER_ERROR) ); return; } } @@ -3846,19 +3912,19 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portN result = midiInStart( data->inHandle ); if ( result != MMSYSERR_NOERROR ) { midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error starting Windows MM MIDI input port."), + Error::DRIVER_ERROR) ); return; } - + connected_ = true; } void MidiInWinMM :: openVirtualPort( std::string /*portName*/ ) { // This function cannot be implemented for the Windows MM MIDI API. - errorString_ = "MidiInWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Cannot be implemented in Windows MM MIDI API."), + Error::WARNING )); } void MidiInWinMM :: closePort( void ) @@ -3875,8 +3941,9 @@ void MidiInWinMM :: closePort( void ) delete [] data->sysexBuffer[i]; if ( result != MMSYSERR_NOERROR ) { midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader)."; - error( Error::DRIVER_ERROR, errorString_ ); + errorString_ = "MidiInWinMM::openPort: "; + error(RTMIDI_ERROR(gettext_noopt("Error closing Windows MM MIDI input port (midiInUnprepareHeader)."), + Error::DRIVER_ERROR) ); return; } } @@ -3897,10 +3964,8 @@ std::string MidiInWinMM :: getPortName( unsigned int portNumber ) std::string stringName; unsigned int nDevices = midiInGetNumDevs(); if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiInWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::WARNING,portNumber)); return stringName; } @@ -3952,8 +4017,8 @@ void MidiOutWinMM :: initialize( const std::string& /*clientName*/ ) // throw an error since the user can plug something in later. unsigned int nDevices = midiOutGetNumDevs(); if ( nDevices == 0 ) { - errorString_ = "MidiOutWinMM::initialize: no MIDI output devices currently available."; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("No MIDI output devices currently available."), + Error::WARNING)); } // Save our api-specific connection information. @@ -3972,9 +4037,10 @@ std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) unsigned int nDevices = midiOutGetNumDevs(); if ( portNumber >= nDevices ) { std::ostringstream ost; - ost << "MidiOutWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; + ost << "MidiOutWinMM::getPortName: "; errorString_ = ost.str(); - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::WARNING)); return stringName; } @@ -3995,23 +4061,21 @@ std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) { if ( connected_ ) { - errorString_ = "MidiOutWinMM::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); return; } unsigned int nDevices = midiOutGetNumDevs(); if (nDevices < 1) { - errorString_ = "MidiOutWinMM::openPort: no MIDI output destinations found!"; - error( Error::NO_DEVICES_FOUND, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("No MIDI output destinations found!"), + Error::NO_DEVICES_FOUND) ); return; } if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiOutWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::INVALID_PARAMETER, errorString_ ); + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::INVALID_PARAMETER, portNumber) ); return; } @@ -4022,8 +4086,8 @@ void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string /*port (DWORD)NULL, CALLBACK_NULL ); if ( result != MMSYSERR_NOERROR ) { - errorString_ = "MidiOutWinMM::openPort: error creating Windows MM MIDI output port."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error creating Windows MM MIDI output port."), + Error::DRIVER_ERROR) ); return; } @@ -4043,8 +4107,8 @@ void MidiOutWinMM :: closePort( void ) void MidiOutWinMM :: openVirtualPort( std::string /*portName*/ ) { // This function cannot be implemented for the Windows MM MIDI API. - errorString_ = "MidiOutWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Cannot be implemented in Windows MM MIDI API."), + Error::WARNING) ); } void MidiOutWinMM :: sendMessage( std::vector *message ) @@ -4053,8 +4117,8 @@ void MidiOutWinMM :: sendMessage( std::vector *message ) unsigned int nBytes = static_cast(message->size()); if ( nBytes == 0 ) { - errorString_ = "MidiOutWinMM::sendMessage: message argument is empty!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Message argument is empty."), + Error::WARNING)); return; } @@ -4065,8 +4129,8 @@ void MidiOutWinMM :: sendMessage( std::vector *message ) // Allocate buffer for sysex data. char *buffer = (char *) malloc( nBytes ); if ( buffer == NULL ) { - errorString_ = "MidiOutWinMM::sendMessage: error allocating sysex message memory!"; - error( Error::MEMORY_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error allocating sysex message memory!"), + Error::MEMORY_ERROR) ); return; } @@ -4081,8 +4145,8 @@ void MidiOutWinMM :: sendMessage( std::vector *message ) result = midiOutPrepareHeader( data->outHandle, &sysex, sizeof(MIDIHDR) ); if ( result != MMSYSERR_NOERROR ) { free( buffer ); - errorString_ = "MidiOutWinMM::sendMessage: error preparing sysex header."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error preparing sysex header."), + Error::DRIVER_ERROR)); return; } @@ -4090,8 +4154,8 @@ void MidiOutWinMM :: sendMessage( std::vector *message ) result = midiOutLongMsg( data->outHandle, &sysex, sizeof(MIDIHDR) ); if ( result != MMSYSERR_NOERROR ) { free( buffer ); - errorString_ = "MidiOutWinMM::sendMessage: error sending sysex message."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error sending sysex message."), + Error::DRIVER_ERROR) ); return; } @@ -4103,8 +4167,8 @@ void MidiOutWinMM :: sendMessage( std::vector *message ) // Make sure the message size isn't too big. if ( nBytes > 3 ) { - errorString_ = "MidiOutWinMM::sendMessage: message size is greater than 3 bytes (and not sysex)!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Message size is greater than 3 bytes (and not sysex)."), + Error::WARNING) ); return; } @@ -4119,8 +4183,8 @@ void MidiOutWinMM :: sendMessage( std::vector *message ) // Send the message immediately. result = midiOutShortMsg( data->outHandle, packet ); if ( result != MMSYSERR_NOERROR ) { - errorString_ = "MidiOutWinMM::sendMessage: error sending MIDI message."; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error sending MIDI message."), + Error::DRIVER_ERROR )); } } } @@ -4369,8 +4433,8 @@ class JackSequencer { if (( client = jack_client_open( name.c_str(), JackNoStartServer, NULL )) == 0) { - throw Error("JackSequencer::init: Could not connect to JACK server. Is it runnig?", - Error::WARNING); + throw RTMIDI_ERROR(gettext_noopt("Could not connect to JACK server. Is it runnig?"), + Error::WARNING); return; } @@ -4442,7 +4506,6 @@ struct JackPortDescriptor:public PortDescriptor static PortList getPortList(int capabilities, const std::string & clientName); operator jack_port_t * () const { return port; } - protected: std::string clientName; jack_port_t * port; @@ -4572,8 +4635,8 @@ struct JackMidiData:public JackPortDescriptor { const std::string & portName) { local = seq->createPort(portName, jackCapabilities); if (!local) { - api->error( Error::DRIVER_ERROR, - "MidiInJack::openPort: JACK error opening port subscription." ); + api->error(RTMIDI_ERROR(gettext_noopt("Error opening JACK port subscription."), + Error::DRIVER_ERROR) ); return -99; } return 0; @@ -4679,8 +4742,8 @@ void MidiInJack :: connect() // Initialize JACK client if (( data->local = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { - errorString_ = "MidiInJack::initialize: JACK server not running?"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("JACK server not running?"), + Error::WARNING) ); return; } @@ -4714,8 +4777,8 @@ void MidiInJack :: openPort( unsigned int portNumber, const std::string & portNa JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); if ( data->local == NULL) { - errorString_ = "MidiInJack::openPort: JACK error creating port"; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error creating JACK port."), + Error::DRIVER_ERROR) ); return; } @@ -4732,10 +4795,9 @@ void MidiInJack :: openVirtualPort( const std::string portName ) if ( data->local == NULL ) data->local = jack_port_register( *(data->seq), portName.c_str(), JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); - if ( data->local == NULL ) { - errorString_ = "MidiInJack::openVirtualPort: JACK error creating virtual port"; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error creating JACK virtual port."), + Error::DRIVER_ERROR) ); } } @@ -4746,20 +4808,20 @@ void MidiInJack :: openPort( const PortDescriptor & p, const JackPortDescriptor * port = dynamic_cast(&p); if ( !data ) { - errorString_ = "MidiInAlsa::openPort: Internal error: data has not been allocated!"; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Internal error: data has not been allocated."), + Error::DRIVER_ERROR) ); return; } #if 0 if ( connected_ ) { - errorString_ = "MidiInAlsa::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); return; } #endif if (!port) { - errorString_ = "MidiInAlsa::openPort: an invalid (i.e. non-ALSA) port descriptor has been passed to openPort!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("An invalid (i.e. non-ALSA) port descriptor has been passed to openPort"), + Error::WARNING) ); return; } @@ -4779,8 +4841,8 @@ void MidiInJack :: openPort( const PortDescriptor & p, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); if ( data->port == NULL) { - errorString_ = "MidiInJack::openPort: JACK error creating port"; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error creating JACK port."), + Error::DRIVER_ERROR) ); return; } @@ -4828,7 +4890,7 @@ unsigned int MidiInJack :: getPortCount() count++; free( ports ); - + return count; } @@ -4845,16 +4907,15 @@ std::string MidiInJack :: getPortName( unsigned int portNumber ) // Check port validity if ( ports == NULL ) { - errorString_ = "MidiInJack::getPortName: no ports available!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("No ports available."), + Error::WARNING) ); return retStr; } if ( ports[portNumber] == NULL ) { std::ostringstream ost; - ost << "MidiInJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::WARNING, portNumber) ); } else retStr.assign( ports[portNumber] ); @@ -4963,8 +5024,8 @@ void MidiOutJack :: connect() // Initialize JACK client if (( *(data->seq) = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { - errorString_ = "MidiOutJack::initialize: JACK server not running?"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("JACK server not running?"), + Error::WARNING) ); return; } @@ -5004,8 +5065,8 @@ void MidiOutJack :: openPort( unsigned int portNumber, const std::string & portN JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); if ( data->local == NULL ) { - errorString_ = "MidiOutJack::openPort: JACK error creating port"; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error creating JACK port."), + Error::DRIVER_ERROR) ); return; } @@ -5024,8 +5085,8 @@ void MidiOutJack :: openVirtualPort( const std::string portName ) JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); if ( data->local == NULL ) { - errorString_ = "MidiOutJack::openVirtualPort: JACK error creating virtual port"; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error creating JACK virtual port."), + Error::DRIVER_ERROR) ); } } @@ -5036,20 +5097,20 @@ void MidiOutJack :: openPort( const PortDescriptor & p, const JackPortDescriptor * port = dynamic_cast(&p); if ( !data ) { - errorString_ = "MidiInAlsa::openPort: Internal error: data has not been allocated!"; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Internal error: data has not been allocated."), + Error::DRIVER_ERROR) ); return; } #if 0 if ( connected_ ) { - errorString_ = "MidiInAlsa::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); return; } #endif if (!port) { - errorString_ = "MidiInAlsa::openPort: an invalid (i.e. non-ALSA) port descriptor has been passed to openPort!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("An invalid (i.e. non-JACK) port descriptor has been passed to openPort"), + Error::WARNING) ); return; } @@ -5069,8 +5130,8 @@ void MidiOutJack :: openPort( const PortDescriptor & p, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); if ( data->port == NULL) { - errorString_ = "MidiOutJack::openPort: JACK error creating port"; - error( Error::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error creating JACK port."), + Error::DRIVER_ERROR) ); return; } @@ -5079,6 +5140,7 @@ void MidiOutJack :: openPort( const PortDescriptor & p, jack_connect( data->client, name.c_str(), jack_port_name( data->port ) ); #endif } + Pointer MidiOutJack :: getDescriptor(bool local) { JackMidiData *data = static_cast (apiData_); @@ -5135,16 +5197,15 @@ std::string MidiOutJack :: getPortName( unsigned int portNumber ) // Check port validity if ( ports == NULL) { - errorString_ = "MidiOutJack::getPortName: no ports available!"; - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("No ports available"), + Error::WARNING) ); return retStr; } if ( ports[portNumber] == NULL) { std::ostringstream ost; - ost << "MidiOutJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( Error::WARNING, errorString_ ); + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::WARNING, portNumber) ); } else retStr.assign( ports[portNumber] ); diff --git a/RtMidi.h b/RtMidi.h index 31b98927..b030b3a2 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -61,6 +61,15 @@ #include #include #include +// the following are used in the error constructor +#include +#include +#include + +#ifdef RTMIDI_GETTEXT +#include "gettext.h" +#endif +#define gettext_noopt(str) (str) #define NAMESPACE_RTMIDI_START namespace rtmidi { #define NAMESPACE_RTMIDI_END } @@ -114,6 +123,14 @@ typedef void (*MidiCallback)( double timeStamp, std::vector *mess */ /************************************************************************/ +#define RTMIDI_ERROR(message, type) \ + rtmidi::Error(message, type, \ + RTMIDI_CLASSNAME, __FUNCTION__, \ + __FILE__, __LINE__) +#define RTMIDI_ERROR1(message, type, arg1) \ + rtmidi::Error(message, type, \ + RTMIDI_CLASSNAME, __FUNCTION__, \ + __FILE__, __LINE__, arg1) class Error : public std::exception { public: @@ -133,13 +150,23 @@ class Error : public std::exception }; //! The constructor. - Error( const std::string& message, Type type = Error::UNSPECIFIED ) throw() : message_(message), type_(type) {} + Error( const char * message, + Type type, + const char * class_name, + const char * function_name, + const char * file_name, + int line_number, ...) throw(); //! The destructor. virtual ~Error( void ) throw() {} //! Prints thrown error message to stderr. - virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } + virtual void printMessage( std::ostream &s = std::cerr ) const throw() { + s << std::endl + << file << ":" << line << ": in function" + << classname << "::" << function << std::endl + << message_ << std::endl << std::endl; + } //! Returns the thrown error message type. virtual const Type& getType(void) const throw() { return type_; } @@ -151,6 +178,10 @@ class Error : public std::exception virtual const char* what( void ) const throw() { return message_.c_str(); } protected: + const char * classname; + const char * function; + const char * file; + int line; std::string message_; Type type_; }; @@ -362,6 +393,7 @@ typedef std::list > PortList; // // **************************************************************** // +#define RTMIDI_CLASSNAME "MidiApi" class MidiApi { public: @@ -417,8 +449,8 @@ class MidiApi */ void openPort( Pointer p, const std::string & portName = std::string( "RtMidi" ) ) { if (!p) { - errorString_ = "MidiApi::openPort: passed NULL pointer"; - error( Error::INVALID_PARAMETER, errorString_ ); + error(RTMIDI_ERROR( gettext_noopt("Passed NULL pointer."), + Error::INVALID_PARAMETER)); return; } openPort(*p, portName); @@ -498,7 +530,7 @@ class MidiApi virtual ApiType getCurrentApi( void ) throw() = 0; //! A basic error reporting function for RtMidi classes. - void error( Error::Type type, std::string errorString ); + void error( Error e ); protected: virtual void initialize( const std::string& clientName ) = 0; @@ -508,7 +540,9 @@ class MidiApi std::string errorString_; ErrorCallback errorCallback_; }; +#undef RTMIDI_CLASSNAME +#define RTMIDI_CLASSNAME "MidiInApi" class MidiInApi : public MidiApi { public: @@ -521,8 +555,8 @@ class MidiInApi : public MidiApi RTMIDI_DEPRECATED(double getMessage( std::vector *message )) { if (!message) { - errorString_ = "MidiInApi::getMessage: passed NULL pointer"; - error( Error::WARNING, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), + Error::WARNING )); } return getMessage(*message); } @@ -575,7 +609,9 @@ class MidiInApi : public MidiApi protected: MidiInData inputData_; }; +#undef RTMIDI_CLASSNAME +#define RTMIDI_CLASSNAME "MidiOutApi" class MidiOutApi : public MidiApi { public: @@ -585,13 +621,14 @@ class MidiOutApi : public MidiApi RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) { if (!message) { - errorString_ = "MidiOutApi::sendMessage: no data in message argument!"; - error( Error::WARNING, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("No data in message argument."), + Error::WARNING)); } sendMessage(*message); } virtual void sendMessage( std::vector &message ) = 0; }; +#undef RTMIDI_CLASSNAME typedef Pointer MidiApiPtr; typedef std::list MidiApiList; @@ -606,6 +643,7 @@ typedef std::list MidiApiList; by Gary P. Scavone, 2003-2014. */ /**********************************************************************/ +#define RTMIDI_CLASSNAME "Midi" class Midi { public: typedef rtmidi::ApiType Api; @@ -791,7 +829,7 @@ class Midi { } //! A basic error reporting function for RtMidi classes. - void error( Error::Type type, std::string errorString ); + void error( Error e ); protected: MidiApi *rtapi_; MidiApiList * list; @@ -812,6 +850,7 @@ class Midi { } } }; +#undef RTMIDI_CLASSNAME /**********************************************************************/ /*! \class MidiIn @@ -845,6 +884,7 @@ class Midi { // // **************************************************************** // +#define RTMIDI_CLASSNAME "MidiIn" class MidiIn : public Midi { public: @@ -909,7 +949,8 @@ class MidiIn : public Midi void openPort( Pointer p, const std::string & portName = std::string( "RtMidi" ) ) { if (!p) { - error( Error::INVALID_PARAMETER, "MidiApi::openPort: passed NULL pointer" ); + error(RTMIDI_ERROR(gettext_noopt("A NULL pointer has been passed as port descriptor"), + Error::INVALID_PARAMETER)); return; } openPort(*p, portName); @@ -940,7 +981,8 @@ class MidiIn : public Midi if (rtapi_) rtapi_->openVirtualPort(portName); else { - error(Error::INVALID_DEVICE,"MidiIn::openVirtualPort: No valid API selected"); + error(RTMIDI_ERROR(gettext_noopt("No valid API selected."), + Error::INVALID_DEVICE)); } } @@ -1008,8 +1050,9 @@ class MidiIn : public Midi { if (rtapi_) return static_cast(rtapi_)->getMessage(message); - std::string errorString_ = "MidiIn::getMessage: No valid API found."; - error( Error::WARNING, errorString_ ); + std::string errorString_ = "MidiIn::getMessage: "; + error( RTMIDI_ERROR(gettext_noopt("No valid API found."), + Error::WARNING)); return 0.0; } @@ -1026,13 +1069,13 @@ class MidiIn : public Midi RTMIDI_DEPRECATED(double getMessage( std::vector *message )) { if (!message) { - error( Error::WARNING, - "MidiIn::getMessage: passed NULL pointer"); + error( RTMIDI_ERROR(gettext_noopt("passed NULL pointer"), + Error::WARNING)); } if (rtapi_) return static_cast(rtapi_)->getMessage(*message); - error( Error::WARNING, - "MidiIn::getMessage: No valid API found."); + error( RTMIDI_ERROR(gettext_noopt("No valid API found."), + Error::WARNING)); return 0.0; } @@ -1042,6 +1085,7 @@ class MidiIn : public Midi void openMidiApi( ApiType api ); }; +#undef RTMIDI_CLASSNAME /**********************************************************************/ /*! \class MidiOut @@ -1059,6 +1103,7 @@ class MidiIn : public Midi */ /**********************************************************************/ +#define RTMIDI_CLASSNAME "MidiOut" class MidiOut : public Midi { public: @@ -1116,7 +1161,8 @@ class MidiOut : public Midi void openPort( Pointer p, const std::string & portName = std::string( "RtMidi" ) ) { if (!p) { - error( Error::INVALID_PARAMETER, "MidiApi::openPort: passed NULL pointer" ); + error(RTMIDI_ERROR(gettext_noopt("passed NULL pointer"), + Error::INVALID_PARAMETER)); return; } openPort(*p, portName); @@ -1148,7 +1194,8 @@ class MidiOut : public Midi if (rtapi_) rtapi_->openVirtualPort(portName); else { - error(Error::INVALID_DEVICE,"MidiOut::openVirtualPort: No valid API selected"); + error(RTMIDI_ERROR(gettext_noopt("No valid API selected."), + Error::INVALID_DEVICE)); } } @@ -1164,13 +1211,14 @@ class MidiOut : public Midi RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) { if (!message) { - error( Error::WARNING, - "MidiOutApi::sendMessage: no data in message argument!"); + error( RTMIDI_ERROR(gettext_noopt("No data in message argument!"), + Error::WARNING)); } if (rtapi_) static_cast(rtapi_)->sendMessage(*message); else - error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); + error( RTMIDI_ERROR(gettext_noopt("The API has not been set."), + Error::WARNING)); } @@ -1182,12 +1230,14 @@ class MidiOut : public Midi void sendMessage( std::vector &message ) { if (rtapi_) static_cast(rtapi_)->sendMessage(message); - error( Error::WARNING, "MidiOut::sendMessage: The API has not been set."); + error( RTMIDI_ERROR(gettext_noopt("The API has not been set."), + Error::WARNING)); } protected: static MidiApiList queryApis; void openMidiApi( ApiType api ); }; +#undef RTMIDI_CLASSNAME // **************************************************************** // From 7939b20a0aba9fade46d47ab67db9b4a13fe4d3c Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 8 Jun 2014 17:08:37 +0200 Subject: [PATCH 060/210] Fix the remaining compilation errors for WinMM and the Error patch. --- RtMidi.cpp | 74 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 5028266c..bac34a66 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -3695,6 +3695,7 @@ NAMESPACE_RTMIDI_START #ifdef UNIQUE_NAME #undef UNIQUE_NAME #endif +NAMESPACE_RTMIDI_START /*! An abstraction layer for the ALSA sequencer layer. It provides the following functionality: - dynamic allocation of the sequencer @@ -3703,6 +3704,7 @@ NAMESPACE_RTMIDI_START the parameter \ref locking. */ +#define RTMIDI_CLASSNAME "WinMMSequencer" template class WinMMSequencer { public: @@ -3762,8 +3764,8 @@ class WinMMSequencer { if ( port >= nDevices ) { std::ostringstream ost; std::cerr << port << "<" << nDevices << std::endl; - throw Error("WinMMSequencer::getPortName: the 'port' argument is invalid.", - Error::WARNING); + throw Error(RTMIDI_ERROR1(gettext_noopt("The port argument %d is invalid."), + Error::WARNING,port)); } if (is_input) { @@ -3986,6 +3988,7 @@ class WinMMSequencer { }; // typedef WinMMSequencer<1> LockingWinMMSequencer; typedef WinMMSequencer<0> NonLockingWinMMSequencer; +#undef RTMIDI_CLASSNAME struct WinMMPortDescriptor:public PortDescriptor { @@ -4228,6 +4231,7 @@ static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, apiData->message.bytes.clear(); } +#define RTMIDI_CLASSNAME "MidiInWinMM" MidiInWinMM :: MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { initialize( clientName ); @@ -4336,7 +4340,7 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string & /*por Error::DRIVER_ERROR) ); return; } - + connected_ = true; } @@ -4350,18 +4354,18 @@ void MidiInWinMM :: openVirtualPort( std::string /*portName*/ ) void MidiInWinMM :: openPort(const PortDescriptor & p, const std::string & portName) { const WinMMPortDescriptor * port = dynamic_cast (&p); if ( !port) { - error( Error::DRIVER_ERROR, - "MidiINWinMM::openPort: an invalid (i.e. non-WinMM) port descriptor has been passed to openPort!"); + error( RTMIDI_ERROR(gettext_noopt("An invalid (i.e. non-WinMM) port descriptor has been passed to openPort."), + Error::DRIVER_ERROR)); return; } if ( connected_ ) { - errorString_ = "MidiInWinMM::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("We are overwriting an existing connection. This is probably a programming error."), + Error::WARNING) ); return; } if (port->getCapabilities() != PortDescriptor::INPUT) { - error( Error::DRIVER_ERROR, - "MidiINWinMM::openPort: the port descriptor cannot be used to open an input port."); + error(RTMIDI_ERROR(gettext_noopt("The port descriptor pased to MidiInWinMM::openPort() cannot be used to open an input port."), + Error::DRIVER_ERROR)); return; } @@ -4370,8 +4374,8 @@ void MidiInWinMM :: openPort(const PortDescriptor & p, const std::string & portN openPort(port->getPortNumber(),portName); if (!port->is_valid()) { closePort(); - error (Error::DRIVER_ERROR, - "MidiINWinMM::openPort: some change in the arrangement of MIDI input ports invalidated the port descriptor."); + error (RTMIDI_ERROR(gettext_noopt("Some change in the arrangement of MIDI input ports invalidated the port descriptor."), + Error::DRIVER_ERROR)); return; } connected_ = true; @@ -4385,16 +4389,16 @@ Pointer MidiInWinMM :: getDescriptor(bool local) UINT devid; switch (midiInGetID(data->inHandle,&devid)) { case MMSYSERR_INVALHANDLE: - error (Error::DRIVER_ERROR, - "MidiInWinMM::getDescriptor: The internal handle is invalid."); + error (RTMIDI_ERROR(gettext_noopt("The handle is invalid. Did you disconnect the device?"), + Error::DRIVER_ERROR)); return 0; case MMSYSERR_NODRIVER: - error (Error::DRIVER_ERROR, - "MidiInWinMM::getDescriptor: The system has no driver for our handle :-(."); + error (RTMIDI_ERROR(gettext_noopt("The system has no driver for our handle :-(. Did you disconnect the device?"), + Error::DRIVER_ERROR)); return 0; case MMSYSERR_NOMEM: - error (Error::DRIVER_ERROR, - "MidiInWinMM::getDescriptor: The system could not provide enough memory."); + error (RTMIDI_ERROR(gettext_noopt("Out of memory."), + Error::DRIVER_ERROR)); return 0; } return new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); @@ -4446,8 +4450,8 @@ std::string MidiInWinMM :: getPortName( unsigned int portNumber ) std::string stringName; unsigned int nDevices = midiInGetNumDevs(); if ( portNumber >= nDevices ) { - error(RTMIDI_ERROR(gettext_noopt("The 'portNumber' argument (%d) is invalid."), - Error::WARNING,portNumber)); + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::WARNING,portNumber)); return stringName; } @@ -4472,12 +4476,15 @@ std::string MidiInWinMM :: getPortName( unsigned int portNumber ) return stringName; } +#undef RTMIDI_CLASSNAME + //*********************************************************************// // API: Windows MM // Class Definitions: MidiOutWinMM //*********************************************************************// +#define RTMIDI_CLASSNAME "MidiOutWinMM" MidiOutWinMM :: MidiOutWinMM( const std::string clientName ) : MidiOutApi() { initialize( clientName ); @@ -4597,18 +4604,18 @@ void MidiOutWinMM :: openVirtualPort( std::string /*portName*/ ) void MidiOutWinMM :: openPort(const PortDescriptor & p, const std::string & portName) { const WinMMPortDescriptor * port = dynamic_cast (&p); if ( !port) { - error( Error::DRIVER_ERROR, - "MidiOUTWinMM::openPort: an invalid (i.e. non-WinMM) port descriptor has been passed to openPort!"); + error( RTMIDI_ERROR(gettext_noopt("An invalid (i.e. non-WinMM) port descriptor has been passed to openPort."), + Error::DRIVER_ERROR)); return; } if ( connected_ ) { - errorString_ = "MidiOutWinMM::openPort: a valid connection already exists!"; - error( Error::WARNING, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("A valid connection already exists." ), + Error::WARNING) ); return; } if (port->getCapabilities() != PortDescriptor::OUTPUT) { - error( Error::DRIVER_ERROR, - "MidiOUTWinMM::openPort: the port descriptor cannot be used to open an output port."); + error( RTMIDI_ERROR(gettext_noopt("The port descriptor cannot be used to open an output port."), + Error::DRIVER_ERROR)); return; } @@ -4617,8 +4624,8 @@ void MidiOutWinMM :: openPort(const PortDescriptor & p, const std::string & port openPort(port->getPortNumber(),portName); if (!port->is_valid()) { closePort(); - error (Error::DRIVER_ERROR, - "MidiOUTWinMM::openPort: some change in the arrangement of MIDI input ports invalidated the port descriptor."); + error (RTMIDI_ERROR(gettext_noopt("Some change in the arrangement of MIDI input ports invalidated the port descriptor."), + Error::DRIVER_ERROR)); return; } connected_ = true; @@ -4632,16 +4639,16 @@ Pointer MidiOutWinMM :: getDescriptor(bool local) UINT devid; switch (midiOutGetID(data->outHandle,&devid)) { case MMSYSERR_INVALHANDLE: - error (Error::DRIVER_ERROR, - "MidiOutWinMM::getDescriptor: The internal handle is invalid."); + error (RTMIDI_ERROR(gettext_noopt("The internal handle is invalid. Did you disconnect the device?"), + Error::DRIVER_ERROR)); return 0; case MMSYSERR_NODRIVER: - error (Error::DRIVER_ERROR, - "MidiOutWinMM::getDescriptor: The system has no driver for our handle :-(."); + error (RTMIDI_ERROR(gettext_noopt("The system has no driver for our handle :-(. Did you disconnect the device?"), + Error::DRIVER_ERROR)); return 0; case MMSYSERR_NOMEM: - error (Error::DRIVER_ERROR, - "MidiOutWinMM::getDescriptor: The system could not handle enough memory."); + error (RTMIDI_ERROR(gettext_noopt("Out of memory."), + Error::DRIVER_ERROR)); return 0; } return new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); @@ -4733,6 +4740,7 @@ void MidiOutWinMM :: sendMessage( std::vector &message ) } } } +#undef RTMIDI_CLASSNAME NAMESPACE_RTMIDI_END #endif // __WINDOWS_MM__ From 5b6f0f8d2bd6762b9ecbf094866cd7cf20551299 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 8 Jun 2014 21:43:06 +0200 Subject: [PATCH 061/210] Gettextize the source tree. --- ABOUT-NLS | 1282 ++++++++++++++++++++++++++++++++++++++++ Makefile.am | 4 +- configure.ac | 5 +- po/Makefile.in.in | 454 ++++++++++++++ po/Makevars | 53 ++ po/POTFILES.in | 3 + po/Rules-quot | 47 ++ po/boldquot.sed | 10 + po/en@boldquot.header | 25 + po/en@quot.header | 22 + po/insert-header.sin | 23 + po/quot.sed | 6 + po/remove-potcdate.sin | 19 + po/rtmidi.pot | 428 ++++++++++++++ 14 files changed, 2378 insertions(+), 3 deletions(-) create mode 100644 ABOUT-NLS create mode 100644 po/Makefile.in.in create mode 100644 po/Makevars create mode 100644 po/POTFILES.in create mode 100644 po/Rules-quot create mode 100644 po/boldquot.sed create mode 100644 po/en@boldquot.header create mode 100644 po/en@quot.header create mode 100644 po/insert-header.sin create mode 100644 po/quot.sed create mode 100644 po/remove-potcdate.sin create mode 100644 po/rtmidi.pot diff --git a/ABOUT-NLS b/ABOUT-NLS new file mode 100644 index 00000000..b1de1b68 --- /dev/null +++ b/ABOUT-NLS @@ -0,0 +1,1282 @@ +1 Notes on the Free Translation Project +*************************************** + +Free software is going international! The Free Translation Project is +a way to get maintainers of free software, translators, and users all +together, so that free software will gradually become able to speak many +languages. A few packages already provide translations for their +messages. + + If you found this `ABOUT-NLS' file inside a distribution, you may +assume that the distributed package does use GNU `gettext' internally, +itself available at your nearest GNU archive site. But you do _not_ +need to install GNU `gettext' prior to configuring, installing or using +this package with messages translated. + + Installers will find here some useful hints. These notes also +explain how users should proceed for getting the programs to use the +available translations. They tell how people wanting to contribute and +work on translations can contact the appropriate team. + +1.1 INSTALL Matters +=================== + +Some packages are "localizable" when properly installed; the programs +they contain can be made to speak your own native language. Most such +packages use GNU `gettext'. Other packages have their own ways to +internationalization, predating GNU `gettext'. + + By default, this package will be installed to allow translation of +messages. It will automatically detect whether the system already +provides the GNU `gettext' functions. Installers may use special +options at configuration time for changing the default behaviour. The +command: + + ./configure --disable-nls + +will _totally_ disable translation of messages. + + When you already have GNU `gettext' installed on your system and run +configure without an option for your new package, `configure' will +probably detect the previously built and installed `libintl' library +and will decide to use it. If not, you may have to to use the +`--with-libintl-prefix' option to tell `configure' where to look for it. + + Internationalized packages usually have many `po/LL.po' files, where +LL gives an ISO 639 two-letter code identifying the language. Unless +translations have been forbidden at `configure' time by using the +`--disable-nls' switch, all available translations are installed +together with the package. However, the environment variable `LINGUAS' +may be set, prior to configuration, to limit the installed set. +`LINGUAS' should then contain a space separated list of two-letter +codes, stating which languages are allowed. + +1.2 Using This Package +====================== + +As a user, if your language has been installed for this package, you +only have to set the `LANG' environment variable to the appropriate +`LL_CC' combination. If you happen to have the `LC_ALL' or some other +`LC_xxx' environment variables set, you should unset them before +setting `LANG', otherwise the setting of `LANG' will not have the +desired effect. Here `LL' is an ISO 639 two-letter language code, and +`CC' is an ISO 3166 two-letter country code. For example, let's +suppose that you speak German and live in Germany. At the shell +prompt, merely execute `setenv LANG de_DE' (in `csh'), +`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). +This can be done from your `.login' or `.profile' file, once and for +all. + + You might think that the country code specification is redundant. +But in fact, some languages have dialects in different countries. For +example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The +country code serves to distinguish the dialects. + + The locale naming convention of `LL_CC', with `LL' denoting the +language and `CC' denoting the country, is the one use on systems based +on GNU libc. On other systems, some variations of this scheme are +used, such as `LL' or `LL_CC.ENCODING'. You can get the list of +locales supported by your system for your language by running the +command `locale -a | grep '^LL''. + + Not all programs have translations for all languages. By default, an +English message is shown in place of a nonexistent translation. If you +understand other languages, you can set up a priority list of languages. +This is done through a different environment variable, called +`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' +for the purpose of message handling, but you still need to have `LANG' +set to the primary language; this is required by other parts of the +system libraries. For example, some Swedish users who would rather +read translations in German than English for when Swedish is not +available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. + + Special advice for Norwegian users: The language code for Norwegian +bokma*l changed from `no' to `nb' recently (in 2003). During the +transition period, while some message catalogs for this language are +installed under `nb' and some older ones under `no', it's recommended +for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and +older translations are used. + + In the `LANGUAGE' environment variable, but not in the `LANG' +environment variable, `LL_CC' combinations can be abbreviated as `LL' +to denote the language's main dialect. For example, `de' is equivalent +to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' +(Portuguese as spoken in Portugal) in this context. + +1.3 Translating Teams +===================== + +For the Free Translation Project to be a success, we need interested +people who like their own language and write it well, and who are also +able to synergize with other translators speaking the same language. +Each translation team has its own mailing list. The up-to-date list of +teams can be found at the Free Translation Project's homepage, +`http://translationproject.org/', in the "Teams" area. + + If you'd like to volunteer to _work_ at translating messages, you +should become a member of the translating team for your own language. +The subscribing address is _not_ the same as the list itself, it has +`-request' appended. For example, speakers of Swedish can send a +message to `sv-request@li.org', having this message body: + + subscribe + + Keep in mind that team members are expected to participate +_actively_ in translations, or at solving translational difficulties, +rather than merely lurking around. If your team does not exist yet and +you want to start one, or if you are unsure about what to do or how to +get started, please write to `coordinator@translationproject.org' to +reach the coordinator for all translator teams. + + The English team is special. It works at improving and uniformizing +the terminology in use. Proven linguistic skills are praised more than +programming skills, here. + +1.4 Available Packages +====================== + +Languages are not equally supported in all packages. The following +matrix shows the current state of internationalization, as of June +2010. The matrix shows, in regard of each package, for which languages +PO files have been submitted to translation coordination, with a +translation percentage of at least 50%. + + Ready PO files af am an ar as ast az be be@latin bg bn_IN bs ca + +--------------------------------------------------+ + a2ps | [] [] | + aegis | | + ant-phone | | + anubis | | + aspell | [] [] | + bash | | + bfd | | + bibshelf | [] | + binutils | | + bison | | + bison-runtime | [] | + bluez-pin | [] [] | + bombono-dvd | | + buzztard | | + cflow | | + clisp | | + coreutils | [] [] | + cpio | | + cppi | | + cpplib | [] | + cryptsetup | | + dfarc | | + dialog | [] [] | + dico | | + diffutils | [] | + dink | | + doodle | | + e2fsprogs | [] | + enscript | [] | + exif | | + fetchmail | [] | + findutils | [] | + flex | [] | + freedink | | + gas | | + gawk | [] [] | + gcal | [] | + gcc | | + gettext-examples | [] [] [] [] | + gettext-runtime | [] [] | + gettext-tools | [] [] | + gip | [] | + gjay | | + gliv | [] | + glunarclock | [] [] | + gnubiff | | + gnucash | [] | + gnuedu | | + gnulib | | + gnunet | | + gnunet-gtk | | + gnutls | | + gold | | + gpe-aerial | | + gpe-beam | | + gpe-bluetooth | | + gpe-calendar | | + gpe-clock | [] | + gpe-conf | | + gpe-contacts | | + gpe-edit | | + gpe-filemanager | | + gpe-go | | + gpe-login | | + gpe-ownerinfo | [] | + gpe-package | | + gpe-sketchbook | | + gpe-su | [] | + gpe-taskmanager | [] | + gpe-timesheet | [] | + gpe-today | [] | + gpe-todo | | + gphoto2 | | + gprof | [] | + gpsdrive | | + gramadoir | | + grep | | + grub | [] [] | + gsasl | | + gss | | + gst-plugins-bad | [] | + gst-plugins-base | [] | + gst-plugins-good | [] | + gst-plugins-ugly | [] | + gstreamer | [] [] [] | + gtick | | + gtkam | [] | + gtkorphan | [] | + gtkspell | [] [] [] | + gutenprint | | + hello | [] | + help2man | | + hylafax | | + idutils | | + indent | [] [] | + iso_15924 | | + iso_3166 | [] [] [] [] [] [] [] | + iso_3166_2 | | + iso_4217 | | + iso_639 | [] [] [] [] | + iso_639_3 | | + jwhois | | + kbd | | + keytouch | [] | + keytouch-editor | | + keytouch-keyboa... | [] | + klavaro | [] | + latrine | | + ld | [] | + leafpad | [] [] | + libc | [] [] | + libexif | () | + libextractor | | + libgnutls | | + libgpewidget | | + libgpg-error | | + libgphoto2 | | + libgphoto2_port | | + libgsasl | | + libiconv | [] | + libidn | | + lifelines | | + liferea | [] [] | + lilypond | | + linkdr | [] | + lordsawar | | + lprng | | + lynx | [] | + m4 | | + mailfromd | | + mailutils | | + make | | + man-db | | + man-db-manpages | | + minicom | | + mkisofs | | + myserver | | + nano | [] [] | + opcodes | | + parted | | + pies | | + popt | | + psmisc | | + pspp | [] | + pwdutils | | + radius | [] | + recode | [] [] | + rosegarden | | + rpm | | + rush | | + sarg | | + screem | | + scrollkeeper | [] [] [] | + sed | [] [] | + sharutils | [] [] | + shishi | | + skencil | | + solfege | | + solfege-manual | | + soundtracker | | + sp | | + sysstat | | + tar | [] | + texinfo | | + tin | | + unicode-han-tra... | | + unicode-transla... | | + util-linux-ng | [] | + vice | | + vmm | | + vorbis-tools | | + wastesedge | | + wdiff | | + wget | [] [] | + wyslij-po | | + xchat | [] [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] | + +--------------------------------------------------+ + af am an ar as ast az be be@latin bg bn_IN bs ca + 6 0 1 2 3 19 1 10 3 28 3 1 38 + + crh cs da de el en en_GB en_ZA eo es et eu fa + +-------------------------------------------------+ + a2ps | [] [] [] [] [] [] [] | + aegis | [] [] [] | + ant-phone | [] () | + anubis | [] [] | + aspell | [] [] [] [] [] | + bash | [] [] [] | + bfd | [] | + bibshelf | [] [] [] | + binutils | [] | + bison | [] [] | + bison-runtime | [] [] [] [] | + bluez-pin | [] [] [] [] [] [] | + bombono-dvd | [] | + buzztard | [] [] [] | + cflow | [] [] | + clisp | [] [] [] [] | + coreutils | [] [] [] [] | + cpio | | + cppi | | + cpplib | [] [] [] | + cryptsetup | [] | + dfarc | [] [] [] | + dialog | [] [] [] [] [] | + dico | | + diffutils | [] [] [] [] [] [] | + dink | [] [] [] | + doodle | [] | + e2fsprogs | [] [] [] | + enscript | [] [] [] | + exif | () [] [] | + fetchmail | [] [] () [] [] [] | + findutils | [] [] [] | + flex | [] [] | + freedink | [] [] [] | + gas | [] | + gawk | [] [] [] | + gcal | [] | + gcc | [] [] | + gettext-examples | [] [] [] [] | + gettext-runtime | [] [] [] [] | + gettext-tools | [] [] [] | + gip | [] [] [] [] | + gjay | [] | + gliv | [] [] [] | + glunarclock | [] [] | + gnubiff | () | + gnucash | [] () () () () | + gnuedu | [] [] | + gnulib | [] [] | + gnunet | | + gnunet-gtk | [] | + gnutls | [] [] | + gold | [] | + gpe-aerial | [] [] [] [] | + gpe-beam | [] [] [] [] | + gpe-bluetooth | [] [] | + gpe-calendar | [] | + gpe-clock | [] [] [] [] | + gpe-conf | [] [] [] | + gpe-contacts | [] [] [] | + gpe-edit | [] [] | + gpe-filemanager | [] [] [] | + gpe-go | [] [] [] [] | + gpe-login | [] [] | + gpe-ownerinfo | [] [] [] [] | + gpe-package | [] [] [] | + gpe-sketchbook | [] [] [] [] | + gpe-su | [] [] [] [] | + gpe-taskmanager | [] [] [] [] | + gpe-timesheet | [] [] [] [] | + gpe-today | [] [] [] [] | + gpe-todo | [] [] [] | + gphoto2 | [] [] () [] [] [] | + gprof | [] [] [] | + gpsdrive | [] [] [] | + gramadoir | [] [] [] | + grep | [] | + grub | [] [] | + gsasl | [] | + gss | | + gst-plugins-bad | [] [] [] [] [] | + gst-plugins-base | [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] | + gtick | [] () [] | + gtkam | [] [] () [] [] | + gtkorphan | [] [] [] [] | + gtkspell | [] [] [] [] [] [] [] | + gutenprint | [] [] [] | + hello | [] [] [] [] | + help2man | [] | + hylafax | [] [] | + idutils | [] [] | + indent | [] [] [] [] [] [] [] | + iso_15924 | [] () [] [] | + iso_3166 | [] [] [] [] () [] [] [] () | + iso_3166_2 | () | + iso_4217 | [] [] [] () [] [] | + iso_639 | [] [] [] [] () [] [] | + iso_639_3 | [] | + jwhois | [] | + kbd | [] [] [] [] [] | + keytouch | [] [] | + keytouch-editor | [] [] | + keytouch-keyboa... | [] | + klavaro | [] [] [] [] | + latrine | [] () | + ld | [] [] | + leafpad | [] [] [] [] [] [] | + libc | [] [] [] [] | + libexif | [] [] () | + libextractor | | + libgnutls | [] | + libgpewidget | [] [] | + libgpg-error | [] [] | + libgphoto2 | [] () | + libgphoto2_port | [] () [] | + libgsasl | | + libiconv | [] [] [] [] [] | + libidn | [] [] [] | + lifelines | [] () | + liferea | [] [] [] [] [] | + lilypond | [] [] [] | + linkdr | [] [] [] | + lordsawar | [] | + lprng | | + lynx | [] [] [] [] | + m4 | [] [] [] [] | + mailfromd | | + mailutils | [] | + make | [] [] [] | + man-db | | + man-db-manpages | | + minicom | [] [] [] [] | + mkisofs | | + myserver | | + nano | [] [] [] | + opcodes | [] [] | + parted | [] [] | + pies | | + popt | [] [] [] [] [] | + psmisc | [] [] [] | + pspp | [] | + pwdutils | [] | + radius | [] | + recode | [] [] [] [] [] [] | + rosegarden | () () () | + rpm | [] [] [] | + rush | | + sarg | | + screem | | + scrollkeeper | [] [] [] [] [] | + sed | [] [] [] [] [] [] | + sharutils | [] [] [] [] | + shishi | | + skencil | [] () [] | + solfege | [] [] [] | + solfege-manual | [] [] | + soundtracker | [] [] [] | + sp | [] | + sysstat | [] [] [] | + tar | [] [] [] [] | + texinfo | [] [] [] | + tin | [] [] | + unicode-han-tra... | | + unicode-transla... | | + util-linux-ng | [] [] [] [] | + vice | () () | + vmm | [] | + vorbis-tools | [] [] | + wastesedge | [] | + wdiff | [] [] | + wget | [] [] [] | + wyslij-po | | + xchat | [] [] [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] [] [] | + +-------------------------------------------------+ + crh cs da de el en en_GB en_ZA eo es et eu fa + 5 64 105 117 18 1 8 0 28 89 18 19 0 + + fi fr ga gl gu he hi hr hu hy id is it ja ka kn + +----------------------------------------------------+ + a2ps | [] [] [] [] | + aegis | [] [] | + ant-phone | [] [] | + anubis | [] [] [] [] | + aspell | [] [] [] [] | + bash | [] [] [] [] | + bfd | [] [] [] | + bibshelf | [] [] [] [] [] | + binutils | [] [] [] | + bison | [] [] [] [] | + bison-runtime | [] [] [] [] [] [] | + bluez-pin | [] [] [] [] [] [] [] [] | + bombono-dvd | [] | + buzztard | [] | + cflow | [] [] [] | + clisp | [] | + coreutils | [] [] [] [] [] | + cpio | [] [] [] [] | + cppi | [] [] | + cpplib | [] [] [] | + cryptsetup | [] [] [] | + dfarc | [] [] [] | + dialog | [] [] [] [] [] [] [] | + dico | | + diffutils | [] [] [] [] [] [] [] [] [] | + dink | [] | + doodle | [] [] | + e2fsprogs | [] [] | + enscript | [] [] [] [] | + exif | [] [] [] [] [] [] | + fetchmail | [] [] [] [] | + findutils | [] [] [] [] [] [] | + flex | [] [] [] | + freedink | [] [] [] | + gas | [] [] | + gawk | [] [] [] [] () [] | + gcal | [] | + gcc | [] | + gettext-examples | [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] | + gettext-tools | [] [] [] [] | + gip | [] [] [] [] [] [] | + gjay | [] | + gliv | [] () | + glunarclock | [] [] [] [] | + gnubiff | () [] () | + gnucash | () () () () () [] | + gnuedu | [] [] | + gnulib | [] [] [] [] [] [] | + gnunet | | + gnunet-gtk | [] | + gnutls | [] [] | + gold | [] [] | + gpe-aerial | [] [] [] | + gpe-beam | [] [] [] [] | + gpe-bluetooth | [] [] [] [] | + gpe-calendar | [] [] | + gpe-clock | [] [] [] [] [] | + gpe-conf | [] [] [] [] | + gpe-contacts | [] [] [] [] | + gpe-edit | [] [] [] | + gpe-filemanager | [] [] [] [] | + gpe-go | [] [] [] [] [] | + gpe-login | [] [] [] | + gpe-ownerinfo | [] [] [] [] [] | + gpe-package | [] [] [] | + gpe-sketchbook | [] [] [] [] | + gpe-su | [] [] [] [] [] [] | + gpe-taskmanager | [] [] [] [] [] | + gpe-timesheet | [] [] [] [] [] | + gpe-today | [] [] [] [] [] [] [] | + gpe-todo | [] [] [] | + gphoto2 | [] [] [] [] [] [] | + gprof | [] [] [] [] | + gpsdrive | [] [] [] | + gramadoir | [] [] [] | + grep | [] [] | + grub | [] [] [] [] | + gsasl | [] [] [] [] [] | + gss | [] [] [] [] [] | + gst-plugins-bad | [] [] [] [] [] [] | + gst-plugins-base | [] [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] | + gtick | [] [] [] [] [] | + gtkam | [] [] [] [] [] | + gtkorphan | [] [] [] | + gtkspell | [] [] [] [] [] [] [] [] [] | + gutenprint | [] [] [] [] | + hello | [] [] [] | + help2man | [] [] | + hylafax | [] | + idutils | [] [] [] [] [] [] | + indent | [] [] [] [] [] [] [] [] | + iso_15924 | [] () [] [] | + iso_3166 | [] () [] [] [] [] [] [] [] [] [] [] | + iso_3166_2 | () [] [] [] | + iso_4217 | [] () [] [] [] [] | + iso_639 | [] () [] [] [] [] [] [] [] | + iso_639_3 | () [] [] | + jwhois | [] [] [] [] [] | + kbd | [] [] | + keytouch | [] [] [] [] [] [] | + keytouch-editor | [] [] [] [] [] | + keytouch-keyboa... | [] [] [] [] [] | + klavaro | [] [] | + latrine | [] [] [] | + ld | [] [] [] [] | + leafpad | [] [] [] [] [] [] [] () | + libc | [] [] [] [] [] | + libexif | [] | + libextractor | | + libgnutls | [] [] | + libgpewidget | [] [] [] [] | + libgpg-error | [] [] | + libgphoto2 | [] [] [] | + libgphoto2_port | [] [] [] | + libgsasl | [] [] [] [] [] | + libiconv | [] [] [] [] [] [] | + libidn | [] [] [] [] | + lifelines | () | + liferea | [] [] [] [] | + lilypond | [] [] | + linkdr | [] [] [] [] [] | + lordsawar | | + lprng | [] | + lynx | [] [] [] [] [] | + m4 | [] [] [] [] [] [] | + mailfromd | | + mailutils | [] [] | + make | [] [] [] [] [] [] [] [] [] | + man-db | [] [] | + man-db-manpages | [] | + minicom | [] [] [] [] [] | + mkisofs | [] [] [] [] | + myserver | | + nano | [] [] [] [] [] [] | + opcodes | [] [] [] [] | + parted | [] [] [] [] | + pies | | + popt | [] [] [] [] [] [] [] [] [] | + psmisc | [] [] [] | + pspp | | + pwdutils | [] [] | + radius | [] [] | + recode | [] [] [] [] [] [] [] [] | + rosegarden | () () () () () | + rpm | [] [] | + rush | | + sarg | [] | + screem | [] [] | + scrollkeeper | [] [] [] [] | + sed | [] [] [] [] [] [] [] [] | + sharutils | [] [] [] [] [] [] [] | + shishi | [] | + skencil | [] | + solfege | [] [] [] [] | + solfege-manual | [] [] | + soundtracker | [] [] | + sp | [] () | + sysstat | [] [] [] [] [] | + tar | [] [] [] [] [] [] [] | + texinfo | [] [] [] [] | + tin | [] | + unicode-han-tra... | | + unicode-transla... | [] [] | + util-linux-ng | [] [] [] [] [] [] | + vice | () () () | + vmm | [] | + vorbis-tools | [] | + wastesedge | () () | + wdiff | [] | + wget | [] [] [] [] [] [] [] [] | + wyslij-po | [] [] [] | + xchat | [] [] [] [] [] [] [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] [] | + +----------------------------------------------------+ + fi fr ga gl gu he hi hr hu hy id is it ja ka kn + 105 121 53 20 4 8 3 5 53 2 120 5 84 67 0 4 + + ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne + +-----------------------------------------------+ + a2ps | [] | + aegis | | + ant-phone | | + anubis | [] [] | + aspell | [] | + bash | | + bfd | | + bibshelf | [] [] | + binutils | | + bison | [] | + bison-runtime | [] [] [] [] [] | + bluez-pin | [] [] [] [] [] | + bombono-dvd | | + buzztard | | + cflow | | + clisp | | + coreutils | [] | + cpio | | + cppi | | + cpplib | | + cryptsetup | | + dfarc | [] | + dialog | [] [] [] [] [] | + dico | | + diffutils | [] [] | + dink | | + doodle | | + e2fsprogs | | + enscript | | + exif | [] | + fetchmail | | + findutils | | + flex | | + freedink | [] | + gas | | + gawk | | + gcal | | + gcc | | + gettext-examples | [] [] [] [] | + gettext-runtime | [] | + gettext-tools | [] | + gip | [] [] | + gjay | | + gliv | | + glunarclock | [] | + gnubiff | | + gnucash | () () () () | + gnuedu | | + gnulib | | + gnunet | | + gnunet-gtk | | + gnutls | [] | + gold | | + gpe-aerial | [] | + gpe-beam | [] | + gpe-bluetooth | [] [] | + gpe-calendar | [] | + gpe-clock | [] [] [] [] [] | + gpe-conf | [] [] | + gpe-contacts | [] [] | + gpe-edit | [] | + gpe-filemanager | [] [] | + gpe-go | [] [] [] | + gpe-login | [] | + gpe-ownerinfo | [] [] | + gpe-package | [] [] | + gpe-sketchbook | [] [] | + gpe-su | [] [] [] [] [] [] | + gpe-taskmanager | [] [] [] [] [] [] | + gpe-timesheet | [] [] | + gpe-today | [] [] [] [] | + gpe-todo | [] [] | + gphoto2 | | + gprof | [] | + gpsdrive | | + gramadoir | | + grep | | + grub | | + gsasl | | + gss | | + gst-plugins-bad | [] [] [] [] | + gst-plugins-base | [] [] | + gst-plugins-good | [] [] | + gst-plugins-ugly | [] [] [] [] [] | + gstreamer | | + gtick | | + gtkam | [] | + gtkorphan | [] [] | + gtkspell | [] [] [] [] [] [] [] | + gutenprint | | + hello | [] [] [] | + help2man | | + hylafax | | + idutils | | + indent | | + iso_15924 | [] [] | + iso_3166 | [] [] () [] [] [] [] [] | + iso_3166_2 | | + iso_4217 | [] [] | + iso_639 | [] [] | + iso_639_3 | [] | + jwhois | [] | + kbd | | + keytouch | [] | + keytouch-editor | [] | + keytouch-keyboa... | [] | + klavaro | [] | + latrine | [] | + ld | | + leafpad | [] [] [] | + libc | [] | + libexif | | + libextractor | | + libgnutls | [] | + libgpewidget | [] [] | + libgpg-error | | + libgphoto2 | | + libgphoto2_port | | + libgsasl | | + libiconv | | + libidn | | + lifelines | | + liferea | | + lilypond | | + linkdr | | + lordsawar | | + lprng | | + lynx | | + m4 | | + mailfromd | | + mailutils | | + make | [] | + man-db | | + man-db-manpages | | + minicom | [] | + mkisofs | | + myserver | | + nano | [] [] | + opcodes | | + parted | | + pies | | + popt | [] [] [] | + psmisc | | + pspp | | + pwdutils | | + radius | | + recode | | + rosegarden | | + rpm | | + rush | | + sarg | | + screem | | + scrollkeeper | [] [] | + sed | | + sharutils | | + shishi | | + skencil | | + solfege | [] | + solfege-manual | | + soundtracker | | + sp | | + sysstat | [] | + tar | [] | + texinfo | [] | + tin | | + unicode-han-tra... | | + unicode-transla... | | + util-linux-ng | | + vice | | + vmm | | + vorbis-tools | | + wastesedge | | + wdiff | | + wget | [] | + wyslij-po | | + xchat | [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] | + +-----------------------------------------------+ + ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne + 20 5 10 1 13 48 4 2 2 4 24 10 20 3 1 + + nl nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr + +---------------------------------------------------+ + a2ps | [] [] [] [] [] [] [] [] | + aegis | [] [] [] | + ant-phone | [] [] | + anubis | [] [] [] | + aspell | [] [] [] [] [] | + bash | [] [] | + bfd | [] | + bibshelf | [] [] | + binutils | [] [] | + bison | [] [] [] | + bison-runtime | [] [] [] [] [] [] [] | + bluez-pin | [] [] [] [] [] [] [] [] | + bombono-dvd | [] () | + buzztard | [] [] | + cflow | [] | + clisp | [] [] | + coreutils | [] [] [] [] [] [] | + cpio | [] [] [] | + cppi | [] | + cpplib | [] | + cryptsetup | [] | + dfarc | [] | + dialog | [] [] [] [] | + dico | [] | + diffutils | [] [] [] [] [] [] | + dink | () | + doodle | [] [] | + e2fsprogs | [] [] | + enscript | [] [] [] [] [] | + exif | [] [] [] () [] | + fetchmail | [] [] [] [] | + findutils | [] [] [] [] [] | + flex | [] [] [] [] [] | + freedink | [] [] | + gas | | + gawk | [] [] [] [] | + gcal | | + gcc | [] | + gettext-examples | [] [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] [] [] [] | + gettext-tools | [] [] [] [] [] [] | + gip | [] [] [] [] [] | + gjay | | + gliv | [] [] [] [] [] [] | + glunarclock | [] [] [] [] [] | + gnubiff | [] () | + gnucash | [] () () () | + gnuedu | [] | + gnulib | [] [] [] [] | + gnunet | | + gnunet-gtk | | + gnutls | [] [] | + gold | | + gpe-aerial | [] [] [] [] [] [] [] | + gpe-beam | [] [] [] [] [] [] [] | + gpe-bluetooth | [] [] | + gpe-calendar | [] [] [] [] | + gpe-clock | [] [] [] [] [] [] [] [] | + gpe-conf | [] [] [] [] [] [] [] | + gpe-contacts | [] [] [] [] [] | + gpe-edit | [] [] [] | + gpe-filemanager | [] [] [] | + gpe-go | [] [] [] [] [] [] [] [] | + gpe-login | [] [] | + gpe-ownerinfo | [] [] [] [] [] [] [] [] | + gpe-package | [] [] | + gpe-sketchbook | [] [] [] [] [] [] [] | + gpe-su | [] [] [] [] [] [] [] [] | + gpe-taskmanager | [] [] [] [] [] [] [] [] | + gpe-timesheet | [] [] [] [] [] [] [] [] | + gpe-today | [] [] [] [] [] [] [] [] | + gpe-todo | [] [] [] [] [] | + gphoto2 | [] [] [] [] [] [] [] [] | + gprof | [] [] [] | + gpsdrive | [] [] | + gramadoir | [] [] | + grep | [] [] [] [] | + grub | [] [] [] | + gsasl | [] [] [] [] | + gss | [] [] [] | + gst-plugins-bad | [] [] [] [] [] [] | + gst-plugins-base | [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] | + gtick | [] [] [] | + gtkam | [] [] [] [] [] [] | + gtkorphan | [] | + gtkspell | [] [] [] [] [] [] [] [] [] [] | + gutenprint | [] [] | + hello | [] [] [] [] | + help2man | [] [] | + hylafax | [] | + idutils | [] [] [] [] [] | + indent | [] [] [] [] [] [] [] | + iso_15924 | [] [] [] [] | + iso_3166 | [] [] [] [] [] () [] [] [] [] [] [] [] [] | + iso_3166_2 | [] [] [] | + iso_4217 | [] [] [] [] [] [] [] [] | + iso_639 | [] [] [] [] [] [] [] [] [] | + iso_639_3 | [] [] | + jwhois | [] [] [] [] | + kbd | [] [] [] | + keytouch | [] [] [] | + keytouch-editor | [] [] [] | + keytouch-keyboa... | [] [] [] | + klavaro | [] [] | + latrine | [] [] | + ld | | + leafpad | [] [] [] [] [] [] [] [] [] | + libc | [] [] [] [] | + libexif | [] [] () [] | + libextractor | | + libgnutls | [] [] | + libgpewidget | [] [] [] | + libgpg-error | [] [] | + libgphoto2 | [] [] | + libgphoto2_port | [] [] [] [] [] | + libgsasl | [] [] [] [] [] | + libiconv | [] [] [] [] [] | + libidn | [] [] | + lifelines | [] [] | + liferea | [] [] [] [] [] () () [] | + lilypond | [] | + linkdr | [] [] [] | + lordsawar | | + lprng | [] | + lynx | [] [] [] | + m4 | [] [] [] [] [] | + mailfromd | [] | + mailutils | [] | + make | [] [] [] [] | + man-db | [] [] [] | + man-db-manpages | [] [] [] | + minicom | [] [] [] [] | + mkisofs | [] [] [] | + myserver | | + nano | [] [] [] [] | + opcodes | [] [] | + parted | [] [] [] [] | + pies | [] | + popt | [] [] [] [] | + psmisc | [] [] [] | + pspp | [] [] | + pwdutils | [] | + radius | [] [] [] | + recode | [] [] [] [] [] [] [] [] | + rosegarden | () () | + rpm | [] [] [] | + rush | [] [] | + sarg | | + screem | | + scrollkeeper | [] [] [] [] [] [] [] [] | + sed | [] [] [] [] [] [] [] [] [] | + sharutils | [] [] [] [] | + shishi | [] | + skencil | [] [] | + solfege | [] [] [] [] | + solfege-manual | [] [] [] | + soundtracker | [] | + sp | | + sysstat | [] [] [] [] | + tar | [] [] [] [] | + texinfo | [] [] [] [] | + tin | [] | + unicode-han-tra... | | + unicode-transla... | | + util-linux-ng | [] [] [] [] [] | + vice | [] | + vmm | [] | + vorbis-tools | [] [] | + wastesedge | [] | + wdiff | [] [] | + wget | [] [] [] [] [] [] [] | + wyslij-po | [] [] [] | + xchat | [] [] [] [] [] [] [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] | + +---------------------------------------------------+ + nl nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr + 135 10 4 7 105 1 29 62 47 91 3 54 46 9 37 + + sv sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW + +---------------------------------------------------+ + a2ps | [] [] [] [] [] | 27 + aegis | [] | 9 + ant-phone | [] [] [] [] | 9 + anubis | [] [] [] [] | 15 + aspell | [] [] [] | 20 + bash | [] [] [] | 12 + bfd | [] | 6 + bibshelf | [] [] [] | 16 + binutils | [] [] | 8 + bison | [] [] | 12 + bison-runtime | [] [] [] [] [] [] | 29 + bluez-pin | [] [] [] [] [] [] [] [] | 37 + bombono-dvd | [] | 4 + buzztard | [] | 7 + cflow | [] [] [] | 9 + clisp | | 10 + coreutils | [] [] [] [] | 22 + cpio | [] [] [] [] [] [] | 13 + cppi | [] [] | 5 + cpplib | [] [] [] [] [] [] | 14 + cryptsetup | [] [] | 7 + dfarc | [] | 9 + dialog | [] [] [] [] [] [] [] | 30 + dico | [] | 2 + diffutils | [] [] [] [] [] [] | 30 + dink | | 4 + doodle | [] [] | 7 + e2fsprogs | [] [] [] | 11 + enscript | [] [] [] [] | 17 + exif | [] [] [] | 16 + fetchmail | [] [] [] | 17 + findutils | [] [] [] [] [] | 20 + flex | [] [] [] [] | 15 + freedink | [] | 10 + gas | [] | 4 + gawk | [] [] [] [] | 18 + gcal | [] [] | 5 + gcc | [] [] [] | 7 + gettext-examples | [] [] [] [] [] [] [] | 34 + gettext-runtime | [] [] [] [] [] [] [] | 29 + gettext-tools | [] [] [] [] [] [] | 22 + gip | [] [] [] [] | 22 + gjay | [] | 3 + gliv | [] [] [] | 14 + glunarclock | [] [] [] [] [] | 19 + gnubiff | [] [] | 4 + gnucash | () [] () [] () | 10 + gnuedu | [] [] | 7 + gnulib | [] [] [] [] | 16 + gnunet | [] | 1 + gnunet-gtk | [] [] [] | 5 + gnutls | [] [] [] | 10 + gold | [] | 4 + gpe-aerial | [] [] [] | 18 + gpe-beam | [] [] [] | 19 + gpe-bluetooth | [] [] [] | 13 + gpe-calendar | [] [] [] [] | 12 + gpe-clock | [] [] [] [] [] | 28 + gpe-conf | [] [] [] [] | 20 + gpe-contacts | [] [] [] | 17 + gpe-edit | [] [] [] | 12 + gpe-filemanager | [] [] [] [] | 16 + gpe-go | [] [] [] [] [] | 25 + gpe-login | [] [] [] | 11 + gpe-ownerinfo | [] [] [] [] [] | 25 + gpe-package | [] [] [] | 13 + gpe-sketchbook | [] [] [] | 20 + gpe-su | [] [] [] [] [] | 30 + gpe-taskmanager | [] [] [] [] [] | 29 + gpe-timesheet | [] [] [] [] [] | 25 + gpe-today | [] [] [] [] [] [] | 30 + gpe-todo | [] [] [] [] | 17 + gphoto2 | [] [] [] [] [] | 24 + gprof | [] [] [] | 15 + gpsdrive | [] [] [] | 11 + gramadoir | [] [] [] | 11 + grep | [] [] [] | 10 + grub | [] [] [] | 14 + gsasl | [] [] [] [] | 14 + gss | [] [] [] | 11 + gst-plugins-bad | [] [] [] [] | 26 + gst-plugins-base | [] [] [] [] [] | 24 + gst-plugins-good | [] [] [] [] | 24 + gst-plugins-ugly | [] [] [] [] [] | 29 + gstreamer | [] [] [] [] | 22 + gtick | [] [] [] | 13 + gtkam | [] [] [] | 20 + gtkorphan | [] [] [] | 14 + gtkspell | [] [] [] [] [] [] [] [] [] | 45 + gutenprint | [] | 10 + hello | [] [] [] [] [] [] | 21 + help2man | [] [] | 7 + hylafax | [] | 5 + idutils | [] [] [] [] | 17 + indent | [] [] [] [] [] [] | 30 + iso_15924 | () [] () [] [] | 16 + iso_3166 | [] [] () [] [] () [] [] [] () | 53 + iso_3166_2 | () [] () [] | 9 + iso_4217 | [] () [] [] () [] [] | 26 + iso_639 | [] [] [] () [] () [] [] [] [] | 38 + iso_639_3 | [] () | 8 + jwhois | [] [] [] [] [] | 16 + kbd | [] [] [] [] [] | 15 + keytouch | [] [] [] | 16 + keytouch-editor | [] [] [] | 14 + keytouch-keyboa... | [] [] [] | 14 + klavaro | [] | 11 + latrine | [] [] [] | 10 + ld | [] [] [] [] | 11 + leafpad | [] [] [] [] [] [] | 33 + libc | [] [] [] [] [] | 21 + libexif | [] () | 7 + libextractor | [] | 1 + libgnutls | [] [] [] | 9 + libgpewidget | [] [] [] | 14 + libgpg-error | [] [] [] | 9 + libgphoto2 | [] [] | 8 + libgphoto2_port | [] [] [] [] | 14 + libgsasl | [] [] [] | 13 + libiconv | [] [] [] [] | 21 + libidn | () [] [] | 11 + lifelines | [] | 4 + liferea | [] [] [] | 21 + lilypond | [] | 7 + linkdr | [] [] [] [] [] | 17 + lordsawar | | 1 + lprng | [] | 3 + lynx | [] [] [] [] | 17 + m4 | [] [] [] [] | 19 + mailfromd | [] [] | 3 + mailutils | [] | 5 + make | [] [] [] [] | 21 + man-db | [] [] [] | 8 + man-db-manpages | | 4 + minicom | [] [] | 16 + mkisofs | [] [] | 9 + myserver | | 0 + nano | [] [] [] [] | 21 + opcodes | [] [] [] | 11 + parted | [] [] [] [] [] | 15 + pies | [] [] | 3 + popt | [] [] [] [] [] [] | 27 + psmisc | [] [] | 11 + pspp | | 4 + pwdutils | [] [] | 6 + radius | [] [] | 9 + recode | [] [] [] [] | 28 + rosegarden | () | 0 + rpm | [] [] [] | 11 + rush | [] [] | 4 + sarg | | 1 + screem | [] | 3 + scrollkeeper | [] [] [] [] [] | 27 + sed | [] [] [] [] [] | 30 + sharutils | [] [] [] [] [] | 22 + shishi | [] | 3 + skencil | [] [] | 7 + solfege | [] [] [] [] | 16 + solfege-manual | [] | 8 + soundtracker | [] [] [] | 9 + sp | [] | 3 + sysstat | [] [] | 15 + tar | [] [] [] [] [] [] | 23 + texinfo | [] [] [] [] [] | 17 + tin | | 4 + unicode-han-tra... | | 0 + unicode-transla... | | 2 + util-linux-ng | [] [] [] [] | 20 + vice | () () | 1 + vmm | [] | 4 + vorbis-tools | [] | 6 + wastesedge | | 2 + wdiff | [] [] | 7 + wget | [] [] [] [] [] | 26 + wyslij-po | [] [] | 8 + xchat | [] [] [] [] [] [] | 36 + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] | 63 + xkeyboard-config | [] [] [] | 22 + +---------------------------------------------------+ + 85 teams sv sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW + 178 domains 119 1 3 3 0 10 65 51 155 17 98 7 41 2618 + + Some counters in the preceding matrix are higher than the number of +visible blocks let us expect. This is because a few extra PO files are +used for implementing regional variants of languages, or language +dialects. + + For a PO file in the matrix above to be effective, the package to +which it applies should also have been internationalized and +distributed as such by its maintainer. There might be an observable +lag between the mere existence a PO file and its wide availability in a +distribution. + + If June 2010 seems to be old, you may fetch a more recent copy of +this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date +matrix with full percentage details can be found at +`http://translationproject.org/extra/matrix.html'. + +1.5 Using `gettext' in new packages +=================================== + +If you are writing a freely available program and want to +internationalize it you are welcome to use GNU `gettext' in your +package. Of course you have to respect the GNU Library General Public +License which covers the use of the GNU `gettext' library. This means +in particular that even non-free programs can use `libintl' as a shared +library, whereas only free software can use `libintl' as a static +library or use modified versions of `libintl'. + + Once the sources are changed appropriately and the setup can handle +the use of `gettext' the only thing missing are the translations. The +Free Translation Project is also available for packages which are not +developed inside the GNU project. Therefore the information given above +applies also for every other Free Software Project. Contact +`coordinator@translationproject.org' to make the `.pot' files available +to the translation teams. + diff --git a/Makefile.am b/Makefile.am index 88c162b7..141ea74d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,8 @@ -SUBDIRS = . tests +SUBDIRS = po . tests lib_LTLIBRARIES = %D%/librtmidi.la %C%_librtmidi_la_LDFLAGS = -no-undefined %C%_librtmidi_la_SOURCES = \ %D%/RtMidi.cpp \ %D%/RtMidi.h + +EXTRA_DIST = config/config.rpath m4/ChangeLog diff --git a/configure.ac b/configure.ac index 1eb07dcd..d01e6366 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_INIT(RtMidi, 2.1.0, gary@music.mcgill.ca, rtmidi) AC_CONFIG_AUX_DIR(config) AC_CONFIG_SRCDIR(RtMidi.cpp) -AC_CONFIG_FILES([rtmidi-config librtmidi.pc Makefile tests/Makefile]) +AC_CONFIG_FILES([rtmidi-config librtmidi.pc Makefile tests/Makefile po/Makefile.in]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) # Fill GXX with something before test. @@ -235,7 +235,8 @@ return jack_port_uuid(NULL); ;; esac AM_CONDITIONAL(HAVE_VIRTUAL_DEVICES,test "$have_virtual_devices" == yes) - +AM_GNU_GETTEXT([external]) +AM_GNU_GETTEXT_VERSION([0.18]) CPPFLAGS="$CPPFLAGS $api" diff --git a/po/Makefile.in.in b/po/Makefile.in.in new file mode 100644 index 00000000..fabdc76c --- /dev/null +++ b/po/Makefile.in.in @@ -0,0 +1,454 @@ +# Makefile for PO directory in any package using GNU gettext. +# Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU General Public +# License but which still want to provide support for the GNU gettext +# functionality. +# Please note that the actual code of GNU gettext is covered by the GNU +# General Public License and is *not* in the public domain. +# +# Origin: gettext-0.18.3 +GETTEXT_MACRO_VERSION = 0.18 + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ + +SED = @SED@ +SHELL = /bin/sh +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datarootdir = @datarootdir@ +datadir = @datadir@ +localedir = @localedir@ +gettextsrcdir = $(datadir)/gettext/po + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +# We use $(mkdir_p). +# In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as +# "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions, +# @install_sh@ does not start with $(SHELL), so we add it. +# In automake >= 1.10, @mkdir_p@ is derived from ${MKDIR_P}, which is defined +# either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake +# versions, $(mkinstalldirs) and $(install_sh) are unused. +mkinstalldirs = $(SHELL) @install_sh@ -d +install_sh = $(SHELL) @install_sh@ +MKDIR_P = @MKDIR_P@ +mkdir_p = @mkdir_p@ + +GMSGFMT_ = @GMSGFMT@ +GMSGFMT_no = @GMSGFMT@ +GMSGFMT_yes = @GMSGFMT_015@ +GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT)) +MSGFMT_ = @MSGFMT@ +MSGFMT_no = @MSGFMT@ +MSGFMT_yes = @MSGFMT_015@ +MSGFMT = $(MSGFMT_$(USE_MSGCTXT)) +XGETTEXT_ = @XGETTEXT@ +XGETTEXT_no = @XGETTEXT@ +XGETTEXT_yes = @XGETTEXT_015@ +XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT)) +MSGMERGE = msgmerge +MSGMERGE_UPDATE = @MSGMERGE@ --update +MSGINIT = msginit +MSGCONV = msgconv +MSGFILTER = msgfilter + +POFILES = @POFILES@ +GMOFILES = @GMOFILES@ +UPDATEPOFILES = @UPDATEPOFILES@ +DUMMYPOFILES = @DUMMYPOFILES@ +DISTFILES.common = Makefile.in.in remove-potcdate.sin \ +$(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3) +DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \ +$(POFILES) $(GMOFILES) \ +$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) + +POTFILES = \ + +CATALOGS = @CATALOGS@ + +# Makevars gets inserted here. (Don't remove this line!) + +.SUFFIXES: +.SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update + +.po.mo: + @echo "$(MSGFMT) -c -o $@ $<"; \ + $(MSGFMT) -c -o t-$@ $< && mv t-$@ $@ + +.po.gmo: + @lang=`echo $* | sed -e 's,.*/,,'`; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o $${lang}.gmo $${lang}.po"; \ + cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo + +.sin.sed: + sed -e '/^#/d' $< > t-$@ + mv t-$@ $@ + + +all: all-@USE_NLS@ + +all-yes: stamp-po +all-no: + +# Ensure that the gettext macros and this Makefile.in.in are in sync. +CHECK_MACRO_VERSION = \ + test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \ + || { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \ + exit 1; \ + } + +# $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no +# internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because +# we don't want to bother translators with empty POT files). We assume that +# LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty. +# In this case, stamp-po is a nop (i.e. a phony target). + +# stamp-po is a timestamp denoting the last time at which the CATALOGS have +# been loosely updated. Its purpose is that when a developer or translator +# checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS, +# "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent +# invocations of "make" will do nothing. This timestamp would not be necessary +# if updating the $(CATALOGS) would always touch them; however, the rule for +# $(POFILES) has been designed to not touch files that don't need to be +# changed. +stamp-po: $(srcdir)/$(DOMAIN).pot + @$(CHECK_MACRO_VERSION) + test ! -f $(srcdir)/$(DOMAIN).pot || \ + test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) + @test ! -f $(srcdir)/$(DOMAIN).pot || { \ + echo "touch stamp-po" && \ + echo timestamp > stamp-poT && \ + mv stamp-poT stamp-po; \ + } + +# Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', +# otherwise packages like GCC can not be built if only parts of the source +# have been downloaded. + +# This target rebuilds $(DOMAIN).pot; it is an expensive operation. +# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed. +# The determination of whether the package xyz is a GNU one is based on the +# heuristic whether some file in the top level directory mentions "GNU xyz". +# If GNU 'find' is available, we avoid grepping through monster files. +$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed + if { if (LC_ALL=C find --version) 2>/dev/null | grep GNU >/dev/null; then \ + LC_ALL=C find -L $(top_srcdir) -maxdepth 1 -type f -size -10000000c -exec grep 'GNU @PACKAGE@' /dev/null '{}' ';' 2>/dev/null; \ + else \ + LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null; \ + fi; \ + } | grep -v 'libtool:' >/dev/null; then \ + package_gnu='GNU '; \ + else \ + package_gnu=''; \ + fi; \ + if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \ + msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \ + else \ + msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \ + fi; \ + case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + ;; \ + *) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --package-name="$${package_gnu}@PACKAGE@" \ + --package-version='@VERSION@' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + ;; \ + esac + test ! -f $(DOMAIN).po || { \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ + sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ + if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \ + else \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + else \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + } + +# This rule has no dependencies: we don't need to update $(DOMAIN).pot at +# every "make" invocation, only create it when it is missing. +# Only "make $(DOMAIN).pot-update" or "make dist" will force an update. +$(srcdir)/$(DOMAIN).pot: + $(MAKE) $(DOMAIN).pot-update + +# This target rebuilds a PO file if $(DOMAIN).pot has changed. +# Note that a PO file is not touched if it doesn't need to be changed. +$(POFILES): $(srcdir)/$(DOMAIN).pot + @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ + if test -f "$(srcdir)/$${lang}.po"; then \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot"; \ + cd $(srcdir) \ + && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ + $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \ + *) \ + $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot;; \ + esac; \ + }; \ + else \ + $(MAKE) $${lang}.po-create; \ + fi + + +install: install-exec install-data +install-exec: +install-data: install-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ + for file in $(DISTFILES.common) Makevars.template; do \ + $(INSTALL_DATA) $(srcdir)/$$file \ + $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + for file in Makevars; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +install-data-no: all +install-data-yes: all + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $(DESTDIR)$$dir; \ + if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ + $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ + echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ + fi; \ + done; \ + done + +install-strip: install + +installdirs: installdirs-exec installdirs-data +installdirs-exec: +installdirs-data: installdirs-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ + else \ + : ; \ + fi +installdirs-data-no: +installdirs-data-yes: + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $(DESTDIR)$$dir; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + fi; \ + done; \ + done + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: uninstall-exec uninstall-data +uninstall-exec: +uninstall-data: uninstall-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + for file in $(DISTFILES.common) Makevars.template; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +uninstall-data-no: +uninstall-data-yes: + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + done; \ + done + +check: all + +info dvi ps pdf html tags TAGS ctags CTAGS ID: + +mostlyclean: + rm -f remove-potcdate.sed + rm -f stamp-poT + rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po + rm -fr *.o + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES *.mo + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f stamp-po $(GMOFILES) + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: + $(MAKE) update-po + @$(MAKE) dist2 +# This is a separate target because 'update-po' must be executed before. +dist2: stamp-po $(DISTFILES) + dists="$(DISTFILES)"; \ + if test "$(PACKAGE)" = "gettext-tools"; then \ + dists="$$dists Makevars.template"; \ + fi; \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + dists="$$dists $(DOMAIN).pot stamp-po"; \ + fi; \ + if test -f $(srcdir)/ChangeLog; then \ + dists="$$dists ChangeLog"; \ + fi; \ + for i in 0 1 2 3 4 5 6 7 8 9; do \ + if test -f $(srcdir)/ChangeLog.$$i; then \ + dists="$$dists ChangeLog.$$i"; \ + fi; \ + done; \ + if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \ + for file in $$dists; do \ + if test -f $$file; then \ + cp -p $$file $(distdir) || exit 1; \ + else \ + cp -p $(srcdir)/$$file $(distdir) || exit 1; \ + fi; \ + done + +update-po: Makefile + $(MAKE) $(DOMAIN).pot-update + test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) + $(MAKE) update-gmo + +# General rule for creating PO files. + +.nop.po-create: + @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \ + echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \ + exit 1 + +# General rule for updating PO files. + +.nop.po-update: + @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ + if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ + cd $(srcdir); \ + if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ + $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ + *) \ + $(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ + esac; \ + }; then \ + if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "msgmerge for $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +$(DUMMYPOFILES): + +update-gmo: Makefile $(GMOFILES) + @: + +# Recreate Makefile by invoking config.status. Explicitly invoke the shell, +# because execution permission bits may not work on the current file system. +# Use @SHELL@, which is the shell determined by autoconf for the use by its +# scripts, not $(SHELL) which is hardwired to /bin/sh and may be deficient. +Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@ + cd $(top_builddir) \ + && @SHELL@ ./config.status $(subdir)/$@.in po-directories + +force: + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/po/Makevars b/po/Makevars new file mode 100644 index 00000000..fdb198cf --- /dev/null +++ b/po/Makevars @@ -0,0 +1,53 @@ +# Makefile variables for PO directory in any package using GNU gettext. + +# Usually the message domain is the same as the package name. +DOMAIN = $(PACKAGE) + +# These two variables depend on the location of this directory. +subdir = po +top_builddir = .. + +# These options get passed to xgettext. +XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ --keyword=gettext_noopt + +# This is the copyright holder that gets inserted into the header of the +# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding +# package. (Note that the msgstr strings, extracted from the package's +# sources, belong to the copyright holder of the package.) Translators are +# expected to transfer the copyright for their translations to this person +# or entity, or to disclaim their copyright. The empty string stands for +# the public domain; in this case the translators are expected to disclaim +# their copyright. +COPYRIGHT_HOLDER = Gary P. Scavone + +# This is the email address or URL to which the translators shall report +# bugs in the untranslated strings: +# - Strings which are not entire sentences, see the maintainer guidelines +# in the GNU gettext documentation, section 'Preparing Strings'. +# - Strings which use unclear terms or require additional context to be +# understood. +# - Strings which make invalid assumptions about notation of date, time or +# money. +# - Pluralisation problems. +# - Incorrect English spelling. +# - Incorrect formatting. +# It can be your email address, or a mailing list address where translators +# can write to without being subscribed, or the URL of a web page through +# which the translators can contact you. +MSGID_BUGS_ADDRESS = https://github.com/thestk/rtmidi + +# This is the list of locale categories, beyond LC_MESSAGES, for which the +# message catalogs shall be used. It is usually empty. +EXTRA_LOCALE_CATEGORIES = + +# This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt' +# context. Possible values are "yes" and "no". Set this to yes if the +# package uses functions taking also a message context, like pgettext(), or +# if in $(XGETTEXT_OPTIONS) you define keywords with a context argument. +USE_MSGCTXT = no + +# These options get passed to msgmerge. +# Useful options are in particular: +# --previous to keep previous msgids of translated messages, +# --quiet to reduce the verbosity. +MSGMERGE_OPTIONS = diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 00000000..b4596b4b --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,3 @@ +# List of source files which contain translatable strings. +RtMidi.h +RtMidi.cpp \ No newline at end of file diff --git a/po/Rules-quot b/po/Rules-quot new file mode 100644 index 00000000..5931e539 --- /dev/null +++ b/po/Rules-quot @@ -0,0 +1,47 @@ +# Special Makefile rules for English message catalogs with quotation marks. + +DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot + +.SUFFIXES: .insert-header .po-update-en + +en@quot.po-create: + $(MAKE) en@quot.po-update +en@boldquot.po-create: + $(MAKE) en@boldquot.po-update + +en@quot.po-update: en@quot.po-update-en +en@boldquot.po-update: en@boldquot.po-update-en + +.insert-header.po-update-en: + @lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \ + if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + ll=`echo $$lang | sed -e 's/@.*//'`; \ + LC_ALL=C; export LC_ALL; \ + cd $(srcdir); \ + if $(MSGINIT) -i $(DOMAIN).pot --no-translator -l $$lang -o - 2>/dev/null | sed -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | $(MSGFILTER) $(SED) -f `echo $$lang | sed -e 's/.*@//'`.sed 2>/dev/null > $$tmpdir/$$lang.new.po; then \ + if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "creation of $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +en@quot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header + +en@boldquot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header + +mostlyclean: mostlyclean-quot +mostlyclean-quot: + rm -f *.insert-header diff --git a/po/boldquot.sed b/po/boldquot.sed new file mode 100644 index 00000000..4b937aa5 --- /dev/null +++ b/po/boldquot.sed @@ -0,0 +1,10 @@ +s/"\([^"]*\)"/“\1”/g +s/`\([^`']*\)'/‘\1’/g +s/ '\([^`']*\)' / ‘\1’ /g +s/ '\([^`']*\)'$/ ‘\1’/g +s/^'\([^`']*\)' /‘\1’ /g +s/“”/""/g +s/“/“/g +s/”/”/g +s/‘/‘/g +s/’/’/g diff --git a/po/en@boldquot.header b/po/en@boldquot.header new file mode 100644 index 00000000..fedb6a06 --- /dev/null +++ b/po/en@boldquot.header @@ -0,0 +1,25 @@ +# All this catalog "translates" are quotation characters. +# The msgids must be ASCII and therefore cannot contain real quotation +# characters, only substitutes like grave accent (0x60), apostrophe (0x27) +# and double quote (0x22). These substitutes look strange; see +# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html +# +# This catalog translates grave accent (0x60) and apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019). +# It also translates pairs of apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019) +# and pairs of quotation mark (0x22) to +# left double quotation mark (U+201C) and right double quotation mark (U+201D). +# +# When output to an UTF-8 terminal, the quotation characters appear perfectly. +# When output to an ISO-8859-1 terminal, the single quotation marks are +# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to +# grave/acute accent (by libiconv), and the double quotation marks are +# transliterated to 0x22. +# When output to an ASCII terminal, the single quotation marks are +# transliterated to apostrophes, and the double quotation marks are +# transliterated to 0x22. +# +# This catalog furthermore displays the text between the quotation marks in +# bold face, assuming the VT100/XTerm escape sequences. +# diff --git a/po/en@quot.header b/po/en@quot.header new file mode 100644 index 00000000..a9647fc3 --- /dev/null +++ b/po/en@quot.header @@ -0,0 +1,22 @@ +# All this catalog "translates" are quotation characters. +# The msgids must be ASCII and therefore cannot contain real quotation +# characters, only substitutes like grave accent (0x60), apostrophe (0x27) +# and double quote (0x22). These substitutes look strange; see +# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html +# +# This catalog translates grave accent (0x60) and apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019). +# It also translates pairs of apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019) +# and pairs of quotation mark (0x22) to +# left double quotation mark (U+201C) and right double quotation mark (U+201D). +# +# When output to an UTF-8 terminal, the quotation characters appear perfectly. +# When output to an ISO-8859-1 terminal, the single quotation marks are +# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to +# grave/acute accent (by libiconv), and the double quotation marks are +# transliterated to 0x22. +# When output to an ASCII terminal, the single quotation marks are +# transliterated to apostrophes, and the double quotation marks are +# transliterated to 0x22. +# diff --git a/po/insert-header.sin b/po/insert-header.sin new file mode 100644 index 00000000..b26de01f --- /dev/null +++ b/po/insert-header.sin @@ -0,0 +1,23 @@ +# Sed script that inserts the file called HEADER before the header entry. +# +# At each occurrence of a line starting with "msgid ", we execute the following +# commands. At the first occurrence, insert the file. At the following +# occurrences, do nothing. The distinction between the first and the following +# occurrences is achieved by looking at the hold space. +/^msgid /{ +x +# Test if the hold space is empty. +s/m/m/ +ta +# Yes it was empty. First occurrence. Read the file. +r HEADER +# Output the file's contents by reading the next line. But don't lose the +# current line while doing this. +g +N +bb +:a +# The hold space was nonempty. Following occurrences. Do nothing. +x +:b +} diff --git a/po/quot.sed b/po/quot.sed new file mode 100644 index 00000000..0122c463 --- /dev/null +++ b/po/quot.sed @@ -0,0 +1,6 @@ +s/"\([^"]*\)"/“\1”/g +s/`\([^`']*\)'/‘\1’/g +s/ '\([^`']*\)' / ‘\1’ /g +s/ '\([^`']*\)'$/ ‘\1’/g +s/^'\([^`']*\)' /‘\1’ /g +s/“”/""/g diff --git a/po/remove-potcdate.sin b/po/remove-potcdate.sin new file mode 100644 index 00000000..2436c49e --- /dev/null +++ b/po/remove-potcdate.sin @@ -0,0 +1,19 @@ +# Sed script that remove the POT-Creation-Date line in the header entry +# from a POT file. +# +# The distinction between the first and the following occurrences of the +# pattern is achieved by looking at the hold space. +/^"POT-Creation-Date: .*"$/{ +x +# Test if the hold space is empty. +s/P/P/ +ta +# Yes it was empty. First occurrence. Remove the line. +g +d +bb +:a +# The hold space was nonempty. Following occurrences. Do nothing. +x +:b +} diff --git a/po/rtmidi.pot b/po/rtmidi.pot new file mode 100644 index 00000000..d359b86f --- /dev/null +++ b/po/rtmidi.pot @@ -0,0 +1,428 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Gary P. Scavone +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#: RtMidi.cpp:3403 +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: rtmidi 2.1.0\n" +"Report-Msgid-Bugs-To: https://github.com/thestk/rtmidi\n" +"POT-Creation-Date: 2014-06-08 21:28+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: RtMidi.h:450 RtMidi.h:557 +msgid "Passed NULL pointer." +msgstr "" + +#: RtMidi.h:623 RtMidi.cpp:2150 +msgid "No data in message argument." +msgstr "" + +#: RtMidi.h:951 +msgid "A NULL pointer has been passed as port descriptor" +msgstr "" + +#: RtMidi.h:983 RtMidi.h:1196 +msgid "No valid API selected." +msgstr "" + +#: RtMidi.h:1053 RtMidi.h:1076 +msgid "No valid API found." +msgstr "" + +#: RtMidi.h:1071 RtMidi.h:1163 +msgid "passed NULL pointer" +msgstr "" + +#: RtMidi.h:1213 +msgid "No data in message argument!" +msgstr "" + +#: RtMidi.h:1219 RtMidi.h:1232 +msgid "The API has not been set." +msgstr "" + +#: RtMidi.cpp:71 +#, c-format +msgid "" +"Error formatting the error string:\n" +"'%s'\n" +"Found in %s::%s at \n" +"%s:%d" +msgstr "" + +#: RtMidi.cpp:83 +msgid "Error: could not format the error message" +msgstr "" + +#: RtMidi.cpp:274 RtMidi.cpp:375 +msgid "No compiled API support found." +msgstr "" + +#: RtMidi.cpp:454 +msgid "A callback function is already set." +msgstr "" + +#: RtMidi.cpp:460 +msgid "The callback function value is invalid." +msgstr "" + +#: RtMidi.cpp:473 +msgid "No callback function was set." +msgstr "" + +#: RtMidi.cpp:496 +msgid "A user callback is currently set for this port." +msgstr "" + +#: RtMidi.cpp:1151 +msgid "Could not get the UID of a midi endpoint." +msgstr "" + +#: RtMidi.cpp:1162 +msgid "Could not get the endpoint back from UID of a midi endpoint." +msgstr "" + +#: RtMidi.cpp:1178 +msgid "Could not get the entity of a midi endpoint." +msgstr "" + +#: RtMidi.cpp:1255 RtMidi.cpp:1295 +msgid "Error creating OS X MIDI port because of invalid port flags" +msgstr "" + +#: RtMidi.cpp:1259 RtMidi.cpp:1299 RtMidi.cpp:1861 +msgid "Error creating OS-X MIDI port." +msgstr "" + +#: RtMidi.cpp:1319 +msgid "CORE error allocation port subscription." +msgstr "" + +#: RtMidi.cpp:1334 +msgid "CORE error making port connection." +msgstr "" + +#: RtMidi.cpp:1412 +msgid "Error creating OS-X MIDI client object." +msgstr "" + +#: RtMidi.cpp:1750 RtMidi.cpp:1842 RtMidi.cpp:1996 RtMidi.cpp:3109 +#: RtMidi.cpp:3226 RtMidi.cpp:3476 RtMidi.cpp:3624 RtMidi.cpp:4274 +#: RtMidi.cpp:4550 RtMidi.cpp:4609 RtMidi.cpp:5369 RtMidi.cpp:5658 +msgid "A valid connection already exists." +msgstr "" + +#: RtMidi.cpp:1758 RtMidi.cpp:3116 RtMidi.cpp:4281 +msgid "No MIDI input sources found." +msgstr "" + +#: RtMidi.cpp:1767 RtMidi.cpp:1924 RtMidi.cpp:1979 RtMidi.cpp:2013 +#: RtMidi.cpp:3126 RtMidi.cpp:3496 RtMidi.cpp:4450 RtMidi.cpp:4528 +#: RtMidi.cpp:4563 RtMidi.cpp:5469 RtMidi.cpp:5759 +#, c-format +msgid "The 'portNumber' argument (%d) is invalid." +msgstr "" + +#: RtMidi.cpp:1779 +msgid "Error creating OS-X MIDI input port." +msgstr "" + +#: RtMidi.cpp:1789 +msgid "Error getting MIDI input source reference." +msgstr "" + +#: RtMidi.cpp:1799 +msgid "Error connecting OS-X MIDI input port." +msgstr "" + +#: RtMidi.cpp:1821 +msgid "Error creating virtual OS-X MIDI destination." +msgstr "" + +#: RtMidi.cpp:1837 RtMidi.cpp:2087 RtMidi.cpp:3221 RtMidi.cpp:3619 +#: RtMidi.cpp:5363 RtMidi.cpp:5652 +msgid "Internal error: data has not been allocated." +msgstr "" + +#: RtMidi.cpp:1847 RtMidi.cpp:2097 +msgid "An invalid (i.e. non-CORE) port descriptor has been passed to openPort." +msgstr "" + +#: RtMidi.cpp:2004 +msgid "No MIDI output destinations found." +msgstr "" + +#: RtMidi.cpp:2025 +msgid "Error creating OS-X MIDI output port." +msgstr "" + +#: RtMidi.cpp:2035 +msgid "Error getting MIDI output destination reference." +msgstr "" + +#: RtMidi.cpp:2060 +msgid "A virtual output port already exists." +msgstr "" + +#: RtMidi.cpp:2071 +msgid "Error creating OS-X virtual MIDI source." +msgstr "" + +#: RtMidi.cpp:2092 +msgid "A valid connection already exists" +msgstr "" + +#: RtMidi.cpp:2210 +msgid "Could not allocate packet list." +msgstr "" + +#: RtMidi.cpp:2219 +msgid "Error sending MIDI to virtual destinations." +msgstr "" + +#: RtMidi.cpp:2228 RtMidi.cpp:3605 +msgid "Error sending MIDI message to port." +msgstr "" + +#: RtMidi.cpp:2431 RtMidi.cpp:3170 +msgid "Error allocating ALSA port subscription." +msgstr "" + +#: RtMidi.cpp:2446 RtMidi.cpp:3179 RtMidi.cpp:3532 +msgid "Error making ALSA port connection." +msgstr "" + +#: RtMidi.cpp:2516 RtMidi.cpp:3003 +msgid "Error creating ALSA sequencer client object." +msgstr "" + +#: RtMidi.cpp:2693 +msgid "Error while trying to allocate ALSA port subscription." +msgstr "" + +#: RtMidi.cpp:2755 RtMidi.cpp:3205 RtMidi.cpp:3335 +msgid "Error starting MIDI input thread!" +msgstr "" + +#: RtMidi.cpp:3021 +msgid "Error creating pipe objects." +msgstr "" + +#: RtMidi.cpp:3101 RtMidi.cpp:3468 +msgid "Error looking for port name." +msgstr "" + +#: RtMidi.cpp:3157 +msgid "Error creating ALSA input port." +msgstr "" + +#: RtMidi.cpp:3231 +msgid "Error while allocating ALSA port subscription." +msgstr "" + +#: RtMidi.cpp:3236 RtMidi.cpp:3634 +msgid "An invalid (i.e. non-ALSA) port descriptor has been passed to openPort." +msgstr "" + +#: RtMidi.cpp:3301 RtMidi.cpp:3559 +msgid "Error creating ALSA virtual port." +msgstr "" + +#: RtMidi.cpp:3420 +msgid "Error initializing MIDI event parser." +msgstr "" + +#: RtMidi.cpp:3427 RtMidi.cpp:3583 +msgid "Error allocating buffer memory." +msgstr "" + +#: RtMidi.cpp:3484 +msgid "No MIDI output sources found." +msgstr "" + +#: RtMidi.cpp:3511 +msgid "Error creating ALSA output port." +msgstr "" + +#: RtMidi.cpp:3522 +msgid "Error allocating port subscription." +msgstr "" + +#: RtMidi.cpp:3576 +msgid "ALSA error resizing MIDI event buffer." +msgstr "" + +#: RtMidi.cpp:3597 +msgid "Event parsing error." +msgstr "" + +#: RtMidi.cpp:3629 +msgid "ALSA error allocation port subscription." +msgstr "" + +#: RtMidi.cpp:3766 +#, c-format +msgid "The port argument %d is invalid." +msgstr "" + +#: RtMidi.cpp:4255 +msgid "No MIDI input devices currently available." +msgstr "" + +#: RtMidi.cpp:4266 +msgid "InitializeCriticalSectionAndSpinCount failed." +msgstr "" + +#: RtMidi.cpp:4290 +#, c-format +msgid "the 'portNumber' argument (%d) is invalid." +msgstr "" + +#: RtMidi.cpp:4302 +msgid "Error creating Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4318 +msgid "Error starting Windows MM MIDI input port (PrepareHeader)." +msgstr "" + +#: RtMidi.cpp:4327 +msgid "Error starting Windows MM MIDI input port (AddBuffer)." +msgstr "" + +#: RtMidi.cpp:4336 +msgid "Error starting Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4347 RtMidi.cpp:4596 +msgid "Cannot be implemented in Windows MM MIDI API." +msgstr "" + +#: RtMidi.cpp:4354 RtMidi.cpp:4604 +msgid "" +"An invalid (i.e. non-WinMM) port descriptor has been passed to openPort." +msgstr "" + +#: RtMidi.cpp:4359 +msgid "" +"We are overwriting an existing connection. This is probably a programming " +"error." +msgstr "" + +#: RtMidi.cpp:4364 +msgid "" +"The port descriptor pased to MidiInWinMM::openPort() cannot be used to open " +"an input port." +msgstr "" + +#: RtMidi.cpp:4374 RtMidi.cpp:4624 +msgid "" +"Some change in the arrangement of MIDI input ports invalidated the port " +"descriptor." +msgstr "" + +#: RtMidi.cpp:4389 +msgid "The handle is invalid. Did you disconnect the device?" +msgstr "" + +#: RtMidi.cpp:4393 RtMidi.cpp:4643 +msgid "" +"The system has no driver for our handle :-(. Did you disconnect the device?" +msgstr "" + +#: RtMidi.cpp:4397 RtMidi.cpp:4647 +msgid "Out of memory." +msgstr "" + +#: RtMidi.cpp:4428 +msgid "Error closing Windows MM MIDI input port (midiInUnprepareHeader)." +msgstr "" + +#: RtMidi.cpp:4506 +msgid "No MIDI output devices currently available." +msgstr "" + +#: RtMidi.cpp:4557 +msgid "No MIDI output destinations found!" +msgstr "" + +#: RtMidi.cpp:4575 +msgid "Error creating Windows MM MIDI output port." +msgstr "" + +#: RtMidi.cpp:4614 +msgid "The port descriptor cannot be used to open an output port." +msgstr "" + +#: RtMidi.cpp:4639 +msgid "The internal handle is invalid. Did you disconnect the device?" +msgstr "" + +#: RtMidi.cpp:4669 +msgid "Message argument is empty." +msgstr "" + +#: RtMidi.cpp:4681 +msgid "Error allocating sysex message memory!" +msgstr "" + +#: RtMidi.cpp:4697 +msgid "Error preparing sysex header." +msgstr "" + +#: RtMidi.cpp:4706 +msgid "Error sending sysex message." +msgstr "" + +#: RtMidi.cpp:4719 +msgid "Message size is greater than 3 bytes (and not sysex)." +msgstr "" + +#: RtMidi.cpp:4735 +msgid "Error sending MIDI message." +msgstr "" + +#: RtMidi.cpp:4986 +msgid "Could not connect to JACK server. Is it runnig?" +msgstr "" + +#: RtMidi.cpp:5189 +msgid "Error opening JACK port subscription." +msgstr "" + +#: RtMidi.cpp:5296 RtMidi.cpp:5579 +msgid "JACK server not running?" +msgstr "" + +#: RtMidi.cpp:5331 RtMidi.cpp:5396 RtMidi.cpp:5620 RtMidi.cpp:5685 +msgid "Error creating JACK port." +msgstr "" + +#: RtMidi.cpp:5351 RtMidi.cpp:5640 +msgid "Error creating JACK virtual port." +msgstr "" + +#: RtMidi.cpp:5375 +msgid "An invalid (i.e. non-ALSA) port descriptor has been passed to openPort" +msgstr "" + +#: RtMidi.cpp:5462 +msgid "No ports available." +msgstr "" + +#: RtMidi.cpp:5664 +msgid "An invalid (i.e. non-JACK) port descriptor has been passed to openPort" +msgstr "" + +#: RtMidi.cpp:5752 +msgid "No ports available" +msgstr "" From fd664e5570d4f8ba966d8defecfa2f8d3e0643e8 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 8 Jun 2014 21:44:12 +0200 Subject: [PATCH 062/210] Example locale: German without any translated strings. --- po/LINGUAS | 1 + po/de.mo | Bin 0 -> 577 bytes po/de.po | 430 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 431 insertions(+) create mode 100644 po/LINGUAS create mode 100644 po/de.mo create mode 100644 po/de.po diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 00000000..c42e816f --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1 @@ +de \ No newline at end of file diff --git a/po/de.mo b/po/de.mo new file mode 100644 index 0000000000000000000000000000000000000000..2e1aeee2a024243b4d68c08eb0bc2fa5d232a25c GIT binary patch literal 577 zcmZut+iuh_5ZwY2QXc!v!yxehDt0au2;MHLy1l3pD^_iac=aaJ#5A!Zds4L@!teE4 zm=M%`C?g$@M{~~H9(G^+p0VvPUNPPApxli6n1l~n%(6`0~S>acf+j`J7iUM_~;0%4IEzrMu+#HA#Pius0 zX_2;i1rYjjz#*6I;5< z*jhopF%+%a!RuC>I^P8aw*MQ3MK*`&yLfBi^#am&^XR8ILyLYo#@b, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: rtmidi 2.1.0\n" +"Report-Msgid-Bugs-To: https://github.com/thestk/rtmidi\n" +"POT-Creation-Date: 2014-06-08 21:28+0200\n" +"PO-Revision-Date: 2014-06-08 21:37+0100\n" +"Last-Translator: Tobias Schlemmer \n" +"Language-Team: German translation team \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.5.4\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Poedit-Basepath: .\n" + +#: RtMidi.h:450 RtMidi.h:557 +msgid "Passed NULL pointer." +msgstr "" + +#: RtMidi.h:623 RtMidi.cpp:2150 +msgid "No data in message argument." +msgstr "" + +#: RtMidi.h:951 +msgid "A NULL pointer has been passed as port descriptor" +msgstr "" + +#: RtMidi.h:983 RtMidi.h:1196 +msgid "No valid API selected." +msgstr "" + +#: RtMidi.h:1053 RtMidi.h:1076 +msgid "No valid API found." +msgstr "" + +#: RtMidi.h:1071 RtMidi.h:1163 +msgid "passed NULL pointer" +msgstr "" + +#: RtMidi.h:1213 +msgid "No data in message argument!" +msgstr "" + +#: RtMidi.h:1219 RtMidi.h:1232 +msgid "The API has not been set." +msgstr "" + +#: RtMidi.cpp:71 +#, c-format +msgid "" +"Error formatting the error string:\n" +"'%s'\n" +"Found in %s::%s at \n" +"%s:%d" +msgstr "" + +#: RtMidi.cpp:83 +msgid "Error: could not format the error message" +msgstr "" + +#: RtMidi.cpp:274 RtMidi.cpp:375 +msgid "No compiled API support found." +msgstr "" + +#: RtMidi.cpp:454 +msgid "A callback function is already set." +msgstr "" + +#: RtMidi.cpp:460 +msgid "The callback function value is invalid." +msgstr "" + +#: RtMidi.cpp:473 +msgid "No callback function was set." +msgstr "" + +#: RtMidi.cpp:496 +msgid "A user callback is currently set for this port." +msgstr "" + +#: RtMidi.cpp:1151 +msgid "Could not get the UID of a midi endpoint." +msgstr "" + +#: RtMidi.cpp:1162 +msgid "Could not get the endpoint back from UID of a midi endpoint." +msgstr "" + +#: RtMidi.cpp:1178 +msgid "Could not get the entity of a midi endpoint." +msgstr "" + +#: RtMidi.cpp:1255 RtMidi.cpp:1295 +msgid "Error creating OS X MIDI port because of invalid port flags" +msgstr "" + +#: RtMidi.cpp:1259 RtMidi.cpp:1299 RtMidi.cpp:1861 +msgid "Error creating OS-X MIDI port." +msgstr "" + +#: RtMidi.cpp:1319 +msgid "CORE error allocation port subscription." +msgstr "" + +#: RtMidi.cpp:1334 +msgid "CORE error making port connection." +msgstr "" + +#: RtMidi.cpp:1412 +msgid "Error creating OS-X MIDI client object." +msgstr "" + +#: RtMidi.cpp:1750 RtMidi.cpp:1842 RtMidi.cpp:1996 RtMidi.cpp:3109 +#: RtMidi.cpp:3226 RtMidi.cpp:3476 RtMidi.cpp:3624 RtMidi.cpp:4274 +#: RtMidi.cpp:4550 RtMidi.cpp:4609 RtMidi.cpp:5369 RtMidi.cpp:5658 +msgid "A valid connection already exists." +msgstr "" + +#: RtMidi.cpp:1758 RtMidi.cpp:3116 RtMidi.cpp:4281 +msgid "No MIDI input sources found." +msgstr "" + +#: RtMidi.cpp:1767 RtMidi.cpp:1924 RtMidi.cpp:1979 RtMidi.cpp:2013 +#: RtMidi.cpp:3126 RtMidi.cpp:3496 RtMidi.cpp:4450 RtMidi.cpp:4528 +#: RtMidi.cpp:4563 RtMidi.cpp:5469 RtMidi.cpp:5759 +#, c-format +msgid "The 'portNumber' argument (%d) is invalid." +msgstr "" + +#: RtMidi.cpp:1779 +msgid "Error creating OS-X MIDI input port." +msgstr "" + +#: RtMidi.cpp:1789 +msgid "Error getting MIDI input source reference." +msgstr "" + +#: RtMidi.cpp:1799 +msgid "Error connecting OS-X MIDI input port." +msgstr "" + +#: RtMidi.cpp:1821 +msgid "Error creating virtual OS-X MIDI destination." +msgstr "" + +#: RtMidi.cpp:1837 RtMidi.cpp:2087 RtMidi.cpp:3221 RtMidi.cpp:3619 +#: RtMidi.cpp:5363 RtMidi.cpp:5652 +msgid "Internal error: data has not been allocated." +msgstr "" + +#: RtMidi.cpp:1847 RtMidi.cpp:2097 +msgid "An invalid (i.e. non-CORE) port descriptor has been passed to openPort." +msgstr "" + +#: RtMidi.cpp:2004 +msgid "No MIDI output destinations found." +msgstr "" + +#: RtMidi.cpp:2025 +msgid "Error creating OS-X MIDI output port." +msgstr "" + +#: RtMidi.cpp:2035 +msgid "Error getting MIDI output destination reference." +msgstr "" + +#: RtMidi.cpp:2060 +msgid "A virtual output port already exists." +msgstr "" + +#: RtMidi.cpp:2071 +msgid "Error creating OS-X virtual MIDI source." +msgstr "" + +#: RtMidi.cpp:2092 +msgid "A valid connection already exists" +msgstr "" + +#: RtMidi.cpp:2210 +msgid "Could not allocate packet list." +msgstr "" + +#: RtMidi.cpp:2219 +msgid "Error sending MIDI to virtual destinations." +msgstr "" + +#: RtMidi.cpp:2228 RtMidi.cpp:3605 +msgid "Error sending MIDI message to port." +msgstr "" + +#: RtMidi.cpp:2431 RtMidi.cpp:3170 +msgid "Error allocating ALSA port subscription." +msgstr "" + +#: RtMidi.cpp:2446 RtMidi.cpp:3179 RtMidi.cpp:3532 +msgid "Error making ALSA port connection." +msgstr "" + +#: RtMidi.cpp:2516 RtMidi.cpp:3003 +msgid "Error creating ALSA sequencer client object." +msgstr "" + +#: RtMidi.cpp:2693 +msgid "Error while trying to allocate ALSA port subscription." +msgstr "" + +#: RtMidi.cpp:2755 RtMidi.cpp:3205 RtMidi.cpp:3335 +msgid "Error starting MIDI input thread!" +msgstr "" + +#: RtMidi.cpp:3021 +msgid "Error creating pipe objects." +msgstr "" + +#: RtMidi.cpp:3101 RtMidi.cpp:3468 +msgid "Error looking for port name." +msgstr "" + +#: RtMidi.cpp:3157 +msgid "Error creating ALSA input port." +msgstr "" + +#: RtMidi.cpp:3231 +msgid "Error while allocating ALSA port subscription." +msgstr "" + +#: RtMidi.cpp:3236 RtMidi.cpp:3634 +msgid "An invalid (i.e. non-ALSA) port descriptor has been passed to openPort." +msgstr "" + +#: RtMidi.cpp:3301 RtMidi.cpp:3559 +msgid "Error creating ALSA virtual port." +msgstr "" + +#: RtMidi.cpp:3420 +msgid "Error initializing MIDI event parser." +msgstr "" + +#: RtMidi.cpp:3427 RtMidi.cpp:3583 +msgid "Error allocating buffer memory." +msgstr "" + +#: RtMidi.cpp:3484 +msgid "No MIDI output sources found." +msgstr "" + +#: RtMidi.cpp:3511 +msgid "Error creating ALSA output port." +msgstr "" + +#: RtMidi.cpp:3522 +msgid "Error allocating port subscription." +msgstr "" + +#: RtMidi.cpp:3576 +msgid "ALSA error resizing MIDI event buffer." +msgstr "" + +#: RtMidi.cpp:3597 +msgid "Event parsing error." +msgstr "" + +#: RtMidi.cpp:3629 +msgid "ALSA error allocation port subscription." +msgstr "" + +#: RtMidi.cpp:3766 +#, c-format +msgid "The port argument %d is invalid." +msgstr "" + +#: RtMidi.cpp:4255 +msgid "No MIDI input devices currently available." +msgstr "" + +#: RtMidi.cpp:4266 +msgid "InitializeCriticalSectionAndSpinCount failed." +msgstr "" + +#: RtMidi.cpp:4290 +#, c-format +msgid "the 'portNumber' argument (%d) is invalid." +msgstr "" + +#: RtMidi.cpp:4302 +msgid "Error creating Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4318 +msgid "Error starting Windows MM MIDI input port (PrepareHeader)." +msgstr "" + +#: RtMidi.cpp:4327 +msgid "Error starting Windows MM MIDI input port (AddBuffer)." +msgstr "" + +#: RtMidi.cpp:4336 +msgid "Error starting Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4347 RtMidi.cpp:4596 +msgid "Cannot be implemented in Windows MM MIDI API." +msgstr "" + +#: RtMidi.cpp:4354 RtMidi.cpp:4604 +msgid "" +"An invalid (i.e. non-WinMM) port descriptor has been passed to openPort." +msgstr "" + +#: RtMidi.cpp:4359 +msgid "" +"We are overwriting an existing connection. This is probably a programming " +"error." +msgstr "" + +#: RtMidi.cpp:4364 +msgid "" +"The port descriptor pased to MidiInWinMM::openPort() cannot be used to open " +"an input port." +msgstr "" + +#: RtMidi.cpp:4374 RtMidi.cpp:4624 +msgid "" +"Some change in the arrangement of MIDI input ports invalidated the port " +"descriptor." +msgstr "" + +#: RtMidi.cpp:4389 +msgid "The handle is invalid. Did you disconnect the device?" +msgstr "" + +#: RtMidi.cpp:4393 RtMidi.cpp:4643 +msgid "" +"The system has no driver for our handle :-(. Did you disconnect the device?" +msgstr "" + +#: RtMidi.cpp:4397 RtMidi.cpp:4647 +msgid "Out of memory." +msgstr "" + +#: RtMidi.cpp:4428 +msgid "Error closing Windows MM MIDI input port (midiInUnprepareHeader)." +msgstr "" + +#: RtMidi.cpp:4506 +msgid "No MIDI output devices currently available." +msgstr "" + +#: RtMidi.cpp:4557 +msgid "No MIDI output destinations found!" +msgstr "" + +#: RtMidi.cpp:4575 +msgid "Error creating Windows MM MIDI output port." +msgstr "" + +#: RtMidi.cpp:4614 +msgid "The port descriptor cannot be used to open an output port." +msgstr "" + +#: RtMidi.cpp:4639 +msgid "The internal handle is invalid. Did you disconnect the device?" +msgstr "" + +#: RtMidi.cpp:4669 +msgid "Message argument is empty." +msgstr "" + +#: RtMidi.cpp:4681 +msgid "Error allocating sysex message memory!" +msgstr "" + +#: RtMidi.cpp:4697 +msgid "Error preparing sysex header." +msgstr "" + +#: RtMidi.cpp:4706 +msgid "Error sending sysex message." +msgstr "" + +#: RtMidi.cpp:4719 +msgid "Message size is greater than 3 bytes (and not sysex)." +msgstr "" + +#: RtMidi.cpp:4735 +msgid "Error sending MIDI message." +msgstr "" + +#: RtMidi.cpp:4986 +msgid "Could not connect to JACK server. Is it runnig?" +msgstr "" + +#: RtMidi.cpp:5189 +msgid "Error opening JACK port subscription." +msgstr "" + +#: RtMidi.cpp:5296 RtMidi.cpp:5579 +msgid "JACK server not running?" +msgstr "" + +#: RtMidi.cpp:5331 RtMidi.cpp:5396 RtMidi.cpp:5620 RtMidi.cpp:5685 +msgid "Error creating JACK port." +msgstr "" + +#: RtMidi.cpp:5351 RtMidi.cpp:5640 +msgid "Error creating JACK virtual port." +msgstr "" + +#: RtMidi.cpp:5375 +msgid "An invalid (i.e. non-ALSA) port descriptor has been passed to openPort" +msgstr "" + +#: RtMidi.cpp:5462 +msgid "No ports available." +msgstr "" + +#: RtMidi.cpp:5664 +msgid "An invalid (i.e. non-JACK) port descriptor has been passed to openPort" +msgstr "" + +#: RtMidi.cpp:5752 +msgid "No ports available" +msgstr "" From cbe9bce64a915d62ccea07f5e2b54f4c52366338 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 8 Jun 2014 21:45:45 +0200 Subject: [PATCH 063/210] Advice people to run autoreconf after git checkout. --- readme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme b/readme index 545ffc61..e6b966b5 100644 --- a/readme +++ b/readme @@ -9,7 +9,7 @@ tests: example RtMidi programs On unix systems, type "./configure" in the top level directory, then "make" in the tests/ directory to compile the test programs. In Windows, open the Visual C++ workspace file located in the tests/ directory. -If you checked out the code from git, please run "autoconf" before "./configure". +If you checked out the code from git, please run "autoreconf" before "./configure". OVERVIEW: From ce8fb4c5abdf4dda3f557c0abf02e1fff0277f54 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Tue, 10 Jun 2014 21:02:10 +0200 Subject: [PATCH 064/210] Revise some error messages and make API descriptions translatable. --- RtMidi.cpp | 114 +++++++++++++++++++++++++++-------------------------- RtMidi.h | 54 ++++++++++++------------- 2 files changed, 85 insertions(+), 83 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 0492c645..0bf5c6fd 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -255,7 +255,9 @@ MidiIn :: MidiIn( ApiType api, // No compiled support for specified API value. Issue a warning // and continue as if no API was specified. - std::cerr << "\nMidiIn: no compiled support for specified API argument!\n\n" << std::endl; + throw RTMIDI_ERROR1(gettext_noopt("Support for the selected MIDI system %d has not been compiled into the RtMidi library."), + Error::INVALID_PARAMETER, + api); } // Iterate through the compiled APIs and return as soon as we find @@ -271,8 +273,8 @@ MidiIn :: MidiIn( ApiType api, // We may reach this point if the only API is JACK, // but no JACK devices are found. - throw( RTMIDI_ERROR( gettext_noopt("No compiled API support found."), - Error::UNSPECIFIED ) ); + throw( RTMIDI_ERROR( gettext_noopt("No supported MIDI system has been found."), + Error::SYSTEM ) ); } MidiIn :: ~MidiIn() throw() @@ -286,11 +288,11 @@ MidiIn :: ~MidiIn() throw() //*********************************************************************// #define RTMIDI_CLASSNAME "MidiOut" - void MidiOut :: openMidiApi( ApiType api ) - { - if ( rtapi_ ) - delete rtapi_; - rtapi_ = 0; +void MidiOut :: openMidiApi( ApiType api ) +{ + if ( rtapi_ ) + delete rtapi_; + rtapi_ = 0; switch (api) { case rtmidi::UNIX_JACK: @@ -356,7 +358,8 @@ MidiOut :: MidiOut( ApiType api, const std::string clientName, bool pfsystem ) // No compiled support for specified API value. Issue a warning // and continue as if no API was specified. - std::cerr << "\nMidiOut: no compiled support for specified API argument!\n\n" << std::endl; + throw RTMIDI_ERROR(gettext_noopt("Support for the selected MIDI system %d has not been compiled into the RtMidi library."), + Error::INVALID_PARAMETER, api); } // Iterate through the compiled APIs and return as soon as we find @@ -372,7 +375,7 @@ MidiOut :: MidiOut( ApiType api, const std::string clientName, bool pfsystem ) // We may reach this point, e.g. if JACK is the only // compiled API, but no JACK devices are found. - throw( RTMIDI_ERROR(gettext_noopt("No compiled API support found."), + throw( RTMIDI_ERROR(gettext_noopt("No supported MIDI system has been found."), Error::UNSPECIFIED ) ); } @@ -493,7 +496,7 @@ double MidiInApi :: getMessage( std::vector &message ) message.clear(); if ( inputData_.usingCallback ) { - error(RTMIDI_ERROR(gettext_noopt("A user callback is currently set for this port."), + error(RTMIDI_ERROR(gettext_noopt("Returning an empty MIDI message as all input is handled by a callback function."), Error::WARNING)); return 0.0; } @@ -1148,7 +1151,7 @@ class CoreSequencer { &uid); if (stat != noErr) { throw - RTMIDI_ERROR(gettext_noopt("Could not get the UID of a midi endpoint."), + RTMIDI_ERROR(gettext_noopt("Could not get the unique identifier of a midi endpoint."), Error::DRIVER_ERROR); return 0; } @@ -1159,7 +1162,7 @@ class CoreSequencer { &type); if (stat != noErr || obj != port) { throw - RTMIDI_ERROR(gettext_noopt("Could not get the endpoint back from UID of a midi endpoint."), + RTMIDI_ERROR(gettext_noopt("Could not get the endpoint back from the unique identifier of a midi endpoint."), Error::DRIVER_ERROR); return 0; } @@ -1252,7 +1255,7 @@ class CoreSequencer { &port); break; default: - throw RTMIDI_ERROR(gettext_noopt("Error creating OS X MIDI port because of invalid port flags"), + throw RTMIDI_ERROR(gettext_noopt("Error creating OS X MIDI port because of invalid port flags."), Error::DRIVER_ERROR); } if ( result != noErr ) { @@ -1292,7 +1295,7 @@ class CoreSequencer { &port); break; default: - throw RTMIDI_ERROR(gettext_noopt("Error creating OS X MIDI port because of invalid port flags"), + throw RTMIDI_ERROR(gettext_noopt("Error creating OS X MIDI port because of invalid port flags."), Error::DRIVER_ERROR); } if ( result != noErr ) { @@ -1834,8 +1837,8 @@ void MidiInCore :: openPort( const PortDescriptor & port, const CorePortDescriptor * remote = dynamic_cast(&port); if ( !data ) { - error(RTMIDI_ERROR(gettext_noopt("Internal error: data has not been allocated."), - Error::DRIVER_ERROR) ); + error(RTMIDI_ERROR(gettext_noopt("Data has not been allocated."), + Error::SYSTEM_ERROR) ); return; } if ( connected_ || data -> localEndpoint) { @@ -1844,7 +1847,7 @@ void MidiInCore :: openPort( const PortDescriptor & port, return; } if (!remote) { - error(RTMIDI_ERROR(gettext_noopt("An invalid (i.e. non-CORE) port descriptor has been passed to openPort."), + error(RTMIDI_ERROR(gettext_noopt("Core MIDI has been instructed to open a non-Core MIDI port. This doesn't work."), Error::WARNING) ); return; } @@ -2084,17 +2087,17 @@ void MidiOutCore :: openPort( const PortDescriptor & port, const CorePortDescriptor * remote = dynamic_cast(&port); if ( !data ) { - error(RTMIDI_ERROR(gettext_noopt("Internal error: data has not been allocated."), - Error::DRIVER_ERROR) ); + error(RTMIDI_ERROR(gettext_noopt("Data has not been allocated."), + Error::SYSTEM_ERROR) ); return; } if ( connected_ || data -> localEndpoint) { - error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists"), + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), Error::WARNING) ); return; } if (!remote) { - error(RTMIDI_ERROR(gettext_noopt("An invalid (i.e. non-CORE) port descriptor has been passed to openPort."), + error(RTMIDI_ERROR(gettext_noopt("Core MIDI has been instructed to open a non-Core MIDI port. This doesn't work."), Error::WARNING) ); return; } @@ -2428,7 +2431,7 @@ class AlsaSequencer { snd_seq_port_subscribe_t *subscription; if (snd_seq_port_subscribe_malloc( &subscription ) < 0) { - throw RTMIDI_ERROR(gettext_noopt("Error allocating ALSA port subscription."), + throw RTMIDI_ERROR(gettext_noopt("Could not allocate ALSA port subscription."), Error::DRIVER_ERROR ); return 0; } @@ -2666,7 +2669,7 @@ struct AlsaMidiData:public AlsaPortDescriptor { } snd_seq_addr_t local; /*!< Our port and client id. If client = 0 (default) this means we didn't aquire a port so far. */ NonLockingAlsaSequencer seq; - // unsigned int portNum; + // unsigned int portNum; snd_seq_port_subscribe_t *subscription; snd_midi_event_t *coder; unsigned int bufferSize; @@ -2690,7 +2693,7 @@ struct AlsaMidiData:public AlsaPortDescriptor { int openPort(int alsaCapabilities, const std::string & portName) { if (subscription) { - api->error( RTMIDI_ERROR(gettext_noopt("Error while trying to allocate ALSA port subscription."), + api->error( RTMIDI_ERROR(gettext_noopt("Could not allocate ALSA port subscription."), Error::DRIVER_ERROR )); return -99; } @@ -3167,7 +3170,7 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string & portNa if ( !data->subscription ) { // Make subscription if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { - error( RTMIDI_ERROR(gettext_noopt("Error allocating ALSA port subscription."), + error( RTMIDI_ERROR(gettext_noopt("Could not allocate ALSA port subscription."), Error::DRIVER_ERROR) ); return; } @@ -3218,8 +3221,8 @@ void MidiInAlsa :: openPort( const PortDescriptor & port, const AlsaPortDescriptor * remote = dynamic_cast(&port); if ( !data ) { - error( RTMIDI_ERROR(gettext_noopt("Internal error: data has not been allocated."), - Error::DRIVER_ERROR) ); + error( RTMIDI_ERROR(gettext_noopt("Data has not been allocated."), + Error::SYSTEM_ERROR) ); return; } if ( connected_ ) { @@ -3228,12 +3231,12 @@ void MidiInAlsa :: openPort( const PortDescriptor & port, return; } if (data->subscription) { - error( RTMIDI_ERROR(gettext_noopt("Error while allocating ALSA port subscription."), + error( RTMIDI_ERROR(gettext_noopt("Could not allocate ALSA port subscription."), Error::DRIVER_ERROR)); return; } if (!remote) { - error( RTMIDI_ERROR(gettext_noopt("An invalid (i.e. non-ALSA) port descriptor has been passed to openPort."), + error( RTMIDI_ERROR(gettext_noopt("ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work."), Error::WARNING) ); return; } @@ -3424,7 +3427,7 @@ void MidiOutAlsa :: initialize( const std::string& clientName ) data->buffer = (unsigned char *) malloc( data->bufferSize ); if ( data->buffer == NULL ) { delete data; - error( RTMIDI_ERROR(gettext_noopt("Error allocating buffer memory."), + error( RTMIDI_ERROR(gettext_noopt("Error while allocating buffer memory."), Error::MEMORY_ERROR) ); return; } @@ -3481,7 +3484,7 @@ void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string & portN unsigned int nSrc = this->getPortCount(); if (nSrc < 1) { errorString_ = "MidiOutAlsa::openPort: !"; - error(RTMIDI_ERROR(gettext_noopt("No MIDI output sources found."), + error(RTMIDI_ERROR(gettext_noopt("No MIDI output sinks found."), Error::NO_DEVICES_FOUND) ); return; } @@ -3519,7 +3522,7 @@ void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string & portN // Make subscription if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { snd_seq_port_subscribe_free( data->subscription ); - error(RTMIDI_ERROR(gettext_noopt("Error allocating port subscription."), + error(RTMIDI_ERROR(gettext_noopt("Could not allocate ALSA port subscription."), Error::DRIVER_ERROR) ); return; } @@ -3580,7 +3583,7 @@ void MidiOutAlsa :: sendMessage( std::vector &message ) free (data->buffer); data->buffer = (unsigned char *) malloc( data->bufferSize ); if ( data->buffer == NULL ) { - error(RTMIDI_ERROR(gettext_noopt("Error allocating buffer memory."), + error(RTMIDI_ERROR(gettext_noopt("Error while allocating buffer memory."), Error::MEMORY_ERROR) ); return; } @@ -3616,8 +3619,8 @@ void MidiOutAlsa :: openPort( const PortDescriptor & port, const AlsaPortDescriptor * remote = dynamic_cast(&port); if ( !data ) { - error(RTMIDI_ERROR(gettext_noopt("Internal error: data has not been allocated."), - Error::DRIVER_ERROR) ); + error(RTMIDI_ERROR(gettext_noopt("Data has not been allocated."), + Error::SYSTEM_ERROR) ); return; } if ( connected_ ) { @@ -3626,12 +3629,12 @@ void MidiOutAlsa :: openPort( const PortDescriptor & port, return; } if (data->subscription) { - error(RTMIDI_ERROR(gettext_noopt("ALSA error allocation port subscription."), + error(RTMIDI_ERROR(gettext_noopt("Error allocating ALSA port subscription."), Error::DRIVER_ERROR) ); return; } if (!remote) { - error(RTMIDI_ERROR(gettext_noopt("An invalid (i.e. non-ALSA) port descriptor has been passed to openPort."), + error(RTMIDI_ERROR(gettext_noopt("ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work."), Error::WARNING) ); return; } @@ -4264,7 +4267,7 @@ void MidiInWinMM :: initialize( const std::string& clientName ) data->message.bytes.clear(); // needs to be empty for first input message if ( !InitializeCriticalSectionAndSpinCount(&(data->_mutex), 0x00000400) ) { - error(RTMIDI_ERROR(gettext_noopt("InitializeCriticalSectionAndSpinCount failed."), + error(RTMIDI_ERROR(gettext_noopt("Failed to initialize a critical section."), Error::WARNING) ); } } @@ -4316,7 +4319,7 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string & /*por result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); if ( result != MMSYSERR_NOERROR ) { midiInClose( data->inHandle ); - error(RTMIDI_ERROR(gettext_noopt("Error starting Windows MM MIDI input port (PrepareHeader)."), + error(RTMIDI_ERROR(gettext_noopt("Error initializing data for Windows MM MIDI input port."), Error::DRIVER_ERROR )); return; } @@ -4325,7 +4328,7 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string & /*por result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); if ( result != MMSYSERR_NOERROR ) { midiInClose( data->inHandle ); - error(RTMIDI_ERROR(gettext_noopt("Error starting Windows MM MIDI input port (AddBuffer)."), + error(RTMIDI_ERROR(gettext_noopt("Could not register the input buffer for Windows MM MIDI input port."), Error::DRIVER_ERROR) ); return; } @@ -4345,14 +4348,14 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string & /*por void MidiInWinMM :: openVirtualPort( std::string /*portName*/ ) { // This function cannot be implemented for the Windows MM MIDI API. - error(RTMIDI_ERROR(gettext_noopt("Cannot be implemented in Windows MM MIDI API."), + error(RTMIDI_ERROR(gettext_noopt("Virtual ports are not available Windows Multimedia MIDI API."), Error::WARNING )); } void MidiInWinMM :: openPort(const PortDescriptor & p, const std::string & portName) { const WinMMPortDescriptor * port = dynamic_cast (&p); if ( !port) { - error( RTMIDI_ERROR(gettext_noopt("An invalid (i.e. non-WinMM) port descriptor has been passed to openPort."), + error( RTMIDI_ERROR(gettext_noopt("Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI port. This doesn't work."), Error::DRIVER_ERROR)); return; } @@ -4362,7 +4365,7 @@ void MidiInWinMM :: openPort(const PortDescriptor & p, const std::string & portN return; } if (port->getCapabilities() != PortDescriptor::INPUT) { - error(RTMIDI_ERROR(gettext_noopt("The port descriptor pased to MidiInWinMM::openPort() cannot be used to open an input port."), + error(RTMIDI_ERROR(gettext_noopt("Trying to open a non-input port as input MIDI port. This doesn't work."), Error::DRIVER_ERROR)); return; } @@ -4425,8 +4428,7 @@ void MidiInWinMM :: closePort( void ) delete [] data->sysexBuffer[i]; if ( result != MMSYSERR_NOERROR ) { midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: "; - error(RTMIDI_ERROR(gettext_noopt("Error closing Windows MM MIDI input port (midiInUnprepareHeader)."), + error(RTMIDI_ERROR(gettext_noopt("Error closing Windows MM MIDI input port."), Error::DRIVER_ERROR) ); return; } @@ -4594,7 +4596,7 @@ void MidiOutWinMM :: closePort( void ) void MidiOutWinMM :: openVirtualPort( std::string /*portName*/ ) { // This function cannot be implemented for the Windows MM MIDI API. - error(RTMIDI_ERROR(gettext_noopt("Cannot be implemented in Windows MM MIDI API."), + error(RTMIDI_ERROR(gettext_noopt("Virtual ports are not available Windows Multimedia MIDI API."), Error::WARNING) ); } @@ -4602,7 +4604,7 @@ void MidiOutWinMM :: openVirtualPort( std::string /*portName*/ ) void MidiOutWinMM :: openPort(const PortDescriptor & p, const std::string & portName) { const WinMMPortDescriptor * port = dynamic_cast (&p); if ( !port) { - error( RTMIDI_ERROR(gettext_noopt("An invalid (i.e. non-WinMM) port descriptor has been passed to openPort."), + error( RTMIDI_ERROR(gettext_noopt("Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI port. This doesn't work."), Error::DRIVER_ERROR)); return; } @@ -4679,7 +4681,7 @@ void MidiOutWinMM :: sendMessage( std::vector &message ) // Allocate buffer for sysex data. char *buffer = (char *) malloc( nBytes ); if ( buffer == NULL ) { - error(RTMIDI_ERROR(gettext_noopt("Error allocating sysex message memory!"), + error(RTMIDI_ERROR(gettext_noopt("Error while allocating sysex message memory."), Error::MEMORY_ERROR) ); return; } @@ -5361,8 +5363,8 @@ void MidiInJack :: openPort( const PortDescriptor & p, const JackPortDescriptor * port = dynamic_cast(&p); if ( !data ) { - error(RTMIDI_ERROR(gettext_noopt("Internal error: data has not been allocated."), - Error::DRIVER_ERROR) ); + error(RTMIDI_ERROR(gettext_noopt("Data has not been allocated."), + Error::SYSTEM_ERROR) ); return; } #if 0 @@ -5373,7 +5375,7 @@ void MidiInJack :: openPort( const PortDescriptor & p, } #endif if (!port) { - error(RTMIDI_ERROR(gettext_noopt("An invalid (i.e. non-ALSA) port descriptor has been passed to openPort"), + error(RTMIDI_ERROR(gettext_noopt("JACK has been instructed to open a non-JACK MIDI port. This doesn't work."), Error::WARNING) ); return; } @@ -5650,8 +5652,8 @@ void MidiOutJack :: openPort( const PortDescriptor & p, const JackPortDescriptor * port = dynamic_cast(&p); if ( !data ) { - error(RTMIDI_ERROR(gettext_noopt("Internal error: data has not been allocated."), - Error::DRIVER_ERROR) ); + error(RTMIDI_ERROR(gettext_noopt("Data has not been allocated."), + Error::SYSTEM_ERROR) ); return; } #if 0 @@ -5662,7 +5664,7 @@ void MidiOutJack :: openPort( const PortDescriptor & p, } #endif if (!port) { - error(RTMIDI_ERROR(gettext_noopt("An invalid (i.e. non-JACK) port descriptor has been passed to openPort"), + error(RTMIDI_ERROR(gettext_noopt("JACK has been instructed to open a non-JACK MIDI port. This doesn't work."), Error::WARNING) ); return; } @@ -5750,7 +5752,7 @@ std::string MidiOutJack :: getPortName( unsigned int portNumber ) // Check port validity if ( ports == NULL) { - error(RTMIDI_ERROR(gettext_noopt("No ports available"), + error(RTMIDI_ERROR(gettext_noopt("No ports available."), Error::WARNING) ); return retStr; } diff --git a/RtMidi.h b/RtMidi.h index d94cad80..e0abb32a 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -76,29 +76,30 @@ NAMESPACE_RTMIDI_START + //! MIDI API specifier arguments. -enum ApiType { - UNSPECIFIED, /*!< Search for a working compiled API. */ - MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ - LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ - UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ - WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ - WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ - DUMMY, /*!< A compilable but non-functional API. */ - ALL_API /*!< Use all available APIs for port selection. */ + enum ApiType { +UNSPECIFIED, /*!< Search for a working compiled API. */ +MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ +LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ +UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ +WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ +WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ +DUMMY, /*!< A compilable but non-functional API. */ +ALL_API /*!< Use all available APIs for port selection. */ }; //! Return the name on a MIDI API inline std::string getApiName(ApiType type) { switch (type) { - case UNSPECIFIED: return "Automatic API selection"; - case MACOSX_CORE: return "Core MIDI"; - case LINUX_ALSA: return "ALSA"; - case UNIX_JACK: return "JACK"; - case WINDOWS_MM: return "Windows Multimedia"; - case WINDOWS_KS: return "DirectX/Kernel Streaming"; - case DUMMY: return "NULL device"; - case ALL_API: return "All available APIs"; + case UNSPECIFIED: return gettext_noopt("Automatic selection"); + case MACOSX_CORE: return gettext_noopt("Core MIDI"); + case LINUX_ALSA: return gettext_noopt("ALSA"); + case UNIX_JACK: return gettext_noopt("JACK"); + case WINDOWS_MM: return gettext_noopt("Windows Multimedia"); + case WINDOWS_KS: return gettext_noopt("DirectX/Kernel Streaming"); + case DUMMY: return gettext_noopt("NULL device"); + case ALL_API: return gettext_noopt("All available MIDI systems"); } return ""; } @@ -983,7 +984,7 @@ class MidiIn : public Midi if (rtapi_) rtapi_->openVirtualPort(portName); else { - error(RTMIDI_ERROR(gettext_noopt("No valid API selected."), + error(RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), Error::INVALID_DEVICE)); } } @@ -1052,8 +1053,7 @@ class MidiIn : public Midi { if (rtapi_) return static_cast(rtapi_)->getMessage(message); - std::string errorString_ = "MidiIn::getMessage: "; - error( RTMIDI_ERROR(gettext_noopt("No valid API found."), + error( RTMIDI_ERROR(gettext_noopt("Could not find any valid MIDI system."), Error::WARNING)); return 0.0; } @@ -1071,12 +1071,12 @@ class MidiIn : public Midi RTMIDI_DEPRECATED(double getMessage( std::vector *message )) { if (!message) { - error( RTMIDI_ERROR(gettext_noopt("passed NULL pointer"), + error( RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), Error::WARNING)); } if (rtapi_) return static_cast(rtapi_)->getMessage(*message); - error( RTMIDI_ERROR(gettext_noopt("No valid API found."), + error( RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been found."), Error::WARNING)); return 0.0; } @@ -1163,7 +1163,7 @@ class MidiOut : public Midi void openPort( Pointer p, const std::string & portName = std::string( "RtMidi" ) ) { if (!p) { - error(RTMIDI_ERROR(gettext_noopt("passed NULL pointer"), + error(RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), Error::INVALID_PARAMETER)); return; } @@ -1196,7 +1196,7 @@ class MidiOut : public Midi if (rtapi_) rtapi_->openVirtualPort(portName); else { - error(RTMIDI_ERROR(gettext_noopt("No valid API selected."), + error(RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), Error::INVALID_DEVICE)); } } @@ -1213,13 +1213,13 @@ class MidiOut : public Midi RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) { if (!message) { - error( RTMIDI_ERROR(gettext_noopt("No data in message argument!"), + error( RTMIDI_ERROR(gettext_noopt("No data in MIDI message."), Error::WARNING)); } if (rtapi_) static_cast(rtapi_)->sendMessage(*message); else - error( RTMIDI_ERROR(gettext_noopt("The API has not been set."), + error( RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), Error::WARNING)); } @@ -1232,7 +1232,7 @@ class MidiOut : public Midi void sendMessage( std::vector &message ) { if (rtapi_) static_cast(rtapi_)->sendMessage(message); - error( RTMIDI_ERROR(gettext_noopt("The API has not been set."), + error( RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), Error::WARNING)); } protected: From e710038085239c8bfeb3ec1b3592f99f788a8357 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Tue, 10 Jun 2014 21:02:50 +0200 Subject: [PATCH 065/210] Remove some unused functions. --- RtMidi.cpp | 62 ------------------------------------------------------ 1 file changed, 62 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 0bf5c6fd..bdf10e2a 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1305,58 +1305,6 @@ class CoreSequencer { return port; } -#if 0 - void deletePort(int port) { - init(); - scoped_lock lock (mutex); - snd_seq_delete_port( seq, port ); - } - - snd_seq_port_subscribe_t * connectPorts(const snd_seq_addr_t & from, - const snd_seq_addr_t & to, - bool real_time) { - init(); - snd_seq_port_subscribe_t *subscription; - - if (snd_seq_port_subscribe_malloc( &subscription ) < 0) { - throw RTMIDI_ERROR(gettext_noopt("CORE error allocation port subscription."), - Error::DRIVER_ERROR ); - return 0; - } - snd_seq_port_subscribe_set_sender(subscription, &from); - snd_seq_port_subscribe_set_dest(subscription, &to); - if (real_time) { - snd_seq_port_subscribe_set_time_update(subscription, 1); - snd_seq_port_subscribe_set_time_real(subscription, 1); - } - { - scoped_lock lock (mutex); - if ( snd_seq_subscribe_port(seq, subscription) ) { - snd_seq_port_subscribe_free( subscription ); - subscription = 0; - throw RTMIDI_ERROR(gettext_noopt("CORE error making port connection."), - Error::DRIVER_ERROR); - return 0; - } - } - return subscription; - } - - void closePort(snd_seq_port_subscribe_t * subscription ) { - init(); - scoped_lock lock(mutex); - snd_seq_unsubscribe_port( seq, subscription ); - } - - - void startQueue(int queue_id) { - init(); - scoped_lock lock(mutex); - snd_seq_start_queue( seq, queue_id, NULL ); - snd_seq_drain_output( seq ); - } -#endif - /*! Use CoreSequencer like a C pointer. \note This function breaks the design to control thread safety by the selection of the \ref locking parameter to the class. @@ -1385,16 +1333,6 @@ class CoreSequencer { MIDIClientRef seq; std::string name; -#if 0 - snd_seq_client_info_t * GetClient(int id) { - init(); - snd_seq_client_info_t * cinfo; - scoped_lock lock(mutex); - snd_seq_get_any_client_info(seq,id,cinfo); - return cinfo; - } -#endif - void init() { init (seq); From f4dc403d8429bb88bbf027896b8aa0ced354fc20 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Tue, 10 Jun 2014 21:03:24 +0200 Subject: [PATCH 066/210] Update translation strings. --- po/rtmidi.pot | 322 ++++++++++++++++++++++++++------------------------ 1 file changed, 167 insertions(+), 155 deletions(-) diff --git a/po/rtmidi.pot b/po/rtmidi.pot index d359b86f..31553e53 100644 --- a/po/rtmidi.pot +++ b/po/rtmidi.pot @@ -3,13 +3,13 @@ # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # -#: RtMidi.cpp:3403 +#: RtMidi.cpp:3346 #, fuzzy msgid "" msgstr "" "Project-Id-Version: rtmidi 2.1.0\n" "Report-Msgid-Bugs-To: https://github.com/thestk/rtmidi\n" -"POT-Creation-Date: 2014-06-08 21:28+0200\n" +"POT-Creation-Date: 2014-06-10 21:00+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,11 +18,43 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: RtMidi.h:450 RtMidi.h:557 +#: RtMidi.h:91 +msgid "Automatic selection" +msgstr "" + +#: RtMidi.h:92 +msgid "Core MIDI" +msgstr "" + +#: RtMidi.h:93 +msgid "ALSA" +msgstr "" + +#: RtMidi.h:94 +msgid "JACK" +msgstr "" + +#: RtMidi.h:95 +msgid "Windows Multimedia" +msgstr "" + +#: RtMidi.h:96 +msgid "DirectX/Kernel Streaming" +msgstr "" + +#: RtMidi.h:97 +msgid "NULL device" +msgstr "" + +#: RtMidi.h:98 +msgid "All available MIDI systems" +msgstr "" + +#: RtMidi.h:450 RtMidi.h:557 RtMidi.h:1070 RtMidi.h:1162 msgid "Passed NULL pointer." msgstr "" -#: RtMidi.h:623 RtMidi.cpp:2150 +#: RtMidi.h:623 RtMidi.cpp:2093 msgid "No data in message argument." msgstr "" @@ -30,24 +62,20 @@ msgstr "" msgid "A NULL pointer has been passed as port descriptor" msgstr "" -#: RtMidi.h:983 RtMidi.h:1196 -msgid "No valid API selected." +#: RtMidi.h:983 RtMidi.h:1195 RtMidi.h:1218 RtMidi.h:1231 +msgid "No valid MIDI system has been selected." msgstr "" -#: RtMidi.h:1053 RtMidi.h:1076 -msgid "No valid API found." +#: RtMidi.h:1052 +msgid "Could not find any valid MIDI system." msgstr "" -#: RtMidi.h:1071 RtMidi.h:1163 -msgid "passed NULL pointer" +#: RtMidi.h:1075 +msgid "No valid MIDI system has been found." msgstr "" -#: RtMidi.h:1213 -msgid "No data in message argument!" -msgstr "" - -#: RtMidi.h:1219 RtMidi.h:1232 -msgid "The API has not been set." +#: RtMidi.h:1212 +msgid "No data in MIDI message." msgstr "" #: RtMidi.cpp:71 @@ -63,366 +91,350 @@ msgstr "" msgid "Error: could not format the error message" msgstr "" -#: RtMidi.cpp:274 RtMidi.cpp:375 -msgid "No compiled API support found." +#: RtMidi.cpp:258 RtMidi.cpp:361 +#, c-format +msgid "" +"Support for the selected MIDI system %d has not been compiled into the " +"RtMidi library." +msgstr "" + +#: RtMidi.cpp:276 RtMidi.cpp:378 +msgid "No supported MIDI system has been found." msgstr "" -#: RtMidi.cpp:454 +#: RtMidi.cpp:457 msgid "A callback function is already set." msgstr "" -#: RtMidi.cpp:460 +#: RtMidi.cpp:463 msgid "The callback function value is invalid." msgstr "" -#: RtMidi.cpp:473 +#: RtMidi.cpp:476 msgid "No callback function was set." msgstr "" -#: RtMidi.cpp:496 -msgid "A user callback is currently set for this port." +#: RtMidi.cpp:499 +msgid "" +"Returning an empty MIDI message as all input is handled by a callback " +"function." msgstr "" -#: RtMidi.cpp:1151 -msgid "Could not get the UID of a midi endpoint." +#: RtMidi.cpp:1154 +msgid "Could not get the unique identifier of a midi endpoint." msgstr "" -#: RtMidi.cpp:1162 -msgid "Could not get the endpoint back from UID of a midi endpoint." +#: RtMidi.cpp:1165 +msgid "" +"Could not get the endpoint back from the unique identifier of a midi " +"endpoint." msgstr "" -#: RtMidi.cpp:1178 +#: RtMidi.cpp:1181 msgid "Could not get the entity of a midi endpoint." msgstr "" -#: RtMidi.cpp:1255 RtMidi.cpp:1295 -msgid "Error creating OS X MIDI port because of invalid port flags" +#: RtMidi.cpp:1258 RtMidi.cpp:1298 +msgid "Error creating OS X MIDI port because of invalid port flags." msgstr "" -#: RtMidi.cpp:1259 RtMidi.cpp:1299 RtMidi.cpp:1861 +#: RtMidi.cpp:1262 RtMidi.cpp:1302 RtMidi.cpp:1804 msgid "Error creating OS-X MIDI port." msgstr "" -#: RtMidi.cpp:1319 -msgid "CORE error allocation port subscription." -msgstr "" - -#: RtMidi.cpp:1334 -msgid "CORE error making port connection." -msgstr "" - -#: RtMidi.cpp:1412 +#: RtMidi.cpp:1355 msgid "Error creating OS-X MIDI client object." msgstr "" -#: RtMidi.cpp:1750 RtMidi.cpp:1842 RtMidi.cpp:1996 RtMidi.cpp:3109 -#: RtMidi.cpp:3226 RtMidi.cpp:3476 RtMidi.cpp:3624 RtMidi.cpp:4274 -#: RtMidi.cpp:4550 RtMidi.cpp:4609 RtMidi.cpp:5369 RtMidi.cpp:5658 +#: RtMidi.cpp:1693 RtMidi.cpp:1785 RtMidi.cpp:1939 RtMidi.cpp:2035 +#: RtMidi.cpp:3052 RtMidi.cpp:3169 RtMidi.cpp:3419 RtMidi.cpp:3567 +#: RtMidi.cpp:4217 RtMidi.cpp:4492 RtMidi.cpp:4551 RtMidi.cpp:5311 +#: RtMidi.cpp:5600 msgid "A valid connection already exists." msgstr "" -#: RtMidi.cpp:1758 RtMidi.cpp:3116 RtMidi.cpp:4281 +#: RtMidi.cpp:1701 RtMidi.cpp:3059 RtMidi.cpp:4224 msgid "No MIDI input sources found." msgstr "" -#: RtMidi.cpp:1767 RtMidi.cpp:1924 RtMidi.cpp:1979 RtMidi.cpp:2013 -#: RtMidi.cpp:3126 RtMidi.cpp:3496 RtMidi.cpp:4450 RtMidi.cpp:4528 -#: RtMidi.cpp:4563 RtMidi.cpp:5469 RtMidi.cpp:5759 +#: RtMidi.cpp:1710 RtMidi.cpp:1867 RtMidi.cpp:1922 RtMidi.cpp:1956 +#: RtMidi.cpp:3069 RtMidi.cpp:3439 RtMidi.cpp:4392 RtMidi.cpp:4470 +#: RtMidi.cpp:4505 RtMidi.cpp:5411 RtMidi.cpp:5701 #, c-format msgid "The 'portNumber' argument (%d) is invalid." msgstr "" -#: RtMidi.cpp:1779 +#: RtMidi.cpp:1722 msgid "Error creating OS-X MIDI input port." msgstr "" -#: RtMidi.cpp:1789 +#: RtMidi.cpp:1732 msgid "Error getting MIDI input source reference." msgstr "" -#: RtMidi.cpp:1799 +#: RtMidi.cpp:1742 msgid "Error connecting OS-X MIDI input port." msgstr "" -#: RtMidi.cpp:1821 +#: RtMidi.cpp:1764 msgid "Error creating virtual OS-X MIDI destination." msgstr "" -#: RtMidi.cpp:1837 RtMidi.cpp:2087 RtMidi.cpp:3221 RtMidi.cpp:3619 -#: RtMidi.cpp:5363 RtMidi.cpp:5652 -msgid "Internal error: data has not been allocated." +#: RtMidi.cpp:1780 RtMidi.cpp:2030 RtMidi.cpp:3164 RtMidi.cpp:3562 +#: RtMidi.cpp:5305 RtMidi.cpp:5594 +msgid "Data has not been allocated." msgstr "" -#: RtMidi.cpp:1847 RtMidi.cpp:2097 -msgid "An invalid (i.e. non-CORE) port descriptor has been passed to openPort." +#: RtMidi.cpp:1790 RtMidi.cpp:2040 +msgid "" +"Core MIDI has been instructed to open a non-Core MIDI port. This doesn't " +"work." msgstr "" -#: RtMidi.cpp:2004 +#: RtMidi.cpp:1947 msgid "No MIDI output destinations found." msgstr "" -#: RtMidi.cpp:2025 +#: RtMidi.cpp:1968 msgid "Error creating OS-X MIDI output port." msgstr "" -#: RtMidi.cpp:2035 +#: RtMidi.cpp:1978 msgid "Error getting MIDI output destination reference." msgstr "" -#: RtMidi.cpp:2060 +#: RtMidi.cpp:2003 msgid "A virtual output port already exists." msgstr "" -#: RtMidi.cpp:2071 +#: RtMidi.cpp:2014 msgid "Error creating OS-X virtual MIDI source." msgstr "" -#: RtMidi.cpp:2092 -msgid "A valid connection already exists" -msgstr "" - -#: RtMidi.cpp:2210 +#: RtMidi.cpp:2153 msgid "Could not allocate packet list." msgstr "" -#: RtMidi.cpp:2219 +#: RtMidi.cpp:2162 msgid "Error sending MIDI to virtual destinations." msgstr "" -#: RtMidi.cpp:2228 RtMidi.cpp:3605 +#: RtMidi.cpp:2171 RtMidi.cpp:3548 msgid "Error sending MIDI message to port." msgstr "" -#: RtMidi.cpp:2431 RtMidi.cpp:3170 -msgid "Error allocating ALSA port subscription." +#: RtMidi.cpp:2374 RtMidi.cpp:2636 RtMidi.cpp:3113 RtMidi.cpp:3174 +#: RtMidi.cpp:3465 +msgid "Could not allocate ALSA port subscription." msgstr "" -#: RtMidi.cpp:2446 RtMidi.cpp:3179 RtMidi.cpp:3532 +#: RtMidi.cpp:2389 RtMidi.cpp:3122 RtMidi.cpp:3475 msgid "Error making ALSA port connection." msgstr "" -#: RtMidi.cpp:2516 RtMidi.cpp:3003 +#: RtMidi.cpp:2459 RtMidi.cpp:2946 msgid "Error creating ALSA sequencer client object." msgstr "" -#: RtMidi.cpp:2693 -msgid "Error while trying to allocate ALSA port subscription." -msgstr "" - -#: RtMidi.cpp:2755 RtMidi.cpp:3205 RtMidi.cpp:3335 +#: RtMidi.cpp:2698 RtMidi.cpp:3148 RtMidi.cpp:3278 msgid "Error starting MIDI input thread!" msgstr "" -#: RtMidi.cpp:3021 +#: RtMidi.cpp:2964 msgid "Error creating pipe objects." msgstr "" -#: RtMidi.cpp:3101 RtMidi.cpp:3468 +#: RtMidi.cpp:3044 RtMidi.cpp:3411 msgid "Error looking for port name." msgstr "" -#: RtMidi.cpp:3157 +#: RtMidi.cpp:3100 msgid "Error creating ALSA input port." msgstr "" -#: RtMidi.cpp:3231 -msgid "Error while allocating ALSA port subscription." -msgstr "" - -#: RtMidi.cpp:3236 RtMidi.cpp:3634 -msgid "An invalid (i.e. non-ALSA) port descriptor has been passed to openPort." +#: RtMidi.cpp:3179 RtMidi.cpp:3577 +msgid "" +"ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work." msgstr "" -#: RtMidi.cpp:3301 RtMidi.cpp:3559 +#: RtMidi.cpp:3244 RtMidi.cpp:3502 msgid "Error creating ALSA virtual port." msgstr "" -#: RtMidi.cpp:3420 +#: RtMidi.cpp:3363 msgid "Error initializing MIDI event parser." msgstr "" -#: RtMidi.cpp:3427 RtMidi.cpp:3583 -msgid "Error allocating buffer memory." +#: RtMidi.cpp:3370 RtMidi.cpp:3526 +msgid "Error while allocating buffer memory." msgstr "" -#: RtMidi.cpp:3484 -msgid "No MIDI output sources found." +#: RtMidi.cpp:3427 +msgid "No MIDI output sinks found." msgstr "" -#: RtMidi.cpp:3511 +#: RtMidi.cpp:3454 msgid "Error creating ALSA output port." msgstr "" -#: RtMidi.cpp:3522 -msgid "Error allocating port subscription." -msgstr "" - -#: RtMidi.cpp:3576 +#: RtMidi.cpp:3519 msgid "ALSA error resizing MIDI event buffer." msgstr "" -#: RtMidi.cpp:3597 +#: RtMidi.cpp:3540 msgid "Event parsing error." msgstr "" -#: RtMidi.cpp:3629 -msgid "ALSA error allocation port subscription." +#: RtMidi.cpp:3572 +msgid "Error allocating ALSA port subscription." msgstr "" -#: RtMidi.cpp:3766 +#: RtMidi.cpp:3709 #, c-format msgid "The port argument %d is invalid." msgstr "" -#: RtMidi.cpp:4255 +#: RtMidi.cpp:4198 msgid "No MIDI input devices currently available." msgstr "" -#: RtMidi.cpp:4266 -msgid "InitializeCriticalSectionAndSpinCount failed." +#: RtMidi.cpp:4209 +msgid "Failed to initialize a critical section." msgstr "" -#: RtMidi.cpp:4290 +#: RtMidi.cpp:4233 #, c-format msgid "the 'portNumber' argument (%d) is invalid." msgstr "" -#: RtMidi.cpp:4302 +#: RtMidi.cpp:4245 msgid "Error creating Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4318 -msgid "Error starting Windows MM MIDI input port (PrepareHeader)." +#: RtMidi.cpp:4261 +msgid "Error initializing data for Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4327 -msgid "Error starting Windows MM MIDI input port (AddBuffer)." +#: RtMidi.cpp:4270 +msgid "Could not register the input buffer for Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4336 +#: RtMidi.cpp:4279 msgid "Error starting Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4347 RtMidi.cpp:4596 -msgid "Cannot be implemented in Windows MM MIDI API." +#: RtMidi.cpp:4290 RtMidi.cpp:4538 +msgid "Virtual ports are not available Windows Multimedia MIDI API." msgstr "" -#: RtMidi.cpp:4354 RtMidi.cpp:4604 +#: RtMidi.cpp:4297 RtMidi.cpp:4546 msgid "" -"An invalid (i.e. non-WinMM) port descriptor has been passed to openPort." +"Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI " +"port. This doesn't work." msgstr "" -#: RtMidi.cpp:4359 +#: RtMidi.cpp:4302 msgid "" "We are overwriting an existing connection. This is probably a programming " "error." msgstr "" -#: RtMidi.cpp:4364 -msgid "" -"The port descriptor pased to MidiInWinMM::openPort() cannot be used to open " -"an input port." +#: RtMidi.cpp:4307 +msgid "Trying to open a non-input port as input MIDI port. This doesn't work." msgstr "" -#: RtMidi.cpp:4374 RtMidi.cpp:4624 +#: RtMidi.cpp:4317 RtMidi.cpp:4566 msgid "" "Some change in the arrangement of MIDI input ports invalidated the port " "descriptor." msgstr "" -#: RtMidi.cpp:4389 +#: RtMidi.cpp:4332 msgid "The handle is invalid. Did you disconnect the device?" msgstr "" -#: RtMidi.cpp:4393 RtMidi.cpp:4643 +#: RtMidi.cpp:4336 RtMidi.cpp:4585 msgid "" "The system has no driver for our handle :-(. Did you disconnect the device?" msgstr "" -#: RtMidi.cpp:4397 RtMidi.cpp:4647 +#: RtMidi.cpp:4340 RtMidi.cpp:4589 msgid "Out of memory." msgstr "" -#: RtMidi.cpp:4428 -msgid "Error closing Windows MM MIDI input port (midiInUnprepareHeader)." +#: RtMidi.cpp:4370 +msgid "Error closing Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4506 +#: RtMidi.cpp:4448 msgid "No MIDI output devices currently available." msgstr "" -#: RtMidi.cpp:4557 +#: RtMidi.cpp:4499 msgid "No MIDI output destinations found!" msgstr "" -#: RtMidi.cpp:4575 +#: RtMidi.cpp:4517 msgid "Error creating Windows MM MIDI output port." msgstr "" -#: RtMidi.cpp:4614 +#: RtMidi.cpp:4556 msgid "The port descriptor cannot be used to open an output port." msgstr "" -#: RtMidi.cpp:4639 +#: RtMidi.cpp:4581 msgid "The internal handle is invalid. Did you disconnect the device?" msgstr "" -#: RtMidi.cpp:4669 +#: RtMidi.cpp:4611 msgid "Message argument is empty." msgstr "" -#: RtMidi.cpp:4681 -msgid "Error allocating sysex message memory!" +#: RtMidi.cpp:4623 +msgid "Error while allocating sysex message memory." msgstr "" -#: RtMidi.cpp:4697 +#: RtMidi.cpp:4639 msgid "Error preparing sysex header." msgstr "" -#: RtMidi.cpp:4706 +#: RtMidi.cpp:4648 msgid "Error sending sysex message." msgstr "" -#: RtMidi.cpp:4719 +#: RtMidi.cpp:4661 msgid "Message size is greater than 3 bytes (and not sysex)." msgstr "" -#: RtMidi.cpp:4735 +#: RtMidi.cpp:4677 msgid "Error sending MIDI message." msgstr "" -#: RtMidi.cpp:4986 +#: RtMidi.cpp:4928 msgid "Could not connect to JACK server. Is it runnig?" msgstr "" -#: RtMidi.cpp:5189 +#: RtMidi.cpp:5131 msgid "Error opening JACK port subscription." msgstr "" -#: RtMidi.cpp:5296 RtMidi.cpp:5579 +#: RtMidi.cpp:5238 RtMidi.cpp:5521 msgid "JACK server not running?" msgstr "" -#: RtMidi.cpp:5331 RtMidi.cpp:5396 RtMidi.cpp:5620 RtMidi.cpp:5685 +#: RtMidi.cpp:5273 RtMidi.cpp:5338 RtMidi.cpp:5562 RtMidi.cpp:5627 msgid "Error creating JACK port." msgstr "" -#: RtMidi.cpp:5351 RtMidi.cpp:5640 +#: RtMidi.cpp:5293 RtMidi.cpp:5582 msgid "Error creating JACK virtual port." msgstr "" -#: RtMidi.cpp:5375 -msgid "An invalid (i.e. non-ALSA) port descriptor has been passed to openPort" +#: RtMidi.cpp:5317 RtMidi.cpp:5606 +msgid "" +"JACK has been instructed to open a non-JACK MIDI port. This doesn't work." msgstr "" -#: RtMidi.cpp:5462 +#: RtMidi.cpp:5404 RtMidi.cpp:5694 msgid "No ports available." msgstr "" - -#: RtMidi.cpp:5664 -msgid "An invalid (i.e. non-JACK) port descriptor has been passed to openPort" -msgstr "" - -#: RtMidi.cpp:5752 -msgid "No ports available" -msgstr "" From 908667350ce7454d3f98b25c8ad07660f4e9f7f2 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Tue, 10 Jun 2014 21:04:25 +0200 Subject: [PATCH 067/210] Provide a preliminary complete German translation. --- po/de.mo | Bin 577 -> 12222 bytes po/de.po | 524 ++++++++++++++++++++++++++++++++----------------------- 2 files changed, 306 insertions(+), 218 deletions(-) diff --git a/po/de.mo b/po/de.mo index 2e1aeee2a024243b4d68c08eb0bc2fa5d232a25c..4e5cab19025b7bbab6828efab81e4c70367037be 100644 GIT binary patch literal 12222 zcmcJVTWlQHdB>-|#bzAGc9SM)o#e=kDk|14N%<0cB}<_w%AzPrtVqe1rm<&t4|k{B zo!QPs6j>N)U=)4ILy$NHiX;wD!9`&pFKPTF)J6Fav_T6rC>->md1=uWy#OtWzzEuh z{=Re0T=qgra?yci|2sS1Ip;gy{e09<9=_{!kE_Z32=|dYJ?}N}_&t1ZoxRud=D;QJ zm%-lx9|hk44}yON-Ua?M_$%PQgG=B??(@7~1iuLWJh%<=&-)4=7r@^GKMVdN_-XK= zDbJe$=Rld)2Zio;!6V?i;OD?QKj?W2;4x76{Sx?b@SET?_E1MmR&E$|cIJMQ^!!Q(vtH+Tqq`a_=g8SoWQ`1&32Q{Y>mtoIk-XTkph9|J%2 zfaU8PSmU_^&V#RmLib~E7QExbcD~0!+1HDp?B}bX$oISM{a=Hhsw>b(rg{F|Vx`wdX|{hq^jLE-CXpzwJRsUI=i?%{0Iq>w1FwMp1PVVVK5EAWpz!-u@C5h+P=WXSg6B2B zL*O#l1kZrq1&@P21y{kNAM-p|_g({E0lxvt{O^IU-oakk#3`P?gK$K@e-9e@vRT0s zpvZF*Tm%Q;W$E|4&f(eiY-D_vb+I^H;&A!Rw&B|2wb_-p$Js;1i(OSpv#B-vovJ zT~Ol1hZ!^jJ_Ftb2H+|ff~ekm2V|?>k3sR1pMkifx4@)g?`t5ed0zs>F0MQLk$W$T z$nQr$e)3)d5sCMj!#6?2^Phtv$A5A7D8?uIdKaRC%t`2hEQ+-%KUvi{xN zgd}r`9E4Yq%e?u;`qUY|{~EXW8*H0PWL&)#-NSRB*p=cId5Ubr4>3PuPmh4>+;SnB z;<}S>&vT0o<+_7g?8N83hZ{FH*DHJydW@|+2@=k{d$~m?n5MBwzuW)hCWa)4)6DOwC`$)fYS$T~I=?pW&GVsj97nN=brS3ZVMnbjonBJf!YHg6GBaFuR#)p?xNk=~2@j=eD~dOnsn=8fRX^zY z&7QVPCEH1=`-wN7rBUBcgBBa@*{yjCQEaKoZ@0ilG0NE2Uknbl5hwq^yC&QQ!QWg~4xTS_N$s7HkAqTC{;a`awG=hD@F= z4btsfB);86V%7uS^A zuJye3g43FJMtvmBb(`TzrQBY3$4d1Y`8XVhpb_b?9Jn zXzEOq5mJIs9ZVXHgQSjBP4V?$+s!~MF~iOFt-uo_1j0X&UTiL3Y>3qDtHRUxfFKOg z!0(MEk%1o*2=i%&sM_M}H;V{%@4YD66bBP(V|Jn6FL>?y=3VLZWp>Qhl{6*e3x`m{ zQQodHh&AjA9dTG+Q(Y2o$$LTwmUl*aeVrtJM@z7;n%g9roQI)zjLVf?5o=)?Ij!Zx zEmlmF`thh9(=JBYKHwCcC*L&OcLlRRfy zo3#nd*sI%$w`eL1F%A)_mUngU43&W`D+)V-HAR6$T|hyT*t($Zi5ktvEtCUBl zQIpCNLt@jlDGE%k4oTK4PRoAW$@&tBsc3Y6kRq4-6=f4SE>Rr`3MS?Gp?X|3w^N;{ zX&---RA$6=xbB&nu&u8KE$v;1s`@D9V*GJ^`_0x7$ikH z^dhFpQG+?H=uA8nf_#TVl04WRF2!0=e_$MxBTZ!Hy_BvNJO-?I=_2ASvo@7Pnq>(lBBUULj%Q z{S7xV%WY60i&3sdgo^4yTeT|cq{`tatRBSd#w(^8;t_GcLBZ&PY@D;(s7=>zy3Kf7 z!YA6OoWn{(5L2^H#zKVQiN~QUl^PP`u$QgT8JDzO|G2)up=kyqF`U z4O`ffKn*`)_i`GQ@0DC^LoZ?+#8HzIpx8TKJF(xFGCt1&Mb0W#^TvNt)BLuwa@bg? zIVkLTE;WRf;XNfFK5&bMyBbGQjn|giwJVzR6@?8Ir{=(Qv_4m#ow}rDnc7Oy3EH(& zStqHjM-A0Y(?Qahndt;+H*41Mr5P4Y(#;t=cxv_HdTqf}mYk(I2kC}7Iy?77ZT6|! z+$>)kPtH9yJ2yKEVeJwbL{^?m_l%`G?t578+hi_ z%F@bWDKin(LPT>Ugv;##+fDVgbY{@=gYcNdJL<;t*~{x^YEPGRvM`luZ82;`Qj9g! z)6F2ATJ2@A->aRWLQWbg9GJ)C*`vpl{rc>5s17`<<_;g5dZG554s~oLvKnE`shX=l zS$~2z_OZ5RYT^aUK|@&$=m1+;+?E2)D3&5TMWMZ(4x4nAC<=onv#8x0gyW8GYB^0LZVc~HAlldJ((aAc zW=y{)3pY*UsiTqpj+{BEc#JP=Qb=V)XZHrdfRuz2G&#|;iXrX<%_?1J%Ur{e@xj`B zmUOTx+g38YrP>*dMaG=>gT73+dp)G=4l$WnJs0o3z59j)b{Yn>rfL^_b``X`*iCKK zG^nKKB^@d!2=d}q0Qcb$yR}e=O>?SdCcyklDXE=I?Y_OS5h56M8t3TfZmP@>)2-5q zu(q*#qthhD*_x%cX6g)1A9>3Psn9>lk}bd6D?3%@n^|&y&ZJ#+yPPf4m!M}Q?h99I z1I->07L3N!SBaW$LV$Tuv5F8yJd>7a>dlBifK9jw+ksZAKFuxZZIJ~;bVT!>?g-IR ztE)Ec%6;Cr*L@tQP2D9$bZyP_yhLbX6C%{}yVtXgl-Pb!Ovw!w#!+{er8^>6r&=pm zRDcySR&8l4yTV+qfJItiVy8yGv3$05W^8fEwZS&c!C6gTzPxn$u;X*$W(jD!*Hg_D zUClm3o{pJ(5uU9WCXT=9+P60&J6t5H`AzL?+i~RbUu~sGiB_G4IPBys>Uc+IMpcqO zLMQF8&|`H=j3tDsx?C}h__%eyYHS7wcG2kjFnL-0?xx{y*k{)=(mLUrlE)~eFSUDF zyoAyOE%W2f7Qz}2AbI#FK*9pO28lRDejbWnzLX8@mNkXjTL~(z*fbH3{JnUswj2#M z^oUH>Xq_^tEInMr8T~m;jO=}{A%#tvnQWr7zCrPVTp{Q>Pa*oe-VAZlX$4MEQkFCDq zxN6=NWwDvi$ZTjP<3vr;?EjhCoZu!gJG{gYAN-jT>Cp?c$GiRbaNFPe#A)Sc9h*!r z9yD?>-2%yQysRAN4ELMmG3wS&Ba~zBcbv6!QU9LH`9v+fwR^qWovnA?x*a?D>E6XdlFFH_6yi+m%N(<3(4*1|`o(vX=~A1kw?8bom3N964>LR*z)2 zp$0}#TjB>aOS;J5G$Sv|f38W=-5cqSELI$Va~V39#!2N*12l213S6iY>tYhy#jc$S zn!O;RDYq%|qh9qhx5_I0yf8B@Gt&o7%TgCMh&8#45{_2+vDD8taK>x{fro`Oi~fp) zmSRsBBdiPyhZK#1=-&=kIXZ!z5zq!`L{%fBHyikcBD7ZRT{6B`FLQ z4*O0{gueOY5>SWdEMn@oh>TSXQx7S3lg_zQiERqxXVfE#@(yLNWfK!k1VYbb`m%5~ ztmJ?DN%N-2y0pGfjWLNVq`fI}n<$0pzV60{m1(%&hI}#eL<%(PZ5K#&X^ovqbIT-) zGKyP{_v|xGI1*>2UArAsOPhS=8Ya|MCghq*hh}^b+g@K{dw=X%#HX%CvHTUpL}}@w z!F%4cGi@)iGK`|1(fP3vKvC@2&O8k;Q>@GE?tktSZHNg!6`lEg^Ey+ltV}vq?$?kL JkKfl9{}%-LyIueQ delta 112 zcmdlNe~`uEo)F7a1|VPrVi_P-0b*t#)&XJ=umECqCI$veAPrIj1CtdcO1KRy6pRe5 pj4ZSbj3zITkmZ2zjm;+?m9XSWN-fIC%rDkUN!`pVsmRF4001CT5sLr- diff --git a/po/de.po b/po/de.po index 5ea5b84f..c37ebdad 100644 --- a/po/de.po +++ b/po/de.po @@ -3,13 +3,14 @@ # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # +#: RtMidi.cpp:3346 msgid "" msgstr "" "Project-Id-Version: rtmidi 2.1.0\n" "Report-Msgid-Bugs-To: https://github.com/thestk/rtmidi\n" -"POT-Creation-Date: 2014-06-08 21:28+0200\n" -"PO-Revision-Date: 2014-06-08 21:37+0100\n" -"Last-Translator: Tobias Schlemmer \n" +"POT-Creation-Date: 2014-06-10 21:00+0200\n" +"PO-Revision-Date: 2014-06-10 20:59+0100\n" +"Last-Translator: Tobias Schlemmer \n" "Language-Team: German translation team \n" "Language: de\n" "MIME-Version: 1.0\n" @@ -19,38 +20,68 @@ msgstr "" "X-Generator: Poedit 1.5.4\n" "X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-Basepath: .\n" +"X-Poedit-KeywordsList: gettext_noopt\n" +"X-Poedit-SearchPath-0: /home/tobias/macbookbackup/Entwicklung/rtmidi-beides\n" -#: RtMidi.h:450 RtMidi.h:557 +#: RtMidi.h:91 +msgid "Automatic selection" +msgstr "Automatische Auswahl" + +#: RtMidi.h:92 +msgid "Core MIDI" +msgstr "Core MIDI" + +#: RtMidi.h:93 +msgid "ALSA" +msgstr "ALSA" + +#: RtMidi.h:94 +msgid "JACK" +msgstr "JACK" + +#: RtMidi.h:95 +msgid "Windows Multimedia" +msgstr "Windows Multimedia" + +#: RtMidi.h:96 +msgid "DirectX/Kernel Streaming" +msgstr "DirectX/Kernel Streaming" + +#: RtMidi.h:97 +msgid "NULL device" +msgstr "Keine Funktion." + +#: RtMidi.h:98 +msgid "All available MIDI systems" +msgstr "Alle verfügbaren MIDI-Systeme." + +#: RtMidi.h:450 RtMidi.h:557 RtMidi.h:1070 RtMidi.h:1162 msgid "Passed NULL pointer." -msgstr "" +msgstr "Nullzeiger übergeben." -#: RtMidi.h:623 RtMidi.cpp:2150 +#: RtMidi.h:623 RtMidi.cpp:2093 msgid "No data in message argument." -msgstr "" +msgstr "Keine Daten in der MIDI-Nachricht." #: RtMidi.h:951 msgid "A NULL pointer has been passed as port descriptor" -msgstr "" +msgstr "Ein leerer Zeiger wurde als Schnittstellenbeschreibung übergeben." -#: RtMidi.h:983 RtMidi.h:1196 -msgid "No valid API selected." -msgstr "" - -#: RtMidi.h:1053 RtMidi.h:1076 -msgid "No valid API found." -msgstr "" +#: RtMidi.h:983 RtMidi.h:1195 RtMidi.h:1218 RtMidi.h:1231 +msgid "No valid MIDI system has been selected." +msgstr "Es wurde kein benutzbares MIDI-System ausgewählt." -#: RtMidi.h:1071 RtMidi.h:1163 -msgid "passed NULL pointer" -msgstr "" +#: RtMidi.h:1052 +msgid "Could not find any valid MIDI system." +msgstr "Es konnte kein benutzbares MIDI-System gefunden werden." -#: RtMidi.h:1213 -msgid "No data in message argument!" -msgstr "" +#: RtMidi.h:1075 +msgid "No valid MIDI system has been found." +msgstr "Es konnte kein benutzbares MIDI-System gefunden werden." -#: RtMidi.h:1219 RtMidi.h:1232 -msgid "The API has not been set." -msgstr "" +#: RtMidi.h:1212 +msgid "No data in MIDI message." +msgstr "Keine Daten in der MIDI-Nachricht." #: RtMidi.cpp:71 #, c-format @@ -60,371 +91,428 @@ msgid "" "Found in %s::%s at \n" "%s:%d" msgstr "" +"Fehler bei der Formatierung der Fehlermeldung:\n" +"'%s'\n" +"gefunden in %s::%s bei \n" +"%s:%d" #: RtMidi.cpp:83 msgid "Error: could not format the error message" -msgstr "" +msgstr "Fehler: Ich konnte eine Fehlermeldung nicht formatieren." -#: RtMidi.cpp:274 RtMidi.cpp:375 -msgid "No compiled API support found." +#: RtMidi.cpp:258 RtMidi.cpp:361 +#, c-format +msgid "" +"Support for the selected MIDI system %d has not been compiled into the " +"RtMidi library." msgstr "" +"Die Unterstützung für das gewählte MIDI-System %d wurde nicht in die RtMidi-" +"Bibliothek eingebaut." + +#: RtMidi.cpp:276 RtMidi.cpp:378 +msgid "No supported MIDI system has been found." +msgstr "Es konnte kein benutzbares MIDI-System gefunden werden." -#: RtMidi.cpp:454 +#: RtMidi.cpp:457 msgid "A callback function is already set." -msgstr "" +msgstr "Es wurde schon eine Rückruffunktion gesetzt." -#: RtMidi.cpp:460 +#: RtMidi.cpp:463 msgid "The callback function value is invalid." -msgstr "" +msgstr "Der Funktionswert einer aufgerufenen Rückruffunktion ist ungültig." -#: RtMidi.cpp:473 +#: RtMidi.cpp:476 msgid "No callback function was set." -msgstr "" +msgstr "Es wurde keine Rückruffunktion gesetzt." -#: RtMidi.cpp:496 -msgid "A user callback is currently set for this port." +#: RtMidi.cpp:499 +msgid "" +"Returning an empty MIDI message as all input is handled by a callback " +"function." msgstr "" +"Es wird eine leere MIDI-Nachricht generiert, weil alle Eingaben durch eine " +"Rückruf-Funktion (engl. callback) abgefangen werden." -#: RtMidi.cpp:1151 -msgid "Could not get the UID of a midi endpoint." +#: RtMidi.cpp:1154 +msgid "Could not get the unique identifier of a midi endpoint." msgstr "" +"Konnte die eindeutige Identifikation (UUID) eines MIDI-Endpunktes nicht " +"bekommen." -#: RtMidi.cpp:1162 -msgid "Could not get the endpoint back from UID of a midi endpoint." +#: RtMidi.cpp:1165 +msgid "" +"Could not get the endpoint back from the unique identifier of a midi " +"endpoint." msgstr "" +"Konnte den MIDI-Endpunkt einer eindeutige Identifikation (UUID) nicht " +"bekommen." -#: RtMidi.cpp:1178 +#: RtMidi.cpp:1181 msgid "Could not get the entity of a midi endpoint." -msgstr "" +msgstr "Konnte die Geräteeinheit eines MIDI-Endpunktes nicht bekommen." -#: RtMidi.cpp:1255 RtMidi.cpp:1295 -msgid "Error creating OS X MIDI port because of invalid port flags" +#: RtMidi.cpp:1258 RtMidi.cpp:1298 +msgid "Error creating OS X MIDI port because of invalid port flags." msgstr "" +"Konnte die OS X-MIDI-Schnittstelle nicht anlegen, da ungültige Eigenschaften " +"angegeben wurden." -#: RtMidi.cpp:1259 RtMidi.cpp:1299 RtMidi.cpp:1861 +#: RtMidi.cpp:1262 RtMidi.cpp:1302 RtMidi.cpp:1804 msgid "Error creating OS-X MIDI port." -msgstr "" - -#: RtMidi.cpp:1319 -msgid "CORE error allocation port subscription." -msgstr "" +msgstr "Es gab einen Fehler beim Erzeugen der MIDI-Schnittstelle." -#: RtMidi.cpp:1334 -msgid "CORE error making port connection." -msgstr "" - -#: RtMidi.cpp:1412 +#: RtMidi.cpp:1355 msgid "Error creating OS-X MIDI client object." -msgstr "" +msgstr "Fehler beim erzeugen des OS-X-MIDI-Klienten." -#: RtMidi.cpp:1750 RtMidi.cpp:1842 RtMidi.cpp:1996 RtMidi.cpp:3109 -#: RtMidi.cpp:3226 RtMidi.cpp:3476 RtMidi.cpp:3624 RtMidi.cpp:4274 -#: RtMidi.cpp:4550 RtMidi.cpp:4609 RtMidi.cpp:5369 RtMidi.cpp:5658 +#: RtMidi.cpp:1693 RtMidi.cpp:1785 RtMidi.cpp:1939 RtMidi.cpp:2035 +#: RtMidi.cpp:3052 RtMidi.cpp:3169 RtMidi.cpp:3419 RtMidi.cpp:3567 +#: RtMidi.cpp:4217 RtMidi.cpp:4492 RtMidi.cpp:4551 RtMidi.cpp:5311 +#: RtMidi.cpp:5600 msgid "A valid connection already exists." -msgstr "" +msgstr "Es existiert schon eine gültige Verbindung." -#: RtMidi.cpp:1758 RtMidi.cpp:3116 RtMidi.cpp:4281 +#: RtMidi.cpp:1701 RtMidi.cpp:3059 RtMidi.cpp:4224 msgid "No MIDI input sources found." -msgstr "" +msgstr "Keine MIDI-Eingabe-Geräte gefunden." -#: RtMidi.cpp:1767 RtMidi.cpp:1924 RtMidi.cpp:1979 RtMidi.cpp:2013 -#: RtMidi.cpp:3126 RtMidi.cpp:3496 RtMidi.cpp:4450 RtMidi.cpp:4528 -#: RtMidi.cpp:4563 RtMidi.cpp:5469 RtMidi.cpp:5759 +#: RtMidi.cpp:1710 RtMidi.cpp:1867 RtMidi.cpp:1922 RtMidi.cpp:1956 +#: RtMidi.cpp:3069 RtMidi.cpp:3439 RtMidi.cpp:4392 RtMidi.cpp:4470 +#: RtMidi.cpp:4505 RtMidi.cpp:5411 RtMidi.cpp:5701 #, c-format msgid "The 'portNumber' argument (%d) is invalid." -msgstr "" +msgstr "Die Portnummer %d ist ungültig." -#: RtMidi.cpp:1779 +#: RtMidi.cpp:1722 msgid "Error creating OS-X MIDI input port." -msgstr "" +msgstr "Fehler beim Erzeugen der OS-X-MIDI-Eingabe-Schnittstelle." -#: RtMidi.cpp:1789 +#: RtMidi.cpp:1732 msgid "Error getting MIDI input source reference." -msgstr "" +msgstr "Konnte keine Referenz zum MIDI-Eingang bekommen." -#: RtMidi.cpp:1799 +#: RtMidi.cpp:1742 msgid "Error connecting OS-X MIDI input port." -msgstr "" +msgstr "Fehler beim verbinden mit dem OS-X-MIDI-Eingang." -#: RtMidi.cpp:1821 +#: RtMidi.cpp:1764 msgid "Error creating virtual OS-X MIDI destination." -msgstr "" +msgstr "Konnte den virtuellen OS-X-MIDI-Ausgang nicht erzeugen." -#: RtMidi.cpp:1837 RtMidi.cpp:2087 RtMidi.cpp:3221 RtMidi.cpp:3619 -#: RtMidi.cpp:5363 RtMidi.cpp:5652 -msgid "Internal error: data has not been allocated." -msgstr "" +#: RtMidi.cpp:1780 RtMidi.cpp:2030 RtMidi.cpp:3164 RtMidi.cpp:3562 +#: RtMidi.cpp:5305 RtMidi.cpp:5594 +msgid "Data has not been allocated." +msgstr "Daten konnten nicht angelegt werden." -#: RtMidi.cpp:1847 RtMidi.cpp:2097 -msgid "An invalid (i.e. non-CORE) port descriptor has been passed to openPort." +#: RtMidi.cpp:1790 RtMidi.cpp:2040 +msgid "" +"Core MIDI has been instructed to open a non-Core MIDI port. This doesn't " +"work." msgstr "" +"Core-MIDI wurde angewiesen, eine nicht-Core-MIDI-Schnittstelle zu öffnen. " +"Das geht nicht." -#: RtMidi.cpp:2004 +#: RtMidi.cpp:1947 msgid "No MIDI output destinations found." -msgstr "" +msgstr "Es wurden keine MIDI-Ausgabegeräte gefunden." -#: RtMidi.cpp:2025 +#: RtMidi.cpp:1968 msgid "Error creating OS-X MIDI output port." -msgstr "" +msgstr "Fehler beim Erzeugen der OS-X-MIDI-Ausgabe-Schnittstelle." -#: RtMidi.cpp:2035 +#: RtMidi.cpp:1978 msgid "Error getting MIDI output destination reference." -msgstr "" +msgstr "Konnte keine Referenz zum MIDI-Ausgang bekommen." -#: RtMidi.cpp:2060 +#: RtMidi.cpp:2003 msgid "A virtual output port already exists." -msgstr "" +msgstr "Es gibt schon einen virtuellen MIDI-Ausgang." -#: RtMidi.cpp:2071 +#: RtMidi.cpp:2014 msgid "Error creating OS-X virtual MIDI source." -msgstr "" +msgstr "Konnte den virtuellen OS-X-MIDI-Eingang nicht erzeugen." -#: RtMidi.cpp:2092 -msgid "A valid connection already exists" -msgstr "" - -#: RtMidi.cpp:2210 +#: RtMidi.cpp:2153 msgid "Could not allocate packet list." -msgstr "" +msgstr "Konnte die Paketliste nicht anlegen." -#: RtMidi.cpp:2219 +#: RtMidi.cpp:2162 msgid "Error sending MIDI to virtual destinations." -msgstr "" +msgstr "Konnte MIDI-Daten nicht zu virtuellen Ausgängen senden." -#: RtMidi.cpp:2228 RtMidi.cpp:3605 +#: RtMidi.cpp:2171 RtMidi.cpp:3548 msgid "Error sending MIDI message to port." -msgstr "" +msgstr "Fehler beim Senden der MIDI-Nachricht zum Ausgang." -#: RtMidi.cpp:2431 RtMidi.cpp:3170 -msgid "Error allocating ALSA port subscription." +#: RtMidi.cpp:2374 RtMidi.cpp:2636 RtMidi.cpp:3113 RtMidi.cpp:3174 +#: RtMidi.cpp:3465 +msgid "Could not allocate ALSA port subscription." msgstr "" +"Konnte keinen Speicher für das Abonnoment der ALSA-MIDI-Schnittstelle " +"bekommen." -#: RtMidi.cpp:2446 RtMidi.cpp:3179 RtMidi.cpp:3532 +#: RtMidi.cpp:2389 RtMidi.cpp:3122 RtMidi.cpp:3475 msgid "Error making ALSA port connection." -msgstr "" +msgstr "Konnte zwei ALSA-Schnittstellen nicht miteinander verbinden." -#: RtMidi.cpp:2516 RtMidi.cpp:3003 +#: RtMidi.cpp:2459 RtMidi.cpp:2946 msgid "Error creating ALSA sequencer client object." -msgstr "" - -#: RtMidi.cpp:2693 -msgid "Error while trying to allocate ALSA port subscription." -msgstr "" +msgstr "Fehler beim erzeugen des ALSA-Klienten." -#: RtMidi.cpp:2755 RtMidi.cpp:3205 RtMidi.cpp:3335 +#: RtMidi.cpp:2698 RtMidi.cpp:3148 RtMidi.cpp:3278 msgid "Error starting MIDI input thread!" -msgstr "" +msgstr "Konnte den MIDI-Eingabe-Prozess nicht starten." -#: RtMidi.cpp:3021 +#: RtMidi.cpp:2964 msgid "Error creating pipe objects." -msgstr "" +msgstr "Fehler beim anlegen einer Pipe." -#: RtMidi.cpp:3101 RtMidi.cpp:3468 +#: RtMidi.cpp:3044 RtMidi.cpp:3411 msgid "Error looking for port name." -msgstr "" +msgstr "Fehler beim Suchen nach einem Schnittstellennamen." -#: RtMidi.cpp:3157 +#: RtMidi.cpp:3100 msgid "Error creating ALSA input port." -msgstr "" - -#: RtMidi.cpp:3231 -msgid "Error while allocating ALSA port subscription." -msgstr "" +msgstr "Fehler beim Erzeugen der ALSA-Eingabe-Schnittstelle." -#: RtMidi.cpp:3236 RtMidi.cpp:3634 -msgid "An invalid (i.e. non-ALSA) port descriptor has been passed to openPort." +#: RtMidi.cpp:3179 RtMidi.cpp:3577 +msgid "" +"ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work." msgstr "" +"ALSA wurde angewiesen, eine nicht-ALSA-MIDI-Schnittstelle zu öffnen. Das " +"geht nicht." -#: RtMidi.cpp:3301 RtMidi.cpp:3559 +#: RtMidi.cpp:3244 RtMidi.cpp:3502 msgid "Error creating ALSA virtual port." -msgstr "" +msgstr "Fehler beim Erzeugen einer virtuellen ALSA-Schnittstelle." -#: RtMidi.cpp:3420 +#: RtMidi.cpp:3363 msgid "Error initializing MIDI event parser." -msgstr "" +msgstr "Fehler bei der Initialisierung des MIDI-Ereeignisparsers." -#: RtMidi.cpp:3427 RtMidi.cpp:3583 -msgid "Error allocating buffer memory." -msgstr "" +#: RtMidi.cpp:3370 RtMidi.cpp:3526 +msgid "Error while allocating buffer memory." +msgstr "Fehler beim Anlegen des Pufferspeichers." -#: RtMidi.cpp:3484 -msgid "No MIDI output sources found." -msgstr "" +#: RtMidi.cpp:3427 +msgid "No MIDI output sinks found." +msgstr "Es wurden kiene Midi-Ausgabegeräte gefunden." -#: RtMidi.cpp:3511 +#: RtMidi.cpp:3454 msgid "Error creating ALSA output port." -msgstr "" - -#: RtMidi.cpp:3522 -msgid "Error allocating port subscription." -msgstr "" +msgstr "Fehler beim Erzeugen der ALSA-Ausgangs." -#: RtMidi.cpp:3576 +#: RtMidi.cpp:3519 msgid "ALSA error resizing MIDI event buffer." -msgstr "" +msgstr "ALSA-Fehler beim Verändern der Größe des MIDI-Nachrichten-Puffers." -#: RtMidi.cpp:3597 +#: RtMidi.cpp:3540 msgid "Event parsing error." -msgstr "" +msgstr "Fehler bei der Analyse eines Ereignisses." -#: RtMidi.cpp:3629 -msgid "ALSA error allocation port subscription." +#: RtMidi.cpp:3572 +msgid "Error allocating ALSA port subscription." msgstr "" +"Konnte keinen Speicher für das Abonnoment der ALSA-MIDI-Schnittstelle " +"bekommen." -#: RtMidi.cpp:3766 +#: RtMidi.cpp:3709 #, c-format msgid "The port argument %d is invalid." -msgstr "" +msgstr "Das Schnittstellenargument %d ist ungültig." -#: RtMidi.cpp:4255 +#: RtMidi.cpp:4198 msgid "No MIDI input devices currently available." -msgstr "" +msgstr "Es gibt momentan keine MIDI-Eingabegeräte." -#: RtMidi.cpp:4266 -msgid "InitializeCriticalSectionAndSpinCount failed." -msgstr "" +#: RtMidi.cpp:4209 +msgid "Failed to initialize a critical section." +msgstr "Konnte kritischen Bereich nicht initialisieren." -#: RtMidi.cpp:4290 +#: RtMidi.cpp:4233 #, c-format msgid "the 'portNumber' argument (%d) is invalid." -msgstr "" +msgstr "Die Portnummer %d ist ungültig." -#: RtMidi.cpp:4302 +#: RtMidi.cpp:4245 msgid "Error creating Windows MM MIDI input port." -msgstr "" +msgstr "Konnte den Windows-Multimedia-MIDI-Eingang nicht erzeugen." -#: RtMidi.cpp:4318 -msgid "Error starting Windows MM MIDI input port (PrepareHeader)." +#: RtMidi.cpp:4261 +msgid "Error initializing data for Windows MM MIDI input port." msgstr "" +"Fehler beim Erzeugen der daten für einen Windows Multimedia MIDI-Eingang." -#: RtMidi.cpp:4327 -msgid "Error starting Windows MM MIDI input port (AddBuffer)." +#: RtMidi.cpp:4270 +msgid "Could not register the input buffer for Windows MM MIDI input port." msgstr "" +"Konnte den Eingabe-Puffer eines Windows-Multimedia-MIDI-Eingangs nicht " +"erzeugen." -#: RtMidi.cpp:4336 +#: RtMidi.cpp:4279 msgid "Error starting Windows MM MIDI input port." -msgstr "" +msgstr "Konnte einen Windows-Multimedia-MIDI-Eingang nicht aktivieren." -#: RtMidi.cpp:4347 RtMidi.cpp:4596 -msgid "Cannot be implemented in Windows MM MIDI API." +#: RtMidi.cpp:4290 RtMidi.cpp:4538 +msgid "Virtual ports are not available Windows Multimedia MIDI API." msgstr "" +"Windows Multimedia unterstützt keine virtuellen MIDI-Ein- und -Ausgänge." -#: RtMidi.cpp:4354 RtMidi.cpp:4604 +#: RtMidi.cpp:4297 RtMidi.cpp:4546 msgid "" -"An invalid (i.e. non-WinMM) port descriptor has been passed to openPort." +"Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI " +"port. This doesn't work." msgstr "" +"Windows Multimedia (WinMM) wurde angewiesen, eine nicht-WinMM-MIDI-" +"Schnittstelle zu öffnen. Das geht nicht." -#: RtMidi.cpp:4359 +#: RtMidi.cpp:4302 msgid "" "We are overwriting an existing connection. This is probably a programming " "error." msgstr "" +"Wir überschreiben eine vorhandene MIDI-Verbindung. Das ist vermutlich ein " +"Programmierfehler." -#: RtMidi.cpp:4364 -msgid "" -"The port descriptor pased to MidiInWinMM::openPort() cannot be used to open " -"an input port." +#: RtMidi.cpp:4307 +msgid "Trying to open a non-input port as input MIDI port. This doesn't work." msgstr "" +"Versuche eine Nicht-Eingang als MIDI-Eingang zu öffnen. Das geht nicht." -#: RtMidi.cpp:4374 RtMidi.cpp:4624 +#: RtMidi.cpp:4317 RtMidi.cpp:4566 msgid "" "Some change in the arrangement of MIDI input ports invalidated the port " "descriptor." msgstr "" +"Eine Veränderung bei den MIDI-Schnittstellen hat die interne " +"Schnittstellenbeschreibung ungültig gemacht." -#: RtMidi.cpp:4389 +#: RtMidi.cpp:4332 msgid "The handle is invalid. Did you disconnect the device?" msgstr "" +"Ein Schnittstellenverweis ist ungültig. Haben Sie das zugehörige Gerät " +"entfernt?" -#: RtMidi.cpp:4393 RtMidi.cpp:4643 +#: RtMidi.cpp:4336 RtMidi.cpp:4585 msgid "" "The system has no driver for our handle :-(. Did you disconnect the device?" msgstr "" +"Das System hat keinen Treiber für unseren Schnittstellenverweis (mehr) :-(. " +"Haben Sie das zugehörige Gerät entfernt?" -#: RtMidi.cpp:4397 RtMidi.cpp:4647 +#: RtMidi.cpp:4340 RtMidi.cpp:4589 msgid "Out of memory." -msgstr "" +msgstr "Hauptspeicher erschöpft." -#: RtMidi.cpp:4428 -msgid "Error closing Windows MM MIDI input port (midiInUnprepareHeader)." +#: RtMidi.cpp:4370 +msgid "Error closing Windows MM MIDI input port." msgstr "" +"Konnte den Windows Multimedia MIDI-Eingang nicht ordnungsgemäß schließen." -#: RtMidi.cpp:4506 +#: RtMidi.cpp:4448 msgid "No MIDI output devices currently available." -msgstr "" +msgstr "Es gibt momentan keine MIDI-Ausgabegeräte." -#: RtMidi.cpp:4557 +#: RtMidi.cpp:4499 msgid "No MIDI output destinations found!" -msgstr "" +msgstr "Es wurden keine MIDI-Ausgabegeräte gefunden." -#: RtMidi.cpp:4575 +#: RtMidi.cpp:4517 msgid "Error creating Windows MM MIDI output port." -msgstr "" +msgstr "Konnte den Windows Multimedia MIDI-Ausgang nicht erzeugen." -#: RtMidi.cpp:4614 +#: RtMidi.cpp:4556 msgid "The port descriptor cannot be used to open an output port." msgstr "" +"Eine Schnittstellenbeschreibung kann nicht benutzt werden, um einen MIDI-" +"Ausgang zu erzeugen." -#: RtMidi.cpp:4639 +#: RtMidi.cpp:4581 msgid "The internal handle is invalid. Did you disconnect the device?" msgstr "" +"Ein interner Schnittstellenverweis ist ungültig. Haben sie das zugehörige " +"Gerät entfernt?" -#: RtMidi.cpp:4669 +#: RtMidi.cpp:4611 msgid "Message argument is empty." -msgstr "" +msgstr "Das Nachrichtenargument ist leer." -#: RtMidi.cpp:4681 -msgid "Error allocating sysex message memory!" -msgstr "" +#: RtMidi.cpp:4623 +msgid "Error while allocating sysex message memory." +msgstr "Fehler beim Anlegen des Speichers für SysEx-Nachrichten." -#: RtMidi.cpp:4697 +#: RtMidi.cpp:4639 msgid "Error preparing sysex header." -msgstr "" +msgstr "Fehler beim Erstellen des SysEx-Kopfes." -#: RtMidi.cpp:4706 +#: RtMidi.cpp:4648 msgid "Error sending sysex message." -msgstr "" +msgstr "Fehler beim Senden der SysEx-Nachricht." -#: RtMidi.cpp:4719 +#: RtMidi.cpp:4661 msgid "Message size is greater than 3 bytes (and not sysex)." msgstr "" +"Eine MIDI-Nachricht ist größer als 3 Bytes (und keine SysEx-Nachricht)." -#: RtMidi.cpp:4735 +#: RtMidi.cpp:4677 msgid "Error sending MIDI message." -msgstr "" +msgstr "Fehler beim Senden der MIDI-Nachricht." -#: RtMidi.cpp:4986 +#: RtMidi.cpp:4928 msgid "Could not connect to JACK server. Is it runnig?" -msgstr "" +msgstr "Ich konnte mich nicht mit dem JACK-Server verbinden. Läuft er?" -#: RtMidi.cpp:5189 +#: RtMidi.cpp:5131 msgid "Error opening JACK port subscription." -msgstr "" +msgstr "Fehler beim abonnieren einer JACK-Schnittstelle." -#: RtMidi.cpp:5296 RtMidi.cpp:5579 +#: RtMidi.cpp:5238 RtMidi.cpp:5521 msgid "JACK server not running?" -msgstr "" +msgstr "Läuft der JACK-Server?" -#: RtMidi.cpp:5331 RtMidi.cpp:5396 RtMidi.cpp:5620 RtMidi.cpp:5685 +#: RtMidi.cpp:5273 RtMidi.cpp:5338 RtMidi.cpp:5562 RtMidi.cpp:5627 msgid "Error creating JACK port." -msgstr "" +msgstr "Es gab einen Fehler beim Erzeugen der JACK-Schnittstelle." -#: RtMidi.cpp:5351 RtMidi.cpp:5640 +#: RtMidi.cpp:5293 RtMidi.cpp:5582 msgid "Error creating JACK virtual port." -msgstr "" +msgstr "Fehler beim Erzeugen einer virtuellen JACK-Schnittstelle." -#: RtMidi.cpp:5375 -msgid "An invalid (i.e. non-ALSA) port descriptor has been passed to openPort" +#: RtMidi.cpp:5317 RtMidi.cpp:5606 +msgid "" +"JACK has been instructed to open a non-JACK MIDI port. This doesn't work." msgstr "" +"JACK wurde angewiesen, eine nicht-JACK-Schnittstelle zu öffnen. Das geht " +"nicht." -#: RtMidi.cpp:5462 +#: RtMidi.cpp:5404 RtMidi.cpp:5694 msgid "No ports available." -msgstr "" +msgstr "Keine Schnittstellen verfügbar." -#: RtMidi.cpp:5664 -msgid "An invalid (i.e. non-JACK) port descriptor has been passed to openPort" -msgstr "" +#, fuzzy +#~ msgid "InitializeCriticalSectionAndSpinCount failed." +#~ msgstr "%s: malloc ist fehlgeschlagen: %s\n" -#: RtMidi.cpp:5752 -msgid "No ports available" -msgstr "" +#, fuzzy +#~ msgid "ALSA error allocation port subscription." +#~ msgstr "" +#~ "Konnte keinen Speicher für das Abonnoments der MIDI-Schnittstelle " +#~ "bekommen." + +#, fuzzy +#~ msgid "A valid connection already exists" +#~ msgstr "Es existiert schon eine gültige Verbindung." + +#, fuzzy +#~ msgid "No ports available" +#~ msgstr "Keine Adresse verfügbar" + +#~ msgid "" +#~ "An invalid (i.e. non-CORE) port descriptor has been passed to openPort." +#~ msgstr "Es wurde eine ungültige Schnittstellenbeschreibung (" + +#~ msgid "Internal error: data has not been allocated." +#~ msgstr " " + +#~ msgid "No data in message argument!" +#~ msgstr "Keine Daten in der MIDI-Nachricht." From 8ab3e39c409b1ef4e9b76d80f3c04eebff3c3c33 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 26 Jul 2014 21:19:37 +0200 Subject: [PATCH 068/210] Implement automatic gettext configuration if RtMidi is compiled with gettext support. --- RtMidi.cpp | 43 +++++++++++++++++++++++++++++-------------- RtMidi.h | 25 ++++++++++++++++--------- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index bdf10e2a..3f002950 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -43,21 +43,36 @@ NAMESPACE_RTMIDI_START -//! The constructor. -Error::Error( const char * message, - Type type, - const char * class_name, - const char * function_name, - const char * file_name, - int line_number, ...) throw():exception(), - classname(class_name), - function(function_name), - file(file_name), - line(line_number), - type_(type) -{ #ifdef RTMIDI_GETTEXT - message = gettext(message); + const char * rtmidi_gettext (const char * s) { + init_rtmidi_gettext(); + return dgettext("rtmidi",s); + } + + void init_rtmidi_gettext() { + static initialized = false; + if (initialized) + return; + bindtextdomain("rtmidi",LOCALEDIR); + initialized = true; + } +#endif + + //! The constructor. + Error::Error( const char * message, + Type type, + const char * class_name, + const char * function_name, + const char * file_name, + int line_number, ...) throw():exception(), + classname(class_name), + function(function_name), + file(file_name), + line(line_number), + type_(type) + { +#ifdef RTMIDI_GETTEXT + message = rtmidi_gettext(message); #endif std::va_list args; va_start(args,line_number); diff --git a/RtMidi.h b/RtMidi.h index e0abb32a..d9fb655c 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -77,16 +77,23 @@ NAMESPACE_RTMIDI_START +#ifdef RTMIDI_GETTEXT +const char * rtmidi_gettext(const char * s); +void init_rtmidi_gettext(); +#else +#define rtmidi_gettext(arg) (arg) +#endif + //! MIDI API specifier arguments. - enum ApiType { -UNSPECIFIED, /*!< Search for a working compiled API. */ -MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ -LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ -UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ -WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ -WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ -DUMMY, /*!< A compilable but non-functional API. */ -ALL_API /*!< Use all available APIs for port selection. */ +enum ApiType { + UNSPECIFIED, /*!< Search for a working compiled API. */ + MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ + LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ + UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ + WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ + WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ + DUMMY, /*!< A compilable but non-functional API. */ + ALL_API /*!< Use all available APIs for port selection. */ }; //! Return the name on a MIDI API From af8ee5fce4673b2cbb172cc82c57fb2155bb0c49 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 30 Jul 2014 22:02:01 +0200 Subject: [PATCH 069/210] Remove some unused code. --- RtMidi.cpp | 292 ++++++----------------------------------------------- 1 file changed, 30 insertions(+), 262 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 3f002950..66256a3f 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -44,35 +44,35 @@ NAMESPACE_RTMIDI_START #ifdef RTMIDI_GETTEXT - const char * rtmidi_gettext (const char * s) { - init_rtmidi_gettext(); - return dgettext("rtmidi",s); - } +const char * rtmidi_gettext (const char * s) { + init_rtmidi_gettext(); + return dgettext("rtmidi",s); +} - void init_rtmidi_gettext() { - static initialized = false; - if (initialized) - return; - bindtextdomain("rtmidi",LOCALEDIR); - initialized = true; - } +void init_rtmidi_gettext() { + static initialized = false; + if (initialized) + return; + bindtextdomain("rtmidi",LOCALEDIR); + initialized = true; +} #endif - //! The constructor. - Error::Error( const char * message, - Type type, - const char * class_name, - const char * function_name, - const char * file_name, - int line_number, ...) throw():exception(), - classname(class_name), - function(function_name), - file(file_name), - line(line_number), - type_(type) - { +//! The constructor. +Error::Error( const char * message, + Type type, + const char * class_name, + const char * function_name, + const char * file_name, + int line_number, ...) throw():exception(), + classname(class_name), + function(function_name), + file(file_name), + line(line_number), + type_(type) +{ #ifdef RTMIDI_GETTEXT - message = rtmidi_gettext(message); + message = rtmidi_gettext(message); #endif std::va_list args; va_start(args,line_number); @@ -80,7 +80,7 @@ NAMESPACE_RTMIDI_START length = vsnprintf(NULL,0,message,args); if (length > 0) { message_.resize(length+1); - std::vsnprintf(&(message_[0]),length,message,args); + std::vsnprintf(&(message_[0]),length+1,message,args); message_.resize(length); } else { const char * fmt = gettext_noopt("Error formatting the error string:\n'%s'\nFound in %s::%s at \n%s:%d"); @@ -91,7 +91,7 @@ NAMESPACE_RTMIDI_START length = snprintf(NULL,0,fmt,message,class_name,function_name,file_name,line); if (length > 0) { message_.resize(length+1); - snprintf(&(message_[0]),length,fmt,message,class_name,function_name,file_name,line); + snprintf(&(message_[0]),length+1,fmt,message,class_name,function_name,file_name,line); message_.resize(length); } else { const char * msg @@ -159,23 +159,8 @@ void Midi :: getCompiledApi( std::vector &apis, bool preferSystem ) thr void Midi :: error(Error e) { -#if 0 - if ( errorCallback_ ) { - static bool firstErrorOccured = false; - - if ( firstErrorOccured ) - return; - - firstErrorOccured = true; - std::ostringstream s; - e.printMessage(s); - - errorCallback_( type, s.str() ); - firstErrorOccured = false; - return; - } -#endif - + return; +} if ( e.getType() == Error::WARNING ) { e.printMessage(); } @@ -1228,18 +1213,6 @@ class CoreSequencer { return retval; } -#if 0 - int getNextClient(snd_seq_client_info_t * cinfo ) { - init(); - scoped_lock lock (mutex); - return snd_seq_query_next_client (seq, cinfo); - } - int getNextPort(snd_seq_port_info_t * pinfo ) { - init(); - scoped_lock lock (mutex); - return snd_seq_query_next_port (seq, pinfo); - } -#endif MIDIPortRef createPort (std::string portName, int flags, @@ -2950,17 +2923,6 @@ MidiInAlsa :: ~MidiInAlsa() void MidiInAlsa :: initialize( const std::string& clientName ) { -#if 0 - /* this will be done in the AlsaSequencer class */ - // Set up the ALSA sequencer client. - snd_seq_t *seq; - int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); - if ( result < 0 ) { - error(RTMIDI_ERROR(gettext_noopt("Error creating ALSA sequencer client object."), - Error::DRIVER_ERROR)); - return; - } -#endif // Save our api-specific connection information. AlsaMidiData *data = new AlsaMidiData (clientName); @@ -3794,100 +3756,6 @@ class WinMMSequencer { return os.str(); } -#if 0 - int getPortCapabilities(int client, int port) { - init(); - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); - { - scoped_lock lock (mutex); - snd_seq_get_any_port_info(seq,client,port,pinfo); - } - unsigned int caps = snd_seq_port_info_get_capability(pinfo); - int retval = (caps & (SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ))? - PortDescriptor::INPUT:0; - if (caps & (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) - retval |= PortDescriptor::OUTPUT; - return retval; - } - - int getNextClient(snd_seq_client_info_t * cinfo ) { - init(); - scoped_lock lock (mutex); - return snd_seq_query_next_client (seq, cinfo); - } - int getNextPort(snd_seq_port_info_t * pinfo ) { - init(); - scoped_lock lock (mutex); - return snd_seq_query_next_port (seq, pinfo); - } - - int createPort (snd_seq_port_info_t *pinfo) { - init(); - scoped_lock lock (mutex); - return snd_seq_create_port(seq, pinfo); - } - - void deletePort(int port) { - init(); - scoped_lock lock (mutex); - snd_seq_delete_port( seq, port ); - } - - snd_seq_port_subscribe_t * connectPorts(const snd_seq_addr_t & from, - const snd_seq_addr_t & to, - bool real_time) { - init(); - snd_seq_port_subscribe_t *subscription; - - if (snd_seq_port_subscribe_malloc( &subscription ) < 0) { - throw Error("MidiInWinMM::openPort: WINMM error allocation port subscription.", - Error::DRIVER_ERROR ); - return 0; - } - snd_seq_port_subscribe_set_sender(subscription, &from); - snd_seq_port_subscribe_set_dest(subscription, &to); - if (real_time) { - snd_seq_port_subscribe_set_time_update(subscription, 1); - snd_seq_port_subscribe_set_time_real(subscription, 1); - } - { - scoped_lock lock (mutex); - if ( snd_seq_subscribe_port(seq, subscription) ) { - snd_seq_port_subscribe_free( subscription ); - subscription = 0; - throw Error("MidiInWinMM::openPort: WINMM error making port connection.", - Error::DRIVER_ERROR); - return 0; - } - } - return subscription; - } - - void closePort(snd_seq_port_subscribe_t * subscription ) { - init(); - scoped_lock lock(mutex); - snd_seq_unsubscribe_port( seq, subscription ); - } - - void startQueue(int queue_id) { - init(); - scoped_lock lock(mutex); - snd_seq_start_queue( seq, queue_id, NULL ); - snd_seq_drain_output( seq ); - } - - /*! Use WinMMSequencer like a C pointer. - \note This function breaks the design to control thread safety - by the selection of the \ref locking parameter to the class. - It should be removed as soon as possible in order ensure the - thread policy that has been intended by creating this class. - */ - operator snd_seq_t * () - { - return seq; - } -#endif protected: struct scoped_lock { // pthread_mutex_t * mutex; @@ -3910,37 +3778,12 @@ class WinMMSequencer { int mutex; std::string name; -#if 0 - snd_seq_client_info_t * GetClient(int id) { - init(); - snd_seq_client_info_t * cinfo; - scoped_lock lock(mutex); - snd_seq_get_any_client_info(seq,id,cinfo); - return cinfo; - } -#endif void init() { // init (seq); } -#if 0 - void init(snd_seq_t * &s) - { - if (s) return; - { - scoped_lock lock(mutex); - int result = snd_seq_open(&s, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); - if ( result < 0 ) { - throw Error( "MidiInWinMM::initialize: error creating WINMM sequencer client object.", - Error::DRIVER_ERROR ); - return; - } - snd_seq_set_client_name( seq, name.c_str() ); - } - } -#endif }; // typedef WinMMSequencer<1> LockingWinMMSequencer; typedef WinMMSequencer<0> NonLockingWinMMSequencer; @@ -4432,6 +4275,7 @@ std::string MidiInWinMM :: getPortName( unsigned int portNumber ) #undef RTMIDI_CLASSNAME + //*********************************************************************// // API: Windows MM // Class Definitions: MidiOutWinMM @@ -4831,18 +4675,6 @@ class JackSequencer { return retval; } -#if 0 - int getNextClient(snd_seq_client_info_t * cinfo ) { - init(); - scoped_lock lock (mutex); - return snd_seq_query_next_client (client, cinfo); - } - int getNextPort(snd_seq_port_info_t * pinfo ) { - init(); - scoped_lock lock (mutex); - return snd_seq_query_next_port (client, pinfo); - } -#endif jack_port_t * createPort (const std::string & portName, unsigned long portOptions) { init(); @@ -4878,14 +4710,6 @@ class JackSequencer { jack_port_name( to ) ); } -#if 0 - void startQueue(int queue_id) { - init(); - scoped_lock lock(mutex); - snd_seq_start_queue( client, queue_id, NULL ); - snd_seq_drain_output( client ); - } -#endif /*! Use JackSequencer like a C pointer. \note This function breaks the design to control thread safety @@ -4916,15 +4740,6 @@ class JackSequencer { std::string name; JackMidiData * data; -#if 0 - snd_seq_client_info_t * GetClient(int id) { - init(); - snd_seq_client_info_t * cinfo; - scoped_lock lock(mutex); - snd_seq_get_any_client_info(client,id,cinfo); - return cinfo; - } -#endif void init() { @@ -5338,26 +5153,6 @@ void MidiInJack :: openPort( const PortDescriptor & p, portName); data->setRemote(*port); data->connectPorts(*port,data->local); - -#if 0 - - connect(); - - // Creating new port - if ( data->port == NULL) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); - - if ( data->port == NULL) { - error(RTMIDI_ERROR(gettext_noopt("Error creating JACK port."), - Error::DRIVER_ERROR) ); - return; - } - - // Connecting to the output - std::string name = getPortName( portNumber ); - jack_connect( data->client, name.c_str(), jack_port_name( data->port ) ); -#endif } Pointer MidiInJack :: getDescriptor(bool local) @@ -5549,14 +5344,6 @@ MidiOutJack :: ~MidiOutJack() JackMidiData *data = static_cast (apiData_); // closePort(); -#if 0 - if ( *(data->seq) ) { - // Cleanup - jack_client_close( data->client ); - jack_ringbuffer_free( data->buffSize ); - jack_ringbuffer_free( data->buffMessage ); - } -#endif data->stateflags = JackMidiData::DELETING; } @@ -5628,25 +5415,6 @@ void MidiOutJack :: openPort( const PortDescriptor & p, data->setRemote(*port); data->connectPorts(data->local,*port); -#if 0 - - connect(); - - // Creating new port - if ( data->port == NULL) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); - - if ( data->port == NULL) { - error(RTMIDI_ERROR(gettext_noopt("Error creating JACK port."), - Error::DRIVER_ERROR) ); - return; - } - - // Connecting to the output - std::string name = getPortName( portNumber ); - jack_connect( data->client, name.c_str(), jack_port_name( data->port ) ); -#endif } Pointer MidiOutJack :: getDescriptor(bool local) From e838cddd9cd4e18be70c21d2cfa067eae8c5230f Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 30 Jul 2014 22:05:12 +0200 Subject: [PATCH 070/210] Return localized API name from getApiName() --- RtMidi.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index d9fb655c..34ba1207 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -85,7 +85,7 @@ void init_rtmidi_gettext(); #endif //! MIDI API specifier arguments. -enum ApiType { + enum ApiType { UNSPECIFIED, /*!< Search for a working compiled API. */ MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ @@ -99,14 +99,14 @@ enum ApiType { //! Return the name on a MIDI API inline std::string getApiName(ApiType type) { switch (type) { - case UNSPECIFIED: return gettext_noopt("Automatic selection"); - case MACOSX_CORE: return gettext_noopt("Core MIDI"); - case LINUX_ALSA: return gettext_noopt("ALSA"); - case UNIX_JACK: return gettext_noopt("JACK"); - case WINDOWS_MM: return gettext_noopt("Windows Multimedia"); - case WINDOWS_KS: return gettext_noopt("DirectX/Kernel Streaming"); - case DUMMY: return gettext_noopt("NULL device"); - case ALL_API: return gettext_noopt("All available MIDI systems"); + case UNSPECIFIED: return rtmidi_gettext("Automatic selection"); + case MACOSX_CORE: return rtmidi_gettext("Core MIDI"); + case LINUX_ALSA: return rtmidi_gettext("ALSA"); + case UNIX_JACK: return rtmidi_gettext("JACK"); + case WINDOWS_MM: return rtmidi_gettext("Windows Multimedia"); + case WINDOWS_KS: return rtmidi_gettext("DirectX/Kernel Streaming"); + case DUMMY: return rtmidi_gettext("NULL device"); + case ALL_API: return rtmidi_gettext("All available MIDI systems"); } return ""; } From 7ea16f3eefd2cf443c4c1c173a84e835fa5d5d2b Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 30 Jul 2014 22:06:42 +0200 Subject: [PATCH 071/210] Use the API error function if present from global classes. --- RtMidi.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RtMidi.cpp b/RtMidi.cpp index 66256a3f..12012978 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -158,6 +158,11 @@ void Midi :: getCompiledApi( std::vector &apis, bool preferSystem ) thr void Midi :: error(Error e) { + // use the callback if present. + if (rtapi_) { + rtapi_->error(e); + return; + } return; } From 9ded62105ee897459bc284b02b2a0f3cda1f320e Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 30 Jul 2014 22:14:40 +0200 Subject: [PATCH 072/210] Hand over some error exceptions to the error function. --- RtMidi.cpp | 1090 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 967 insertions(+), 123 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 12012978..1afd44d1 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -164,8 +164,6 @@ void Midi :: error(Error e) return; } - return; -} if ( e.getType() == Error::WARNING ) { e.printMessage(); } @@ -193,41 +191,46 @@ void MidiIn :: openMidiApi( ApiType api ) delete rtapi_; rtapi_ = 0; - switch (api) { - case rtmidi::UNIX_JACK: + try { + switch (api) { + case rtmidi::UNIX_JACK: #if defined(__UNIX_JACK__) - rtapi_ = new MidiInJack( clientName, queueSizeLimit ); + rtapi_ = new MidiInJack( clientName, queueSizeLimit ); #endif - break; - case rtmidi::LINUX_ALSA: + break; + case rtmidi::LINUX_ALSA: #if defined(__LINUX_ALSA__) - rtapi_ = new MidiInAlsa( clientName, queueSizeLimit ); + rtapi_ = new MidiInAlsa( clientName, queueSizeLimit ); #endif - break; - case rtmidi::WINDOWS_MM: + break; + case rtmidi::WINDOWS_MM: #if defined(__WINDOWS_MM__) - rtapi_ = new MidiInWinMM( clientName, queueSizeLimit ); + rtapi_ = new MidiInWinMM( clientName, queueSizeLimit ); #endif - break; - case rtmidi::MACOSX_CORE: + break; + case rtmidi::MACOSX_CORE: #if defined(__MACOSX_CORE__) - rtapi_ = new MidiInCore( clientName, queueSizeLimit ); + rtapi_ = new MidiInCore( clientName, queueSizeLimit ); #endif - break; - case rtmidi::DUMMY: + break; + case rtmidi::DUMMY: #if defined(__RTMIDI_DUMMY__) - rtapi_ = new MidiInDummy( clientName, queueSizeLimit ); + rtapi_ = new MidiInDummy( clientName, queueSizeLimit ); #endif - break; - case rtmidi::ALL_API: - case rtmidi::UNSPECIFIED: - default: - break; + break; + case rtmidi::ALL_API: + case rtmidi::UNSPECIFIED: + default: + break; + } + } catch (Error e) { + error(e); } } MidiApiList MidiIn::queryApis; + MidiIn :: MidiIn( ApiType api, const std::string clientName, unsigned int queueSize, @@ -1677,63 +1680,63 @@ void MidiInCore :: initialize( const std::string& clientName ) inputData_.apiData = (void *) data; } - void MidiInCore :: openPort( unsigned int portNumber, - const std::string & portName ) - { - if ( connected_ ) { - error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), - Error::WARNING)); - return; - } +void MidiInCore :: openPort( unsigned int portNumber, + const std::string & portName ) +{ + if ( connected_ ) { + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING)); + return; + } - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - unsigned int nSrc = MIDIGetNumberOfSources(); - if (nSrc < 1) { - error(RTMIDI_ERROR(gettext_noopt("No MIDI input sources found."), - Error::NO_DEVICES_FOUND)); - return; - } + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + unsigned int nSrc = MIDIGetNumberOfSources(); + if (nSrc < 1) { + error(RTMIDI_ERROR(gettext_noopt("No MIDI input sources found."), + Error::NO_DEVICES_FOUND)); + return; + } - if ( portNumber >= nSrc ) { - std::ostringstream ost; - ost << ""; - errorString_ = ost.str(); - error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), - Error::INVALID_PARAMETER, portNumber) ); - return; - } + if ( portNumber >= nSrc ) { + std::ostringstream ost; + ost << ""; + errorString_ = ost.str(); + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::INVALID_PARAMETER, portNumber) ); + return; + } - MIDIPortRef port; - CoreMidiData *data = static_cast (apiData_); - OSStatus result = MIDIInputPortCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingUTF8 ), - midiInputCallback, (void *)&inputData_, &port ); - if ( result != noErr ) { - MIDIClientDispose( data->client ); - error(RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI input port."), - Error::DRIVER_ERROR, errorString_ )); - return; - } + MIDIPortRef port; + CoreMidiData *data = static_cast (apiData_); + OSStatus result = MIDIInputPortCreate( data->client, + CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingUTF8 ), + midiInputCallback, (void *)&inputData_, &port ); + if ( result != noErr ) { + MIDIClientDispose( data->client ); + error(RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI input port."), + Error::DRIVER_ERROR, errorString_ )); + return; + } - // Get the desired input source identifier. - MIDIEndpointRef endpoint = MIDIGetSource( portNumber ); - if ( endpoint == 0 ) { - MIDIPortDispose( port ); - MIDIClientDispose( data->client ); - error(RTMIDI_ERROR(gettext_noopt("Error getting MIDI input source reference."), - Error::DRIVER_ERROR) ); - return; - } + // Get the desired input source identifier. + MIDIEndpointRef endpoint = MIDIGetSource( portNumber ); + if ( endpoint == 0 ) { + MIDIPortDispose( port ); + MIDIClientDispose( data->client ); + error(RTMIDI_ERROR(gettext_noopt("Error getting MIDI input source reference."), + Error::DRIVER_ERROR) ); + return; + } - // Make the connection. - result = MIDIPortConnectSource( port, endpoint, NULL ); - if ( result != noErr ) { - MIDIPortDispose( port ); - MIDIClientDispose( data->client ); - error(RTMIDI_ERROR(gettext_noopt("Error connecting OS-X MIDI input port."), - Error::DRIVER_ERROR) ); - return; - } + // Make the connection. + result = MIDIPortConnectSource( port, endpoint, NULL ); + if ( result != noErr ) { + MIDIPortDispose( port ); + MIDIClientDispose( data->client ); + error(RTMIDI_ERROR(gettext_noopt("Error connecting OS-X MIDI input port."), + Error::DRIVER_ERROR) ); + return; + } // Save our api-specific port information. data->localPort = port; @@ -1823,8 +1826,13 @@ Pointer MidiInCore :: getDescriptor(bool local) PortList MidiInCore :: getPortList(int capabilities) { CoreMidiData *data = static_cast (apiData_); - return CorePortDescriptor::getPortList(capabilities | PortDescriptor::INPUT, - data->getClientName()); + try { + return CorePortDescriptor::getPortList(capabilities | PortDescriptor::INPUT, + data->getClientName()); + } catch (Error e) { + error(e); + return PortList(); + } } void MidiInCore :: closePort( void ) @@ -2033,10 +2041,14 @@ void MidiOutCore :: openPort( const PortDescriptor & port, return; } - data->openPort (portName, - PortDescriptor::OUTPUT); - data->setRemote(*remote); - connected_ = true; + try { + data->openPort (portName, + PortDescriptor::OUTPUT); + data->setRemote(*remote); + connected_ = true; + } catch (Error e) { + error(e); + } } Pointer MidiOutCore :: getDescriptor(bool local) @@ -2046,16 +2058,20 @@ Pointer MidiOutCore :: getDescriptor(bool local) if (!data) { return NULL; } - if (local) { - if (data && data->localEndpoint) { - return new - CorePortDescriptor(data->localEndpoint, - data->getClientName()); - } - } else { - if (data->getEndpoint()) { - return new CorePortDescriptor(*data); + try { + if (local) { + if (data && data->localEndpoint) { + return new + CorePortDescriptor(data->localEndpoint, + data->getClientName()); + } + } else { + if (data->getEndpoint()) { + return new CorePortDescriptor(*data); + } } + } catch (Error e) { + error(e); } return NULL; } @@ -2063,8 +2079,13 @@ Pointer MidiOutCore :: getDescriptor(bool local) PortList MidiOutCore :: getPortList(int capabilities) { CoreMidiData *data = static_cast (apiData_); - return CorePortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT, - data->getClientName()); + try { + return CorePortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT, + data->getClientName()); + } catch (Error e) { + error(e); + return PortList(); + } } @@ -3161,39 +3182,56 @@ void MidiInAlsa :: openPort( const PortDescriptor & port, return; } - if (!data->local.client) - data->openPort (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, - portName); - data->setRemote(remote); - data->connectPorts(*remote,data->local,false); + try { + if (!data->local.client) + data->openPort (SND_SEQ_PORT_CAP_WRITE + | SND_SEQ_PORT_CAP_SUBS_WRITE, + portName); + data->setRemote(remote); + data->connectPorts(*remote, + data->local, + false); - if ( inputData_.doInput == false ) { - inputData_.doInput = data->startQueue(&inputData_); - } + if ( doInput == false ) { + doInput + = data->startQueue(this); + } - connected_ = true; + connected_ = true; + } catch (Error e) { + error(e); + } } Pointer MidiInAlsa :: getDescriptor(bool local) { AlsaMidiData *data = static_cast (apiData_); - if (local) { - if (data && data->local.client) { - return new AlsaPortDescriptor(data->local,data->getClientName()); - } - } else { - if (data && data->client) { - return new AlsaPortDescriptor(*data,data->getClientName()); + try { + if (local) { + if (data && data->local.client) { + return new AlsaPortDescriptor(data->local,data->getClientName()); + } + } else { + if (data && data->client) { + return new AlsaPortDescriptor(*data,data->getClientName()); + } } + } catch (Error e) { + error (e); } return NULL; } PortList MidiInAlsa :: getPortList(int capabilities) { AlsaMidiData *data = static_cast (apiData_); - return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::INPUT, - data->getClientName()); + try { + return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::INPUT, + data->getClientName()); + } catch (Error e) { + error (e); + return PortList(); + } } @@ -3559,25 +3597,33 @@ void MidiOutAlsa :: openPort( const PortDescriptor & port, return; } - if (!data->local.client) - data->openPort (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, - portName); - data->setRemote(remote); - data->connectPorts(data->local,*remote,true); + try { + if (!data->local.client) + data->openPort (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, + portName); + data->setRemote(remote); + data->connectPorts(data->local,*remote,true); - connected_ = true; + connected_ = true; + } catch (Error e) { + error (e); + } } Pointer MidiOutAlsa :: getDescriptor(bool local) { AlsaMidiData *data = static_cast (apiData_); - if (local) { - if (data && data->local.client) { - return new AlsaPortDescriptor(data->local, data->getClientName()); - } - } else { - if (data && data->client) { - return new AlsaPortDescriptor(*data, data->getClientName()); + try { + if (local) { + if (data && data->local.client) { + return new AlsaPortDescriptor(data->local, data->getClientName()); + } + } else { + if (data && data->client) { + return new AlsaPortDescriptor(*data, data->getClientName()); + } } + } catch (Error e) { + error(e); } return NULL; } @@ -3788,11 +3834,691 @@ class WinMMSequencer { { // init (seq); } - }; // typedef WinMMSequencer<1> LockingWinMMSequencer; typedef WinMMSequencer<0> NonLockingWinMMSequencer; #undef RTMIDI_CLASSNAME +======= + + /*! A structure to hold variables related to the WINMM API + implementation. + + \note After all sequencer handling is covered by the \ref + WinMMSequencer class, we should make seq to be a pointer in order + to allow a common client implementation. + */ + + struct WinMidiData:public WinMMPortDescriptor { + /* + WinMMMidiData():seq() + { + init(); + } + */ + WinMidiData(const std::string &clientName):WinMMPortDescriptor(clientName) {} + ~WinMidiData() {} + + HMIDIIN inHandle; // Handle to Midi Input Device + HMIDIOUT outHandle; // Handle to Midi Output Device + DWORD lastTime; + MidiInApi::MidiMessage message; + LPMIDIHDR sysexBuffer[RT_SYSEX_BUFFER_COUNT]; + CRITICAL_SECTION _mutex; // [Patrice] see https://groups.google.com/forum/#!topic/mididev/6OUjHutMpEo + }; + + + //*********************************************************************// + // API: Windows MM + // Class Definitions: MidiInWinMM + //*********************************************************************// + + static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, + UINT inputStatus, + DWORD_PTR instancePtr, + DWORD_PTR midiMessage, + DWORD timestamp ) + { + if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA && inputStatus != MIM_LONGERROR ) return; + + //MidiInApi::MidiInData *data = static_cast (instancePtr); + MidiInApi::MidiInData *data = (MidiInApi::MidiInData *)instancePtr; + WinMidiData *apiData = static_cast (data->apiData); + + // Calculate time stamp. + if ( data->firstMessage == true ) { + apiData->message.timeStamp = 0.0; + data->firstMessage = false; + } + else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001; + apiData->lastTime = timestamp; + + if ( inputStatus == MIM_DATA ) { // Channel or system message + + // Make sure the first byte is a status byte. + unsigned char status = (unsigned char) (midiMessage & 0x000000FF); + if ( !(status & 0x80) ) return; + + // Determine the number of bytes in the MIDI message. + unsigned short nBytes = 1; + if ( status < 0xC0 ) nBytes = 3; + else if ( status < 0xE0 ) nBytes = 2; + else if ( status < 0xF0 ) nBytes = 3; + else if ( status == 0xF1 ) { + if ( data->ignoreFlags & 0x02 ) return; + else nBytes = 2; + } + else if ( status == 0xF2 ) nBytes = 3; + else if ( status == 0xF3 ) nBytes = 2; + else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) { + // A MIDI timing tick message and we're ignoring it. + return; + } + else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { + // A MIDI active sensing message and we're ignoring it. + return; + } + + // Copy bytes to our MIDI message. + unsigned char *ptr = (unsigned char *) &midiMessage; + for ( int i=0; imessage.bytes.push_back( *ptr++ ); + } + else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) + MIDIHDR *sysex = ( MIDIHDR *) midiMessage; + if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { + // Sysex message and we're not ignoring it + for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) + apiData->message.bytes.push_back( sysex->lpData[i] ); + } + + // The WinMM API requires that the sysex buffer be requeued after + // input of each sysex message. Even if we are ignoring sysex + // messages, we still need to requeue the buffer in case the user + // decides to not ignore sysex messages in the future. However, + // it seems that WinMM calls this function with an empty sysex + // buffer when an application closes and in this case, we should + // avoid requeueing it, else the computer suddenly reboots after + // one or two minutes. + if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { + //if ( sysex->dwBytesRecorded > 0 ) { + EnterCriticalSection( &(apiData->_mutex) ); + MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); + LeaveCriticalSection( &(apiData->_mutex) ); + if ( result != MMSYSERR_NOERROR ) + std::cerr << "\nMidiIn::midiInputCallback: error sending sysex to Midi device!!\n\n"; + + if ( data->ignoreFlags & 0x01 ) return; + } + else return; + } + + if ( data->usingCallback ) { + MidiCallback callback = (MidiCallback) data->userCallback; + callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = apiData->message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else + std::cerr << "\nMidiIn: message queue limit reached!!\n\n"; + } + + // Clear the vector for the next input message. + apiData->message.bytes.clear(); + } + +#define RTMIDI_CLASSNAME "MidiInWinMM" + MidiInWinMM :: MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) + { + initialize( clientName ); + } + + MidiInWinMM :: ~MidiInWinMM() + { + // Close a connection if it exists. + closePort(); + + WinMidiData *data = static_cast (apiData_); + DeleteCriticalSection( &(data->_mutex) ); + + // Cleanup. + delete data; + } + + void MidiInWinMM :: initialize( const std::string& clientName ) + { + // We'll issue a warning here if no devices are available but not + // throw an error since the user can plugin something later. + unsigned int nDevices = midiInGetNumDevs(); + if ( nDevices == 0 ) { + error(RTMIDI_ERROR(gettext_noopt("No MIDI input devices currently available."), + Error::WARNING) ); + } + + // Save our api-specific connection information. + WinMidiData *data = (WinMidiData *) new WinMidiData(clientName); + apiData_ = (void *) data; + inputData_.apiData = (void *) data; + data->message.bytes.clear(); // needs to be empty for first input message + + if ( !InitializeCriticalSectionAndSpinCount(&(data->_mutex), 0x00000400) ) { + error(RTMIDI_ERROR(gettext_noopt("Failed to initialize a critical section."), + Error::WARNING) ); + } + } + + void MidiInWinMM :: openPort( unsigned int portNumber, const std::string & /*portName*/ ) + { + if ( connected_ ) { + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); + return; + } + + unsigned int nDevices = midiInGetNumDevs(); + if (nDevices == 0) { + error(RTMIDI_ERROR(gettext_noopt("No MIDI input sources found."), + Error::NO_DEVICES_FOUND) ); + return; + } + + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiInWinMM::openPort: "; + errorString_ = ost.str(); + error(RTMIDI_ERROR1(gettext_noopt("the 'portNumber' argument (%d) is invalid."), + Error::INVALID_PARAMETER, portNumber) ); + return; + } + + WinMidiData *data = static_cast (apiData_); + MMRESULT result = midiInOpen( &data->inHandle, + portNumber, + (DWORD_PTR)&midiInputCallback, + (DWORD_PTR)&inputData_, + CALLBACK_FUNCTION ); + if ( result != MMSYSERR_NOERROR ) { + error(RTMIDI_ERROR(gettext_noopt("Error creating Windows MM MIDI input port."), + Error::DRIVER_ERROR) ); + return; + } + + // Allocate and init the sysex buffers. + for ( int i=0; isysexBuffer[i] = (MIDIHDR*) new char[ sizeof(MIDIHDR) ]; + data->sysexBuffer[i]->lpData = new char[ RT_SYSEX_BUFFER_SIZE ]; + data->sysexBuffer[i]->dwBufferLength = RT_SYSEX_BUFFER_SIZE; + data->sysexBuffer[i]->dwUser = i; // We use the dwUser parameter as buffer indicator + data->sysexBuffer[i]->dwFlags = 0; + + result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + error(RTMIDI_ERROR(gettext_noopt("Error initializing data for Windows MM MIDI input port."), + Error::DRIVER_ERROR )); + return; + } + + // Register the buffer. + result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + error(RTMIDI_ERROR(gettext_noopt("Could not register the input buffer for Windows MM MIDI input port."), + Error::DRIVER_ERROR) ); + return; + } + } + + result = midiInStart( data->inHandle ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + error(RTMIDI_ERROR(gettext_noopt("Error starting Windows MM MIDI input port."), + Error::DRIVER_ERROR) ); + return; + } + + connected_ = true; + } + + void MidiInWinMM :: openVirtualPort( std::string /*portName*/ ) + { + // This function cannot be implemented for the Windows MM MIDI API. + error(RTMIDI_ERROR(gettext_noopt("Virtual ports are not available Windows Multimedia MIDI API."), + Error::WARNING )); + } + + void MidiInWinMM :: openPort(const PortDescriptor & p, const std::string & portName) { + const WinMMPortDescriptor * port = dynamic_cast (&p); + if ( !port) { + error( RTMIDI_ERROR(gettext_noopt("Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI port. This doesn't work."), + Error::DRIVER_ERROR)); + return; + } + if ( connected_ ) { + error( RTMIDI_ERROR(gettext_noopt("We are overwriting an existing connection. This is probably a programming error."), + Error::WARNING) ); + return; + } + if (port->getCapabilities() != PortDescriptor::INPUT) { + error(RTMIDI_ERROR(gettext_noopt("Trying to open a non-input port as input MIDI port. This doesn't work."), + Error::DRIVER_ERROR)); + return; + } + + // there is a possible race condition between opening the port and + // reordering of ports so we must check whether we opened the right port. + try { + openPort(port->getPortNumber(),portName); + } catch (Error e) { + error(e); + } + if (!port->is_valid()) { + closePort(); + error (RTMIDI_ERROR(gettext_noopt("Some change in the arrangement of MIDI input ports invalidated the port descriptor."), + Error::DRIVER_ERROR)); + return; + } + connected_ = true; + } + + Pointer MidiInWinMM :: getDescriptor(bool local) + { + if (local || !connected_) return 0; + WinMidiData *data = static_cast (apiData_); + if (!data) return 0; + UINT devid; + switch (midiInGetID(data->inHandle,&devid)) { + case MMSYSERR_INVALHANDLE: + error (RTMIDI_ERROR(gettext_noopt("The handle is invalid. Did you disconnect the device?"), + Error::DRIVER_ERROR)); + return 0; + case MMSYSERR_NODRIVER: + error (RTMIDI_ERROR(gettext_noopt("The system has no driver for our handle :-(. Did you disconnect the device?"), + Error::DRIVER_ERROR)); + return 0; + case MMSYSERR_NOMEM: + error (RTMIDI_ERROR(gettext_noopt("Out of memory."), + Error::DRIVER_ERROR)); + return 0; + } + return new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); + try { + retval = new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); + } catch (Error e) { + try { + error(e); + } catch (...) { + if (retval) delete retval; + throw; + } + } + + } + + PortList MidiInWinMM :: getPortList(int capabilities) + { + WinMidiData *data = static_cast (apiData_); + if (!data || capabilities != PortDescriptor::INPUT) return PortList(); + try { + return WinMMPortDescriptor::getPortList(PortDescriptor::INPUT,data->getClientName()); + } catch (Error e) { + error(e); + return PortList(); + } + } + + + void MidiInWinMM :: closePort( void ) + { + if ( connected_ ) { + WinMidiData *data = static_cast (apiData_); + EnterCriticalSection( &(data->_mutex) ); + midiInReset( data->inHandle ); + midiInStop( data->inHandle ); + + for ( int i=0; iinHandle, data->sysexBuffer[i], sizeof(MIDIHDR)); + delete [] data->sysexBuffer[i]->lpData; + delete [] data->sysexBuffer[i]; + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + error(RTMIDI_ERROR(gettext_noopt("Error closing Windows MM MIDI input port."), + Error::DRIVER_ERROR) ); + return; + } + } + + midiInClose( data->inHandle ); + connected_ = false; + LeaveCriticalSection( &(data->_mutex) ); + } + } + + unsigned int MidiInWinMM :: getPortCount() + { + return midiInGetNumDevs(); + } + + std::string MidiInWinMM :: getPortName( unsigned int portNumber ) + { + std::string stringName; + unsigned int nDevices = midiInGetNumDevs(); + if ( portNumber >= nDevices ) { + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::WARNING,portNumber)); + return stringName; + } + + MIDIINCAPS deviceCaps; + midiInGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIINCAPS)); + +#if defined( UNICODE ) || defined( _UNICODE ) + int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; + stringName.assign( length, 0 ); + length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); +#else + stringName = std::string( deviceCaps.szPname ); +#endif + + // 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 + std::ostringstream os; + os << " "; + os << portNumber; + stringName += os.str(); + + return stringName; + } +#undef RTMIDI_CLASSNAME + + + //*********************************************************************// + // API: Windows MM + // Class Definitions: MidiOutWinMM + //*********************************************************************// + +#define RTMIDI_CLASSNAME "MidiOutWinMM" + MidiOutWinMM :: MidiOutWinMM( const std::string clientName ) : MidiOutApi() + { + initialize( clientName ); + } + + MidiOutWinMM :: ~MidiOutWinMM() + { + // Close a connection if it exists. + closePort(); + + // Cleanup. + WinMidiData *data = static_cast (apiData_); + delete data; + } + + void MidiOutWinMM :: initialize( const std::string& clientName ) + { + // We'll issue a warning here if no devices are available but not + // throw an error since the user can plug something in later. + unsigned int nDevices = midiOutGetNumDevs(); + if ( nDevices == 0 ) { + error(RTMIDI_ERROR(gettext_noopt("No MIDI output devices currently available."), + Error::WARNING)); + } + + // Save our api-specific connection information. + WinMidiData *data = (WinMidiData *) new WinMidiData(clientName); + apiData_ = (void *) data; + } + + unsigned int MidiOutWinMM :: getPortCount() + { + return midiOutGetNumDevs(); + } + + std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) + { + std::string stringName; + unsigned int nDevices = midiOutGetNumDevs(); + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiOutWinMM::getPortName: "; + errorString_ = ost.str(); + error(RTMIDI_ERROR(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::WARNING)); + return stringName; + } + + MIDIOUTCAPS deviceCaps; + midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS)); + +#if defined( UNICODE ) || defined( _UNICODE ) + int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; + stringName.assign( length, 0 ); + length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); +#else + stringName = std::string( deviceCaps.szPname ); +#endif + + return stringName; + } + + void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string & /*portName*/ ) + { + if ( connected_ ) { + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); + return; + } + + unsigned int nDevices = midiOutGetNumDevs(); + if (nDevices < 1) { + error(RTMIDI_ERROR(gettext_noopt("No MIDI output destinations found!"), + Error::NO_DEVICES_FOUND) ); + return; + } + + if ( portNumber >= nDevices ) { + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::INVALID_PARAMETER, portNumber) ); + return; + } + + WinMidiData *data = static_cast (apiData_); + MMRESULT result = midiOutOpen( &data->outHandle, + portNumber, + (DWORD)NULL, + (DWORD)NULL, + CALLBACK_NULL ); + if ( result != MMSYSERR_NOERROR ) { + error(RTMIDI_ERROR(gettext_noopt("Error creating Windows MM MIDI output port."), + Error::DRIVER_ERROR) ); + return; + } + + connected_ = true; + } + + void MidiOutWinMM :: closePort( void ) + { + if ( connected_ ) { + WinMidiData *data = static_cast (apiData_); + midiOutReset( data->outHandle ); + midiOutClose( data->outHandle ); + connected_ = false; + } + } + + void MidiOutWinMM :: openVirtualPort( std::string /*portName*/ ) + { + // This function cannot be implemented for the Windows MM MIDI API. + error(RTMIDI_ERROR(gettext_noopt("Virtual ports are not available Windows Multimedia MIDI API."), + Error::WARNING) ); + } + + + void MidiOutWinMM :: openPort(const PortDescriptor & p, const std::string & portName) { + const WinMMPortDescriptor * port = dynamic_cast (&p); + if ( !port) { + error( RTMIDI_ERROR(gettext_noopt("Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI port. This doesn't work."), + Error::DRIVER_ERROR)); + return; + } + if ( connected_ ) { + error( RTMIDI_ERROR(gettext_noopt("A valid connection already exists." ), + Error::WARNING) ); + return; + } + if (port->getCapabilities() != PortDescriptor::OUTPUT) { + error( RTMIDI_ERROR(gettext_noopt("The port descriptor cannot be used to open an output port."), + Error::DRIVER_ERROR)); + return; + } + + // there is a possible race condition between opening the port and + // reordering of ports so we must check whether we opened the right port. + try { + openPort(port->getPortNumber(),portName); + } catch (Error e) { + error(e); + } + if (!port->is_valid()) { + closePort(); + error (RTMIDI_ERROR(gettext_noopt("Some change in the arrangement of MIDI input ports invalidated the port descriptor."), + Error::DRIVER_ERROR)); + return; + } + connected_ = true; + } + + Pointer MidiOutWinMM :: getDescriptor(bool local) + { + if (local || !connected_) return 0; + WinMidiData *data = static_cast (apiData_); + if (!data) return 0; + UINT devid; + switch (midiOutGetID(data->outHandle,&devid)) { + case MMSYSERR_INVALHANDLE: + error (RTMIDI_ERROR(gettext_noopt("The internal handle is invalid. Did you disconnect the device?"), + Error::DRIVER_ERROR)); + return 0; + case MMSYSERR_NODRIVER: + error (RTMIDI_ERROR(gettext_noopt("The system has no driver for our handle :-(. Did you disconnect the device?"), + Error::DRIVER_ERROR)); + return 0; + case MMSYSERR_NOMEM: + error (RTMIDI_ERROR(gettext_noopt("Out of memory."), + Error::DRIVER_ERROR)); + return 0; + } + return new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); + + } + + PortList MidiOutWinMM :: getPortList(int capabilities) + { + WinMidiData *data = static_cast (apiData_); + if (!data || capabilities != PortDescriptor::OUTPUT) return PortList(); + try { + return WinMMPortDescriptor::getPortList(PortDescriptor::OUTPUT,data->getClientName()); + } catch (Error e) { + error(e); + return PortList(); + } + } + + + void MidiOutWinMM :: sendMessage( std::vector &message ) + { + if ( !connected_ ) return; + + unsigned int nBytes = static_cast(message.size()); + if ( nBytes == 0 ) { + error(RTMIDI_ERROR(gettext_noopt("Message argument is empty."), + Error::WARNING)); + return; + } + + MMRESULT result; + WinMidiData *data = static_cast (apiData_); + if ( message.at(0) == 0xF0 ) { // Sysex message + + // Allocate buffer for sysex data. + char *buffer = (char *) malloc( nBytes ); + if ( buffer == NULL ) { + error(RTMIDI_ERROR(gettext_noopt("Error while allocating sysex message memory."), + Error::MEMORY_ERROR) ); + return; + } + + // Copy data to buffer. + for ( unsigned int i=0; ioutHandle, &sysex, sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + free( buffer ); + error(RTMIDI_ERROR(gettext_noopt("Error preparing sysex header."), + Error::DRIVER_ERROR)); + return; + } + + // Send the message. + result = midiOutLongMsg( data->outHandle, &sysex, sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + free( buffer ); + error(RTMIDI_ERROR(gettext_noopt("Error sending sysex message."), + Error::DRIVER_ERROR) ); + return; + } + + // Unprepare the buffer and MIDIHDR. + while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof (MIDIHDR) ) ) Sleep( 1 ); + free( buffer ); + } + else { // Channel or system message. + + // Make sure the message size isn't too big. + if ( nBytes > 3 ) { + error(RTMIDI_ERROR(gettext_noopt("Message size is greater than 3 bytes (and not sysex)."), + Error::WARNING) ); + return; + } + + // Pack MIDI bytes into double word. + DWORD packet; + unsigned char *ptr = (unsigned char *) &packet; + for ( unsigned int i=0; ioutHandle, packet ); + if ( result != MMSYSERR_NOERROR ) { + error(RTMIDI_ERROR(gettext_noopt("Error sending MIDI message."), + Error::DRIVER_ERROR )); + } + } + } +#undef RTMIDI_CLASSNAME +} +#endif // __WINDOWS_MM__ + + + //*********************************************************************// + // API: UNIX JACK + // + // Written primarily by Alexander Svetalkin, with updates for delta + // time by Gary Scavone, April 2011. + // + // *********************************************************************// struct WinMMPortDescriptor:public PortDescriptor { @@ -3902,6 +4628,7 @@ PortList WinMMPortDescriptor :: getPortList(int capabilities, const std::string } + /*! A structure to hold variables related to the WINMM API implementation. @@ -4546,6 +5273,17 @@ void MidiOutWinMM :: sendMessage( std::vector &message ) NAMESPACE_RTMIDI_END #endif // __WINDOWS_MM__ +void MidiInJack :: initialize( const std::string& clientName ) +{ + JackMidiData *data = new JackMidiData(clientName,inputData_); + apiData_ = (void *) data; + this->clientName = clientName; + try { + data->init(true); + } catch (Error e) { + error(e); + } +} //*********************************************************************// // API: UNIX JACK @@ -4562,7 +5300,23 @@ NAMESPACE_RTMIDI_END #include #include +<<<<<<< HEAD #define JACK_RINGBUFFER_SIZE 16384 // Default size for ringbuffer +======= + MidiInJack :: ~MidiInJack() + { + JackMidiData *data = static_cast (apiData_); + try { + closePort(); + } catch (Error e) { + try { + delete data; + } catch (...) { + } + error(e); + return; + } +>>>>>>> e5dcd23... Hand over some error exceptions to the error function. NAMESPACE_RTMIDI_START @@ -5079,6 +5833,7 @@ void MidiInJack :: connect() } #endif +<<<<<<< HEAD MidiInJack :: ~MidiInJack() { JackMidiData *data = static_cast (apiData_); @@ -5095,6 +5850,50 @@ MidiInJack :: ~MidiInJack() void MidiInJack :: openPort( unsigned int portNumber, const std::string & portName ) { JackMidiData *data = static_cast (apiData_); +======= + try { + if (!data->local) + data->openPort (JackPortIsInput, + portName); + data->setRemote(*port); + data->connectPorts(*port,data->local); + } catch (Error e) { + error (e); + } + + } + + Pointer MidiInJack :: getDescriptor(bool local) + { + JackMidiData *data = static_cast (apiData_); + try { + if (local) { + if (data && data->local) { + return new JackPortDescriptor(data->local,data->getClientName()); + } + } else { + if (data && *data) { + return new JackPortDescriptor(*data,data->getClientName()); + } + } + } catch (Error e) { + error(e); + } + return NULL; + } + + PortList MidiInJack :: getPortList(int capabilities) + { + JackMidiData *data = static_cast (apiData_); + try { + return JackPortDescriptor::getPortList(capabilities | PortDescriptor::INPUT, + data->getClientName()); + } catch (Error e) { + error(e); + } + return PortList(); + } +>>>>>>> e5dcd23... Hand over some error exceptions to the error function. // connect(); @@ -5408,6 +6207,7 @@ void MidiOutJack :: openPort( const PortDescriptor & p, return; } #endif +<<<<<<< HEAD if (!port) { error(RTMIDI_ERROR(gettext_noopt("JACK has been instructed to open a non-JACK MIDI port. This doesn't work."), Error::WARNING) ); @@ -5419,6 +6219,50 @@ void MidiOutJack :: openPort( const PortDescriptor & p, portName); data->setRemote(*port); data->connectPorts(data->local,*port); +======= + if (!port) { + error(RTMIDI_ERROR(gettext_noopt("JACK has been instructed to open a non-JACK MIDI port. This doesn't work."), + Error::WARNING) ); + return; + } + + try { + if (!data->local) + data->openPort (JackPortIsOutput, + portName); + data->setRemote(*port); + data->connectPorts(data->local,*port); + } catch (Error e) { + error(e); + } + } + + Pointer MidiOutJack :: getDescriptor(bool local) + { + JackMidiData *data = static_cast (apiData_); + try { + if (local) { + if (data && data->local) { + return new JackPortDescriptor(data->local,data->getClientName()); + } + } else { + if (data && *data) { + return new JackPortDescriptor(*data,data->getClientName()); + } + } + } catch (Error e) { + error(e); + } + return NULL; + } + + PortList MidiOutJack :: getPortList(int capabilities) + { + JackMidiData *data = static_cast (apiData_); + return JackPortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT, + data->getClientName()); + } +>>>>>>> e5dcd23... Hand over some error exceptions to the error function. } From 8557bfb93fe726578aad2e8af1173090b2f06032 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 30 Jul 2014 22:22:16 +0200 Subject: [PATCH 073/210] Change some error types to be more specific. --- RtMidi.cpp | 974 +++++++---------------------------------------------- 1 file changed, 118 insertions(+), 856 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 1afd44d1..62567fe2 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -230,7 +230,6 @@ void MidiIn :: openMidiApi( ApiType api ) MidiApiList MidiIn::queryApis; - MidiIn :: MidiIn( ApiType api, const std::string clientName, unsigned int queueSize, @@ -282,7 +281,7 @@ MidiIn :: MidiIn( ApiType api, // We may reach this point if the only API is JACK, // but no JACK devices are found. throw( RTMIDI_ERROR( gettext_noopt("No supported MIDI system has been found."), - Error::SYSTEM ) ); + Error::NO_DEVICES_FOUND ) ); } MidiIn :: ~MidiIn() throw() @@ -384,7 +383,7 @@ MidiOut :: MidiOut( ApiType api, const std::string clientName, bool pfsystem ) // We may reach this point, e.g. if JACK is the only // compiled API, but no JACK devices are found. throw( RTMIDI_ERROR(gettext_noopt("No supported MIDI system has been found."), - Error::UNSPECIFIED ) ); + Error::NO_DEVICES_FOUND ) ); } MidiOut :: ~MidiOut() throw() @@ -1158,9 +1157,8 @@ class CoreSequencer { kMIDIPropertyUniqueID, &uid); if (stat != noErr) { - throw - RTMIDI_ERROR(gettext_noopt("Could not get the unique identifier of a midi endpoint."), - Error::DRIVER_ERROR); + throw RTMIDI_ERROR(gettext_noopt("Could not get the unique identifier of a midi endpoint."), + Error::WARNING); return 0; } MIDIObjectRef obj; @@ -1169,9 +1167,8 @@ class CoreSequencer { &obj, &type); if (stat != noErr || obj != port) { - throw - RTMIDI_ERROR(gettext_noopt("Could not get the endpoint back from the unique identifier of a midi endpoint."), - Error::DRIVER_ERROR); + throw RTMIDI_ERROR(gettext_noopt("Could not get the endpoint back from the unique identifier of a midi endpoint."), + Error::WARNING); return 0; } if (type == kMIDIObjectType_Source @@ -1185,9 +1182,8 @@ class CoreSequencer { } } else if (stat != noErr) { - throw - RTMIDI_ERROR(gettext_noopt("Could not get the entity of a midi endpoint."), - Error::DRIVER_ERROR); + throw RTMIDI_ERROR(gettext_noopt("Could not get the entity of a midi endpoint."), + Error::WARNING); return 0; } /* Theoretically Mac OS X could silently use @@ -1252,7 +1248,7 @@ class CoreSequencer { break; default: throw RTMIDI_ERROR(gettext_noopt("Error creating OS X MIDI port because of invalid port flags."), - Error::DRIVER_ERROR); + Error::INVALID_PARAMETER); } if ( result != noErr ) { throw RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI port."), @@ -1292,7 +1288,7 @@ class CoreSequencer { break; default: throw RTMIDI_ERROR(gettext_noopt("Error creating OS X MIDI port because of invalid port flags."), - Error::DRIVER_ERROR); + Error::INVALID_PARAMETER); } if ( result != noErr ) { throw RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI port."), @@ -1301,6 +1297,7 @@ class CoreSequencer { return port; } + /*! Use CoreSequencer like a C pointer. \note This function breaks the design to control thread safety by the selection of the \ref locking parameter to the class. @@ -1329,6 +1326,7 @@ class CoreSequencer { MIDIClientRef seq; std::string name; + void init() { init (seq); @@ -1714,7 +1712,7 @@ void MidiInCore :: openPort( unsigned int portNumber, if ( result != noErr ) { MIDIClientDispose( data->client ); error(RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI input port."), - Error::DRIVER_ERROR, errorString_ )); + Error::DRIVER_ERROR)); return; } @@ -1782,7 +1780,7 @@ void MidiInCore :: openPort( const PortDescriptor & port, } if (!remote) { error(RTMIDI_ERROR(gettext_noopt("Core MIDI has been instructed to open a non-Core MIDI port. This doesn't work."), - Error::WARNING) ); + Error::INVALID_DEVICE) ); return; } @@ -2037,7 +2035,7 @@ void MidiOutCore :: openPort( const PortDescriptor & port, } if (!remote) { error(RTMIDI_ERROR(gettext_noopt("Core MIDI has been instructed to open a non-Core MIDI port. This doesn't work."), - Error::WARNING) ); + Error::INVALID_DEVICE) ); return; } @@ -3178,7 +3176,7 @@ void MidiInAlsa :: openPort( const PortDescriptor & port, } if (!remote) { error( RTMIDI_ERROR(gettext_noopt("ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work."), - Error::WARNING) ); + Error::INVALID_DEVICE) ); return; } @@ -3593,7 +3591,7 @@ void MidiOutAlsa :: openPort( const PortDescriptor & port, } if (!remote) { error(RTMIDI_ERROR(gettext_noopt("ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work."), - Error::WARNING) ); + Error::INVALID_DEVICE) ); return; } @@ -3664,7 +3662,6 @@ NAMESPACE_RTMIDI_START #ifdef UNIQUE_NAME #undef UNIQUE_NAME #endif -NAMESPACE_RTMIDI_START /*! An abstraction layer for the ALSA sequencer layer. It provides the following functionality: - dynamic allocation of the sequencer @@ -3734,7 +3731,7 @@ class WinMMSequencer { std::ostringstream ost; std::cerr << port << "<" << nDevices << std::endl; throw Error(RTMIDI_ERROR1(gettext_noopt("The port argument %d is invalid."), - Error::WARNING,port)); + Error::INVALID_PARAMETER,port)); } if (is_input) { @@ -3838,687 +3835,6 @@ class WinMMSequencer { // typedef WinMMSequencer<1> LockingWinMMSequencer; typedef WinMMSequencer<0> NonLockingWinMMSequencer; #undef RTMIDI_CLASSNAME -======= - - /*! A structure to hold variables related to the WINMM API - implementation. - - \note After all sequencer handling is covered by the \ref - WinMMSequencer class, we should make seq to be a pointer in order - to allow a common client implementation. - */ - - struct WinMidiData:public WinMMPortDescriptor { - /* - WinMMMidiData():seq() - { - init(); - } - */ - WinMidiData(const std::string &clientName):WinMMPortDescriptor(clientName) {} - ~WinMidiData() {} - - HMIDIIN inHandle; // Handle to Midi Input Device - HMIDIOUT outHandle; // Handle to Midi Output Device - DWORD lastTime; - MidiInApi::MidiMessage message; - LPMIDIHDR sysexBuffer[RT_SYSEX_BUFFER_COUNT]; - CRITICAL_SECTION _mutex; // [Patrice] see https://groups.google.com/forum/#!topic/mididev/6OUjHutMpEo - }; - - - //*********************************************************************// - // API: Windows MM - // Class Definitions: MidiInWinMM - //*********************************************************************// - - static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, - UINT inputStatus, - DWORD_PTR instancePtr, - DWORD_PTR midiMessage, - DWORD timestamp ) - { - if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA && inputStatus != MIM_LONGERROR ) return; - - //MidiInApi::MidiInData *data = static_cast (instancePtr); - MidiInApi::MidiInData *data = (MidiInApi::MidiInData *)instancePtr; - WinMidiData *apiData = static_cast (data->apiData); - - // Calculate time stamp. - if ( data->firstMessage == true ) { - apiData->message.timeStamp = 0.0; - data->firstMessage = false; - } - else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001; - apiData->lastTime = timestamp; - - if ( inputStatus == MIM_DATA ) { // Channel or system message - - // Make sure the first byte is a status byte. - unsigned char status = (unsigned char) (midiMessage & 0x000000FF); - if ( !(status & 0x80) ) return; - - // Determine the number of bytes in the MIDI message. - unsigned short nBytes = 1; - if ( status < 0xC0 ) nBytes = 3; - else if ( status < 0xE0 ) nBytes = 2; - else if ( status < 0xF0 ) nBytes = 3; - else if ( status == 0xF1 ) { - if ( data->ignoreFlags & 0x02 ) return; - else nBytes = 2; - } - else if ( status == 0xF2 ) nBytes = 3; - else if ( status == 0xF3 ) nBytes = 2; - else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) { - // A MIDI timing tick message and we're ignoring it. - return; - } - else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { - // A MIDI active sensing message and we're ignoring it. - return; - } - - // Copy bytes to our MIDI message. - unsigned char *ptr = (unsigned char *) &midiMessage; - for ( int i=0; imessage.bytes.push_back( *ptr++ ); - } - else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) - MIDIHDR *sysex = ( MIDIHDR *) midiMessage; - if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { - // Sysex message and we're not ignoring it - for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) - apiData->message.bytes.push_back( sysex->lpData[i] ); - } - - // The WinMM API requires that the sysex buffer be requeued after - // input of each sysex message. Even if we are ignoring sysex - // messages, we still need to requeue the buffer in case the user - // decides to not ignore sysex messages in the future. However, - // it seems that WinMM calls this function with an empty sysex - // buffer when an application closes and in this case, we should - // avoid requeueing it, else the computer suddenly reboots after - // one or two minutes. - if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { - //if ( sysex->dwBytesRecorded > 0 ) { - EnterCriticalSection( &(apiData->_mutex) ); - MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); - LeaveCriticalSection( &(apiData->_mutex) ); - if ( result != MMSYSERR_NOERROR ) - std::cerr << "\nMidiIn::midiInputCallback: error sending sysex to Midi device!!\n\n"; - - if ( data->ignoreFlags & 0x01 ) return; - } - else return; - } - - if ( data->usingCallback ) { - MidiCallback callback = (MidiCallback) data->userCallback; - callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = apiData->message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else - std::cerr << "\nMidiIn: message queue limit reached!!\n\n"; - } - - // Clear the vector for the next input message. - apiData->message.bytes.clear(); - } - -#define RTMIDI_CLASSNAME "MidiInWinMM" - MidiInWinMM :: MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) - { - initialize( clientName ); - } - - MidiInWinMM :: ~MidiInWinMM() - { - // Close a connection if it exists. - closePort(); - - WinMidiData *data = static_cast (apiData_); - DeleteCriticalSection( &(data->_mutex) ); - - // Cleanup. - delete data; - } - - void MidiInWinMM :: initialize( const std::string& clientName ) - { - // We'll issue a warning here if no devices are available but not - // throw an error since the user can plugin something later. - unsigned int nDevices = midiInGetNumDevs(); - if ( nDevices == 0 ) { - error(RTMIDI_ERROR(gettext_noopt("No MIDI input devices currently available."), - Error::WARNING) ); - } - - // Save our api-specific connection information. - WinMidiData *data = (WinMidiData *) new WinMidiData(clientName); - apiData_ = (void *) data; - inputData_.apiData = (void *) data; - data->message.bytes.clear(); // needs to be empty for first input message - - if ( !InitializeCriticalSectionAndSpinCount(&(data->_mutex), 0x00000400) ) { - error(RTMIDI_ERROR(gettext_noopt("Failed to initialize a critical section."), - Error::WARNING) ); - } - } - - void MidiInWinMM :: openPort( unsigned int portNumber, const std::string & /*portName*/ ) - { - if ( connected_ ) { - error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), - Error::WARNING) ); - return; - } - - unsigned int nDevices = midiInGetNumDevs(); - if (nDevices == 0) { - error(RTMIDI_ERROR(gettext_noopt("No MIDI input sources found."), - Error::NO_DEVICES_FOUND) ); - return; - } - - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiInWinMM::openPort: "; - errorString_ = ost.str(); - error(RTMIDI_ERROR1(gettext_noopt("the 'portNumber' argument (%d) is invalid."), - Error::INVALID_PARAMETER, portNumber) ); - return; - } - - WinMidiData *data = static_cast (apiData_); - MMRESULT result = midiInOpen( &data->inHandle, - portNumber, - (DWORD_PTR)&midiInputCallback, - (DWORD_PTR)&inputData_, - CALLBACK_FUNCTION ); - if ( result != MMSYSERR_NOERROR ) { - error(RTMIDI_ERROR(gettext_noopt("Error creating Windows MM MIDI input port."), - Error::DRIVER_ERROR) ); - return; - } - - // Allocate and init the sysex buffers. - for ( int i=0; isysexBuffer[i] = (MIDIHDR*) new char[ sizeof(MIDIHDR) ]; - data->sysexBuffer[i]->lpData = new char[ RT_SYSEX_BUFFER_SIZE ]; - data->sysexBuffer[i]->dwBufferLength = RT_SYSEX_BUFFER_SIZE; - data->sysexBuffer[i]->dwUser = i; // We use the dwUser parameter as buffer indicator - data->sysexBuffer[i]->dwFlags = 0; - - result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - error(RTMIDI_ERROR(gettext_noopt("Error initializing data for Windows MM MIDI input port."), - Error::DRIVER_ERROR )); - return; - } - - // Register the buffer. - result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - error(RTMIDI_ERROR(gettext_noopt("Could not register the input buffer for Windows MM MIDI input port."), - Error::DRIVER_ERROR) ); - return; - } - } - - result = midiInStart( data->inHandle ); - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - error(RTMIDI_ERROR(gettext_noopt("Error starting Windows MM MIDI input port."), - Error::DRIVER_ERROR) ); - return; - } - - connected_ = true; - } - - void MidiInWinMM :: openVirtualPort( std::string /*portName*/ ) - { - // This function cannot be implemented for the Windows MM MIDI API. - error(RTMIDI_ERROR(gettext_noopt("Virtual ports are not available Windows Multimedia MIDI API."), - Error::WARNING )); - } - - void MidiInWinMM :: openPort(const PortDescriptor & p, const std::string & portName) { - const WinMMPortDescriptor * port = dynamic_cast (&p); - if ( !port) { - error( RTMIDI_ERROR(gettext_noopt("Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI port. This doesn't work."), - Error::DRIVER_ERROR)); - return; - } - if ( connected_ ) { - error( RTMIDI_ERROR(gettext_noopt("We are overwriting an existing connection. This is probably a programming error."), - Error::WARNING) ); - return; - } - if (port->getCapabilities() != PortDescriptor::INPUT) { - error(RTMIDI_ERROR(gettext_noopt("Trying to open a non-input port as input MIDI port. This doesn't work."), - Error::DRIVER_ERROR)); - return; - } - - // there is a possible race condition between opening the port and - // reordering of ports so we must check whether we opened the right port. - try { - openPort(port->getPortNumber(),portName); - } catch (Error e) { - error(e); - } - if (!port->is_valid()) { - closePort(); - error (RTMIDI_ERROR(gettext_noopt("Some change in the arrangement of MIDI input ports invalidated the port descriptor."), - Error::DRIVER_ERROR)); - return; - } - connected_ = true; - } - - Pointer MidiInWinMM :: getDescriptor(bool local) - { - if (local || !connected_) return 0; - WinMidiData *data = static_cast (apiData_); - if (!data) return 0; - UINT devid; - switch (midiInGetID(data->inHandle,&devid)) { - case MMSYSERR_INVALHANDLE: - error (RTMIDI_ERROR(gettext_noopt("The handle is invalid. Did you disconnect the device?"), - Error::DRIVER_ERROR)); - return 0; - case MMSYSERR_NODRIVER: - error (RTMIDI_ERROR(gettext_noopt("The system has no driver for our handle :-(. Did you disconnect the device?"), - Error::DRIVER_ERROR)); - return 0; - case MMSYSERR_NOMEM: - error (RTMIDI_ERROR(gettext_noopt("Out of memory."), - Error::DRIVER_ERROR)); - return 0; - } - return new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); - try { - retval = new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); - } catch (Error e) { - try { - error(e); - } catch (...) { - if (retval) delete retval; - throw; - } - } - - } - - PortList MidiInWinMM :: getPortList(int capabilities) - { - WinMidiData *data = static_cast (apiData_); - if (!data || capabilities != PortDescriptor::INPUT) return PortList(); - try { - return WinMMPortDescriptor::getPortList(PortDescriptor::INPUT,data->getClientName()); - } catch (Error e) { - error(e); - return PortList(); - } - } - - - void MidiInWinMM :: closePort( void ) - { - if ( connected_ ) { - WinMidiData *data = static_cast (apiData_); - EnterCriticalSection( &(data->_mutex) ); - midiInReset( data->inHandle ); - midiInStop( data->inHandle ); - - for ( int i=0; iinHandle, data->sysexBuffer[i], sizeof(MIDIHDR)); - delete [] data->sysexBuffer[i]->lpData; - delete [] data->sysexBuffer[i]; - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - error(RTMIDI_ERROR(gettext_noopt("Error closing Windows MM MIDI input port."), - Error::DRIVER_ERROR) ); - return; - } - } - - midiInClose( data->inHandle ); - connected_ = false; - LeaveCriticalSection( &(data->_mutex) ); - } - } - - unsigned int MidiInWinMM :: getPortCount() - { - return midiInGetNumDevs(); - } - - std::string MidiInWinMM :: getPortName( unsigned int portNumber ) - { - std::string stringName; - unsigned int nDevices = midiInGetNumDevs(); - if ( portNumber >= nDevices ) { - error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), - Error::WARNING,portNumber)); - return stringName; - } - - MIDIINCAPS deviceCaps; - midiInGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIINCAPS)); - -#if defined( UNICODE ) || defined( _UNICODE ) - int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; - stringName.assign( length, 0 ); - length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); -#else - stringName = std::string( deviceCaps.szPname ); -#endif - - // 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 - std::ostringstream os; - os << " "; - os << portNumber; - stringName += os.str(); - - return stringName; - } -#undef RTMIDI_CLASSNAME - - - //*********************************************************************// - // API: Windows MM - // Class Definitions: MidiOutWinMM - //*********************************************************************// - -#define RTMIDI_CLASSNAME "MidiOutWinMM" - MidiOutWinMM :: MidiOutWinMM( const std::string clientName ) : MidiOutApi() - { - initialize( clientName ); - } - - MidiOutWinMM :: ~MidiOutWinMM() - { - // Close a connection if it exists. - closePort(); - - // Cleanup. - WinMidiData *data = static_cast (apiData_); - delete data; - } - - void MidiOutWinMM :: initialize( const std::string& clientName ) - { - // We'll issue a warning here if no devices are available but not - // throw an error since the user can plug something in later. - unsigned int nDevices = midiOutGetNumDevs(); - if ( nDevices == 0 ) { - error(RTMIDI_ERROR(gettext_noopt("No MIDI output devices currently available."), - Error::WARNING)); - } - - // Save our api-specific connection information. - WinMidiData *data = (WinMidiData *) new WinMidiData(clientName); - apiData_ = (void *) data; - } - - unsigned int MidiOutWinMM :: getPortCount() - { - return midiOutGetNumDevs(); - } - - std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) - { - std::string stringName; - unsigned int nDevices = midiOutGetNumDevs(); - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiOutWinMM::getPortName: "; - errorString_ = ost.str(); - error(RTMIDI_ERROR(gettext_noopt("The 'portNumber' argument (%d) is invalid."), - Error::WARNING)); - return stringName; - } - - MIDIOUTCAPS deviceCaps; - midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS)); - -#if defined( UNICODE ) || defined( _UNICODE ) - int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; - stringName.assign( length, 0 ); - length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); -#else - stringName = std::string( deviceCaps.szPname ); -#endif - - return stringName; - } - - void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string & /*portName*/ ) - { - if ( connected_ ) { - error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), - Error::WARNING) ); - return; - } - - unsigned int nDevices = midiOutGetNumDevs(); - if (nDevices < 1) { - error(RTMIDI_ERROR(gettext_noopt("No MIDI output destinations found!"), - Error::NO_DEVICES_FOUND) ); - return; - } - - if ( portNumber >= nDevices ) { - error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), - Error::INVALID_PARAMETER, portNumber) ); - return; - } - - WinMidiData *data = static_cast (apiData_); - MMRESULT result = midiOutOpen( &data->outHandle, - portNumber, - (DWORD)NULL, - (DWORD)NULL, - CALLBACK_NULL ); - if ( result != MMSYSERR_NOERROR ) { - error(RTMIDI_ERROR(gettext_noopt("Error creating Windows MM MIDI output port."), - Error::DRIVER_ERROR) ); - return; - } - - connected_ = true; - } - - void MidiOutWinMM :: closePort( void ) - { - if ( connected_ ) { - WinMidiData *data = static_cast (apiData_); - midiOutReset( data->outHandle ); - midiOutClose( data->outHandle ); - connected_ = false; - } - } - - void MidiOutWinMM :: openVirtualPort( std::string /*portName*/ ) - { - // This function cannot be implemented for the Windows MM MIDI API. - error(RTMIDI_ERROR(gettext_noopt("Virtual ports are not available Windows Multimedia MIDI API."), - Error::WARNING) ); - } - - - void MidiOutWinMM :: openPort(const PortDescriptor & p, const std::string & portName) { - const WinMMPortDescriptor * port = dynamic_cast (&p); - if ( !port) { - error( RTMIDI_ERROR(gettext_noopt("Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI port. This doesn't work."), - Error::DRIVER_ERROR)); - return; - } - if ( connected_ ) { - error( RTMIDI_ERROR(gettext_noopt("A valid connection already exists." ), - Error::WARNING) ); - return; - } - if (port->getCapabilities() != PortDescriptor::OUTPUT) { - error( RTMIDI_ERROR(gettext_noopt("The port descriptor cannot be used to open an output port."), - Error::DRIVER_ERROR)); - return; - } - - // there is a possible race condition between opening the port and - // reordering of ports so we must check whether we opened the right port. - try { - openPort(port->getPortNumber(),portName); - } catch (Error e) { - error(e); - } - if (!port->is_valid()) { - closePort(); - error (RTMIDI_ERROR(gettext_noopt("Some change in the arrangement of MIDI input ports invalidated the port descriptor."), - Error::DRIVER_ERROR)); - return; - } - connected_ = true; - } - - Pointer MidiOutWinMM :: getDescriptor(bool local) - { - if (local || !connected_) return 0; - WinMidiData *data = static_cast (apiData_); - if (!data) return 0; - UINT devid; - switch (midiOutGetID(data->outHandle,&devid)) { - case MMSYSERR_INVALHANDLE: - error (RTMIDI_ERROR(gettext_noopt("The internal handle is invalid. Did you disconnect the device?"), - Error::DRIVER_ERROR)); - return 0; - case MMSYSERR_NODRIVER: - error (RTMIDI_ERROR(gettext_noopt("The system has no driver for our handle :-(. Did you disconnect the device?"), - Error::DRIVER_ERROR)); - return 0; - case MMSYSERR_NOMEM: - error (RTMIDI_ERROR(gettext_noopt("Out of memory."), - Error::DRIVER_ERROR)); - return 0; - } - return new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); - - } - - PortList MidiOutWinMM :: getPortList(int capabilities) - { - WinMidiData *data = static_cast (apiData_); - if (!data || capabilities != PortDescriptor::OUTPUT) return PortList(); - try { - return WinMMPortDescriptor::getPortList(PortDescriptor::OUTPUT,data->getClientName()); - } catch (Error e) { - error(e); - return PortList(); - } - } - - - void MidiOutWinMM :: sendMessage( std::vector &message ) - { - if ( !connected_ ) return; - - unsigned int nBytes = static_cast(message.size()); - if ( nBytes == 0 ) { - error(RTMIDI_ERROR(gettext_noopt("Message argument is empty."), - Error::WARNING)); - return; - } - - MMRESULT result; - WinMidiData *data = static_cast (apiData_); - if ( message.at(0) == 0xF0 ) { // Sysex message - - // Allocate buffer for sysex data. - char *buffer = (char *) malloc( nBytes ); - if ( buffer == NULL ) { - error(RTMIDI_ERROR(gettext_noopt("Error while allocating sysex message memory."), - Error::MEMORY_ERROR) ); - return; - } - - // Copy data to buffer. - for ( unsigned int i=0; ioutHandle, &sysex, sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - free( buffer ); - error(RTMIDI_ERROR(gettext_noopt("Error preparing sysex header."), - Error::DRIVER_ERROR)); - return; - } - - // Send the message. - result = midiOutLongMsg( data->outHandle, &sysex, sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - free( buffer ); - error(RTMIDI_ERROR(gettext_noopt("Error sending sysex message."), - Error::DRIVER_ERROR) ); - return; - } - - // Unprepare the buffer and MIDIHDR. - while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof (MIDIHDR) ) ) Sleep( 1 ); - free( buffer ); - } - else { // Channel or system message. - - // Make sure the message size isn't too big. - if ( nBytes > 3 ) { - error(RTMIDI_ERROR(gettext_noopt("Message size is greater than 3 bytes (and not sysex)."), - Error::WARNING) ); - return; - } - - // Pack MIDI bytes into double word. - DWORD packet; - unsigned char *ptr = (unsigned char *) &packet; - for ( unsigned int i=0; ioutHandle, packet ); - if ( result != MMSYSERR_NOERROR ) { - error(RTMIDI_ERROR(gettext_noopt("Error sending MIDI message."), - Error::DRIVER_ERROR )); - } - } - } -#undef RTMIDI_CLASSNAME -} -#endif // __WINDOWS_MM__ - - - //*********************************************************************// - // API: UNIX JACK - // - // Written primarily by Alexander Svetalkin, with updates for delta - // time by Gary Scavone, April 2011. - // - // *********************************************************************// struct WinMMPortDescriptor:public PortDescriptor { @@ -4884,7 +4200,7 @@ void MidiInWinMM :: openPort(const PortDescriptor & p, const std::string & portN const WinMMPortDescriptor * port = dynamic_cast (&p); if ( !port) { error( RTMIDI_ERROR(gettext_noopt("Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI port. This doesn't work."), - Error::DRIVER_ERROR)); + Error::INVALID_DEVICE)); return; } if ( connected_ ) { @@ -4894,13 +4210,17 @@ void MidiInWinMM :: openPort(const PortDescriptor & p, const std::string & portN } if (port->getCapabilities() != PortDescriptor::INPUT) { error(RTMIDI_ERROR(gettext_noopt("Trying to open a non-input port as input MIDI port. This doesn't work."), - Error::DRIVER_ERROR)); + Error::INVALID_DEVICE)); return; } // there is a possible race condition between opening the port and // reordering of ports so we must check whether we opened the right port. - openPort(port->getPortNumber(),portName); + try { + openPort(port->getPortNumber(),portName); + } catch (Error e) { + error(e); + } if (!port->is_valid()) { closePort(); error (RTMIDI_ERROR(gettext_noopt("Some change in the arrangement of MIDI input ports invalidated the port descriptor."), @@ -4931,6 +4251,16 @@ Pointer MidiInWinMM :: getDescriptor(bool local) return 0; } return new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); + try { + retval = new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); + } catch (Error e) { + try { + error(e); + } catch (...) { + if (retval) delete retval; + throw; + } + } } @@ -4938,7 +4268,12 @@ PortList MidiInWinMM :: getPortList(int capabilities) { WinMidiData *data = static_cast (apiData_); if (!data || capabilities != PortDescriptor::INPUT) return PortList(); - return WinMMPortDescriptor::getPortList(PortDescriptor::INPUT,data->getClientName()); + try { + return WinMMPortDescriptor::getPortList(PortDescriptor::INPUT,data->getClientName()); + } catch (Error e) { + error(e); + return PortList(); + } } @@ -5134,7 +4469,7 @@ void MidiOutWinMM :: openPort(const PortDescriptor & p, const std::string & port const WinMMPortDescriptor * port = dynamic_cast (&p); if ( !port) { error( RTMIDI_ERROR(gettext_noopt("Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI port. This doesn't work."), - Error::DRIVER_ERROR)); + Error::INVALID_DEVICE)); return; } if ( connected_ ) { @@ -5150,7 +4485,11 @@ void MidiOutWinMM :: openPort(const PortDescriptor & p, const std::string & port // there is a possible race condition between opening the port and // reordering of ports so we must check whether we opened the right port. - openPort(port->getPortNumber(),portName); + try { + openPort(port->getPortNumber(),portName); + } catch (Error e) { + error(e); + } if (!port->is_valid()) { closePort(); error (RTMIDI_ERROR(gettext_noopt("Some change in the arrangement of MIDI input ports invalidated the port descriptor."), @@ -5188,7 +4527,12 @@ PortList MidiOutWinMM :: getPortList(int capabilities) { WinMidiData *data = static_cast (apiData_); if (!data || capabilities != PortDescriptor::OUTPUT) return PortList(); - return WinMMPortDescriptor::getPortList(PortDescriptor::OUTPUT,data->getClientName()); + try { + return WinMMPortDescriptor::getPortList(PortDescriptor::OUTPUT,data->getClientName()); + } catch (Error e) { + error(e); + return PortList(); + } } @@ -5273,17 +4617,6 @@ void MidiOutWinMM :: sendMessage( std::vector &message ) NAMESPACE_RTMIDI_END #endif // __WINDOWS_MM__ -void MidiInJack :: initialize( const std::string& clientName ) -{ - JackMidiData *data = new JackMidiData(clientName,inputData_); - apiData_ = (void *) data; - this->clientName = clientName; - try { - data->init(true); - } catch (Error e) { - error(e); - } -} //*********************************************************************// // API: UNIX JACK @@ -5300,23 +4633,7 @@ void MidiInJack :: initialize( const std::string& clientName ) #include #include -<<<<<<< HEAD #define JACK_RINGBUFFER_SIZE 16384 // Default size for ringbuffer -======= - MidiInJack :: ~MidiInJack() - { - JackMidiData *data = static_cast (apiData_); - try { - closePort(); - } catch (Error e) { - try { - delete data; - } catch (...) { - } - error(e); - return; - } ->>>>>>> e5dcd23... Hand over some error exceptions to the error function. NAMESPACE_RTMIDI_START @@ -5810,6 +5127,11 @@ void MidiInJack :: initialize( const std::string& clientName ) JackMidiData *data = new JackMidiData(clientName,inputData_); apiData_ = (void *) data; this->clientName = clientName; + try { + data->init(true); + } catch (Error e) { + error(e); + } } #if 0 @@ -5833,11 +5155,19 @@ void MidiInJack :: connect() } #endif -<<<<<<< HEAD MidiInJack :: ~MidiInJack() { JackMidiData *data = static_cast (apiData_); - closePort(); + try { + closePort(); + } catch (Error e) { + try { + delete data; + } catch (...) { + } + error(e); + return; + } #if 0 if ( data->client ) @@ -5850,50 +5180,6 @@ MidiInJack :: ~MidiInJack() void MidiInJack :: openPort( unsigned int portNumber, const std::string & portName ) { JackMidiData *data = static_cast (apiData_); -======= - try { - if (!data->local) - data->openPort (JackPortIsInput, - portName); - data->setRemote(*port); - data->connectPorts(*port,data->local); - } catch (Error e) { - error (e); - } - - } - - Pointer MidiInJack :: getDescriptor(bool local) - { - JackMidiData *data = static_cast (apiData_); - try { - if (local) { - if (data && data->local) { - return new JackPortDescriptor(data->local,data->getClientName()); - } - } else { - if (data && *data) { - return new JackPortDescriptor(*data,data->getClientName()); - } - } - } catch (Error e) { - error(e); - } - return NULL; - } - - PortList MidiInJack :: getPortList(int capabilities) - { - JackMidiData *data = static_cast (apiData_); - try { - return JackPortDescriptor::getPortList(capabilities | PortDescriptor::INPUT, - data->getClientName()); - } catch (Error e) { - error(e); - } - return PortList(); - } ->>>>>>> e5dcd23... Hand over some error exceptions to the error function. // connect(); @@ -5948,28 +5234,37 @@ void MidiInJack :: openPort( const PortDescriptor & p, #endif if (!port) { error(RTMIDI_ERROR(gettext_noopt("JACK has been instructed to open a non-JACK MIDI port. This doesn't work."), - Error::WARNING) ); + Error::INVALID_DEVICE) ); return; } - if (!data->local) - data->openPort (JackPortIsInput, - portName); - data->setRemote(*port); - data->connectPorts(*port,data->local); + try { + if (!data->local) + data->openPort (JackPortIsInput, + portName); + data->setRemote(*port); + data->connectPorts(*port,data->local); + } catch (Error e) { + error (e); + } + } Pointer MidiInJack :: getDescriptor(bool local) { JackMidiData *data = static_cast (apiData_); - if (local) { - if (data && data->local) { - return new JackPortDescriptor(data->local,data->getClientName()); - } - } else { - if (data && *data) { - return new JackPortDescriptor(*data,data->getClientName()); + try { + if (local) { + if (data && data->local) { + return new JackPortDescriptor(data->local,data->getClientName()); + } + } else { + if (data && *data) { + return new JackPortDescriptor(*data,data->getClientName()); + } } + } catch (Error e) { + error(e); } return NULL; } @@ -5977,8 +5272,13 @@ Pointer MidiInJack :: getDescriptor(bool local) PortList MidiInJack :: getPortList(int capabilities) { JackMidiData *data = static_cast (apiData_); - return JackPortDescriptor::getPortList(capabilities | PortDescriptor::INPUT, - data->getClientName()); + try { + return JackPortDescriptor::getPortList(capabilities | PortDescriptor::INPUT, + data->getClientName()); + } catch (Error e) { + error(e); + } + return PortList(); } unsigned int MidiInJack :: getPortCount() @@ -6207,76 +5507,38 @@ void MidiOutJack :: openPort( const PortDescriptor & p, return; } #endif -<<<<<<< HEAD if (!port) { error(RTMIDI_ERROR(gettext_noopt("JACK has been instructed to open a non-JACK MIDI port. This doesn't work."), - Error::WARNING) ); + Error::INVALID_DEVICE) ); return; } - if (!data->local) - data->openPort (JackPortIsOutput, - portName); - data->setRemote(*port); - data->connectPorts(data->local,*port); -======= - if (!port) { - error(RTMIDI_ERROR(gettext_noopt("JACK has been instructed to open a non-JACK MIDI port. This doesn't work."), - Error::WARNING) ); - return; - } - - try { - if (!data->local) - data->openPort (JackPortIsOutput, - portName); - data->setRemote(*port); - data->connectPorts(data->local,*port); - } catch (Error e) { - error(e); - } - } - - Pointer MidiOutJack :: getDescriptor(bool local) - { - JackMidiData *data = static_cast (apiData_); - try { - if (local) { - if (data && data->local) { - return new JackPortDescriptor(data->local,data->getClientName()); - } - } else { - if (data && *data) { - return new JackPortDescriptor(*data,data->getClientName()); - } - } - } catch (Error e) { - error(e); - } - return NULL; - } - - PortList MidiOutJack :: getPortList(int capabilities) - { - JackMidiData *data = static_cast (apiData_); - return JackPortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT, - data->getClientName()); - } ->>>>>>> e5dcd23... Hand over some error exceptions to the error function. - + try { + if (!data->local) + data->openPort (JackPortIsOutput, + portName); + data->setRemote(*port); + data->connectPorts(data->local,*port); + } catch (Error e) { + error(e); + } } Pointer MidiOutJack :: getDescriptor(bool local) { JackMidiData *data = static_cast (apiData_); - if (local) { - if (data && data->local) { - return new JackPortDescriptor(data->local,data->getClientName()); - } - } else { - if (data && *data) { - return new JackPortDescriptor(*data,data->getClientName()); + try { + if (local) { + if (data && data->local) { + return new JackPortDescriptor(data->local,data->getClientName()); + } + } else { + if (data && *data) { + return new JackPortDescriptor(*data,data->getClientName()); + } } + } catch (Error e) { + error(e); } return NULL; } From 1c1447b7541b2ee01c2b076ec45929d6a4d76768 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 30 Jul 2014 22:31:41 +0200 Subject: [PATCH 074/210] Use C++ to describe callbacks of the different kinds. --- RtMidi.cpp | 410 +++++++++++++++++++++++++++++------------------------ RtMidi.h | 126 ++++++++++++++-- 2 files changed, 341 insertions(+), 195 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 62567fe2..6cbf34aa 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -393,7 +393,7 @@ MidiOut :: ~MidiOut() throw() MidiApi :: MidiApi( void ) - : apiData_( 0 ), connected_( false ), errorCallback_(0), errorCallbackUserData_(0) + : apiData_( 0 ), connected_( false ), errorCallback_(0) { } @@ -403,10 +403,14 @@ MidiApi :: ~MidiApi( void ) void MidiApi :: setErrorCallback( ErrorCallback errorCallback, void *userData ) { - errorCallback_ = errorCallback; - errorCallbackUserData_ = userData; + errorCallback_ = new CompatibilityErrorInterface(errorCallback,userData); } +void MidiApi :: setErrorCallback(ErrorInterface * callback) { + errorCallback_ = callback; +} + + void MidiApi :: error(Error e) { if ( errorCallback_ ) { @@ -419,7 +423,7 @@ void MidiApi :: error(Error e) std::ostringstream s; e.printMessage(s); - errorCallback_( e.getType(), s.str(), errorCallbackUserData_ ); + errorCallback_->rtmidi_error(e); firstErrorOccured = false; return; } @@ -445,6 +449,7 @@ void MidiApi :: error(Error e) #define RTMIDI_CLASSNAME "MidiInApi" MidiInApi :: MidiInApi( unsigned int queueSizeLimit ) : MidiApi() + userCallback(0), { // Allocate the MIDI queue. inputData_.queue.ringSize = queueSizeLimit; @@ -460,7 +465,24 @@ MidiInApi :: ~MidiInApi( void ) void MidiInApi :: setCallback( MidiCallback callback, void *userData ) { - if ( inputData_.usingCallback ) { + if ( userCallback ) { + error(RTMIDI_ERROR(gettext_noopt("A callback function is already set."), + Error::WARNING)); + return; + } + + if ( !callback ) { + error(RTMIDI_ERROR(gettext_noopt("The callback function value is invalid."), + Error::WARNING)); + return; + } + + userCallback = new CompatibilityMidiInterface(callback,userData); +} + +void MidiInApi :: setCallback( MidiInterface * callback ) +{ + if ( userCallback ) { error(RTMIDI_ERROR(gettext_noopt("A callback function is already set."), Error::WARNING)); return; @@ -472,22 +494,18 @@ void MidiInApi :: setCallback( MidiCallback callback, void *userData ) return; } - inputData_.userCallback = callback; - inputData_.userData = userData; - inputData_.usingCallback = true; + userCallback = callback; } void MidiInApi :: cancelCallback() { - if ( !inputData_.usingCallback ) { + if ( !userCallback ) { error(RTMIDI_ERROR(gettext_noopt("No callback function was set."), Error::WARNING)); return; } - inputData_.userCallback = 0; - inputData_.userData = 0; - inputData_.usingCallback = false; + userCallback = 0; } void MidiInApi :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) @@ -502,7 +520,7 @@ double MidiInApi :: getMessage( std::vector &message ) { message.clear(); - if ( inputData_.usingCallback ) { + if ( userCallback ) { error(RTMIDI_ERROR(gettext_noopt("Returning an empty MIDI message as all input is handled by a callback function."), Error::WARNING)); return 0.0; @@ -2701,7 +2719,7 @@ struct AlsaMidiData:public AlsaPortDescriptor { pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_attr_setschedpolicy(&attr, SCHED_OTHER); - int err = pthread_create(&thread, &attr, alsaMidiHandler, userdata); + int err = pthread_create(&thread, &attr, MidiInAlsa::alsaMidiHandler, userdata); pthread_attr_destroy(&attr); if ( err ) { closePort(); @@ -2721,10 +2739,12 @@ struct AlsaMidiData:public AlsaPortDescriptor { // Class Definitions: MidiInAlsa //*********************************************************************// -static void *alsaMidiHandler( void *ptr ) +#define RTMIDI_CLASSNAME "" +// static function: +void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() { - MidiInApi::MidiInData *data = static_cast (ptr); - AlsaMidiData *apiData = static_cast (data->apiData); + MidiInAlsa *data = static_cast (ptr); + AlsaMidiData *apiData = static_cast (data->apiData_); long nBytes; unsigned long long time, lastTime; @@ -2889,9 +2909,8 @@ static void *alsaMidiHandler( void *ptr ) snd_seq_free_event( ev ); if ( message.bytes.size() == 0 || continueSysex ) continue; - if ( data->usingCallback ) { - MidiCallback callback = (MidiCallback) data->userCallback; - callback( message.timeStamp, &message.bytes, data->userData ); + if ( data->userCallback ) { + data->userCallback->rtmidi_midi_in( message.timeStamp, &message.bytes); } else { // As long as we haven't reached our queue size limit, push the message. @@ -2912,6 +2931,7 @@ static void *alsaMidiHandler( void *ptr ) apiData->thread = apiData->dummy_thread_id; return 0; } +#undef RTMIDI_CLASSNAME #define RTMIDI_CLASSNAME "MidiInAlsa" MidiInAlsa :: MidiInAlsa( const std::string clientName, @@ -3944,7 +3964,6 @@ PortList WinMMPortDescriptor :: getPortList(int capabilities, const std::string } - /*! A structure to hold variables related to the WINMM API implementation. @@ -3976,105 +3995,123 @@ struct WinMidiData:public WinMMPortDescriptor { // API: Windows MM // Class Definitions: MidiInWinMM //*********************************************************************// +#define RTMIDI_CLASSNAME "WinMMCallbacks" +//! Windows callbacks +/*! In order to avoid including too many header files in RtMidi.h, we use this + * class to callect all friend functions of Midi*WinMM. + */ +struct WinMMCallbacks { + static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, + UINT inputStatus, + DWORD_PTR instancePtr, + DWORD_PTR midiMessage, + DWORD timestamp ) + { + if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA && inputStatus != MIM_LONGERROR ) return; -static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, - UINT inputStatus, - DWORD_PTR instancePtr, - DWORD_PTR midiMessage, - DWORD timestamp ) -{ - if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA && inputStatus != MIM_LONGERROR ) return; - - //MidiInApi::MidiInData *data = static_cast (instancePtr); - MidiInApi::MidiInData *data = (MidiInApi::MidiInData *)instancePtr; - WinMidiData *apiData = static_cast (data->apiData); - - // Calculate time stamp. - if ( data->firstMessage == true ) { - apiData->message.timeStamp = 0.0; - data->firstMessage = false; - } - else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001; - apiData->lastTime = timestamp; - - if ( inputStatus == MIM_DATA ) { // Channel or system message - - // Make sure the first byte is a status byte. - unsigned char status = (unsigned char) (midiMessage & 0x000000FF); - if ( !(status & 0x80) ) return; - - // Determine the number of bytes in the MIDI message. - unsigned short nBytes = 1; - if ( status < 0xC0 ) nBytes = 3; - else if ( status < 0xE0 ) nBytes = 2; - else if ( status < 0xF0 ) nBytes = 3; - else if ( status == 0xF1 ) { - if ( data->ignoreFlags & 0x02 ) return; - else nBytes = 2; - } - else if ( status == 0xF2 ) nBytes = 3; - else if ( status == 0xF3 ) nBytes = 2; - else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) { - // A MIDI timing tick message and we're ignoring it. - return; - } - else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { - // A MIDI active sensing message and we're ignoring it. - return; + //MidiInApi::MidiInData *data = static_cast (instancePtr); + MidiInWinMM *data = (MidiInWinMM *)instancePtr; + WinMidiData *apiData = static_cast (data->apiData_); + + // Calculate time stamp. + if ( data->firstMessage == true ) { + apiData->message.timeStamp = 0.0; + data->firstMessage = false; } + else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001; + apiData->lastTime = timestamp; - // Copy bytes to our MIDI message. - unsigned char *ptr = (unsigned char *) &midiMessage; - for ( int i=0; imessage.bytes.push_back( *ptr++ ); - } - else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) - MIDIHDR *sysex = ( MIDIHDR *) midiMessage; - if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { - // Sysex message and we're not ignoring it - for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) - apiData->message.bytes.push_back( sysex->lpData[i] ); + if ( inputStatus == MIM_DATA ) { // Channel or system message + + // Make sure the first byte is a status byte. + unsigned char status = (unsigned char) (midiMessage & 0x000000FF); + if ( !(status & 0x80) ) return; + + // Determine the number of bytes in the MIDI message. + unsigned short nBytes = 1; + if ( status < 0xC0 ) nBytes = 3; + else if ( status < 0xE0 ) nBytes = 2; + else if ( status < 0xF0 ) nBytes = 3; + else if ( status == 0xF1 ) { + if ( data->ignoreFlags & 0x02 ) return; + else nBytes = 2; + } + else if ( status == 0xF2 ) nBytes = 3; + else if ( status == 0xF3 ) nBytes = 2; + else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) { + // A MIDI timing tick message and we're ignoring it. + return; + } + else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { + // A MIDI active sensing message and we're ignoring it. + return; + } + + // Copy bytes to our MIDI message. + unsigned char *ptr = (unsigned char *) &midiMessage; + for ( int i=0; imessage.bytes.push_back( *ptr++ ); } + else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) + MIDIHDR *sysex = ( MIDIHDR *) midiMessage; + if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { + // Sysex message and we're not ignoring it + for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) + apiData->message.bytes.push_back( sysex->lpData[i] ); + } - // The WinMM API requires that the sysex buffer be requeued after - // input of each sysex message. Even if we are ignoring sysex - // messages, we still need to requeue the buffer in case the user - // decides to not ignore sysex messages in the future. However, - // it seems that WinMM calls this function with an empty sysex - // buffer when an application closes and in this case, we should - // avoid requeueing it, else the computer suddenly reboots after - // one or two minutes. - if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { - //if ( sysex->dwBytesRecorded > 0 ) { - EnterCriticalSection( &(apiData->_mutex) ); - MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); - LeaveCriticalSection( &(apiData->_mutex) ); - if ( result != MMSYSERR_NOERROR ) - std::cerr << "\nMidiIn::midiInputCallback: error sending sysex to Midi device!!\n\n"; + // The WinMM API requires that the sysex buffer be requeued after + // input of each sysex message. Even if we are ignoring sysex + // messages, we still need to requeue the buffer in case the user + // decides to not ignore sysex messages in the future. However, + // it seems that WinMM calls this function with an empty sysex + // buffer when an application closes and in this case, we should + // avoid requeueing it, else the computer suddenly reboots after + // one or two minutes. + if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { + //if ( sysex->dwBytesRecorded > 0 ) { + EnterCriticalSection( &(apiData->_mutex) ); + MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); + LeaveCriticalSection( &(apiData->_mutex) ); + if ( result != MMSYSERR_NOERROR ){ + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error sending sysex to Midi device."), + Error::WARNING)); + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } + } - if ( data->ignoreFlags & 0x01 ) return; + if ( data->ignoreFlags & 0x01 ) return; + } + else return; } - else return; - } - if ( data->usingCallback ) { - MidiCallback callback = (MidiCallback) data->userCallback; - callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = apiData->message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; + if ( data->userCallback ) { + data->userCallback->rtmidi_midi_in( apiData->message.timeStamp, &apiData->message.bytes ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = apiData->message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else { + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + Error::WARNING)); + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } + } } - else - std::cerr << "\nMidiIn: message queue limit reached!!\n\n"; - } - // Clear the vector for the next input message. - apiData->message.bytes.clear(); -} + // Clear the vector for the next input message. + apiData->message.bytes.clear(); + } +}; +#undef RTMIDI_CLASSNAME #define RTMIDI_CLASSNAME "MidiInWinMM" MidiInWinMM :: MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) @@ -4143,8 +4180,8 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string & /*por WinMidiData *data = static_cast (apiData_); MMRESULT result = midiInOpen( &data->inHandle, portNumber, - (DWORD_PTR)&midiInputCallback, - (DWORD_PTR)&inputData_, + (DWORD_PTR)&WinMMCallbacks::midiInputCallback, + (DWORD_PTR)this, CALLBACK_FUNCTION ); if ( result != MMSYSERR_NOERROR ) { error(RTMIDI_ERROR(gettext_noopt("Error creating Windows MM MIDI input port."), @@ -4342,7 +4379,6 @@ std::string MidiInWinMM :: getPortName( unsigned int portNumber ) #undef RTMIDI_CLASSNAME - //*********************************************************************// // API: Windows MM // Class Definitions: MidiOutWinMM @@ -4638,8 +4674,10 @@ NAMESPACE_RTMIDI_END NAMESPACE_RTMIDI_START struct JackMidiData; -static int jackProcessIn( jack_nframes_t nframes, void *arg ); -static int jackProcessOut( jack_nframes_t nframes, void *arg ); +struct JackBackendCallbacks { + static int jackProcessIn( jack_nframes_t nframes, void *arg ); + static int jackProcessOut( jack_nframes_t nframes, void *arg ); +}; template class JackSequencer { @@ -4836,10 +4874,10 @@ class JackSequencer { } if (isoutput && data) { - jack_set_process_callback( client, jackProcessOut, data ); + jack_set_process_callback( c, JackBackendCallbacks::jackProcessOut, data ); } else if (data) - jack_set_process_callback( client, jackProcessIn, data ); - jack_activate( client ); + jack_set_process_callback( c, JackBackendCallbacks::jackProcessIn, data ); + jack_activate( c ); } } }; @@ -5056,6 +5094,7 @@ struct JackMidiData:public JackPortDescriptor { operator jack_port_t * () const { return port; } }; +#undef RTMIDI_CLASSNAME @@ -5064,10 +5103,11 @@ struct JackMidiData:public JackPortDescriptor { // Class Definitions: MidiInJack //*********************************************************************// -static int jackProcessIn( jack_nframes_t nframes, void *arg ) +#define RTMIDI_CLASSNAME "JackBackendCallbacks" +int JackBackendCallbacks::jackProcessIn( jack_nframes_t nframes, void *arg ) { JackMidiData *jData = (JackMidiData *) arg; - MidiInApi :: MidiInData *rtData = jData->rtMidiIn; + MidiInJack *rtData = jData->rtMidiIn; jack_midi_event_t event; jack_time_t time; @@ -5096,9 +5136,8 @@ static int jackProcessIn( jack_nframes_t nframes, void *arg ) jData->lastTime = time; if ( !rtData->continueSysex ) { - if ( rtData->usingCallback ) { - MidiCallback callback = (MidiCallback) rtData->userCallback; - callback( message.timeStamp, &message.bytes, rtData->userData ); + if ( rtData->userCallback ) { + rtData->userCallback->rtmidi_midi_in( message.timeStamp, &message.bytes); } else { // As long as we haven't reached our queue size limit, push the message. @@ -5117,6 +5156,69 @@ static int jackProcessIn( jack_nframes_t nframes, void *arg ) return 0; } +// Jack process callback +int JackBackendCallbacks::jackProcessOut( jack_nframes_t nframes, void *arg ) +{ + JackMidiData *data = (JackMidiData *) arg; + jack_midi_data_t *midiData; + int space; + + // Is port created? + if ( data->local == NULL ) return 0; + + void *buff = jack_port_get_buffer( data->local, nframes ); + if (buff != NULL) { + jack_midi_clear_buffer( buff ); + + while ( jack_ringbuffer_read_space( data->buffSize ) > 0 ) { + jack_ringbuffer_read( data->buffSize, (char *) &space, (size_t) sizeof(space) ); + midiData = jack_midi_event_reserve( buff, 0, space ); + + jack_ringbuffer_read( data->buffMessage, (char *) midiData, (size_t) space ); + } + } + + switch (data->stateflags) { + case JackMidiData::RUNNING: break; + case JackMidiData::CLOSING: + if (data->state_response != JackMidiData::CLOSING2) { + /* output the transferred data */ + data->state_response = JackMidiData::CLOSING2; + return 0; + } + if ( data->local == NULL ) break; + jack_port_unregister( *(data->seq), data->local ); + data->local = NULL; + data->state_response = JackMidiData::CLOSED; + break; + + case JackMidiData::DELETING: +#if defined(__RTMIDI_DEBUG__) + std::cerr << "deleting port" << std::endl; +#endif + if (data->state_response != JackMidiData::DELETING2) { + data->state_response = JackMidiData::DELETING2; + /* output the transferred data */ + return 0; + } + + if (data->local != NULL && data->state_response != JackMidiData::DELETING2) { + data->stateflags = JackMidiData::CLOSING; + jack_port_unregister( *(data->seq), data->local ); + data->local = NULL; + data->state_response = JackMidiData::DELETING2; + return 0; + } + delete data; +#if defined(__RTMIDI_DEBUG__) + std::cerr << "deleted port" << std::endl; +#endif + break; + } + + return 0; +} +#undef RTMIDI_CLASSNAME MidiInJack :: MidiInJack( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { initialize( clientName ); @@ -5344,68 +5446,6 @@ void MidiInJack :: closePort() // Class Definitions: MidiOutJack //*********************************************************************// -// Jack process callback -static int jackProcessOut( jack_nframes_t nframes, void *arg ) -{ - JackMidiData *data = (JackMidiData *) arg; - jack_midi_data_t *midiData; - int space; - - // Is port created? - if ( data->local == NULL ) return 0; - - void *buff = jack_port_get_buffer( data->local, nframes ); - if (buff != NULL) { - jack_midi_clear_buffer( buff ); - - while ( jack_ringbuffer_read_space( data->buffSize ) > 0 ) { - jack_ringbuffer_read( data->buffSize, (char *) &space, (size_t) sizeof(space) ); - midiData = jack_midi_event_reserve( buff, 0, space ); - - jack_ringbuffer_read( data->buffMessage, (char *) midiData, (size_t) space ); - } - } - - switch (data->stateflags) { - case JackMidiData::RUNNING: break; - case JackMidiData::CLOSING: - if (data->state_response != JackMidiData::CLOSING2) { - /* output the transferred data */ - data->state_response = JackMidiData::CLOSING2; - return 0; - } - if ( data->local == NULL ) break; - jack_port_unregister( *(data->seq), data->local ); - data->local = NULL; - data->state_response = JackMidiData::CLOSED; - break; - - case JackMidiData::DELETING: -#if defined(__RTMIDI_DEBUG__) - std::cerr << "deleting port" << std::endl; -#endif - if (data->state_response != JackMidiData::DELETING2) { - data->state_response = JackMidiData::DELETING2; - /* output the transferred data */ - return 0; - } - - if (data->local != NULL && data->state_response != JackMidiData::DELETING2) { - data->stateflags = JackMidiData::CLOSING; - jack_port_unregister( *(data->seq), data->local ); - data->local = NULL; - data->state_response = JackMidiData::DELETING2; - return 0; - } - delete data; -#if defined(__RTMIDI_DEBUG__) - std::cerr << "deleted port" << std::endl; -#endif - break; - } - - return 0; -} MidiOutJack :: MidiOutJack( const std::string clientName ) : MidiOutApi() { diff --git a/RtMidi.h b/RtMidi.h index 34ba1207..f9c4ec86 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -85,7 +85,7 @@ void init_rtmidi_gettext(); #endif //! MIDI API specifier arguments. - enum ApiType { +enum ApiType { UNSPECIFIED, /*!< Search for a working compiled API. */ MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ @@ -111,16 +111,62 @@ inline std::string getApiName(ApiType type) { return ""; } -//! User callback function type definition. +//! C style user callback function type definition. /*! + This interface type has been replaced by a MidiInterface class. + \param timeStamp timestamp indicating when the event has been received \param message a pointer to the binary MIDI message \param userData a pointer that can be set using setUserdata \sa MidiIn \sa MidiInApi + \sa MidiInterface + \deprecated */ typedef void (*MidiCallback)( double timeStamp, std::vector *message, void *userData); +//! C++ style user callback interface. +/*! + This interface class can be used to implement type safe MIDI callbacks. + Every time a MIDI message is received the function \ref MidiInterface::rtmidi_midi_in of the + currently set callback object is called. +*/ +struct MidiInterface { + //! Virtual destructor to avoid unexpected behaviour. + virtual ~MidiInterface() {} + + //! The MIDI callback function. + /*! This function is called whenever a MIDI packet is received by a + MIDI backend that uses the corresponding callback object. + \param timestamp the timestamp when the MIDI message has been received + \param message the message itself. + */ + virtual void rtmidi_midi_in(double timestamp, std::vector *message) = 0; + + //! Delete the object if necessary. + /*! This function allows the user to delete the Midi callback object, + when MIDI backend drops its reference to it. By default it does nothing. + But, callback objects are owned by the MIDI backend. These must be deleted + after the reference to them has been dropped. + + \sa CompatibilityMidiInterface + */ + virtual void delete_me() {} +}; + +//! Compatibility interface to hold a C style callback function +struct CompatibilityMidiInterface: MidiInterface { + CompatibilityMidiInterface(MidiCallback cb, void * ud): + callback(cb), + userData(ud) {} + void rtmidi_midi_in(double timestamp, std::vector *message) { + callback (timestamp, message, userData); + } + void delete_me() { delete this; } + MidiCallback callback; + void * userData; +}; + /************************************************************************/ /*! \class Error \brief Exception handling class for RtMidi. @@ -203,6 +249,24 @@ class Error : public std::exception a warning) is reported. */ typedef void (*ErrorCallback)( Error::Type type, const std::string &errorText, void * userdata ); +struct ErrorInterface { + virtual ~ErrorInterface() {} + virtual void rtmidi_error (Error e) = 0; + virtual void delete_me() {}; +}; + +struct CompatibilityErrorInterface: ErrorInterface { + CompatibilityErrorInterface(ErrorCallback cb, void * ud): callback(cb), + userdata(ud) {} + void rtmidi_error(Error e) { + callback(e.getType(),e.getMessage(),userdata); + } + + void delete_me() { delete this; } +private: + ErrorCallback callback; + void * userdata; +}; @@ -527,12 +591,22 @@ class MidiApi */ bool isPortOpen() const { return connected_; } - //! Pure virtual function to set an error callback function to be invoked when an error has occured. + //! Virtual function to set an error callback function to be invoked when an error has occured. /*! The callback function will be called whenever an error has occured. It is best to set the error callback function before opening a port. */ - virtual void setErrorCallback( ErrorCallback errorCallback = NULL, void * userData = 0 ); + RTMIDI_DEPRECATED(virtual void setErrorCallback( ErrorCallback errorCallback = NULL, void * userData = 0 )); + + //! Virtual function to set the error callback object + /*! + Everytime an error is detected or a warning is issued the function + \r ErrorInterface::rtmidi_error of the callback object is called with an error object + that describes the situation. + + \param callback An objact that provides an ErrorInterface. + */ + virtual void setErrorCallback(ErrorInterface * callback); //! Returns the MIDI API specifier for the current instance of RtMidiIn. @@ -547,8 +621,7 @@ class MidiApi void *apiData_; bool connected_; std::string errorString_; - ErrorCallback errorCallback_; - void * errorCallbackUserData_; + ErrorInterface * errorCallback_; }; #undef RTMIDI_CLASSNAME @@ -559,7 +632,8 @@ class MidiInApi : public MidiApi MidiInApi( unsigned int queueSizeLimit ); virtual ~MidiInApi( void ); - void setCallback( MidiCallback callback, void *userData = 0 ); + RTMIDI_DEPRECATED(void setCallback( MidiCallback callback, void *userData = 0 )); + void setCallback( MidiInterface * callback); void cancelCallback( void ); virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); RTMIDI_DEPRECATED(double getMessage( std::vector *message )) @@ -605,7 +679,6 @@ class MidiInApi : public MidiApi bool firstMessage; void *apiData; bool usingCallback; - MidiCallback userCallback; void *userData; bool continueSysex; @@ -618,6 +691,8 @@ class MidiInApi : public MidiApi protected: MidiInData inputData_; + MidiInterface * userCallback; + friend struct JackBackendCallbacks; }; #undef RTMIDI_CLASSNAME @@ -833,11 +908,21 @@ class Midi { The callback function will be called whenever an error has occured. It is best to set the error callback function before opening a port. */ - void setErrorCallback( ErrorCallback errorCallback = NULL, void * userData = 0 ) + RTMIDI_DEPRECATED(void setErrorCallback( ErrorCallback errorCallback = NULL, void * userData = 0 )) { if (rtapi_) rtapi_->setErrorCallback(errorCallback, userData); } + //! Pure virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + void setErrorCallback( ErrorInterface * callback) + { + if (rtapi_) rtapi_->setErrorCallback(callback); + } + //! A basic error reporting function for RtMidi classes. void error( Error e ); protected: @@ -1015,12 +1100,29 @@ class MidiIn : public Midi \param userData Opitionally, a pointer to additional data can be passed to the callback function whenever it is called. */ - void setCallback( MidiCallback callback, void *userData = 0 ) + RTMIDI_DEPRECATED(void setCallback( MidiCallback callback, void *userData = 0 )) { if (rtapi_) static_cast(rtapi_)->setCallback(callback,userData); } + //! Set a callback function to be invoked for incoming MIDI messages. + /*! + The callback function will be called whenever an incoming MIDI + message is received. While not absolutely necessary, it is best + to set the callback function before opening a MIDI port to avoid + leaving some messages in the queue. + + \param callback A callback function must be given. + \param userData Opitionally, a pointer to additional data can be + passed to the callback function whenever it is called. + */ + void setCallback( MidiInterface * callback ) + { + if (rtapi_) + static_cast(rtapi_)->setCallback(callback); + } + //! Cancel use of the current callback function (if one exists). /*! Subsequent incoming MIDI messages will be written to the queue @@ -1375,7 +1477,9 @@ class MidiInAlsa: public MidiInApi std::string getPortName( unsigned int portNumber ); protected: + static void * alsaMidiHandler( void *ptr ) throw(); void initialize( const std::string& clientName ); + friend class AlsaMidiData; }; class MidiOutAlsa: public MidiOutApi @@ -1421,6 +1525,8 @@ class MidiInWinMM: public MidiInApi protected: void initialize( const std::string& clientName ); + friend struct WinMMCallbacks; + }; class MidiOutWinMM: public MidiOutApi From 5927e234a3c0f963fe496248919e9ef3ded0824d Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 30 Jul 2014 22:35:39 +0200 Subject: [PATCH 075/210] Integrate inputData_ into MidiInApi. --- RtMidi.cpp | 88 +++++++++++++++++++++++++----------------------------- RtMidi.h | 27 +++++------------ 2 files changed, 47 insertions(+), 68 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 6cbf34aa..8857eb41 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -448,19 +448,20 @@ void MidiApi :: error(Error e) #define RTMIDI_CLASSNAME "MidiInApi" MidiInApi :: MidiInApi( unsigned int queueSizeLimit ) - : MidiApi() + : MidiApi(), ignoreFlags(7), doInput(false), firstMessage(true), userCallback(0), + continueSysex(false) { // Allocate the MIDI queue. - inputData_.queue.ringSize = queueSizeLimit; - if ( inputData_.queue.ringSize > 0 ) - inputData_.queue.ring = new MidiMessage[ inputData_.queue.ringSize ]; + queue.ringSize = queueSizeLimit; + if ( queue.ringSize > 0 ) + queue.ring = new MidiMessage[ queue.ringSize ]; } MidiInApi :: ~MidiInApi( void ) { // Delete the MIDI queue. - if ( inputData_.queue.ringSize > 0 ) delete [] inputData_.queue.ring; + if ( queue.ringSize > 0 ) delete [] queue.ring; } void MidiInApi :: setCallback( MidiCallback callback, void *userData ) @@ -510,10 +511,10 @@ void MidiInApi :: cancelCallback() void MidiInApi :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) { - inputData_.ignoreFlags = 0; - if ( midiSysex ) inputData_.ignoreFlags = 0x01; - if ( midiTime ) inputData_.ignoreFlags |= 0x02; - if ( midiSense ) inputData_.ignoreFlags |= 0x04; + ignoreFlags = 0; + if ( midiSysex ) ignoreFlags = 0x01; + if ( midiTime ) ignoreFlags |= 0x02; + if ( midiSense ) ignoreFlags |= 0x04; } double MidiInApi :: getMessage( std::vector &message ) @@ -526,16 +527,16 @@ double MidiInApi :: getMessage( std::vector &message ) return 0.0; } - if ( inputData_.queue.size == 0 ) return 0.0; + if ( queue.size == 0 ) return 0.0; // Copy queued message to the vector pointer argument and then "pop" it. - std::vector *bytes = &(inputData_.queue.ring[inputData_.queue.front].bytes); + std::vector *bytes = &(queue.ring[queue.front].bytes); message.assign( bytes->begin(), bytes->end() ); - double deltaTime = inputData_.queue.ring[inputData_.queue.front].timeStamp; - inputData_.queue.size--; - inputData_.queue.front++; - if ( inputData_.queue.front == inputData_.queue.ringSize ) - inputData_.queue.front = 0; + double deltaTime = queue.ring[queue.front].timeStamp; + queue.size--; + queue.front++; + if ( queue.front == queue.ringSize ) + queue.front = 0; return deltaTime; } @@ -1693,7 +1694,6 @@ void MidiInCore :: initialize( const std::string& clientName ) // Save our api-specific connection information. CoreMidiData *data = (CoreMidiData *) new CoreMidiData(clientName); apiData_ = (void *) data; - inputData_.apiData = (void *) data; } void MidiInCore :: openPort( unsigned int portNumber, @@ -2947,9 +2947,9 @@ MidiInAlsa :: ~MidiInAlsa() // Shutdown the input thread. AlsaMidiData *data = static_cast (apiData_); - if ( inputData_.doInput ) { - inputData_.doInput = false; - int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput) ); + if ( doInput ) { + doInput = false; + int res = write( data->trigger_fds[1], &doInput, sizeof(doInput) ); (void) res; if ( !pthread_equal(data->thread, data->dummy_thread_id) ) pthread_join( data->thread, NULL ); @@ -2970,14 +2970,7 @@ void MidiInAlsa :: initialize( const std::string& clientName ) // Save our api-specific connection information. AlsaMidiData *data = new AlsaMidiData (clientName); - // Set client name. - - - - //data->seq = seq; - // data->portNum = -1; apiData_ = (void *) data; - inputData_.apiData = (void *) data; if ( pipe(data->trigger_fds) == -1 ) { error(RTMIDI_ERROR(gettext_noopt("Error creating pipe objects."), @@ -3144,7 +3137,7 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string & portNa } } - if ( inputData_.doInput == false ) { + if ( doInput == false ) { // Start the input queue #ifndef AVOID_TIMESTAMPING snd_seq_start_queue( data->seq, data->queue_id, NULL ); @@ -3156,14 +3149,14 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string & portNa pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_attr_setschedpolicy(&attr, SCHED_OTHER); - inputData_.doInput = true; - int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_); + doInput = true; + int err = pthread_create(&data->thread, &attr, alsaMidiHandler, this); pthread_attr_destroy(&attr); if ( err ) { snd_seq_unsubscribe_port( data->seq, data->subscription ); snd_seq_port_subscribe_free( data->subscription ); data->subscription = 0; - inputData_.doInput = false; + doInput = false; error( RTMIDI_ERROR(gettext_noopt("Error starting MIDI input thread!"), Error::THREAD_ERROR) ); return; @@ -3285,7 +3278,7 @@ void MidiInAlsa :: openVirtualPort( std::string portName ) data->local.client = snd_seq_port_info_get_client(pinfo); } - if ( inputData_.doInput == false ) { + if ( doInput == false ) { // Wait for old thread to stop, if still running if ( !pthread_equal(data->thread, data->dummy_thread_id) ) pthread_join( data->thread, NULL ); @@ -3301,8 +3294,8 @@ void MidiInAlsa :: openVirtualPort( std::string portName ) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_attr_setschedpolicy(&attr, SCHED_OTHER); - inputData_.doInput = true; - int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_); + doInput = true; + int err = pthread_create(&data->thread, &attr, alsaMidiHandler, this); pthread_attr_destroy(&attr); if ( err ) { if ( data->subscription ) { @@ -3310,7 +3303,7 @@ void MidiInAlsa :: openVirtualPort( std::string portName ) snd_seq_port_subscribe_free( data->subscription ); data->subscription = 0; } - inputData_.doInput = false; + doInput = false; error( RTMIDI_ERROR(gettext_noopt("Error starting MIDI input thread!"), Error::THREAD_ERROR) ); return; @@ -3337,9 +3330,9 @@ void MidiInAlsa :: closePort( void ) } // Stop thread to avoid triggering the callback, while the port is intended to be closed - if ( inputData_.doInput ) { - inputData_.doInput = false; - int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput) ); + if ( doInput ) { + doInput = false; + int res = write( data->trigger_fds[1], &doInput, sizeof(doInput) ); (void) res; if ( !pthread_equal(data->thread, data->dummy_thread_id) ) pthread_join( data->thread, NULL ); @@ -4144,7 +4137,6 @@ void MidiInWinMM :: initialize( const std::string& clientName ) // Save our api-specific connection information. WinMidiData *data = (WinMidiData *) new WinMidiData(clientName); apiData_ = (void *) data; - inputData_.apiData = (void *) data; data->message.bytes.clear(); // needs to be empty for first input message if ( !InitializeCriticalSectionAndSpinCount(&(data->_mutex), 0x00000400) ) { @@ -5002,7 +4994,7 @@ struct JackMidiData:public JackPortDescriptor { jack_ringbuffer_t *buffSize; jack_ringbuffer_t *buffMessage; jack_time_t lastTime; - MidiInApi :: MidiInData *rtMidiIn; + MidiInJack *rtMidiIn; /*! Sequencer object: This must be deleted _before_ the MIDI data to avoid segmentation faults while queued data is still in the ring buffer. */ NonLockingJackSequencer * seq; @@ -5014,14 +5006,14 @@ struct JackMidiData:public JackPortDescriptor { } */ JackMidiData(const std::string &clientName, - MidiInApi :: MidiInData &inputData_):JackPortDescriptor(clientName), - stateflags(RUNNING), - local(0), - buffSize(0), - buffMessage(0), - lastTime(0), - rtMidiIn(&inputData_), - seq(new NonLockingJackSequencer(clientName,false,this)) + MidiInJack * inputData_):JackPortDescriptor(clientName), + stateflags(RUNNING), + local(0), + buffSize(0), + buffMessage(0), + lastTime(0), + rtMidiIn(inputData_), + seq(new NonLockingJackSequencer(clientName,this)) { } diff --git a/RtMidi.h b/RtMidi.h index f9c4ec86..2029578c 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -669,29 +669,16 @@ class MidiInApi : public MidiApi :front(0), back(0), size(0), ringSize(0) {} }; +protected: // The RtMidiInData structure is used to pass private class data to // the MIDI input handling function or thread. - struct MidiInData { - MidiQueue queue; - MidiMessage message; - unsigned char ignoreFlags; - bool doInput; - bool firstMessage; - void *apiData; - bool usingCallback; - void *userData; - bool continueSysex; - - // Default constructor. - MidiInData() - : ignoreFlags(7), doInput(false), firstMessage(true), - apiData(0), usingCallback(false), userCallback(0), userData(0), - continueSysex(false) {} - }; - -protected: - MidiInData inputData_; + MidiQueue queue; + MidiMessage message; + unsigned char ignoreFlags; + bool doInput; + bool firstMessage; MidiInterface * userCallback; + bool continueSysex; friend struct JackBackendCallbacks; }; #undef RTMIDI_CLASSNAME From 81faa710f83a5082cee868013df64a158876b6da Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 30 Jul 2014 22:38:46 +0200 Subject: [PATCH 076/210] Fix some error messages and documentation. --- RtMidi.cpp | 22 ++++++++++------------ RtMidi.h | 28 ++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 8857eb41..61177cf6 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -365,8 +365,8 @@ MidiOut :: MidiOut( ApiType api, const std::string clientName, bool pfsystem ) // No compiled support for specified API value. Issue a warning // and continue as if no API was specified. - throw RTMIDI_ERROR(gettext_noopt("Support for the selected MIDI system %d has not been compiled into the RtMidi library."), - Error::INVALID_PARAMETER, api); + throw RTMIDI_ERROR1(gettext_noopt("Support for the selected MIDI system %d has not been compiled into the RtMidi library."), + Error::INVALID_PARAMETER, api); } // Iterate through the compiled APIs and return as soon as we find @@ -3371,14 +3371,13 @@ void MidiOutAlsa :: initialize( const std::string& clientName ) snd_seq_t *seq; int result1 = snd_seq_open( &seq, "default", SND_SEQ_OPEN_OUTPUT, SND_SEQ_NONBLOCK ); if ( result1 < 0 ) { - errorString_ = "MidiOutAlsa::initialize: error creating ALSA sequencer client object."; - error(RTMIDI_ERROR(gettext_noopt(""), - Error::DRIVER_ERROR, errorString_ )); - return; - } + error(RTMIDI_ERROR(gettext_noopt("Error creating ALSA sequencer client object."), + Error::DRIVER_ERROR, errorString_ ); + return; + } - // Set client name. - snd_seq_set_client_name( seq, clientName.c_str() ); + // Set client name. + snd_seq_set_client_name( seq, clientName.c_str() ); #endif // Save our api-specific connection information. @@ -4861,7 +4860,7 @@ class JackSequencer { JackNoStartServer, NULL )) == 0) { throw RTMIDI_ERROR(gettext_noopt("Could not connect to JACK server. Is it runnig?"), - Error::WARNING); + Error::NO_DEVICES_FOUND); return; } @@ -4964,7 +4963,6 @@ PortList JackPortDescriptor :: getPortList(int capabilities, const std::string & jack_free(ports); return list; } - /*! A structure to hold variables related to the JACK API implementation. @@ -5218,7 +5216,7 @@ MidiInJack :: MidiInJack( const std::string clientName, unsigned int queueSizeLi void MidiInJack :: initialize( const std::string& clientName ) { - JackMidiData *data = new JackMidiData(clientName,inputData_); + JackMidiData *data = new JackMidiData(clientName,this); apiData_ = (void *) data; this->clientName = clientName; try { diff --git a/RtMidi.h b/RtMidi.h index 2029578c..5b58b51d 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -217,7 +217,7 @@ class Error : public std::exception //! Prints thrown error message to stderr. virtual void printMessage( std::ostream &s = std::cerr ) const throw() { s << std::endl - << file << ":" << line << ": in function" + << file << ":" << line << ": in function " << classname << "::" << function << std::endl << message_ << std::endl << std::endl; } @@ -379,7 +379,7 @@ class PortDescriptor { UNIQUE_NAME = 0x10, /*!< Make all names uniqe. This is usually done by adding numbers to the end of the - string \note: use #undef UNIQUE_NAME + string \note: use #undef UNIQUE_NAME on windows in case of any errors */ INCLUDE_API = 0x20 /*!< Add a string describing the API at the beginning of the @@ -613,6 +613,22 @@ class MidiApi virtual ApiType getCurrentApi( void ) throw() = 0; //! A basic error reporting function for RtMidi classes. + /*! This function hanles errors end warnings that + occur during runtime of RtMidi. If an error callback + has been set the function calls the callback and + returns quietly assuming the callback handled the + case correctly. + + Otherwise it depends on the type of the error. If it + is a warning, a message is displayed to + std::cerr. If it is an error the object is thrown as + an exception. + + \param e Error/Warning object describing the current + situation. + + \throw Error + */ void error( Error e ); protected: @@ -1546,8 +1562,8 @@ class MidiInDummy: public MidiInApi public: MidiInDummy( const std::string /*clientName*/, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { - errorString_ = "MidiInDummy: This class provides no functionality."; - error( Error::WARNING, errorString_ ); + error( RTMIDI_ERROR(_("MidiInDummy: This class provides no functionality."), + Error::WARNING) ); } ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } bool hasVirtualPorts() const { return false; } @@ -1568,8 +1584,8 @@ class MidiOutDummy: public MidiOutApi { public: MidiOutDummy( const std::string /*clientName*/ ) { - errorString_ = "MidiOutDummy: This class provides no functionality."; - error( Error::WARNING, errorString_ ); + error( RTMIDI_ERROR(_("MidiInDummy: This class provides no functionality."), + Error::WARNING) ); } ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } bool hasVirtualPorts() const { return false; } From 2ef2e0e1698526d9952c03e9c94fbf5c75dc6c5a Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 30 Jul 2014 22:41:12 +0200 Subject: [PATCH 077/210] Revise and add some error handling code. --- RtMidi.cpp | 181 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 138 insertions(+), 43 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 61177cf6..f685d2f2 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -158,6 +158,7 @@ void Midi :: getCompiledApi( std::vector &apis, bool preferSystem ) thr void Midi :: error(Error e) { + // use the callback if present. if (rtapi_) { rtapi_->error(e); @@ -1460,10 +1461,17 @@ PortList CorePortDescriptor :: getPortList(int capabilities, const std::string & for (ItemCount i = 0 ; i < count; i++) { MIDIEndpointRef destination = MIDIGetDestination(i); - if ((seq.getPortCapabilities(destination) - & caps) == caps) - list.push_back(new CorePortDescriptor(destination, - clientName)); + try { + if ((seq.getPortCapabilities(destination) + & caps) == caps) + list.push_back(new CorePortDescriptor(destination, + clientName)); + } catch (Error e) { + if (e.getType() == WARNING || + e.getType() == DEBUG_WARNING) + e.printMessage(); + else throw; + } } // Combined sources and destinations // should be both occur as destinations and as @@ -1474,10 +1482,17 @@ PortList CorePortDescriptor :: getPortList(int capabilities, const std::string & for (ItemCount i = 0 ; i < count; i++) { MIDIEndpointRef src = MIDIGetSource(i); - if ((seq.getPortCapabilities(src) - & caps) == caps) - list.push_back(new CorePortDescriptor(src, - clientName)); + try { + if ((seq.getPortCapabilities(src) + & caps) == caps) + list.push_back(new CorePortDescriptor(src, + clientName)); + } catch (Error e) { + if (e.getType() == WARNING || + e.getType() == DEBUG_WARNING) + e.printMessage(); + else throw; + } } } return list; @@ -1594,8 +1609,14 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void * data->queue.back = 0; data->queue.size++; } - else - std::cerr << "\nMidiInCore: message queue limit reached!!\n\n"; + else { + try { + apiData->error(RTMIDI_ERROR(_("Error: Message queue limit reached."), + Error::WARNING)); + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } + } } message.bytes.clear(); } @@ -1659,8 +1680,14 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void * data->queue.back = 0; data->queue.size++; } - else - std::cerr << "\nMidiInCore: message queue limit reached!!\n\n"; + else { + try { + apiData->error(RTMIDI_ERROR(_("Error: Message queue limit reached."), + Error::WARNING)); + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } + } } message.bytes.clear(); } @@ -1681,12 +1708,18 @@ MidiInCore :: MidiInCore( const std::string clientName, MidiInCore :: ~MidiInCore( void ) { - // Close a connection if it exists. - closePort(); - // Cleanup. CoreMidiData *data = static_cast (apiData_); + try { + // Close a connection if it exists. + closePort(); + + } catch (Error e) { + delete data; + throw; + } delete data; + } void MidiInCore :: initialize( const std::string& clientName ) @@ -2205,9 +2238,9 @@ NAMESPACE_RTMIDI_END #endif // __MACOSX_CORE__ -//*********************************************************************// -// API: LINUX ALSA SEQUENCER -//*********************************************************************// + //*********************************************************************// + // API: LINUX ALSA SEQUENCER + //*********************************************************************// // API information found at: // - http://www.alsa-project.org/documentation.php#Library @@ -2760,7 +2793,12 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() result = snd_midi_event_new( 0, &apiData->coder ); if ( result < 0 ) { data->doInput = false; - std::cerr << "\nMidiInAlsa::alsaMidiHandler: error initializing MIDI event parser!\n\n"; + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error initializing MIDI event parser."), + Error::WARNING)); + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } return 0; } unsigned char *buffer = (unsigned char *) malloc( apiData->bufferSize ); @@ -2768,7 +2806,12 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() data->doInput = false; snd_midi_event_free( apiData->coder ); apiData->coder = 0; - std::cerr << "\nMidiInAlsa::alsaMidiHandler: error initializing buffer memory!\n\n"; + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error initializing buffer memory."), + Error::WARNING)); + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } return 0; } snd_midi_event_init( apiData->coder ); @@ -2797,12 +2840,33 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() // If here, there should be data. result = snd_seq_event_input( apiData->seq, &ev ); if ( result == -ENOSPC ) { - std::cerr << "\nMidiInAlsa::alsaMidiHandler: MIDI input buffer overrun!\n\n"; + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("MIDI input buffer overrun."), + Error::WARNING)); + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } + + continue; + } + else if ( result == -EAGAIN ) { + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("ALSA returned without providing a MIDI event."), + Error::WARNING)); + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } + continue; } else if ( result <= 0 ) { - std::cerr << "\nMidiInAlsa::alsaMidiHandler: unknown MIDI input error!\n"; - perror("System reports"); + try { + data->error(RTMIDI_ERROR1(rtmidi_gettext("Unknown MIDI input error.\nThe system reports:\n%s"), + Error::WARNING, + strerror(-result))); + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } continue; } @@ -2854,7 +2918,12 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() buffer = (unsigned char *) malloc( apiData->bufferSize ); if ( buffer == NULL ) { data->doInput = false; - std::cerr << "\nMidiInAlsa::alsaMidiHandler: error resizing buffer memory!\n\n"; + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error resizing buffer memory."), + Error::WARNING)); + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } break; } } @@ -2900,7 +2969,12 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() } else { #if defined(__RTMIDI_DEBUG__) - std::cerr << "\nMidiInAlsa::alsaMidiHandler: event parsing error or not a MIDI event!\n\n"; + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Event parsing error or not a MIDI event."), + Error::WARNING)); + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } #endif } } @@ -2920,8 +2994,14 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() data->queue.back = 0; data->queue.size++; } - else - std::cerr << "\nMidiInAlsa: message queue limit reached!!\n\n"; + else { + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + Error::WARNING)); + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } + } } } @@ -3372,12 +3452,12 @@ void MidiOutAlsa :: initialize( const std::string& clientName ) int result1 = snd_seq_open( &seq, "default", SND_SEQ_OPEN_OUTPUT, SND_SEQ_NONBLOCK ); if ( result1 < 0 ) { error(RTMIDI_ERROR(gettext_noopt("Error creating ALSA sequencer client object."), - Error::DRIVER_ERROR, errorString_ ); - return; - } + Error::DRIVER_ERROR, errorString_ )); + return; + } - // Set client name. - snd_seq_set_client_name( seq, clientName.c_str() ); + // Set client name. + snd_seq_set_client_name( seq, clientName.c_str() ); #endif // Save our api-specific connection information. @@ -3640,10 +3720,15 @@ Pointer MidiOutAlsa :: getDescriptor(bool local) PortList MidiOutAlsa :: getPortList(int capabilities) { AlsaMidiData *data = static_cast (apiData_); - return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT, - data->getClientName()); + try { + return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT, + data->getClientName()); + } catch (Error e) { + return PortList(); + } } NAMESPACE_RTMIDI_END +#undef RTMIDI_CLASSNAME #endif // __LINUX_ALSA__ @@ -3843,6 +3928,7 @@ class WinMMSequencer { { // init (seq); } + }; // typedef WinMMSequencer<1> LockingWinMMSequencer; typedef WinMMSequencer<0> NonLockingWinMMSequencer; @@ -4278,7 +4364,7 @@ Pointer MidiInWinMM :: getDescriptor(bool local) Error::DRIVER_ERROR)); return 0; } - return new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); + WinMMPortDescriptor * retval = NULL; try { retval = new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); } catch (Error e) { @@ -4289,6 +4375,7 @@ Pointer MidiInWinMM :: getDescriptor(bool local) throw; } } + return retval; } @@ -4856,9 +4943,10 @@ class JackSequencer { if (c) return; { scoped_lock lock(mutex); - if (( client = jack_client_open( name.c_str(), - JackNoStartServer, - NULL )) == 0) { + if (( c = jack_client_open( name.c_str(), + JackNoStartServer, + NULL )) == 0) { + c = NULL; throw RTMIDI_ERROR(gettext_noopt("Could not connect to JACK server. Is it runnig?"), Error::NO_DEVICES_FOUND); return; @@ -4885,8 +4973,8 @@ struct JackPortDescriptor:public PortDescriptor } JackPortDescriptor(const char * portname, const std::string & name):api(0),clientName(name) { - port = seq.getPort(portname); seq.setName(name); + port = seq.getPort(portname); } JackPortDescriptor(jack_port_t * other, const std::string & name):api(0), @@ -4963,6 +5051,7 @@ PortList JackPortDescriptor :: getPortList(int capabilities, const std::string & jack_free(ports); return list; } + /*! A structure to hold variables related to the JACK API implementation. @@ -5137,8 +5226,14 @@ int JackBackendCallbacks::jackProcessIn( jack_nframes_t nframes, void *arg ) rtData->queue.back = 0; rtData->queue.size++; } - else - std::cerr << "\nMidiInJack: message queue limit reached!!\n\n"; + else { + try { + rtData->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + Error::WARNING)); + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } + } } } } @@ -5447,7 +5542,6 @@ void MidiOutJack :: initialize( const std::string& clientName ) JackMidiData *data = new JackMidiData(clientName); apiData_ = (void *) data; this->clientName = clientName; - // connect(); } @@ -5478,7 +5572,8 @@ MidiOutJack :: ~MidiOutJack() JackMidiData *data = static_cast (apiData_); // closePort(); - + // signal the output callback to delete the data + // after finishing its job. data->stateflags = JackMidiData::DELETING; } From 1ff3de50e0193e00d20bb0950d3315141519914c Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 30 Jul 2014 22:41:54 +0200 Subject: [PATCH 078/210] Remove some debug output. --- RtMidi.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index f685d2f2..aec1e340 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -42,7 +42,6 @@ #include NAMESPACE_RTMIDI_START - #ifdef RTMIDI_GETTEXT const char * rtmidi_gettext (const char * s) { init_rtmidi_gettext(); @@ -1909,9 +1908,6 @@ std::string MidiInCore :: getPortName( unsigned int portNumber ) std::string stringName; CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); if ( portNumber >= MIDIGetNumberOfSources() ) { - std::ostringstream ost; - ost << "MidiInCore::getPortName: "; - errorString_ = ost.str(); error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), Error::WARNING, portNumber)); return stringName; @@ -1998,9 +1994,6 @@ void MidiOutCore :: openPort( unsigned int portNumber, } if ( portNumber >= nDest ) { - std::ostringstream ost; - ost << "MidiOutCore::openPort: "; - errorString_ = ost.str(); error(RTMIDI_ERROR(gettext_noopt("The 'portNumber' argument (%d) is invalid."), Error::INVALID_PARAMETER, portNumber) ); return; @@ -3825,8 +3818,6 @@ class WinMMSequencer { unsigned int nDevices = is_input?midiInGetNumDevs() : midiOutGetNumDevs(); if ( port < 0 || (unsigned int)port >= nDevices ) { - std::ostringstream ost; - std::cerr << port << "<" << nDevices << std::endl; throw Error(RTMIDI_ERROR1(gettext_noopt("The port argument %d is invalid."), Error::INVALID_PARAMETER,port)); } @@ -3979,17 +3970,13 @@ struct WinMMPortDescriptor:public PortDescriptor bool is_valid() const { if (is_input) { if (midiInGetNumDevs() <= port) { - std::cerr << "In: " << midiInGetNumDevs() << "<=" << port << std::endl; return false; } } else { if (midiOutGetNumDevs() <= port) { - std::cerr << "Out: " << midiOutGetNumDevs() << "<=" << port << std::endl; return false; } } - std::cerr << seq.getPortName(port,is_input,PortDescriptor::STORAGE_PATH) - << "==" << name << std::endl; return seq.getPortName(port,is_input,PortDescriptor::STORAGE_PATH) == name; } @@ -4034,7 +4021,6 @@ PortList WinMMPortDescriptor :: getPortList(int capabilities, const std::string size_t n = midiOutGetNumDevs(); for (size_t i = 0 ; i < n ; i++) { std::string name = seq.getPortName(i,false,PortDescriptor::STORAGE_PATH); - std::cout << name << std::endl; list.push_back(new WinMMPortDescriptor(i,name,false,clientName)); } } From 8cb47f8d11d9ee1184760bd0b70ad764273bc5ca Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 30 Jul 2014 22:43:13 +0200 Subject: [PATCH 079/210] Initialize JackSequencer in a separate step in order to avoid certain exceptiions in a constructor. --- RtMidi.cpp | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index aec1e340..b2241991 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -4718,13 +4718,13 @@ NAMESPACE_RTMIDI_END #endif // __WINDOWS_MM__ -//*********************************************************************// -// API: UNIX JACK -// -// Written primarily by Alexander Svetalkin, with updates for delta -// time by Gary Scavone, April 2011. -// -// *********************************************************************// + //*********************************************************************// + // API: UNIX JACK + // + // Written primarily by Alexander Svetalkin, with updates for delta + // time by Gary Scavone, April 2011. + // + // *********************************************************************// #if defined(__UNIX_JACK__) @@ -4756,7 +4756,7 @@ class JackSequencer { } } - JackSequencer(const std::string & n, bool startqueue, JackMidiData * d):client(0),name(n),data(d) + JackSequencer(const std::string & n, JackMidiData * d):client(0),name(n),data(d) { if (locking) { pthread_mutexattr_t attr; @@ -4764,7 +4764,6 @@ class JackSequencer { pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); pthread_mutex_init(&mutex, &attr); } - init(client,startqueue); } ~JackSequencer() @@ -4783,6 +4782,10 @@ class JackSequencer { } } + void init(bool startqueue) { + init(client,startqueue); + } + bool setName(const std::string & n) { /* we don't want to rename the client after opening it. */ if (client) return false; @@ -4899,6 +4902,7 @@ class JackSequencer { { return client; } + protected: struct scoped_lock { pthread_mutex_t * mutex; @@ -5104,8 +5108,9 @@ struct JackMidiData:public JackPortDescriptor { buffMessage(jack_ringbuffer_create( JACK_RINGBUFFER_SIZE )), lastTime(0), rtMidiIn(), - seq(new NonLockingJackSequencer(clientName,true,this)) - {} + seq(new NonLockingJackSequencer(clientName,this)) + { + } ~JackMidiData() @@ -5120,7 +5125,9 @@ struct JackMidiData:public JackPortDescriptor { jack_ringbuffer_free( buffMessage ); } - + void init(bool isinput) { + seq->init(!isinput); + } void setRemote(jack_port_t * remote) { @@ -5528,7 +5535,8 @@ void MidiOutJack :: initialize( const std::string& clientName ) JackMidiData *data = new JackMidiData(clientName); apiData_ = (void *) data; this->clientName = clientName; - // connect(); + // init is the last as it may throw an exception + data->init(false); } void MidiOutJack :: connect() From 0a46fc5bf79c5b07b8b00aaeea46ccc946106b19 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 30 Jul 2014 22:43:48 +0200 Subject: [PATCH 080/210] Fix some compiler errors that have been left over by the last patches. --- RtMidi.cpp | 71 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index b2241991..fb6e6609 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -974,8 +974,8 @@ class CoreSequencer { if (connObjectType == kMIDIObjectType_ExternalSource || connObjectType == kMIDIObjectType_ExternalDestination) { // Connected to an external - // device's endpoint - // (10.3 and later). + // device's endpoint + // (10.3 and later). strRef = EndpointName(static_cast(connObject), true); } else { @@ -999,14 +999,14 @@ class CoreSequencer { } static std::string getPortName(MIDIEndpointRef port, int flags) { - // std::string clientname; + // std::string clientname; std::string devicename; std::string portname; std::string entityname; - // std::string externaldevicename; + // std::string externaldevicename; std::string connections; std::string recommendedname; - // bool isVirtual; + // bool isVirtual; bool hasManyEntities = false; bool hasManyEndpoints = false; CFStringRef nameRef; @@ -1076,9 +1076,9 @@ class CoreSequencer { os << devicename; os << ":" << portname; os << ":" << entityname; - // os << ":" << externaldevicename; + // os << ":" << externaldevicename; os << ":" << connections; - // os << ":" << recommendedname; + // os << ":" << recommendedname; if (flags & PortDescriptor::UNIQUE_NAME) os << ";" << port; break; @@ -1373,7 +1373,7 @@ class CoreSequencer { typedef CoreSequencer<1> LockingCoreSequencer; typedef CoreSequencer<0> NonLockingCoreSequencer; -struct CorePortDescriptor:public PortDescriptor { +struct CorePortDescriptor:public PortDescriptor { CorePortDescriptor(const std::string & name):api(0), clientName(name), endpoint(0) @@ -2231,9 +2231,9 @@ NAMESPACE_RTMIDI_END #endif // __MACOSX_CORE__ - //*********************************************************************// - // API: LINUX ALSA SEQUENCER - //*********************************************************************// +//*********************************************************************// +// API: LINUX ALSA SEQUENCER +//*********************************************************************// // API information found at: // - http://www.alsa-project.org/documentation.php#Library @@ -2619,8 +2619,6 @@ PortList AlsaPortDescriptor :: getPortList(int capabilities, const std::string & } #undef RTMIDI_CLASSNAME -static void *alsaMidiHandler( void *ptr ); - /*! A structure to hold variables related to the ALSA API implementation. @@ -2663,7 +2661,7 @@ struct AlsaMidiData:public AlsaPortDescriptor { } snd_seq_addr_t local; /*!< Our port and client id. If client = 0 (default) this means we didn't aquire a port so far. */ NonLockingAlsaSequencer seq; - // unsigned int portNum; + // unsigned int portNum; snd_seq_port_subscribe_t *subscription; snd_midi_event_t *coder; unsigned int bufferSize; @@ -3117,7 +3115,7 @@ std::string MidiInAlsa :: getPortName( unsigned int portNumber ) snd_seq_get_any_client_info( data->seq, cnum, cinfo ); std::ostringstream os; os << snd_seq_client_info_get_name( cinfo ); - os << " "; // These lines added to make sure devices are listed + os << " "; // These lines added to make sure devices are listed os << snd_seq_port_info_get_client( pinfo ); // with full portnames added to ensure individual device names os << ":"; os << snd_seq_port_info_get_port( pinfo ); @@ -3456,7 +3454,7 @@ void MidiOutAlsa :: initialize( const std::string& clientName ) // Save our api-specific connection information. AlsaMidiData *data = new AlsaMidiData(clientName); // data->seq = seq; - // data->portNum = -1; + // data->portNum = -1; int result = snd_midi_event_new( data->bufferSize, &data->coder ); if ( result < 0 ) { @@ -3499,7 +3497,7 @@ std::string MidiOutAlsa :: getPortName( unsigned int portNumber ) snd_seq_get_any_client_info( data->seq, cnum, cinfo ); std::ostringstream os; os << snd_seq_client_info_get_name(cinfo); - os << " "; // These lines added to make sure devices are listed + os << " "; // These lines added to make sure devices are listed os << snd_seq_port_info_get_client( pinfo ); // with full portnames added to ensure individual device names os << ":"; os << snd_seq_port_info_get_port(pinfo); @@ -3894,7 +3892,7 @@ class WinMMSequencer { protected: struct scoped_lock { - // pthread_mutex_t * mutex; + // pthread_mutex_t * mutex; scoped_lock(unsigned int &) { #if 0 @@ -3921,7 +3919,7 @@ class WinMMSequencer { } }; -// typedef WinMMSequencer<1> LockingWinMMSequencer; +// typedef WinMMSequencer<1> LockingWinMMSequencer; typedef WinMMSequencer<0> NonLockingWinMMSequencer; #undef RTMIDI_CLASSNAME @@ -4718,13 +4716,13 @@ NAMESPACE_RTMIDI_END #endif // __WINDOWS_MM__ - //*********************************************************************// - // API: UNIX JACK - // - // Written primarily by Alexander Svetalkin, with updates for delta - // time by Gary Scavone, April 2011. - // - // *********************************************************************// +//*********************************************************************// +// API: UNIX JACK +// +// Written primarily by Alexander Svetalkin, with updates for delta +// time by Gary Scavone, April 2011. +// +// *********************************************************************// #if defined(__UNIX_JACK__) @@ -4743,6 +4741,8 @@ struct JackBackendCallbacks { static int jackProcessOut( jack_nframes_t nframes, void *arg ); }; + +#define RTMIDI_CLASSNAME "JackSequencer" template class JackSequencer { public: @@ -4952,7 +4952,9 @@ class JackSequencer { }; typedef JackSequencer<1> LockingJackSequencer; typedef JackSequencer<0> NonLockingJackSequencer; +#undef RTMIDI_CLASSNAME +#define RTMIDI_CLASSNAME "JackPortDescriptor" struct JackPortDescriptor:public PortDescriptor { MidiApi * api; @@ -5041,6 +5043,7 @@ PortList JackPortDescriptor :: getPortList(int capabilities, const std::string & jack_free(ports); return list; } +#undef RTMIDI_CLASSNAME /*! A structure to hold variables related to the JACK API implementation. @@ -5050,6 +5053,7 @@ PortList JackPortDescriptor :: getPortList(int capabilities, const std::string & to allow a common client implementation. */ +#define RTMIDI_CLASSNAME "JackMidiData" struct JackMidiData:public JackPortDescriptor { /* signal the JACK process what to do next */ volatile enum { @@ -5297,6 +5301,8 @@ int JackBackendCallbacks::jackProcessOut( jack_nframes_t nframes, void *arg ) return 0; } #undef RTMIDI_CLASSNAME + +#define RTMIDI_CLASSNAME "MidiInJack" MidiInJack :: MidiInJack( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { initialize( clientName ); @@ -5361,7 +5367,7 @@ void MidiInJack :: openPort( unsigned int portNumber, const std::string & portNa { JackMidiData *data = static_cast (apiData_); - // connect(); + // connect(); // Creating new port if ( data->local == NULL) @@ -5383,7 +5389,7 @@ void MidiInJack :: openVirtualPort( const std::string portName ) { JackMidiData *data = static_cast (apiData_); - // connect(); + // connect(); if ( data->local == NULL ) data->local = jack_port_register( *(data->seq), portName.c_str(), JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); @@ -5486,7 +5492,7 @@ std::string MidiInJack :: getPortName( unsigned int portNumber ) JackMidiData *data = static_cast (apiData_); std::string retStr(""); - // connect(); + // connect(); // List of available ports const char **ports = jack_get_ports(* (data->seq), NULL, @@ -5518,6 +5524,7 @@ void MidiInJack :: closePort() jack_port_unregister( *(data->seq), data->local ); data->local = NULL; } +#undef RTMIDI_CLASSNAME //*********************************************************************// // API: JACK @@ -5525,6 +5532,7 @@ void MidiInJack :: closePort() //*********************************************************************// +#define RTMIDI_CLASSNAME "MidiOutJack" MidiOutJack :: MidiOutJack( const std::string clientName ) : MidiOutApi() { initialize( clientName ); @@ -5564,8 +5572,7 @@ void MidiOutJack :: connect() MidiOutJack :: ~MidiOutJack() { JackMidiData *data = static_cast (apiData_); - // closePort(); - + // closePort(); // signal the output callback to delete the data // after finishing its job. data->stateflags = JackMidiData::DELETING; @@ -5743,6 +5750,8 @@ void MidiOutJack :: sendMessage( std::vector &message ) message.size() ); jack_ringbuffer_write( data->buffSize, ( char * ) &nBytes, sizeof( nBytes ) ); } +#undef RTMIDI_CLASSNAME +} NAMESPACE_RTMIDI_END #endif // __UNIX_JACK__ From c753cb8e512a93559ce9b361a23e286ecb50fee2 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 30 Jul 2014 22:45:11 +0200 Subject: [PATCH 081/210] Add an error test case. --- tests/Makefile.am | 27 +++++++++++--------- tests/errors.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 12 deletions(-) create mode 100644 tests/errors.cpp diff --git a/tests/Makefile.am b/tests/Makefile.am index a6effbce..1a634cd1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -13,12 +13,14 @@ noinst_PROGRAMS = \ cmidiin2 \ qmidiin2 \ midiout2 \ - loopback + loopback \ + errors TESTS = \ midiprobe \ midiprobe2 \ - midiprobe-all + midiprobe-all \ + errors if HAVE_VIRTUAL_DEVICES TESTS += loopback @@ -26,14 +28,15 @@ endif -midiprobe_SOURCES = midiprobe.cpp -midiout_SOURCES = midiout.cpp -qmidiin_SOURCES = qmidiin.cpp -cmidiin_SOURCES = cmidiin.cpp -sysextest_SOURCES = sysextest.cpp -midiprobe2_SOURCES = midiprobe2.cpp +midiprobe_SOURCES = midiprobe.cpp +midiout_SOURCES = midiout.cpp +qmidiin_SOURCES = qmidiin.cpp +cmidiin_SOURCES = cmidiin.cpp +sysextest_SOURCES = sysextest.cpp +midiprobe2_SOURCES = midiprobe2.cpp midiprobe_all_SOURCES = midiprobe-all.cpp -cmidiin2_SOURCES = cmidiin2.cpp -qmidiin2_SOURCES = qmidiin2.cpp -midiout2_SOURCES = midiout2.cpp -loopback_SOURCES = loopback.cpp +cmidiin2_SOURCES = cmidiin2.cpp +qmidiin2_SOURCES = qmidiin2.cpp +midiout2_SOURCES = midiout2.cpp +loopback_SOURCES = loopback.cpp +errors_SOURCES = errors.cpp diff --git a/tests/errors.cpp b/tests/errors.cpp new file mode 100644 index 00000000..af8d3cba --- /dev/null +++ b/tests/errors.cpp @@ -0,0 +1,63 @@ +//*****************************************// +// loopback +// by Tobis Schlemmer, 2014. +// inspired by virtual-loopback-test-automated.js from the node-midi project. +// donated to RtMidi. +// +/*! \example loopback.cpp + Simple program to test MIDI input and + output in an internal loop using a user callback function. +*/ +//*****************************************// + +#include +#include +#include "RtMidi.h" + +// Platform-dependent sleep routines. +#if defined(__WINDOWS_MM__) +#include +#define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) +#else // Unix variants +#include +#define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) +#endif + +using namespace rtmidi; + +bool ok = false; + + +int main( int /* argc */, char * /*argv*/[] ) +{ + + std::vector types = Midi::getCompiledApi(); + if (types.size() > 1) { + for (int i = 0 ; i < types.size() ; i++) { + try { + MidiIn in (types[i]); + PortList ports = in.getPortList(PortDescriptor::INPUT); + if (ports.size()>1) { + MidiIn in2 (types[i?0:1]); + try { + in2.openPort(ports.front()); + } catch (Error e) { + std::string msg = e.getMessage(); + e.printMessage(); + if (e.getType() != Error::INVALID_DEVICE) + abort(); + } + } + } catch (Error e) { + std::string msg = e.getMessage(); + e.printMessage(); + if (msg != rtmidi_gettext("")) { + if (e.getType() != Error::WARNING && + e.getType() != Error::NO_DEVICES_FOUND) + abort(); + } + } + } + } + return 0; +} From 2c3f5c65771548b81b821ac0623f917542f4f27d Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 6 Sep 2014 00:42:33 +0200 Subject: [PATCH 082/210] Copy Windows DLLs into the test directory before running the individual tests. --- configure.ac | 17 +++++++++++++++++ tests/Makefile.am | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/configure.ac b/configure.ac index d01e6366..f4df1d71 100644 --- a/configure.ac +++ b/configure.ac @@ -227,6 +227,22 @@ return jack_port_uuid(NULL); AC_MSG_RESULT(using WinMM) AC_SUBST( LIBS, [-lwinmm] ) fi + + AC_CACHE_CHECK([where to find support dlls], [ac_cv_mingw_dll_dirs], + [ + gccsearchdirs=`$CXX $CXXFLAGS -print-search-dirs|\ + sed -e '/^libraries:/ { s/^libraries: *=\?//;s/:/ /g; p } ; d'` + SEARCHDIRS="" + for d in $gccsearchdirs /usr/share/doc/mingw32-runtime /mingw/lib /mingw/bin /usr/lib /lib /usr/bin /bin + do + AS_IF(test -d $d, + [ SEARCHDIRS="$SEARCHDIRS $d" ]) + done + ac_cv_mingw_dll_dirs="$SEARCHDIRS" + ]) + + AC_SUBST(DLLSEARCHPATH,"$ac_cv_mingw_dll_dirs") + ;; *) @@ -234,6 +250,7 @@ return jack_port_uuid(NULL); AC_MSG_ERROR(Unknown system type for MIDI support!) ;; esac +AM_CONDITIONAL(COPYDLLS,test -n "$DLLSEARCHPATH") AM_CONDITIONAL(HAVE_VIRTUAL_DEVICES,test "$have_virtual_devices" == yes) AM_GNU_GETTEXT([external]) AM_GNU_GETTEXT_VERSION([0.18]) diff --git a/tests/Makefile.am b/tests/Makefile.am index 1a634cd1..048563c5 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -40,3 +40,47 @@ qmidiin2_SOURCES = qmidiin2.cpp midiout2_SOURCES = midiout2.cpp loopback_SOURCES = loopback.cpp errors_SOURCES = errors.cpp + +if COPYDLLS +check-am: check-dll + +check-dll: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) linkchecks + +linkchecks: + for d in `echo $(TESTS)| tr ' ' '\n' | grep -i -e '$(EXEEXT)$$'` ; \ + do \ + ls -l "$$d" ; \ + $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$d" DLLEXEDIR="." installdll ; \ + test -f ".libs/$$d" && \ + $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE=".libs/$$d" DLLEXEDIR="." installdll ; \ + done + +installdll: + @echo 'solving references for $(DLLLINKFILE)... ' + DLLSEARCHPATH="$(DLLSEARCHPATH)" ; \ + for d in `LANG=C $(OBJDUMP) -p $(DLLEXEDIR)/$(DLLLINKFILE) |sed '/^\s*DLL Name:.*\(lib\|thread\|wx\|mingw\|gcc\|stdc++\)/ { s/^\s*DLL Name:\s*//; p } ; d '` ; \ + do \ + echo -n checking "$$d ... " ; \ + if [ ! -f $(DLLEXEDIR)/$$d ] ; then \ + echo -n "searching... " ; \ + f=`( find $$DLLSEARCHPATH -name "$$d" || \ + find $$DLLSEARCHPATH -name "$$d.*")|head -n 1` ; \ + if test -f "$$f" ; \ + then \ + echo "installing $$f " ; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_DATA) "$$f" "`pwd`/$(DLLEXEDIR)" ; \ + case "$$f" in \ + *.gz) GZIP=$(GZIP_ENV) gzip -dc $(DLLEXEDIR)/`basename "$$f"` >$(DLLEXEDIR)/"$$d" ;; \ + esac ; \ + $(MAKE) DLLLINKFILE="$$d" DLLEXEDIR="$(DLLEXEDIR)" installdll ; \ + else \ + echo "not found." ; \ + fi ; \ + fi ; \ + echo "done." ;\ + done ; + +endif + From a7462bb304f5158f55a91ae8f29633b37a26d1ac Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 30 Jul 2014 22:45:53 +0200 Subject: [PATCH 083/210] Add some additionally useful documentational files. --- po/ChangeLog | 12 ++++++++ throwing-functions.txt | 66 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 po/ChangeLog create mode 100644 throwing-functions.txt diff --git a/po/ChangeLog b/po/ChangeLog new file mode 100644 index 00000000..55e4e4dd --- /dev/null +++ b/po/ChangeLog @@ -0,0 +1,12 @@ +2014-06-08 gettextize + + * Makefile.in.in: New file, from gettext-0.18.3. + * Rules-quot: New file, from gettext-0.18.3. + * boldquot.sed: New file, from gettext-0.18.3. + * en@boldquot.header: New file, from gettext-0.18.3. + * en@quot.header: New file, from gettext-0.18.3. + * insert-header.sin: New file, from gettext-0.18.3. + * quot.sed: New file, from gettext-0.18.3. + * remove-potcdate.sin: New file, from gettext-0.18.3. + * POTFILES.in: New file. + diff --git a/throwing-functions.txt b/throwing-functions.txt new file mode 100644 index 00000000..b6ca765b --- /dev/null +++ b/throwing-functions.txt @@ -0,0 +1,66 @@ +-*- Org -*- +* throw +|------------------------------------+-------------------+--------------------------------| +| Function | Type | Should be caught inside RtMidi | +|------------------------------------+-------------------+--------------------------------| +| Midi::error | all | n | +| MidiApi :: error(Error e) | all | n | +| MidiIn :: MidiIn | INVALID_PARAMETER | impossible | +| | NO_DEVICES_FOUND | | +| MidiOut :: MidiOut | INVALID_PARAMETER | impossible | +| | NO_DEVICES_FOUND | | +| CoreSequencer::getPortCapabilities | WARNING | y | +| CoreSequencer::createPort | INVALID_PARAMETER | y | +| | DRIVER_ERROR | | +| CoreSequencer::createVirtualPort | INVALID_PARAMETER | y | +| | DRIVER_ERROR | | +| CoreSequencer::init | DRIVER_ERROR | y | +| AlsaSequencer::connectPorts | DRIVER_ERROR | y | +| AlsaSequencer::init | DRIVER_ERROR | y | +| WinMMSequencer::getPortName | INVALID_PARAMETER | Y | +| JackSequencer::init | NO_DEVICES_FOUND | y | +| JackMidiData::openPort | DRIVER_ERROR | | +|------------------------------------+-------------------+--------------------------------| +* error +|----------------------------+-----------------+-----------------------------| +| Function | Type | Can be caught inside RtMidi | +|----------------------------+-----------------+-----------------------------| +| MidiIn :: openMidiApi | vom Konstructor | | +| MidiInWinMM :: initialize | WARNING | yes | +| MidiOutWinMM :: initialize | WARNING | yes | +| | | | +| | | | +|----------------------------+-----------------+-----------------------------| + +* backtrace +** CoreSequencer::getPortCapabilities +|-------------------------------------+-------------------| +| Function | Type | +|-------------------------------------+-------------------| +| CorePortDescriptor::getCapabilities | WARNING | +| CorePortDescriptor::getPortList | -- | +| CoreMidiData::openPort | INVALID_PARAMETER | +| | DRIVER_ERROR | +| CoreSequencer::CoreSequencer | DRIVER_ERROR | +| AlsaSequencer::GetPortName | DRIVER_ERROR | +| AlsaSequencer::getPortCapabilities | DRIVER_ERROR | +| AlsaSequencer::getNextClient | DRIVER_ERROR | +| AlsaSequencer::getNextPort | DRIVER_ERROR | +| AlsaSequencer::DRIVER_ERROR | DRIVER_ERROR | +| AlsaSequencer::deletePort | DRIVER_ERROR | +| AlsaSequencer::connectPorts | DRIVER_ERROR | +| AlsaSequencer::closePort | DRIVER_ERROR | +| AlsaSequencer::startQueue | DRIVER_ERROR | +| AlsaSequencer::GetClient | DRIVER_ERROR | +| AlsaMidiData::connectPorts | DRIVER_ERROR | +| JackSequencer::getPortList | NO_DEVICES_FOUND | +| JackSequencer::getPort | NO_DEVICES_FOUND | +| JackSequencer::getPortName | NO_DEVICES_FOUND | +| JackSequencer::createPort | NO_DEVICES_FOUND | +| JackSequencer::deletePort | NO_DEVICES_FOUND | +| JackSequencer::connectPorts | NO_DEVICES_FOUND | +| JackSequencer::closePort | NO_DEVICES_FOUND | +| JackMidiData::init | NO_DEVICES_FOUND | +| JackMidiData::connectPorts | NO_DEVICES_FOUND | +| MidiOutJack :: initialize | NO_DEVICES_FOUND | +| | | From cb2bf6444dca9daf56dfd604a21a06ec8a9c6671 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 7 Sep 2014 18:06:28 +0200 Subject: [PATCH 084/210] ignore generated documentation --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 351784d7..755dd8da 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /config /configure +/doc/html Makefile Makefile.in /aclocal.m4 From 32ca0ff74e544ccd53cab08c2d4fed86d69a9115 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 7 Sep 2014 17:43:54 +0200 Subject: [PATCH 085/210] Tell git to ignore all Makefile{,.in} and *.orig and *~ --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9f747efb..351784d7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,10 @@ /config /configure -/Makefile.in +Makefile +Makefile.in /aclocal.m4 /autom4te.cache /configure /m4 +*.orig +*~ From b7815768fb524e71ed5f7424ae5326b6a17419a2 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 7 Sep 2014 19:12:08 +0200 Subject: [PATCH 086/210] Fix the last changes on Mac OS X 10.5. The test has been performed with gcc. --- RtMidi.cpp | 264 +++++++++++++++++++++++++++-------------------------- RtMidi.h | 36 +++++--- 2 files changed, 157 insertions(+), 143 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index fb6e6609..5f3ea62e 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -94,7 +94,7 @@ Error::Error( const char * message, message_.resize(length); } else { const char * msg - = gettext_noopt("Error: could not format the error message"); + = gettext_noopt("Error: could not format the error message"); #ifdef RTMIDI_GETTEXT msg = gettext(msg); #endif @@ -732,9 +732,8 @@ static CFStringRef ConnectedEndpointName( MIDIEndpointRef endpoint ) return EndpointName( endpoint, false ); } -static void midiInputCallback( const MIDIPacketList *list, void *procRef, void */*srcRef*/ ); - +#define RTMIDI_CLASSNAME "CoreSequencer" template class CoreSequencer { public: @@ -1239,7 +1238,7 @@ class CoreSequencer { MIDIPortRef createPort (std::string portName, int flags, - MidiInApi::MidiInData * data = NULL) + MidiInCore * data = NULL) { init(); scoped_lock lock (mutex); @@ -1252,7 +1251,7 @@ class CoreSequencer { NULL, portName.c_str(), kCFStringEncodingUTF8 ), - midiInputCallback, + MidiInCore::midiInputCallback, (void *)data, &port); break; @@ -1278,7 +1277,7 @@ class CoreSequencer { MIDIEndpointRef createVirtualPort (std::string portName, int flags, - MidiInApi::MidiInData * data = NULL) + MidiInCore * data = NULL) { init(); scoped_lock lock (mutex); @@ -1292,7 +1291,7 @@ class CoreSequencer { NULL, portName.c_str(), kCFStringEncodingUTF8 ), - midiInputCallback, + MidiInCore::midiInputCallback, (void *)data, &port); break; @@ -1357,11 +1356,11 @@ class CoreSequencer { { scoped_lock lock(mutex); - CFStringRef name = CFStringCreateWithCString( NULL, - name.c_str(), - kCFStringEncodingUTF8); - OSStatus result = MIDIClientCreate(name, NULL, NULL, &client ); - CFRelease(name); + CFStringRef cfname = CFStringCreateWithCString( NULL, + name.c_str(), + kCFStringEncodingUTF8); + OSStatus result = MIDIClientCreate(cfname, NULL, NULL, &client ); + CFRelease(cfname); if ( result != noErr ) { throw RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI client object."), Error::DRIVER_ERROR); @@ -1370,9 +1369,12 @@ class CoreSequencer { } } }; +#undef RTMIDI_CLASSNAME + typedef CoreSequencer<1> LockingCoreSequencer; typedef CoreSequencer<0> NonLockingCoreSequencer; +#define RTMIDI_CLASSNAME "CorePortDescriptor" struct CorePortDescriptor:public PortDescriptor { CorePortDescriptor(const std::string & name):api(0), clientName(name), @@ -1466,10 +1468,10 @@ PortList CorePortDescriptor :: getPortList(int capabilities, const std::string & list.push_back(new CorePortDescriptor(destination, clientName)); } catch (Error e) { - if (e.getType() == WARNING || - e.getType() == DEBUG_WARNING) - e.printMessage(); - else throw; + if (e.getType() == Error::WARNING || + e.getType() == Error::DEBUG_WARNING) + e.printMessage(); + else throw; } } // Combined sources and destinations @@ -1487,17 +1489,19 @@ PortList CorePortDescriptor :: getPortList(int capabilities, const std::string & list.push_back(new CorePortDescriptor(src, clientName)); } catch (Error e) { - if (e.getType() == WARNING || - e.getType() == DEBUG_WARNING) - e.printMessage(); - else throw; + if (e.getType() == Error::WARNING || + e.getType() == Error::DEBUG_WARNING) + e.printMessage(); + else throw; } } } return list; } +#undef RTMIDI_CLASSNAME +#define RTMIDI_CLASSNAME "CoreMidiData" // A structure to hold variables related to the CoreMIDI API // implementation. struct CoreMidiData:public CorePortDescriptor { @@ -1513,7 +1517,7 @@ struct CoreMidiData:public CorePortDescriptor { void openPort(const std::string & name, int flags, - MidiInApi::MidiInData * data = NULL) { + MidiInCore * data = NULL) { localPort = client.createPort(name, flags, data); } @@ -1528,16 +1532,21 @@ struct CoreMidiData:public CorePortDescriptor { unsigned long long lastTime; MIDISysexSendRequest sysexreq; }; +#undef RTMIDI_CLASSNAME + //*********************************************************************// // API: OS-X // Class Definitions: MidiInCore //*********************************************************************// -static void midiInputCallback( const MIDIPacketList *list, void *procRef, void */*srcRef*/ ) +#define RTMIDI_CLASSNAME "MidiInCore" +void MidiInCore::midiInputCallback( const MIDIPacketList *list, + void *procRef, + void */*srcRef*/ ) throw() { - MidiInApi::MidiInData *data = static_cast (procRef); - CoreMidiData *apiData = static_cast (data->apiData); + MidiInCore *data = static_cast (procRef); + CoreMidiData *apiData = static_cast (data->apiData_); unsigned char status; unsigned short nBytes, iByte, size; @@ -1594,104 +1603,102 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void * continueSysex = packet->data[nBytes-1] != 0xF7; if ( !( data->ignoreFlags & 0x01 ) ) { - if ( !continueSysex ) { - // If not a continuing sysex message, invoke the user callback function or queue the message. - if ( data->usingCallback ) { - MidiCallback callback = (MidiCallback) data->userCallback; - callback( message.timeStamp, &message.bytes, data->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else { - try { - apiData->error(RTMIDI_ERROR(_("Error: Message queue limit reached."), - Error::WARNING)); - } catch (Error e) { - // don't bother ALSA with an unhandled exception - } - } - } - message.bytes.clear(); - } + if ( !continueSysex ) { + // If not a continuing sysex message, invoke the user callback function or queue the message. + if ( data->userCallback ) { + data->userCallback->rtmidi_midi_in( message.timeStamp, &message.bytes); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else { + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + Error::WARNING)); + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } + } + } + message.bytes.clear(); + } } } else { while ( iByte < nBytes ) { - size = 0; - // We are expecting that the next byte in the packet is a status byte. - status = packet->data[iByte]; - if ( !(status & 0x80) ) break; - // Determine the number of bytes in the MIDI message. - if ( status < 0xC0 ) size = 3; - else if ( status < 0xE0 ) size = 2; - else if ( status < 0xF0 ) size = 3; - else if ( status == 0xF0 ) { - // A MIDI sysex - if ( data->ignoreFlags & 0x01 ) { - size = 0; - iByte = nBytes; - } - else size = nBytes - iByte; - continueSysex = packet->data[nBytes-1] != 0xF7; - } - else if ( status == 0xF1 ) { - // A MIDI time code message - if ( data->ignoreFlags & 0x02 ) { - size = 0; - iByte += 2; - } - else size = 2; - } - else if ( status == 0xF2 ) size = 3; - else if ( status == 0xF3 ) size = 2; - else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) { - // A MIDI timing tick message and we're ignoring it. - size = 0; - iByte += 1; - } - else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) { - // A MIDI active sensing message and we're ignoring it. - size = 0; - iByte += 1; - } - else size = 1; - - // Copy the MIDI data to our vector. - if ( size ) { - 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. - if ( data->usingCallback ) { - MidiCallback callback = (MidiCallback) data->userCallback; - callback( message.timeStamp, &message.bytes, data->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else { - try { - apiData->error(RTMIDI_ERROR(_("Error: Message queue limit reached."), - Error::WARNING)); - } catch (Error e) { - // don't bother WinMM with an unhandled exception - } - } - } - message.bytes.clear(); - } - iByte += size; - } + size = 0; + // We are expecting that the next byte in the packet is a status byte. + status = packet->data[iByte]; + if ( !(status & 0x80) ) break; + // Determine the number of bytes in the MIDI message. + if ( status < 0xC0 ) size = 3; + else if ( status < 0xE0 ) size = 2; + else if ( status < 0xF0 ) size = 3; + else if ( status == 0xF0 ) { + // A MIDI sysex + if ( data->ignoreFlags & 0x01 ) { + size = 0; + iByte = nBytes; + } + else size = nBytes - iByte; + continueSysex = packet->data[nBytes-1] != 0xF7; + } + else if ( status == 0xF1 ) { + // A MIDI time code message + if ( data->ignoreFlags & 0x02 ) { + size = 0; + iByte += 2; + } + else size = 2; + } + else if ( status == 0xF2 ) size = 3; + else if ( status == 0xF3 ) size = 2; + else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) { + // A MIDI timing tick message and we're ignoring it. + size = 0; + iByte += 1; + } + else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) { + // A MIDI active sensing message and we're ignoring it. + size = 0; + iByte += 1; + } + else size = 1; + + // Copy the MIDI data to our vector. + if ( size ) { + 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. + if ( data->userCallback ) { + data->userCallback->rtmidi_midi_in( message.timeStamp, &message.bytes); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else { + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + Error::WARNING)); + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } + } + } + message.bytes.clear(); + } + iByte += size; + } } } packet = MIDIPacketNext(packet); @@ -1758,7 +1765,7 @@ void MidiInCore :: openPort( unsigned int portNumber, CoreMidiData *data = static_cast (apiData_); OSStatus result = MIDIInputPortCreate( data->client, CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingUTF8 ), - midiInputCallback, (void *)&inputData_, &port ); + midiInputCallback, (void *)this, &port ); if ( result != noErr ) { MIDIClientDispose( data->client ); error(RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI input port."), @@ -1801,7 +1808,7 @@ void MidiInCore :: openVirtualPort( const std::string portName ) MIDIEndpointRef endpoint; OSStatus result = MIDIDestinationCreate( data->client, CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingUTF8 ), - midiInputCallback, (void *)&inputData_, &endpoint ); + midiInputCallback, (void *)this, &endpoint ); if ( result != noErr ) { error(RTMIDI_ERROR(gettext_noopt("Error creating virtual OS-X MIDI destination."), Error::DRIVER_ERROR) ); @@ -1836,7 +1843,7 @@ void MidiInCore :: openPort( const PortDescriptor & port, data->openPort (portName, PortDescriptor::INPUT, - &inputData_); + this); data->setRemote(*remote); OSStatus result = MIDIPortConnectSource(data->localPort, @@ -1920,12 +1927,15 @@ std::string MidiInCore :: getPortName( unsigned int portNumber ) return stringName = name; } +#undef RTMIDI_CLASSNAME + //*********************************************************************// // API: OS-X // Class Definitions: MidiOutCore //*********************************************************************// +#define RTMIDI_CLASSNAME "MidiOutCore" MidiOutCore :: MidiOutCore( const std::string clientName ) : MidiOutApi() { initialize( clientName ); @@ -1994,8 +2004,8 @@ void MidiOutCore :: openPort( unsigned int portNumber, } if ( portNumber >= nDest ) { - error(RTMIDI_ERROR(gettext_noopt("The 'portNumber' argument (%d) is invalid."), - Error::INVALID_PARAMETER, portNumber) ); + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::INVALID_PARAMETER, portNumber) ); return; } @@ -2227,6 +2237,7 @@ void MidiOutCore :: sendMessage( std::vector &message ) } } } +#undef RTMIDI_CLASSNAME NAMESPACE_RTMIDI_END #endif // __MACOSX_CORE__ @@ -2763,7 +2774,7 @@ struct AlsaMidiData:public AlsaPortDescriptor { // Class Definitions: MidiInAlsa //*********************************************************************// -#define RTMIDI_CLASSNAME "" +#define RTMIDI_CLASSNAME "MidiInAlsa" // static function: void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() { @@ -2967,7 +2978,7 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() // don't bother ALSA with an unhandled exception } #endif - } + } } } @@ -3002,9 +3013,7 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() apiData->thread = apiData->dummy_thread_id; return 0; } -#undef RTMIDI_CLASSNAME -#define RTMIDI_CLASSNAME "MidiInAlsa" MidiInAlsa :: MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { @@ -5751,7 +5760,6 @@ void MidiOutJack :: sendMessage( std::vector &message ) jack_ringbuffer_write( data->buffSize, ( char * ) &nBytes, sizeof( nBytes ) ); } #undef RTMIDI_CLASSNAME -} NAMESPACE_RTMIDI_END #endif // __UNIX_JACK__ diff --git a/RtMidi.h b/RtMidi.h index 5b58b51d..aed429fd 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -205,11 +205,11 @@ class Error : public std::exception //! The constructor. Error( const char * message, - Type type, - const char * class_name, - const char * function_name, - const char * file_name, - int line_number, ...) throw(); + Type type, + const char * class_name, + const char * function_name, + const char * file_name, + int line_number, ...) throw(); //! The destructor. virtual ~Error( void ) throw() {} @@ -327,8 +327,8 @@ class Pointer { Pointer & operator = (const Pointer & other) { if (ptr) { if (!(--ptr->count)) { - delete ptr->descriptor; - delete ptr; + delete ptr->descriptor; + delete ptr; } } ptr = other.ptr; @@ -840,10 +840,10 @@ class Midi { if (list && !list->empty()) { PortList retval; for (MidiApiList::iterator i = list->begin(); - i != list->end(); - ++i) { - PortList tmp = (*i)->getPortList(capabilities); - retval.splice(retval.end(), tmp); + i != list->end(); + ++i) { + PortList tmp = (*i)->getPortList(capabilities); + retval.splice(retval.end(), tmp); } return retval; } @@ -1072,8 +1072,8 @@ class MidiIn : public Midi std::vector< ApiType > apis; getCompiledApi( apis ); for (size_t i = 0 ; i < apis.size() ; i++) { - openMidiApi( apis[0] ); - if (rtapi_ && rtapi_->hasVirtualPorts()) break; + openMidiApi( apis[0] ); + if (rtapi_ && rtapi_->hasVirtualPorts()) break; } } @@ -1301,8 +1301,8 @@ class MidiOut : public Midi std::vector< ApiType > apis; getCompiledApi( apis ); for (size_t i = 0 ; i < apis.size() ; i++) { - openMidiApi( apis[0] ); - if (rtapi_ && rtapi_->hasVirtualPorts()) break; + openMidiApi( apis[0] ); + if (rtapi_ && rtapi_->hasVirtualPorts()) break; } } @@ -1366,6 +1366,9 @@ class MidiOut : public Midi #endif #if defined(__MACOSX_CORE__) +NAMESPACE_RTMIDI_END +struct MIDIPacketList; +NAMESPACE_RTMIDI_START class MidiInCore: public MidiInApi { @@ -1384,6 +1387,9 @@ class MidiInCore: public MidiInApi std::string getPortName( unsigned int portNumber ); protected: + static void MidiInCore::midiInputCallback( const MIDIPacketList *list, + void *procRef, + void */*srcRef*/) throw(); void initialize( const std::string& clientName ); }; From 08addf4d8e71ed988768b1b89f974a3455d6dace Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Mon, 8 Sep 2014 20:29:32 +0200 Subject: [PATCH 087/210] Allow further Applications using the old API to be compiled without changes. --- RtMidi.h | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index 5b58b51d..68a07a3c 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -735,17 +735,6 @@ typedef std::list MidiApiList; class Midi { public: typedef rtmidi::ApiType Api; - //! defined for compatibility - enum Api2 { - UNSPECIFIED = rtmidi::UNSPECIFIED, - MACOSX_CORE = rtmidi::MACOSX_CORE, - LINUX_ALSA = rtmidi::LINUX_ALSA, - UNIX_JACK = rtmidi::UNIX_JACK, - WINDOWS_MM = rtmidi::WINDOWS_MM, - WINDOWS_KS = rtmidi::WINDOWS_KS, - RTMIDI_DUMMY = rtmidi::DUMMY - }; - //! A static function to determine the current RtMidi version. static std::string getVersion( void ) throw(); @@ -1607,8 +1596,31 @@ class MidiOutDummy: public MidiOutApi NAMESPACE_RTMIDI_END -typedef rtmidi::Midi RtMidi; -typedef rtmidi::MidiIn RtMidiIn; -typedef rtmidi::MidiOut RtMidiOut; +class RtMidi: public rtmidi::Midi { +public: + enum Api { + UNSPECIFIED = rtmidi::UNSPECIFIED, + MACOSX_CORE = rtmidi::MACOSX_CORE, + LINUX_ALSA = rtmidi::LINUX_ALSA, + UNIX_JACK = rtmidi::UNIX_JACK, + WINDOWS_MM = rtmidi::WINDOWS_MM, + RTMIDI_DUMMY = rtmidi::DUMMY + }; +}; + +class RtMidiIn: public rtmidi::MidiIn { +public: + RTMIDI_DEPRECATED(RtMidiIn( RtMidi::Api api = RtMidi::UNSPECIFIED, + const std::string clientName = std::string( "RtMidi Input Client"))): + MidiIn((rtmidi::ApiType)api, + clientName) {} +}; +class RtMidiOut: public rtmidi::MidiOut { +public: + RTMIDI_DEPRECATED(RtMidiOut( RtMidi::Api api = RtMidi::UNSPECIFIED, + const std::string clientName = std::string( "RtMidi Output Client"))): + MidiOut((rtmidi::ApiType)api, + clientName) {} +}; typedef rtmidi::Error RtMidiError; #endif From e7243ebf939826ecc06b075236b3ead5133a5638 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Tue, 9 Sep 2014 20:49:03 +0200 Subject: [PATCH 088/210] Fix compilation using clang 3.4 on Mac OS X 10.5 --- RtMidi.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index aed429fd..d14c03d4 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -1387,10 +1387,12 @@ class MidiInCore: public MidiInApi std::string getPortName( unsigned int portNumber ); protected: - static void MidiInCore::midiInputCallback( const MIDIPacketList *list, - void *procRef, - void */*srcRef*/) throw(); + static void midiInputCallback( const MIDIPacketList *list, + void *procRef, + void */*srcRef*/) throw(); void initialize( const std::string& clientName ); + template + friend class CoreSequencer; }; class MidiOutCore: public MidiOutApi From 6b6ecf097116d46e6e3d856a852590d8bcc8db6d Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Thu, 11 Sep 2014 19:10:07 +0200 Subject: [PATCH 089/210] Provide better backwards compatibility and verbose deprecation warnings. This also fixes some test cases, that had been broken by the last patches. --- RtMidi.h | 289 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 161 insertions(+), 128 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index f7cb17be..ddc2360d 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -46,12 +46,12 @@ #define RTMIDI_VERSION "3.0.0alpha" #ifdef __GNUC__ -#define RTMIDI_DEPRECATED(func) func __attribute__ ((deprecated)) +#define RTMIDI_DEPRECATED(func,message) func __attribute__ ((deprecated(message))) #elif defined(_MSC_VER) -#define RTMIDI_DEPRECATED(func) __declspec(deprecated) func +#define RTMIDI_DEPRECATED(func,message) __declspec(deprecated(message)) func #else -#pragma message("WARNING: You need to implement DEPRECATED for this compiler") -#define RTMIDI_DEPRECATED(func) func +#pragma message("WARNING: You need to implement the macro RTMIDI_DEPRECATED for this compiler if this code doesn't compile") +#define RTMIDI_DEPRECATED(func,message) func [[deprecated(message)]] #endif #include @@ -111,20 +111,6 @@ inline std::string getApiName(ApiType type) { return ""; } -//! C style user callback function type definition. -/*! - This interface type has been replaced by a MidiInterface class. - - \param timeStamp timestamp indicating when the event has been received - \param message a pointer to the binary MIDI message - \param userData a pointer that can be set using setUserdata - \sa MidiIn - \sa MidiInApi - \sa MidiInterface - \deprecated -*/ -typedef void (*MidiCallback)( double timeStamp, std::vector *message, void *userData); - //! C++ style user callback interface. /*! This interface class can be used to implement type safe MIDI callbacks. @@ -154,6 +140,20 @@ struct MidiInterface { virtual void delete_me() {} }; +//! C style user callback function type definition. +/*! + This interface type has been replaced by a MidiInterface class. + + \param timeStamp timestamp indicating when the event has been received + \param message a pointer to the binary MIDI message + \param userData a pointer that can be set using setUserdata + \sa MidiIn + \sa MidiInApi + \sa MidiInterface + \deprecated +*/ +RTMIDI_DEPRECATED(typedef void (*MidiCallback)( double timeStamp, std::vector *message, void *userData),"RtMidi now provides a class MidiInterface for MIDI callbacks"); + //! Compatibility interface to hold a C style callback function struct CompatibilityMidiInterface: MidiInterface { CompatibilityMidiInterface(MidiCallback cb, void * ud): @@ -591,12 +591,6 @@ class MidiApi */ bool isPortOpen() const { return connected_; } - //! Virtual function to set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. - */ - RTMIDI_DEPRECATED(virtual void setErrorCallback( ErrorCallback errorCallback = NULL, void * userData = 0 )); //! Virtual function to set the error callback object /*! @@ -631,6 +625,13 @@ class MidiApi */ void error( Error e ); + //! Virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + RTMIDI_DEPRECATED(virtual void setErrorCallback( ErrorCallback errorCallback = NULL, void * userData = 0 ), "RtMidi now provides a typesafe ErrorInterface class"); + protected: virtual void initialize( const std::string& clientName ) = 0; @@ -648,18 +649,9 @@ class MidiInApi : public MidiApi MidiInApi( unsigned int queueSizeLimit ); virtual ~MidiInApi( void ); - RTMIDI_DEPRECATED(void setCallback( MidiCallback callback, void *userData = 0 )); void setCallback( MidiInterface * callback); void cancelCallback( void ); virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); - RTMIDI_DEPRECATED(double getMessage( std::vector *message )) - { - if (!message) { - error( RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), - Error::WARNING )); - } - return getMessage(*message); - } double getMessage( std::vector &message ); // A MIDI structure used internally by the class to store incoming @@ -685,6 +677,18 @@ class MidiInApi : public MidiApi :front(0), back(0), size(0), ringSize(0) {} }; + RTMIDI_DEPRECATED(void setCallback( MidiCallback callback, void *userData = 0 ), + "RtMidi now provides a type-safe MidiInterface class."); + RTMIDI_DEPRECATED(double getMessage( std::vector *message ), + "Please, use a C++ style reference to pass the message vector.") + { + if (!message) { + error( RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), + Error::WARNING )); + } + return getMessage(*message); + } + protected: // The RtMidiInData structure is used to pass private class data to // the MIDI input handling function or thread. @@ -706,7 +710,9 @@ class MidiOutApi : public MidiApi MidiOutApi( void ); virtual ~MidiOutApi( void ); - RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) + virtual void sendMessage( std::vector &message ) = 0; + RTMIDI_DEPRECATED(void sendMessage( std::vector *message ), + "Please, use a C++ style reference to pass the message vector.") { if (!message) { error( RTMIDI_ERROR(gettext_noopt("No data in message argument."), @@ -714,7 +720,6 @@ class MidiOutApi : public MidiApi } sendMessage(*message); } - virtual void sendMessage( std::vector &message ) = 0; }; #undef RTMIDI_CLASSNAME @@ -734,8 +739,6 @@ typedef std::list MidiApiList; #define RTMIDI_CLASSNAME "Midi" class Midi { public: - typedef rtmidi::ApiType Api; - //! A static function to determine the current RtMidi version. static std::string getVersion( void ) throw(); @@ -774,27 +777,6 @@ class Midi { else return rtmidi::UNSPECIFIED; } - //! Compatibilty function for older code - virtual - RTMIDI_DEPRECATED(void openVirtualPort( const std::string portName = std::string( "RtMidi virtual port" ) )) = 0; - - //! Pure virtual function to open a MIDI connection given by enumeration number. - /*! \param portNumber An optional port number greater than 0 - can be specified. Otherwise, the default or first port - found is opened. - - \param portName An optional name for the applicaction port - that will be generated to connect to portId can be - specified. - - \deprecated - */ - RTMIDI_DEPRECATED(void openPort( unsigned int portNumber = 0, - const std::string portName = std::string( "RtMidi" ) )) - { - if (rtapi_) rtapi_->openPort(portNumber,portName); - } - //! Pure virtual function to return a port descirptor if the port is open Pointer getDescriptor(bool local=false) @@ -839,6 +821,84 @@ class Midi { return PortList(); } + //! Close an open MIDI connection (if one exists). + void closePort( void ) + { + if (rtapi_) rtapi_->closePort(); + } + + // ! A basic error reporting function for RtMidi classes. + // static void error( Error::Type type, std::string &errorString ); + + //! Pure virtual function to return whether a port is open or not. + /*! \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). + */ + bool isPortOpen( void ) const + { + if (rtapi_) return rtapi_->isPortOpen(); + return false; + } + + //! Pure virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + void setErrorCallback( ErrorInterface * callback) + { + if (rtapi_) rtapi_->setErrorCallback(callback); + } + + //! A basic error reporting function for RtMidi classes. + void error( Error e ); + + /* old functions */ + RTMIDI_DEPRECATED(enum, + "enum RtMidi::Api has been replaced by enum rtmidi::ApiType") Api { + UNSPECIFIED = rtmidi::UNSPECIFIED, + MACOSX_CORE = rtmidi::MACOSX_CORE, + LINUX_ALSA = rtmidi::LINUX_ALSA, + UNIX_JACK = rtmidi::UNIX_JACK, + WINDOWS_MM = rtmidi::WINDOWS_MM, + RTMIDI_DUMMY = rtmidi::DUMMY + }; + RTMIDI_DEPRECATED(static void getCompiledApi( std::vector &apis, bool + preferSystem + = true ) throw(), "enum RtMidi::Api has been replaced by enum rtmidi::ApiType" ) { + std::vector api2; + Midi::getCompiledApi(api2,preferSystem); + apis.reserve(api2.size()); + size_t s = api2.size(); + for (size_t i = 0; i < s; i++) { + apis.push_back((Api)api2[i]); + } + } + + //! Compatibilty function for older code + virtual + RTMIDI_DEPRECATED(void openVirtualPort( const + std::string portName = std::string( "RtMidi virtual port" ) ), + "For better usability you should call this function from a derived class") = 0; + + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. + + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. + + \deprecated + */ + RTMIDI_DEPRECATED(void openPort( unsigned int portNumber = 0, + const std::string portName = std::string( "RtMidi" ) + ),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)") + { + if (rtapi_) rtapi_->openPort(portNumber,portName); + } + //! Pure virtual to return the number of available MIDI ports of the current API. /*! \return This function returns the number of MIDI ports of @@ -851,7 +911,7 @@ class Midi { \sa getPortName \deprecated */ - RTMIDI_DEPRECATED(unsigned int getPortCount()) + RTMIDI_DEPRECATED(unsigned int getPortCount(),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)") { if (rtapi_) return rtapi_->getPortCount(); return 0; @@ -870,53 +930,23 @@ class Midi { \sa getPortCount() \deprecated */ - RTMIDI_DEPRECATED(std::string getPortName( unsigned int portNumber = 0 )) + RTMIDI_DEPRECATED(std::string getPortName( unsigned int portNumber = 0 ),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)") { if (rtapi_) return rtapi_->getPortName(portNumber); return ""; } - //! Close an open MIDI connection (if one exists). - void closePort( void ) - { - if (rtapi_) rtapi_->closePort(); - } - - // ! A basic error reporting function for RtMidi classes. - // static void error( Error::Type type, std::string &errorString ); - - //! Pure virtual function to return whether a port is open or not. - /*! \retval true if a port is open and - \retval false if the port is not open (e.g. not opend or closed). - */ - bool isPortOpen( void ) const - { - if (rtapi_) return rtapi_->isPortOpen(); - return false; - } - //! Pure virtual function to set an error callback function to be invoked when an error has occured. /*! The callback function will be called whenever an error has occured. It is best to set the error callback function before opening a port. */ - RTMIDI_DEPRECATED(void setErrorCallback( ErrorCallback errorCallback = NULL, void * userData = 0 )) + RTMIDI_DEPRECATED(void setErrorCallback( ErrorCallback errorCallback = NULL, void * userData = 0 ), "setErrorCallback now expects an object of type ErrorInterface") { if (rtapi_) rtapi_->setErrorCallback(errorCallback, userData); } - //! Pure virtual function to set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. - */ - void setErrorCallback( ErrorInterface * callback) - { - if (rtapi_) rtapi_->setErrorCallback(callback); - } - //! A basic error reporting function for RtMidi classes. - void error( Error e ); protected: MidiApi *rtapi_; MidiApiList * list; @@ -937,6 +967,14 @@ class Midi { } } }; + +inline RTMIDI_DEPRECATED(std::string getApiName(Midi::Api type),"Use rtmidi::ApiType instead of RtMidi::Api"); +inline std::string getApiName(Midi::Api type) +{ + return getApiName((ApiType)type); +} + + #undef RTMIDI_CLASSNAME /**********************************************************************/ @@ -1081,22 +1119,6 @@ class MidiIn : public Midi return 0; } - //! Set a callback function to be invoked for incoming MIDI messages. - /*! - The callback function will be called whenever an incoming MIDI - message is received. While not absolutely necessary, it is best - to set the callback function before opening a MIDI port to avoid - leaving some messages in the queue. - - \param callback A callback function must be given. - \param userData Opitionally, a pointer to additional data can be - passed to the callback function whenever it is called. - */ - RTMIDI_DEPRECATED(void setCallback( MidiCallback callback, void *userData = 0 )) - { - if (rtapi_) - static_cast(rtapi_)->setCallback(callback,userData); - } //! Set a callback function to be invoked for incoming MIDI messages. /*! @@ -1159,6 +1181,23 @@ class MidiIn : public Midi return 0.0; } + //! Set a callback function to be invoked for incoming MIDI messages. + /*! + The callback function will be called whenever an incoming MIDI + message is received. While not absolutely necessary, it is best + to set the callback function before opening a MIDI port to avoid + leaving some messages in the queue. + + \param callback A callback function must be given. + \param userData Opitionally, a pointer to additional data can be + passed to the callback function whenever it is called. + */ + RTMIDI_DEPRECATED(void setCallback( MidiCallback callback, void *userData = 0 ), + "RtMidi now provides a type-safe MidiInterface class.") + { + if (rtapi_) + static_cast(rtapi_)->setCallback(callback,userData); + } //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. /*! This function returns immediately whether a new message is @@ -1169,7 +1208,8 @@ class MidiIn : public Midi \deprecated */ - RTMIDI_DEPRECATED(double getMessage( std::vector *message )) + RTMIDI_DEPRECATED(double getMessage( std::vector *message ), + "Please, use a C++ style reference to pass the message vector.") { if (!message) { error( RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), @@ -1311,7 +1351,8 @@ class MidiOut : public Midi \deprecated */ - RTMIDI_DEPRECATED(void sendMessage( std::vector *message )) + RTMIDI_DEPRECATED(void sendMessage( std::vector *message ), + "Please, use a C++ style reference to pass the message vector.") { if (!message) { error( RTMIDI_ERROR(gettext_noopt("No data in MIDI message."), @@ -1604,31 +1645,23 @@ class MidiOutDummy: public MidiOutApi NAMESPACE_RTMIDI_END -class RtMidi: public rtmidi::Midi { -public: - enum Api { - UNSPECIFIED = rtmidi::UNSPECIFIED, - MACOSX_CORE = rtmidi::MACOSX_CORE, - LINUX_ALSA = rtmidi::LINUX_ALSA, - UNIX_JACK = rtmidi::UNIX_JACK, - WINDOWS_MM = rtmidi::WINDOWS_MM, - RTMIDI_DUMMY = rtmidi::DUMMY - }; -}; +typedef rtmidi::Midi RTMIDI_DEPRECATED(RtMidi,"RtMidi has been replaced by rtmidi::Midi"); class RtMidiIn: public rtmidi::MidiIn { public: - RTMIDI_DEPRECATED(RtMidiIn( RtMidi::Api api = RtMidi::UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Input Client"))): - MidiIn((rtmidi::ApiType)api, - clientName) {} + RTMIDI_DEPRECATED(RtMidiIn( RtMidi::Api api = RtMidi::UNSPECIFIED, + const std::string clientName = std::string( "RtMidi Input Client")), + "Class RtMidiIn has been replaced by rtmidi::MidiIn"): + MidiIn((rtmidi::ApiType)api, + clientName) {} }; class RtMidiOut: public rtmidi::MidiOut { public: - RTMIDI_DEPRECATED(RtMidiOut( RtMidi::Api api = RtMidi::UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Output Client"))): - MidiOut((rtmidi::ApiType)api, - clientName) {} + RTMIDI_DEPRECATED(RtMidiOut( RtMidi::Api api = RtMidi::UNSPECIFIED, + const std::string clientName = std::string( "RtMidi Output Client")), + "Class RtMidiOut has been replaced by rtmidi::MidiOut"): + MidiOut((rtmidi::ApiType)api, + clientName) {} }; typedef rtmidi::Error RtMidiError; #endif From 369c567ce00b69c77218020e225bbe39d03579ec Mon Sep 17 00:00:00 2001 From: Douglas Heriot Date: Wed, 2 Sep 2015 23:54:02 +1000 Subject: [PATCH 090/210] Fix compiling with C++11 - can't typedef a template, can't implicitly construct std::shared_ptr - Must use using x = y instead of typedef. - std::shared_ptr's constructor accepting a pointer is marked explicit, unlike the Pointer class. So, I have put in explicit constructors everywhere. --- RtMidi.cpp | 781 +++++++++++++++++++++++++++-------------------------- RtMidi.h | 2 +- 2 files changed, 398 insertions(+), 385 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 5f3ea62e..557e01dc 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -248,8 +248,8 @@ MidiIn :: MidiIn( ApiType api, for ( unsigned int i=0; i 0 ) - CFStringInsert( result, 0, CFSTR(" ") ); - CFStringInsert( result, 0, str ); + // prepend the device name to the entity name + if ( CFStringGetLength( result ) > 0 ) + CFStringInsert( result, 0, CFSTR(" ") ); + CFStringInsert( result, 0, str ); } CFRelease( str ); } @@ -699,28 +699,28 @@ static CFStringRef ConnectedEndpointName( MIDIEndpointRef endpoint ) if ( nConnected ) { const SInt32 *pid = (const SInt32 *)(CFDataGetBytePtr(connections)); for ( i=0; i(CFDataGetBytePtr(connections)); - for (int i = 0; i < nConnected; ++i, ++pid) { - MIDIUniqueID id = EndianS32_BtoN(*pid); - MIDIObjectRef connObject; - MIDIObjectType connObjectType; - err = MIDIObjectFindByUniqueID(id, &connObject, &connObjectType); - if (err == noErr) { - if (connObjectType == kMIDIObjectType_ExternalSource || - connObjectType == kMIDIObjectType_ExternalDestination) { - // Connected to an external device's endpoint (10.3 and later). - str = EndpointName(static_cast(connObject), true); - } else { - // Connected to an external device (10.2) (or something else, catch-all) - str = NULL; - MIDIObjectGetStringProperty(connObject, kMIDIPropertyName, &str); - } - - if (str != NULL) { - if (anyStrings) - CFStringAppend(result, CFSTR(", ")); - else anyStrings = true; - CFStringAppend(result, str); - CFRelease(str); - } - } - } + const SInt32 *pid = reinterpret_cast(CFDataGetBytePtr(connections)); + for (int i = 0; i < nConnected; ++i, ++pid) { + MIDIUniqueID id = EndianS32_BtoN(*pid); + MIDIObjectRef connObject; + MIDIObjectType connObjectType; + err = MIDIObjectFindByUniqueID(id, &connObject, &connObjectType); + if (err == noErr) { + if (connObjectType == kMIDIObjectType_ExternalSource || + connObjectType == kMIDIObjectType_ExternalDestination) { + // Connected to an external device's endpoint (10.3 and later). + str = EndpointName(static_cast(connObject), true); + } else { + // Connected to an external device (10.2) (or something else, catch-all) + str = NULL; + MIDIObjectGetStringProperty(connObject, kMIDIPropertyName, &str); + } + + if (str != NULL) { + if (anyStrings) + CFStringAppend(result, CFSTR(", ")); + else anyStrings = true; + CFStringAppend(result, str); + CFRelease(str); + } + } + } } CFRelease(connections); } @@ -894,8 +894,8 @@ class CoreSequencer { str = NULL; MIDIObjectGetStringProperty(entity, kMIDIPropertyName, &str); if (str != NULL) { - CFStringAppend(result, str); - CFRelease(str); + CFStringAppend(result, str); + CFRelease(str); } } @@ -912,25 +912,25 @@ class CoreSequencer { // if an external device has only one entity, throw away // the endpoint name and just use the device name if (isExternal && MIDIDeviceGetNumberOfEntities(device) < 2) { - CFRelease(result); - return str; + CFRelease(result); + return str; } else { - // does the entity name already start with the device name? - // (some drivers do this though they shouldn't) - // if so, do not prepend + // does the entity name already start with the device name? + // (some drivers do this though they shouldn't) + // if so, do not prepend - if (CFStringCompareWithOptions(str /* device name */, + if (CFStringCompareWithOptions(str /* device name */, result /* endpoint name */, CFRangeMake(0, CFStringGetLength(str)), 0) - != kCFCompareEqualTo) { - // prepend the device name to the entity name - if (CFStringGetLength(result) > 0) - CFStringInsert(result, 0, CFSTR(" ")); - CFStringInsert(result, 0, str); - } - CFRelease(str); + != kCFCompareEqualTo) { + // prepend the device name to the entity name + if (CFStringGetLength(result) > 0) + CFStringInsert(result, 0, CFSTR(" ")); + CFStringInsert(result, 0, str); + } + CFRelease(str); } } @@ -968,29 +968,29 @@ class CoreSequencer { MIDIObjectType connObjectType; err = MIDIObjectFindByUniqueID(id, &connObject, &connObjectType); if (err != noErr) - continue; + continue; if (connObjectType == kMIDIObjectType_ExternalSource || - connObjectType == kMIDIObjectType_ExternalDestination) { - // Connected to an external + connObjectType == kMIDIObjectType_ExternalDestination) { + // Connected to an external // device's endpoint // (10.3 and later). - strRef = EndpointName(static_cast(connObject), + strRef = EndpointName(static_cast(connObject), true); } else { - // Connected to an external device - // (10.2) (or something else, catch-all) - strRef = NULL; - MIDIObjectGetStringProperty(connObject, + // Connected to an external device + // (10.2) (or something else, catch-all) + strRef = NULL; + MIDIObjectGetStringProperty(connObject, kMIDIPropertyName, &strRef); } if (strRef != NULL) { - if (anyStrings) - result << ", "; - else anyStrings = true; - result << str(strRef); - CFRelease(strRef); + if (anyStrings) + result << ", "; + else anyStrings = true; + result << str(strRef); + CFRelease(strRef); } } CFRelease(connections); @@ -1028,33 +1028,33 @@ class CoreSequencer { nameRef = NULL; MIDIObjectGetStringProperty(entity, kMIDIPropertyName, &nameRef); if (nameRef != NULL) { - entityname = str(nameRef); - CFRelease(nameRef); + entityname = str(nameRef); + CFRelease(nameRef); } hasManyEndpoints = - MIDIEntityGetNumberOfSources(entity) >= 2 || - MIDIEntityGetNumberOfDestinations(entity) - >= 2; + MIDIEntityGetNumberOfSources(entity) >= 2 || + MIDIEntityGetNumberOfDestinations(entity) + >= 2; // now consider the device's name MIDIDeviceRef device = 0; MIDIEntityGetDevice(entity, &device); if (device != 0) { - hasManyEntities = MIDIDeviceGetNumberOfEntities(device) >= 2; - MIDIObjectGetStringProperty(device, + hasManyEntities = MIDIDeviceGetNumberOfEntities(device) >= 2; + MIDIObjectGetStringProperty(device, kMIDIPropertyName, &nameRef); - devicename = str(nameRef); - CFRelease(nameRef); + devicename = str(nameRef); + CFRelease(nameRef); } // does the entity name already start with the device name? // (some drivers do this though they shouldn't) if (entityname.substr(0,devicename.length()) - == devicename) { - int start = devicename.length(); - while (isspace(entityname[start])) - start++; - entityname = entityname.substr(start); + == devicename) { + int start = devicename.length(); + while (isspace(entityname[start])) + start++; + entityname = entityname.substr(start); } } @@ -1065,68 +1065,68 @@ class CoreSequencer { switch (naming) { case PortDescriptor::SESSION_PATH: if (flags & PortDescriptor::INCLUDE_API) - os << "CORE:"; + os << "CORE:"; os << port; break; case PortDescriptor::STORAGE_PATH: if (flags & PortDescriptor::INCLUDE_API) - os << "CORE:"; + os << "CORE:"; // os << clientname; os << devicename; os << ":" << portname; os << ":" << entityname; - // os << ":" << externaldevicename; + // os << ":" << externaldevicename; os << ":" << connections; - // os << ":" << recommendedname; + // os << ":" << recommendedname; if (flags & PortDescriptor::UNIQUE_NAME) - os << ";" << port; + os << ";" << port; break; case PortDescriptor::LONG_NAME: needcolon = !devicename.empty(); os << devicename; if (hasManyEndpoints || - hasManyEntities || - devicename.empty()) { - if (!entityname.empty()) { - if (needcolon) - os << ": "; - os << entityname; - needcolon = true; - } - if ((hasManyEndpoints - || entityname.empty()) + hasManyEntities || + devicename.empty()) { + if (!entityname.empty()) { + if (needcolon) + os << ": "; + os << entityname; + needcolon = true; + } + if ((hasManyEndpoints + || entityname.empty()) && !portname.empty()) { - if (needcolon) - os << ": "; - os << portname; - } + if (needcolon) + os << ": "; + os << portname; + } } if (!connections.empty()) { - os << " ⇒ "; - os << connections; + os << " ⇒ "; + os << connections; } if (flags & - (PortDescriptor::INCLUDE_API - | PortDescriptor::UNIQUE_NAME)) { - os << " ("; - if (flags & - PortDescriptor::INCLUDE_API) { - os << "CORE"; - if (flags & PortDescriptor::UNIQUE_NAME) - os << ":"; - } - if (flags & PortDescriptor::UNIQUE_NAME) { - os << port; - } - os << ")"; + (PortDescriptor::INCLUDE_API + | PortDescriptor::UNIQUE_NAME)) { + os << " ("; + if (flags & + PortDescriptor::INCLUDE_API) { + os << "CORE"; + if (flags & PortDescriptor::UNIQUE_NAME) + os << ":"; + } + if (flags & PortDescriptor::UNIQUE_NAME) { + os << port; + } + os << ")"; } break; case PortDescriptor::SHORT_NAME: default: if (!recommendedname.empty()) { - os << recommendedname; + os << recommendedname; } else - if (!connections.empty()) { + if (!connections.empty()) { os << connections; } else { os << devicename; @@ -1144,19 +1144,19 @@ class CoreSequencer { } } if (flags & - (PortDescriptor::INCLUDE_API - | PortDescriptor::UNIQUE_NAME)) { - os << " ("; - if (flags & - PortDescriptor::INCLUDE_API) { - os << "CORE"; - if (flags & PortDescriptor::UNIQUE_NAME) - os << ":"; - } - if (flags & PortDescriptor::UNIQUE_NAME) { - os << port; - } - os << ")"; + (PortDescriptor::INCLUDE_API + | PortDescriptor::UNIQUE_NAME)) { + os << " ("; + if (flags & + PortDescriptor::INCLUDE_API) { + os << "CORE"; + if (flags & PortDescriptor::UNIQUE_NAME) + os << ":"; + } + if (flags & PortDescriptor::UNIQUE_NAME) { + os << port; + } + os << ")"; } break; } @@ -1175,9 +1175,9 @@ class CoreSequencer { kMIDIPropertyUniqueID, &uid); if (stat != noErr) { - throw RTMIDI_ERROR(gettext_noopt("Could not get the unique identifier of a midi endpoint."), + throw RTMIDI_ERROR(gettext_noopt("Could not get the unique identifier of a midi endpoint."), Error::WARNING); - return 0; + return 0; } MIDIObjectRef obj; MIDIObjectType type; @@ -1185,18 +1185,18 @@ class CoreSequencer { &obj, &type); if (stat != noErr || obj != port) { - throw RTMIDI_ERROR(gettext_noopt("Could not get the endpoint back from the unique identifier of a midi endpoint."), + throw RTMIDI_ERROR(gettext_noopt("Could not get the endpoint back from the unique identifier of a midi endpoint."), Error::WARNING); - return 0; + return 0; } if (type == kMIDIObjectType_Source - || type == kMIDIObjectType_ExternalSource) - return PortDescriptor::INPUT; + || type == kMIDIObjectType_ExternalSource) + return PortDescriptor::INPUT; else if (type == kMIDIObjectType_Destination || type == kMIDIObjectType_ExternalDestination) - return PortDescriptor::OUTPUT; + return PortDescriptor::OUTPUT; else { - return 0; + return 0; } } else if (stat != noErr) { @@ -1215,21 +1215,21 @@ class CoreSequencer { MIDIEntityGetNumberOfDestinations(entity); for (ItemCount i = 0; i < count ; i++) { MIDIEndpointRef dest= - MIDIEntityGetDestination(entity,i); + MIDIEntityGetDestination(entity,i); if (dest == port) { - retval |= - PortDescriptor::OUTPUT; - break; + retval |= + PortDescriptor::OUTPUT; + break; } } count = MIDIEntityGetNumberOfSources(entity); for (ItemCount i = 0; i < count ; i++) { MIDIEndpointRef src= - MIDIEntityGetSource(entity,i); + MIDIEntityGetSource(entity,i); if (src == port) { - retval |= - PortDescriptor::INPUT; + retval |= + PortDescriptor::INPUT; } } return retval; @@ -1257,7 +1257,7 @@ class CoreSequencer { break; case PortDescriptor::OUTPUT: result - = MIDIOutputPortCreate(seq, + = MIDIOutputPortCreate(seq, CFStringCreateWithCString( NULL, portName.c_str(), @@ -1286,7 +1286,7 @@ class CoreSequencer { switch (flags) { case PortDescriptor::INPUT: result - = MIDIDestinationCreate(seq, + = MIDIDestinationCreate(seq, CFStringCreateWithCString( NULL, portName.c_str(), @@ -1297,7 +1297,7 @@ class CoreSequencer { break; case PortDescriptor::OUTPUT: result - = MIDISourceCreate(seq, + = MIDISourceCreate(seq, CFStringCreateWithCString( NULL, portName.c_str(), @@ -1332,12 +1332,12 @@ class CoreSequencer { scoped_lock(pthread_mutex_t & m): mutex(&m) { if (locking) - pthread_mutex_lock(mutex); + pthread_mutex_lock(mutex); } ~scoped_lock() { if (locking) - pthread_mutex_unlock(mutex); + pthread_mutex_unlock(mutex); } }; pthread_mutex_t mutex; @@ -1362,9 +1362,9 @@ class CoreSequencer { OSStatus result = MIDIClientCreate(cfname, NULL, NULL, &client ); CFRelease(cfname); if ( result != noErr ) { - throw RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI client object."), + throw RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI client object."), Error::DRIVER_ERROR); - return; + return; } } } @@ -1461,12 +1461,12 @@ PortList CorePortDescriptor :: getPortList(int capabilities, const std::string & MIDIGetNumberOfDestinations(); for (ItemCount i = 0 ; i < count; i++) { MIDIEndpointRef destination = - MIDIGetDestination(i); + MIDIGetDestination(i); try { - if ((seq.getPortCapabilities(destination) - & caps) == caps) - list.push_back(new CorePortDescriptor(destination, - clientName)); + if ((seq.getPortCapabilities(destination) + & caps) == caps) + list.push_back(Pointer( + new CorePortDescriptor(destination, clientName))); } catch (Error e) { if (e.getType() == Error::WARNING || e.getType() == Error::DEBUG_WARNING) @@ -1482,12 +1482,12 @@ PortList CorePortDescriptor :: getPortList(int capabilities, const std::string & MIDIGetNumberOfSources(); for (ItemCount i = 0 ; i < count; i++) { MIDIEndpointRef src = - MIDIGetSource(i); + MIDIGetSource(i); try { - if ((seq.getPortCapabilities(src) - & caps) == caps) - list.push_back(new CorePortDescriptor(src, - clientName)); + if ((seq.getPortCapabilities(src) + & caps) == caps) + list.push_back(Pointer( + new CorePortDescriptor(src, clientName))); } catch (Error e) { if (e.getType() == Error::WARNING || e.getType() == Error::DEBUG_WARNING) @@ -1579,12 +1579,12 @@ void MidiInCore::midiInputCallback( const MIDIPacketList *list, else { time = packet->timeStamp; if ( time == 0 ) { // this happens when receiving asynchronous sysex messages - time = AudioGetCurrentHostTime(); + time = AudioGetCurrentHostTime(); } time -= apiData->lastTime; time = AudioConvertHostTimeToNanos( time ); 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 @@ -1596,9 +1596,9 @@ void MidiInCore::midiInputCallback( const MIDIPacketList *list, if ( continueSysex ) { // We have a continuing, segmented sysex message. if ( !( data->ignoreFlags & 0x01 ) ) { - // If we're not ignoring sysex messages, copy the entire packet. - for ( unsigned int j=0; jdata[j] ); + // If we're not ignoring sysex messages, copy the entire packet. + for ( unsigned int j=0; jdata[j] ); } continueSysex = packet->data[nBytes-1] != 0xF7; @@ -1866,13 +1866,12 @@ Pointer MidiInCore :: getDescriptor(bool local) } if (local) { if (data && data->localEndpoint) { - return new - CorePortDescriptor(data->localEndpoint, - data->getClientName()); + return Pointer(new + CorePortDescriptor(data->localEndpoint, data->getClientName())); } } else { if (data->getEndpoint()) { - return new CorePortDescriptor(*data); + return Pointer(new CorePortDescriptor(*data)); } } return NULL; @@ -2113,13 +2112,13 @@ Pointer MidiOutCore :: getDescriptor(bool local) try { if (local) { if (data && data->localEndpoint) { - return new - CorePortDescriptor(data->localEndpoint, - data->getClientName()); + return Pointer( + new CorePortDescriptor(data->localEndpoint, data->getClientName())); } } else { if (data->getEndpoint()) { - return new CorePortDescriptor(*data); + return Pointer( + new CorePortDescriptor(*data)); } } } catch (Error e) { @@ -2348,42 +2347,42 @@ class AlsaSequencer { switch (naming) { case PortDescriptor::SESSION_PATH: if (flags & PortDescriptor::INCLUDE_API) - os << "ALSA:"; + os << "ALSA:"; os << client << ":" << port; break; case PortDescriptor::STORAGE_PATH: if (flags & PortDescriptor::INCLUDE_API) - os << "ALSA:"; + os << "ALSA:"; os << snd_seq_client_info_get_name(cinfo); os << ":"; os << snd_seq_port_info_get_name(pinfo); if (flags & PortDescriptor::UNIQUE_NAME) - os << ";" << client << ":" << port; + os << ";" << client << ":" << port; break; case PortDescriptor::LONG_NAME: os << snd_seq_client_info_get_name( cinfo ); if (flags & PortDescriptor::UNIQUE_NAME) { - os << " " << client; + os << " " << client; } os << ":"; if (flags & PortDescriptor::UNIQUE_NAME) { - os << port; + os << port; } os << " " << snd_seq_port_info_get_name(pinfo); if (flags & PortDescriptor::INCLUDE_API) - os << " (ALSA)"; + os << " (ALSA)"; break; case PortDescriptor::SHORT_NAME: default: os << snd_seq_client_info_get_name( cinfo ); if (flags & PortDescriptor::UNIQUE_NAME) { - os << " "; - os << client; + os << " "; + os << client; } os << ":" << port; if (flags & PortDescriptor::INCLUDE_API) - os << " (ALSA)"; + os << " (ALSA)"; break; } @@ -2449,11 +2448,11 @@ class AlsaSequencer { { scoped_lock lock (mutex); if ( snd_seq_subscribe_port(seq, subscription) ) { - snd_seq_port_subscribe_free( subscription ); - subscription = 0; - throw RTMIDI_ERROR(gettext_noopt("Error making ALSA port connection."), + snd_seq_port_subscribe_free( subscription ); + subscription = 0; + throw RTMIDI_ERROR(gettext_noopt("Error making ALSA port connection."), Error::DRIVER_ERROR); - return 0; + return 0; } } return subscription; @@ -2488,12 +2487,12 @@ class AlsaSequencer { scoped_lock(pthread_mutex_t & m): mutex(&m) { if (locking) - pthread_mutex_lock(mutex); + pthread_mutex_lock(mutex); } ~scoped_lock() { if (locking) - pthread_mutex_unlock(mutex); + pthread_mutex_unlock(mutex); } }; pthread_mutex_t mutex; @@ -2521,9 +2520,9 @@ class AlsaSequencer { scoped_lock lock(mutex); int result = snd_seq_open(&s, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); if ( result < 0 ) { - throw RTMIDI_ERROR(gettext_noopt("Error creating ALSA sequencer client object."), + throw RTMIDI_ERROR(gettext_noopt("Error creating ALSA sequencer client object."), Error::DRIVER_ERROR ); - return; + return; } snd_seq_set_client_name( seq, name.c_str() ); } @@ -2609,21 +2608,22 @@ PortList AlsaPortDescriptor :: getPortList(int capabilities, const std::string & unsigned int atyp = snd_seq_port_info_get_type( pinfo ); // otherwise we get ports without any if ( !(capabilities & UNLIMITED) && - !( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) ) continue; + !( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) ) continue; unsigned int caps = snd_seq_port_info_get_capability( pinfo ); if (capabilities & INPUT) { - /* we need both READ and SUBS_READ */ - if ((caps & (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) - != (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) - continue; + /* we need both READ and SUBS_READ */ + if ((caps & (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) + != (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) + continue; } if (capabilities & OUTPUT) { - /* we need both WRITE and SUBS_WRITE */ - if ((caps & (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) - != (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) - continue; + /* we need both WRITE and SUBS_WRITE */ + if ((caps & (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) + != (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) + continue; } - list.push_back(new AlsaPortDescriptor(client,snd_seq_port_info_get_port(pinfo),clientName)); + list.push_back(Pointer( + new AlsaPortDescriptor(client,snd_seq_port_info_get_port(pinfo),clientName))); } } return list; @@ -2830,11 +2830,11 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() if ( snd_seq_event_input_pending( apiData->seq, 1 ) == 0 ) { // No data pending if ( poll( poll_fds, poll_fd_count, -1) >= 0 ) { - if ( poll_fds[0].revents & POLLIN ) { - bool dummy; - int res = read( poll_fds[0].fd, &dummy, sizeof(dummy) ); - (void) res; - } + if ( poll_fds[0].revents & POLLIN ) { + bool dummy; + int res = read( poll_fds[0].fd, &dummy, sizeof(dummy) ); + (void) res; + } } continue; } @@ -2843,31 +2843,31 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() result = snd_seq_event_input( apiData->seq, &ev ); if ( result == -ENOSPC ) { try { - data->error(RTMIDI_ERROR(rtmidi_gettext("MIDI input buffer overrun."), + data->error(RTMIDI_ERROR(rtmidi_gettext("MIDI input buffer overrun."), Error::WARNING)); } catch (Error e) { - // don't bother ALSA with an unhandled exception + // don't bother ALSA with an unhandled exception } continue; } else if ( result == -EAGAIN ) { try { - data->error(RTMIDI_ERROR(rtmidi_gettext("ALSA returned without providing a MIDI event."), + data->error(RTMIDI_ERROR(rtmidi_gettext("ALSA returned without providing a MIDI event."), Error::WARNING)); } catch (Error e) { - // don't bother ALSA with an unhandled exception + // don't bother ALSA with an unhandled exception } continue; } else if ( result <= 0 ) { try { - data->error(RTMIDI_ERROR1(rtmidi_gettext("Unknown MIDI input error.\nThe system reports:\n%s"), + data->error(RTMIDI_ERROR1(rtmidi_gettext("Unknown MIDI input error.\nThe system reports:\n%s"), Error::WARNING, strerror(-result))); } catch (Error e) { - // don't bother ALSA with an unhandled exception + // don't bother ALSA with an unhandled exception } continue; } @@ -2915,19 +2915,19 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() case SND_SEQ_EVENT_SYSEX: if ( (data->ignoreFlags & 0x01) ) break; if ( ev->data.ext.len > apiData->bufferSize ) { - apiData->bufferSize = ev->data.ext.len; - free( buffer ); - buffer = (unsigned char *) malloc( apiData->bufferSize ); - if ( buffer == NULL ) { - data->doInput = false; - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error resizing buffer memory."), + apiData->bufferSize = ev->data.ext.len; + free( buffer ); + buffer = (unsigned char *) malloc( apiData->bufferSize ); + if ( buffer == NULL ) { + data->doInput = false; + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error resizing buffer memory."), Error::WARNING)); - } catch (Error e) { - // don't bother ALSA with an unhandled exception - } - break; - } + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } + break; + } } default: @@ -2938,45 +2938,45 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() nBytes = snd_midi_event_decode( apiData->coder, buffer, apiData->bufferSize, ev ); if ( nBytes > 0 ) { - // The ALSA sequencer has a maximum buffer size for MIDI sysex - // events of 256 bytes. If a device sends sysex messages larger - // than this, they are segmented into 256 byte chunks. So, - // we'll watch for this and concatenate sysex chunks into a - // single sysex message if necessary. - if ( !continueSysex ) - message.bytes.assign( buffer, &buffer[nBytes] ); - else - message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] ); - - continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) ); - if ( !continueSysex ) { - - // Calculate the time stamp: - message.timeStamp = 0.0; - - // Method 1: Use the system time. - //(void)gettimeofday(&tv, (struct timezone *)NULL); - //time = (tv.tv_sec * 1000000) + tv.tv_usec; - - // Method 2: Use the ALSA sequencer event time data. - // (thanks to Pedro Lopez-Cabanillas!). - time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 ); - lastTime = time; - time -= apiData->lastTime; - apiData->lastTime = lastTime; - if ( data->firstMessage == true ) - data->firstMessage = false; - else - message.timeStamp = time * 0.000001; - } - else { + // The ALSA sequencer has a maximum buffer size for MIDI sysex + // events of 256 bytes. If a device sends sysex messages larger + // than this, they are segmented into 256 byte chunks. So, + // we'll watch for this and concatenate sysex chunks into a + // single sysex message if necessary. + if ( !continueSysex ) + message.bytes.assign( buffer, &buffer[nBytes] ); + else + message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] ); + + continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) ); + if ( !continueSysex ) { + + // Calculate the time stamp: + message.timeStamp = 0.0; + + // Method 1: Use the system time. + //(void)gettimeofday(&tv, (struct timezone *)NULL); + //time = (tv.tv_sec * 1000000) + tv.tv_usec; + + // Method 2: Use the ALSA sequencer event time data. + // (thanks to Pedro Lopez-Cabanillas!). + time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 ); + lastTime = time; + time -= apiData->lastTime; + apiData->lastTime = lastTime; + if ( data->firstMessage == true ) + data->firstMessage = false; + else + message.timeStamp = time * 0.000001; + } + else { #if defined(__RTMIDI_DEBUG__) - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Event parsing error or not a MIDI event."), + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Event parsing error or not a MIDI event."), Error::WARNING)); - } catch (Error e) { - // don't bother ALSA with an unhandled exception - } + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } #endif } } @@ -2991,18 +2991,18 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() else { // As long as we haven't reached our queue size limit, push the message. if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; } else { - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother ALSA with an unhandled exception - } + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } } } } @@ -3286,7 +3286,7 @@ void MidiInAlsa :: openPort( const PortDescriptor & port, if ( doInput == false ) { doInput - = data->startQueue(this); + = data->startQueue(this); } connected_ = true; @@ -3301,11 +3301,13 @@ Pointer MidiInAlsa :: getDescriptor(bool local) try { if (local) { if (data && data->local.client) { - return new AlsaPortDescriptor(data->local,data->getClientName()); + return Pointer( + new AlsaPortDescriptor(data->local,data->getClientName())); } } else { if (data && data->client) { - return new AlsaPortDescriptor(*data,data->getClientName()); + return Pointer( + new AlsaPortDescriptor(*data,data->getClientName())); } } } catch (Error e) { @@ -3379,9 +3381,9 @@ void MidiInAlsa :: openVirtualPort( std::string portName ) pthread_attr_destroy(&attr); if ( err ) { if ( data->subscription ) { - snd_seq_unsubscribe_port( data->seq, data->subscription ); - snd_seq_port_subscribe_free( data->subscription ); - data->subscription = 0; + snd_seq_unsubscribe_port( data->seq, data->subscription ); + snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; } doInput = false; error( RTMIDI_ERROR(gettext_noopt("Error starting MIDI input thread!"), @@ -3705,17 +3707,19 @@ Pointer MidiOutAlsa :: getDescriptor(bool local) try { if (local) { if (data && data->local.client) { - return new AlsaPortDescriptor(data->local, data->getClientName()); + return Pointer( + new AlsaPortDescriptor(data->local, data->getClientName())); } } else { if (data && data->client) { - return new AlsaPortDescriptor(*data, data->getClientName()); - } + return Pointer( + new AlsaPortDescriptor(*data, data->getClientName()))); } - } catch (Error e) { - error(e); } - return NULL; +} catch (Error e) { + error(e); + } +return NULL; } PortList MidiOutAlsa :: getPortList(int capabilities) { @@ -3873,26 +3877,26 @@ class WinMMSequencer { switch (naming) { case PortDescriptor::SESSION_PATH: if (flags & PortDescriptor::INCLUDE_API) - os << "WinMM:"; + os << "WinMM:"; os << port << ":" << name.c_str(); break; case PortDescriptor::STORAGE_PATH: if (flags & PortDescriptor::INCLUDE_API) - os << "WinMM:"; + os << "WinMM:"; os << name.c_str(); if (flags & PortDescriptor::UNIQUE_NAME) - os << ";" << port; + os << ";" << port; break; case PortDescriptor::LONG_NAME: case PortDescriptor::SHORT_NAME: default: os << name.c_str(); if (flags & PortDescriptor::UNIQUE_NAME) { - os << " "; - os << port; + os << " "; + os << port; } if (flags & PortDescriptor::INCLUDE_API) - os << " (WinMM)"; + os << " (WinMM)"; break; } @@ -3906,14 +3910,14 @@ class WinMMSequencer { { #if 0 if (locking) - pthread_mutex_lock(mutex); + pthread_mutex_lock(mutex); #endif } ~scoped_lock() { #if 0 if (locking) - pthread_mutex_unlock(mutex); + pthread_mutex_unlock(mutex); #endif } }; @@ -3977,11 +3981,11 @@ struct WinMMPortDescriptor:public PortDescriptor bool is_valid() const { if (is_input) { if (midiInGetNumDevs() <= port) { - return false; + return false; } } else { if (midiOutGetNumDevs() <= port) { - return false; + return false; } } return seq.getPortName(port,is_input,PortDescriptor::STORAGE_PATH) @@ -4022,13 +4026,15 @@ PortList WinMMPortDescriptor :: getPortList(int capabilities, const std::string size_t n = midiInGetNumDevs(); for (size_t i = 0 ; i < n ; i++) { std::string name = seq.getPortName(i,true,PortDescriptor::STORAGE_PATH); - list.push_back(new WinMMPortDescriptor(i,name,true,clientName)); + list.push_back(Pointer( + new WinMMPortDescriptor(i,name,true,clientName))); } } else { size_t n = midiOutGetNumDevs(); for (size_t i = 0 ; i < n ; i++) { std::string name = seq.getPortName(i,false,PortDescriptor::STORAGE_PATH); - list.push_back(new WinMMPortDescriptor(i,name,false,clientName)); + list.push_back(Pointer( + new WinMMPortDescriptor(i,name,false,clientName))); } } return list; @@ -4104,18 +4110,18 @@ struct WinMMCallbacks { else if ( status < 0xE0 ) nBytes = 2; else if ( status < 0xF0 ) nBytes = 3; else if ( status == 0xF1 ) { - if ( data->ignoreFlags & 0x02 ) return; - else nBytes = 2; + if ( data->ignoreFlags & 0x02 ) return; + else nBytes = 2; } else if ( status == 0xF2 ) nBytes = 3; else if ( status == 0xF3 ) nBytes = 2; else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) { - // A MIDI timing tick message and we're ignoring it. - return; + // A MIDI timing tick message and we're ignoring it. + return; } else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { - // A MIDI active sensing message and we're ignoring it. - return; + // A MIDI active sensing message and we're ignoring it. + return; } // Copy bytes to our MIDI message. @@ -4125,9 +4131,9 @@ struct WinMMCallbacks { else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) MIDIHDR *sysex = ( MIDIHDR *) midiMessage; if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { - // Sysex message and we're not ignoring it - for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) - apiData->message.bytes.push_back( sysex->lpData[i] ); + // Sysex message and we're not ignoring it + for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) + apiData->message.bytes.push_back( sysex->lpData[i] ); } // The WinMM API requires that the sysex buffer be requeued after @@ -4139,20 +4145,20 @@ struct WinMMCallbacks { // avoid requeueing it, else the computer suddenly reboots after // one or two minutes. if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { - //if ( sysex->dwBytesRecorded > 0 ) { - EnterCriticalSection( &(apiData->_mutex) ); - MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); - LeaveCriticalSection( &(apiData->_mutex) ); - if ( result != MMSYSERR_NOERROR ){ - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error sending sysex to Midi device."), + //if ( sysex->dwBytesRecorded > 0 ) { + EnterCriticalSection( &(apiData->_mutex) ); + MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); + LeaveCriticalSection( &(apiData->_mutex) ); + if ( result != MMSYSERR_NOERROR ){ + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error sending sysex to Midi device."), Error::WARNING)); - } catch (Error e) { - // don't bother WinMM with an unhandled exception - } - } + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } + } - if ( data->ignoreFlags & 0x01 ) return; + if ( data->ignoreFlags & 0x01 ) return; } else return; } @@ -4163,18 +4169,18 @@ struct WinMMCallbacks { else { // As long as we haven't reached our queue size limit, push the message. if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = apiData->message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; + data->queue.ring[data->queue.back++] = apiData->message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; } else { - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother WinMM with an unhandled exception - } + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } } } @@ -4359,7 +4365,8 @@ Pointer MidiInWinMM :: getDescriptor(bool local) } WinMMPortDescriptor * retval = NULL; try { - retval = new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); + retval = Pointer( + new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName())); } catch (Error e) { try { error(e); @@ -4398,10 +4405,10 @@ void MidiInWinMM :: closePort( void ) delete [] data->sysexBuffer[i]->lpData; delete [] data->sysexBuffer[i]; if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - error(RTMIDI_ERROR(gettext_noopt("Error closing Windows MM MIDI input port."), + midiInClose( data->inHandle ); + error(RTMIDI_ERROR(gettext_noopt("Error closing Windows MM MIDI input port."), Error::DRIVER_ERROR) ); - return; + return; } } @@ -4626,7 +4633,8 @@ Pointer MidiOutWinMM :: getDescriptor(bool local) Error::DRIVER_ERROR)); return 0; } - return new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); + return Pointer( + new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName())); } @@ -4780,10 +4788,10 @@ class JackSequencer { { scoped_lock lock (mutex); if (client) { - jack_deactivate (client); - // the latter doesn't flush the queue - jack_client_close (client); - client = 0; + jack_deactivate (client); + // the latter doesn't flush the queue + jack_client_close (client); + client = 0; } } if (locking) { @@ -4823,7 +4831,7 @@ class JackSequencer { switch (naming) { case PortDescriptor::SESSION_PATH: if (flags & PortDescriptor::INCLUDE_API) - os << "JACK:"; + os << "JACK:"; #if __UNIX_JACK_HAS_UUID__ os << "UUID:" << std::hex << jack_port_uuid(port); #else @@ -4832,19 +4840,19 @@ class JackSequencer { break; case PortDescriptor::STORAGE_PATH: if (flags & PortDescriptor::INCLUDE_API) - os << "JACK:"; + os << "JACK:"; os << jack_port_name(port); break; case PortDescriptor::LONG_NAME: os << jack_port_name(port); if (flags & PortDescriptor::INCLUDE_API) - os << " (JACK)"; + os << " (JACK)"; break; case PortDescriptor::SHORT_NAME: default: os << jack_port_short_name(port); if (flags & PortDescriptor::INCLUDE_API) - os << " (JACK)"; + os << " (JACK)"; break; } return os.str(); @@ -4918,12 +4926,12 @@ class JackSequencer { scoped_lock(pthread_mutex_t & m): mutex(&m) { if (locking) - pthread_mutex_lock(mutex); + pthread_mutex_lock(mutex); } ~scoped_lock() { if (locking) - pthread_mutex_unlock(mutex); + pthread_mutex_unlock(mutex); } }; pthread_mutex_t mutex; @@ -4945,16 +4953,16 @@ class JackSequencer { if (( c = jack_client_open( name.c_str(), JackNoStartServer, NULL )) == 0) { - c = NULL; - throw RTMIDI_ERROR(gettext_noopt("Could not connect to JACK server. Is it runnig?"), + c = NULL; + throw RTMIDI_ERROR(gettext_noopt("Could not connect to JACK server. Is it runnig?"), Error::NO_DEVICES_FOUND); - return; + return; } if (isoutput && data) { - jack_set_process_callback( c, JackBackendCallbacks::jackProcessOut, data ); + jack_set_process_callback( c, JackBackendCallbacks::jackProcessOut, data ); } else if (data) - jack_set_process_callback( c, JackBackendCallbacks::jackProcessIn, data ); + jack_set_process_callback( c, JackBackendCallbacks::jackProcessIn, data ); jack_activate( c ); } } @@ -5047,7 +5055,8 @@ PortList JackPortDescriptor :: getPortList(int capabilities, const std::string & const char ** ports = seq.getPortList(flags); if (!ports) return list; for (const char ** port = ports; *port; port++) { - list.push_back(new JackPortDescriptor(*port, clientName)); + list.push_back(Pointer( + new JackPortDescriptor(*port, clientName))); } jack_free(ports); return list; @@ -5222,24 +5231,24 @@ int JackBackendCallbacks::jackProcessIn( jack_nframes_t nframes, void *arg ) if ( !rtData->continueSysex ) { if ( rtData->userCallback ) { - rtData->userCallback->rtmidi_midi_in( message.timeStamp, &message.bytes); + rtData->userCallback->rtmidi_midi_in( message.timeStamp, &message.bytes); } else { - // As long as we haven't reached our queue size limit, push the message. - if ( rtData->queue.size < rtData->queue.ringSize ) { - rtData->queue.ring[rtData->queue.back++] = message; - if ( rtData->queue.back == rtData->queue.ringSize ) - rtData->queue.back = 0; - rtData->queue.size++; - } - else { - try { - rtData->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + // As long as we haven't reached our queue size limit, push the message. + if ( rtData->queue.size < rtData->queue.ringSize ) { + rtData->queue.ring[rtData->queue.back++] = message; + if ( rtData->queue.back == rtData->queue.ringSize ) + rtData->queue.back = 0; + rtData->queue.size++; + } + else { + try { + rtData->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother WinMM with an unhandled exception - } - } + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } + } } } } @@ -5451,11 +5460,13 @@ Pointer MidiInJack :: getDescriptor(bool local) try { if (local) { if (data && data->local) { - return new JackPortDescriptor(data->local,data->getClientName()); + return Pointer( + new JackPortDescriptor(data->local,data->getClientName())); } } else { if (data && *data) { - return new JackPortDescriptor(*data,data->getClientName()); + return Pointer( + new JackPortDescriptor(*data,data->getClientName())); } } } catch (Error e) { @@ -5665,11 +5676,13 @@ Pointer MidiOutJack :: getDescriptor(bool local) try { if (local) { if (data && data->local) { - return new JackPortDescriptor(data->local,data->getClientName()); + return Pointer( + new JackPortDescriptor(data->local,data->getClientName())); } } else { if (data && *data) { - return new JackPortDescriptor(*data,data->getClientName()); + return Pointer( + new JackPortDescriptor(*data,data->getClientName())); } } } catch (Error e) { diff --git a/RtMidi.h b/RtMidi.h index ddc2360d..75de2ce8 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -340,7 +340,7 @@ class Pointer { }; #else template -typedef std::shared_ptr Pointer; +using Pointer = std::shared_ptr; #endif class MidiApi; From 443e8f3841982c675ce50ff3d12106509b61eae7 Mon Sep 17 00:00:00 2001 From: Douglas Heriot Date: Fri, 4 Sep 2015 00:13:00 +1000 Subject: [PATCH 091/210] Fix building on Windows with Visual Studio - Had to change C++11 detection. - Missing includes. - Fixed a bug introduced in my previous commit wrapping something with Pointer() --- RtMidi.cpp | 7 ++++--- RtMidi.h | 16 +++++++++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 557e01dc..e4820bdb 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -39,7 +39,9 @@ #include "RtMidi.h" #include #include +#include #include +#include NAMESPACE_RTMIDI_START #ifdef RTMIDI_GETTEXT @@ -4365,8 +4367,7 @@ Pointer MidiInWinMM :: getDescriptor(bool local) } WinMMPortDescriptor * retval = NULL; try { - retval = Pointer( - new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName())); + retval = new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); } catch (Error e) { try { error(e); @@ -4375,7 +4376,7 @@ Pointer MidiInWinMM :: getDescriptor(bool local) throw; } } - return retval; + return Pointer(retval); } diff --git a/RtMidi.h b/RtMidi.h index 75de2ce8..6d1fedaa 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -54,6 +54,16 @@ #define RTMIDI_DEPRECATED(func,message) func [[deprecated(message)]] #endif +// Check for C++11 support +#ifdef _MSC_VER && _MSC_VER >= 1800 +// At least Visual Studio 2013 +#define RTMIDI_SUPPORTS_CPP11 1 +#elif __cplusplus >= 201103L +#define RTMIDI_SUPPORTS_CPP11 1 +#else +#define RTMIDI_SUPPORTS_CPP11 0 +#endif + #include #include #include @@ -270,7 +280,7 @@ struct CompatibilityErrorInterface: ErrorInterface { -#if __cplusplus < 201103L +#if !RTMIDI_SUPPORTS_CPP11 class PortDescriptor; template @@ -327,8 +337,8 @@ class Pointer { Pointer & operator = (const Pointer & other) { if (ptr) { if (!(--ptr->count)) { - delete ptr->descriptor; - delete ptr; + delete ptr->descriptor; + delete ptr; } } ptr = other.ptr; From 2b3a29cdf6841460e0a92851d282e8d42396d38e Mon Sep 17 00:00:00 2001 From: Douglas Heriot Date: Sat, 5 Sep 2015 23:31:20 +1000 Subject: [PATCH 092/210] Oops, fix #ifdef --- RtMidi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RtMidi.h b/RtMidi.h index 6d1fedaa..e3b8b970 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -55,7 +55,7 @@ #endif // Check for C++11 support -#ifdef _MSC_VER && _MSC_VER >= 1800 +#if defined(_MSC_VER) && _MSC_VER >= 1800 // At least Visual Studio 2013 #define RTMIDI_SUPPORTS_CPP11 1 #elif __cplusplus >= 201103L From c24e696d3433db93f73d3b21b43d4deeb987122f Mon Sep 17 00:00:00 2001 From: Douglas Heriot Date: Sat, 5 Sep 2015 23:31:42 +1000 Subject: [PATCH 093/210] Fix Linux Alsa build - oops, extra bracket. --- RtMidi.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index e4820bdb..af3ecdde 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -3709,19 +3709,19 @@ Pointer MidiOutAlsa :: getDescriptor(bool local) try { if (local) { if (data && data->local.client) { - return Pointer( + return Pointer( new AlsaPortDescriptor(data->local, data->getClientName())); } } else { if (data && data->client) { - return Pointer( - new AlsaPortDescriptor(*data, data->getClientName()))); + return Pointer( + new AlsaPortDescriptor(*data, data->getClientName())); + } } + } catch (Error e) { + error(e); } -} catch (Error e) { - error(e); - } -return NULL; + return NULL; } PortList MidiOutAlsa :: getPortList(int capabilities) { From c889a1fa130a1df5d5971494aec1bfdc3e8b12f3 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 14 Oct 2015 19:52:09 +0200 Subject: [PATCH 094/210] Properly return after finishing the loopback test. --- tests/loopback.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/loopback.cpp b/tests/loopback.cpp index c8446174..be7e14ec 100644 --- a/tests/loopback.cpp +++ b/tests/loopback.cpp @@ -206,4 +206,5 @@ int main( int /* argc */, char * /*argv*/[] ) } catch ( rtmidi::Error &error ) { error.printMessage(); } + return 0; } From 74a0483f5da9f60c3cfc2d248fe8426f3778d778 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 14 Oct 2015 19:56:33 +0200 Subject: [PATCH 095/210] Fix deleting of callback objects. So far objects could decide whether they want to be cleaned up by RtMidi. But this was not used by cancelCallback and the rtmidiin destructor. Both functions call userCallback->delete_me(), now. --- RtMidi.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RtMidi.cpp b/RtMidi.cpp index af3ecdde..da488f83 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -462,6 +462,8 @@ MidiInApi :: MidiInApi( unsigned int queueSizeLimit ) MidiInApi :: ~MidiInApi( void ) { + if (userCallback) + userCallback->delete_me(); // Delete the MIDI queue. if ( queue.ringSize > 0 ) delete [] queue.ring; } @@ -508,6 +510,7 @@ void MidiInApi :: cancelCallback() return; } + userCallback->delete_me(); userCallback = 0; } From 850d4b4734a9df3c10766da79ed76bbd1ebdfd0a Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 14 Oct 2015 21:59:06 +0200 Subject: [PATCH 096/210] Add rtmidi_gettext to the keywords used by xgettext. For certain reasons we use rtmidi_gettext() in some files instead of calling gettext() or using the macro _(). This change must be made permanent. --- po/Makevars | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/po/Makevars b/po/Makevars index fdb198cf..f1d4cd38 100644 --- a/po/Makevars +++ b/po/Makevars @@ -8,7 +8,7 @@ subdir = po top_builddir = .. # These options get passed to xgettext. -XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ --keyword=gettext_noopt +XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ --keyword=gettext_noopt --keyword=rtmidi_gettext # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding From d9d97203d5d833ca4b7048bf2621d57806e3ffd7 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 14 Oct 2015 21:55:19 +0200 Subject: [PATCH 097/210] Change bug report address and package name to avoid confusion. We must be aware that it may take some time until the changes here can be merged upstream. In the meantime developers and users should be informed to blame the right person for bugs. --- configure.ac | 3 +- po/rtmidi-ts.pot | 440 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 442 insertions(+), 1 deletion(-) create mode 100644 po/rtmidi-ts.pot diff --git a/configure.ac b/configure.ac index f4df1d71..78f679f1 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,6 @@ # Process this file with autoconf to produce a configure script. -AC_INIT(RtMidi, 2.1.0, gary@music.mcgill.ca, rtmidi) +#AC_INIT(RtMidi, 2.1.0, gary@music.mcgill.ca, rtmidi) +AC_INIT(RtMidi-ts, 3.0, keinstein_junoir@gmx.net, rtmidi-ts) AC_CONFIG_AUX_DIR(config) AC_CONFIG_SRCDIR(RtMidi.cpp) AC_CONFIG_FILES([rtmidi-config librtmidi.pc Makefile tests/Makefile po/Makefile.in]) diff --git a/po/rtmidi-ts.pot b/po/rtmidi-ts.pot new file mode 100644 index 00000000..31553e53 --- /dev/null +++ b/po/rtmidi-ts.pot @@ -0,0 +1,440 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Gary P. Scavone +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#: RtMidi.cpp:3346 +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: rtmidi 2.1.0\n" +"Report-Msgid-Bugs-To: https://github.com/thestk/rtmidi\n" +"POT-Creation-Date: 2014-06-10 21:00+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: RtMidi.h:91 +msgid "Automatic selection" +msgstr "" + +#: RtMidi.h:92 +msgid "Core MIDI" +msgstr "" + +#: RtMidi.h:93 +msgid "ALSA" +msgstr "" + +#: RtMidi.h:94 +msgid "JACK" +msgstr "" + +#: RtMidi.h:95 +msgid "Windows Multimedia" +msgstr "" + +#: RtMidi.h:96 +msgid "DirectX/Kernel Streaming" +msgstr "" + +#: RtMidi.h:97 +msgid "NULL device" +msgstr "" + +#: RtMidi.h:98 +msgid "All available MIDI systems" +msgstr "" + +#: RtMidi.h:450 RtMidi.h:557 RtMidi.h:1070 RtMidi.h:1162 +msgid "Passed NULL pointer." +msgstr "" + +#: RtMidi.h:623 RtMidi.cpp:2093 +msgid "No data in message argument." +msgstr "" + +#: RtMidi.h:951 +msgid "A NULL pointer has been passed as port descriptor" +msgstr "" + +#: RtMidi.h:983 RtMidi.h:1195 RtMidi.h:1218 RtMidi.h:1231 +msgid "No valid MIDI system has been selected." +msgstr "" + +#: RtMidi.h:1052 +msgid "Could not find any valid MIDI system." +msgstr "" + +#: RtMidi.h:1075 +msgid "No valid MIDI system has been found." +msgstr "" + +#: RtMidi.h:1212 +msgid "No data in MIDI message." +msgstr "" + +#: RtMidi.cpp:71 +#, c-format +msgid "" +"Error formatting the error string:\n" +"'%s'\n" +"Found in %s::%s at \n" +"%s:%d" +msgstr "" + +#: RtMidi.cpp:83 +msgid "Error: could not format the error message" +msgstr "" + +#: RtMidi.cpp:258 RtMidi.cpp:361 +#, c-format +msgid "" +"Support for the selected MIDI system %d has not been compiled into the " +"RtMidi library." +msgstr "" + +#: RtMidi.cpp:276 RtMidi.cpp:378 +msgid "No supported MIDI system has been found." +msgstr "" + +#: RtMidi.cpp:457 +msgid "A callback function is already set." +msgstr "" + +#: RtMidi.cpp:463 +msgid "The callback function value is invalid." +msgstr "" + +#: RtMidi.cpp:476 +msgid "No callback function was set." +msgstr "" + +#: RtMidi.cpp:499 +msgid "" +"Returning an empty MIDI message as all input is handled by a callback " +"function." +msgstr "" + +#: RtMidi.cpp:1154 +msgid "Could not get the unique identifier of a midi endpoint." +msgstr "" + +#: RtMidi.cpp:1165 +msgid "" +"Could not get the endpoint back from the unique identifier of a midi " +"endpoint." +msgstr "" + +#: RtMidi.cpp:1181 +msgid "Could not get the entity of a midi endpoint." +msgstr "" + +#: RtMidi.cpp:1258 RtMidi.cpp:1298 +msgid "Error creating OS X MIDI port because of invalid port flags." +msgstr "" + +#: RtMidi.cpp:1262 RtMidi.cpp:1302 RtMidi.cpp:1804 +msgid "Error creating OS-X MIDI port." +msgstr "" + +#: RtMidi.cpp:1355 +msgid "Error creating OS-X MIDI client object." +msgstr "" + +#: RtMidi.cpp:1693 RtMidi.cpp:1785 RtMidi.cpp:1939 RtMidi.cpp:2035 +#: RtMidi.cpp:3052 RtMidi.cpp:3169 RtMidi.cpp:3419 RtMidi.cpp:3567 +#: RtMidi.cpp:4217 RtMidi.cpp:4492 RtMidi.cpp:4551 RtMidi.cpp:5311 +#: RtMidi.cpp:5600 +msgid "A valid connection already exists." +msgstr "" + +#: RtMidi.cpp:1701 RtMidi.cpp:3059 RtMidi.cpp:4224 +msgid "No MIDI input sources found." +msgstr "" + +#: RtMidi.cpp:1710 RtMidi.cpp:1867 RtMidi.cpp:1922 RtMidi.cpp:1956 +#: RtMidi.cpp:3069 RtMidi.cpp:3439 RtMidi.cpp:4392 RtMidi.cpp:4470 +#: RtMidi.cpp:4505 RtMidi.cpp:5411 RtMidi.cpp:5701 +#, c-format +msgid "The 'portNumber' argument (%d) is invalid." +msgstr "" + +#: RtMidi.cpp:1722 +msgid "Error creating OS-X MIDI input port." +msgstr "" + +#: RtMidi.cpp:1732 +msgid "Error getting MIDI input source reference." +msgstr "" + +#: RtMidi.cpp:1742 +msgid "Error connecting OS-X MIDI input port." +msgstr "" + +#: RtMidi.cpp:1764 +msgid "Error creating virtual OS-X MIDI destination." +msgstr "" + +#: RtMidi.cpp:1780 RtMidi.cpp:2030 RtMidi.cpp:3164 RtMidi.cpp:3562 +#: RtMidi.cpp:5305 RtMidi.cpp:5594 +msgid "Data has not been allocated." +msgstr "" + +#: RtMidi.cpp:1790 RtMidi.cpp:2040 +msgid "" +"Core MIDI has been instructed to open a non-Core MIDI port. This doesn't " +"work." +msgstr "" + +#: RtMidi.cpp:1947 +msgid "No MIDI output destinations found." +msgstr "" + +#: RtMidi.cpp:1968 +msgid "Error creating OS-X MIDI output port." +msgstr "" + +#: RtMidi.cpp:1978 +msgid "Error getting MIDI output destination reference." +msgstr "" + +#: RtMidi.cpp:2003 +msgid "A virtual output port already exists." +msgstr "" + +#: RtMidi.cpp:2014 +msgid "Error creating OS-X virtual MIDI source." +msgstr "" + +#: RtMidi.cpp:2153 +msgid "Could not allocate packet list." +msgstr "" + +#: RtMidi.cpp:2162 +msgid "Error sending MIDI to virtual destinations." +msgstr "" + +#: RtMidi.cpp:2171 RtMidi.cpp:3548 +msgid "Error sending MIDI message to port." +msgstr "" + +#: RtMidi.cpp:2374 RtMidi.cpp:2636 RtMidi.cpp:3113 RtMidi.cpp:3174 +#: RtMidi.cpp:3465 +msgid "Could not allocate ALSA port subscription." +msgstr "" + +#: RtMidi.cpp:2389 RtMidi.cpp:3122 RtMidi.cpp:3475 +msgid "Error making ALSA port connection." +msgstr "" + +#: RtMidi.cpp:2459 RtMidi.cpp:2946 +msgid "Error creating ALSA sequencer client object." +msgstr "" + +#: RtMidi.cpp:2698 RtMidi.cpp:3148 RtMidi.cpp:3278 +msgid "Error starting MIDI input thread!" +msgstr "" + +#: RtMidi.cpp:2964 +msgid "Error creating pipe objects." +msgstr "" + +#: RtMidi.cpp:3044 RtMidi.cpp:3411 +msgid "Error looking for port name." +msgstr "" + +#: RtMidi.cpp:3100 +msgid "Error creating ALSA input port." +msgstr "" + +#: RtMidi.cpp:3179 RtMidi.cpp:3577 +msgid "" +"ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work." +msgstr "" + +#: RtMidi.cpp:3244 RtMidi.cpp:3502 +msgid "Error creating ALSA virtual port." +msgstr "" + +#: RtMidi.cpp:3363 +msgid "Error initializing MIDI event parser." +msgstr "" + +#: RtMidi.cpp:3370 RtMidi.cpp:3526 +msgid "Error while allocating buffer memory." +msgstr "" + +#: RtMidi.cpp:3427 +msgid "No MIDI output sinks found." +msgstr "" + +#: RtMidi.cpp:3454 +msgid "Error creating ALSA output port." +msgstr "" + +#: RtMidi.cpp:3519 +msgid "ALSA error resizing MIDI event buffer." +msgstr "" + +#: RtMidi.cpp:3540 +msgid "Event parsing error." +msgstr "" + +#: RtMidi.cpp:3572 +msgid "Error allocating ALSA port subscription." +msgstr "" + +#: RtMidi.cpp:3709 +#, c-format +msgid "The port argument %d is invalid." +msgstr "" + +#: RtMidi.cpp:4198 +msgid "No MIDI input devices currently available." +msgstr "" + +#: RtMidi.cpp:4209 +msgid "Failed to initialize a critical section." +msgstr "" + +#: RtMidi.cpp:4233 +#, c-format +msgid "the 'portNumber' argument (%d) is invalid." +msgstr "" + +#: RtMidi.cpp:4245 +msgid "Error creating Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4261 +msgid "Error initializing data for Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4270 +msgid "Could not register the input buffer for Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4279 +msgid "Error starting Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4290 RtMidi.cpp:4538 +msgid "Virtual ports are not available Windows Multimedia MIDI API." +msgstr "" + +#: RtMidi.cpp:4297 RtMidi.cpp:4546 +msgid "" +"Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI " +"port. This doesn't work." +msgstr "" + +#: RtMidi.cpp:4302 +msgid "" +"We are overwriting an existing connection. This is probably a programming " +"error." +msgstr "" + +#: RtMidi.cpp:4307 +msgid "Trying to open a non-input port as input MIDI port. This doesn't work." +msgstr "" + +#: RtMidi.cpp:4317 RtMidi.cpp:4566 +msgid "" +"Some change in the arrangement of MIDI input ports invalidated the port " +"descriptor." +msgstr "" + +#: RtMidi.cpp:4332 +msgid "The handle is invalid. Did you disconnect the device?" +msgstr "" + +#: RtMidi.cpp:4336 RtMidi.cpp:4585 +msgid "" +"The system has no driver for our handle :-(. Did you disconnect the device?" +msgstr "" + +#: RtMidi.cpp:4340 RtMidi.cpp:4589 +msgid "Out of memory." +msgstr "" + +#: RtMidi.cpp:4370 +msgid "Error closing Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4448 +msgid "No MIDI output devices currently available." +msgstr "" + +#: RtMidi.cpp:4499 +msgid "No MIDI output destinations found!" +msgstr "" + +#: RtMidi.cpp:4517 +msgid "Error creating Windows MM MIDI output port." +msgstr "" + +#: RtMidi.cpp:4556 +msgid "The port descriptor cannot be used to open an output port." +msgstr "" + +#: RtMidi.cpp:4581 +msgid "The internal handle is invalid. Did you disconnect the device?" +msgstr "" + +#: RtMidi.cpp:4611 +msgid "Message argument is empty." +msgstr "" + +#: RtMidi.cpp:4623 +msgid "Error while allocating sysex message memory." +msgstr "" + +#: RtMidi.cpp:4639 +msgid "Error preparing sysex header." +msgstr "" + +#: RtMidi.cpp:4648 +msgid "Error sending sysex message." +msgstr "" + +#: RtMidi.cpp:4661 +msgid "Message size is greater than 3 bytes (and not sysex)." +msgstr "" + +#: RtMidi.cpp:4677 +msgid "Error sending MIDI message." +msgstr "" + +#: RtMidi.cpp:4928 +msgid "Could not connect to JACK server. Is it runnig?" +msgstr "" + +#: RtMidi.cpp:5131 +msgid "Error opening JACK port subscription." +msgstr "" + +#: RtMidi.cpp:5238 RtMidi.cpp:5521 +msgid "JACK server not running?" +msgstr "" + +#: RtMidi.cpp:5273 RtMidi.cpp:5338 RtMidi.cpp:5562 RtMidi.cpp:5627 +msgid "Error creating JACK port." +msgstr "" + +#: RtMidi.cpp:5293 RtMidi.cpp:5582 +msgid "Error creating JACK virtual port." +msgstr "" + +#: RtMidi.cpp:5317 RtMidi.cpp:5606 +msgid "" +"JACK has been instructed to open a non-JACK MIDI port. This doesn't work." +msgstr "" + +#: RtMidi.cpp:5404 RtMidi.cpp:5694 +msgid "No ports available." +msgstr "" From 60ec696d7de5ec979d2011eff61a5659f9740ad2 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 14 Oct 2015 22:16:25 +0200 Subject: [PATCH 098/210] Updated translation files: rtmidi.pot de.po --- po/de.mo | Bin 12222 -> 13272 bytes po/de.po | 266 +++++++++++++++++++++++++++++--------------------- po/rtmidi.pot | 262 ++++++++++++++++++++++++++++--------------------- 3 files changed, 306 insertions(+), 222 deletions(-) diff --git a/po/de.mo b/po/de.mo index 4e5cab19025b7bbab6828efab81e4c70367037be..35d26d00faae1a850ad8a22d151605fe825f42e6 100644 GIT binary patch delta 3108 zcmZwIeQX>@8OQOllRAzY$1h17J1OWk1JLPUfRRzw96Ab~;=Ek!6GAw~QJNG+)F{oP$r zBN*xNXLj#)=b2|_&Obc+T72>MwJX11Xfwn;M6kjb-MCT4ADUflOcyrc{WyX5;Q}_} zbGQxp5mCapT>_Y{x#-0CD7t=CimB zU&lUNy~ddRID|_4Q&^9e@d5k+K8UwaiLI?HyuTMM*OR!7@y$G)CT@Hk8}NGZ`c2%; zb;(*|T5%A!;4~_+r}19=4r;((q9*bdw&9klLSo0Uo$FZ~!X?!A-oQ@AH|5oZ7xtqP zIg6U%Cr~rHiYoa{)WC1y`>?U5;KQh;IgOif5tYCa>iM4(Kfi@~e|c>ofvvcx7f#aI zh95<}=mk{iZlGrN4_uFpETFD;pw|2`9LFhC>0d;x_4T5Ez+SHZiQU-6OISS5zhCrss2RM2n$gw`g_(|`28yAcdjfg4c@CA>%cv##4Qk2$g{+3zQdgKj z4<6(C08ZegI_m!@o!i_{M*BAw9`vx6>t}HgZ=l7y8GQh^;USFUDCV#e-^Sh8#zs1h z38Z-DDn5=kP~)^yrYA~`IkiYIy?B~>Phd+;Lm;o_@wR1!^39~{T`}yMT;Y#q^d@Te zuIFi=*}!Xf+<@|$8>DJNaihZM_1QG4rR(eD*MzlDqXpqf9* zbP!n{6EFG{TCQJ0&G6?%%b2DrGKdX$4mm*PY5X`|#u>by**JU#E&d&cv5qq9_?_;g z{%7dC!VQu!Yr6PR!G2u8FX92LVl?gcQ+NiC3Y1g0*gy1eMLV@}ftJ3ifIK=ePp3Uv?7wuHDhJ zPpXI ^KP7@bFnQ9|u5VlAN~skWccrYs|>2^}T&VZP}XE=uV1oF=9S9npP64WZMa zX7hiId8jDcCg18cP4-y+zmkrc8o#V}v<+NsA|{A4xsmcsC2fZ%hOF;`tnay)T}TFr zbT+VaetJF`OL}n|u}8*-$E}-pUXVMpy1FbZt=SOvS5=0os#osvT_$-Ue5bl0++6)s zc(J;&GDzDaJZWQYJ{b*{s=vMYh|6Rmac9qEUDnxDayA(-U?iGwv2b_Io((qbTQ42l zF;YhuuX&+C11G&X@|ns`PdneH=bi6oy^gT5_K_|PGwuy%XJ^k3*b|9l#zs?-Os1H- z%kWY=o%NzYGVMiD$>4nMvD!;3J14yvFTLOurd4=5FHQR$6(?RiByDvY%&wrR9KO>0mp zxe)Q~%>QH_R<{1MNxP$cgybVrZmzIO`S-?MDw3Uctkuod*}ZqH6`5t6J*35=;DJk} zg8bW^9nE?(S}umBXqMHUUcMI3dhy)Q13hIsC%q{*6Y;!&tlm4WvUV)sa3o_V3JW;v UQZW~3{Y)5XT$lTFM_|(kd&CR=>iiA{ygU){Bgd|>-XHw^ZR|D@9+6` z;`(stZf4A)(Z+~8q9WRC4x8iH&^i;$g4l(R;Hy}O@8S;p1Y_`L+=;(q7iK4#<>FDy z!Wrae^K1^{n^{r1@O7-fHQbHS51F;&9@KzCxCJj@30}ie zyo(x8LUQE)tI^MXFY5nJU;)p!i*&YfVAVZfb_bi;{~L?3A;qi+M^FPhi`#Go^}x@u z4FAG%+?E;{ST|O(KY?wyh`R1J1~4j(|Ks_#i;iYCh?>!PREn?Y0{jZ|aUJyva?;Hn z#zxcw`%(9u!2)~-^`MVY_y39&n2{05ObceS{{n_IgIPLyhs)T7E2xy-N4>+;OtU&H zMY3wcs0U1;9=wDaaM*JVHLwS$f$pFHG=VnM{|=+>dpV2zt2h?fXdoY;Qhf`R`gJ5* zww>W>#8qs1u^kVig9G>zYCtVHk^3f513r%}cmw?yx5=yti?IjCHj)4Rbgpoq8Si5s z)@(Lo@HU4dxP*GZI?hHhTc)v>{Y#`r@AwCFQ_OT_3o4^ixDQWYKYoNN_GG5dn5`m2 zhXr75ID|c@0W703v5u{nNB(x>5mW{iP{;4#lUPJW>b_~zeK%04{>?ic%To`qKY#&z z4{I^>4IQOA(H}90jqDG4I-XzPFvsJmFwJlRb=`vJm!1g}f(E)5mFibKuOW}JKfLql zR5Ak(StlKh=q=Bis6YM(yRn|>)ZiIx#t%`~|A`uSAtkQ!-Kh0Giw$@gb^bf7!dOnW zU@fZFPGY0h{{=d_VGZ@+NaL<*Y{VFx#6CQZynb6nCTq7*tK|W*GOe9|Rn;Fx#^x?9 z)y8G^M4$GF zAfbEISQIu$9MBH!F+xSh9Z_me>~U(6nlX-CpD~t!^68O7s$s5^4p+fZK~?$1RG@9O&^5id`G}M>q7<<(uMG zcsf#>Zq*+`trmTZ+Qa#YxxVmtQc9e&kbc!Uo009jlrin3WnOZ=&a8K8vKE~0v--l% zXD`Ks%eTJmYpAUZ)K>-r{+d8jU9db53@7_)D%j@uhd1oU)*EuIy81ru, YEAR. # -#: RtMidi.cpp:3346 msgid "" msgstr "" "Project-Id-Version: rtmidi 2.1.0\n" "Report-Msgid-Bugs-To: https://github.com/thestk/rtmidi\n" -"POT-Creation-Date: 2014-06-10 21:00+0200\n" -"PO-Revision-Date: 2014-06-10 20:59+0100\n" +"POT-Creation-Date: 2015-10-14 22:01+0200\n" +"PO-Revision-Date: 2015-10-14 22:10+0200\n" "Last-Translator: Tobias Schlemmer \n" "Language-Team: German translation team \n" "Language: de\n" @@ -17,73 +16,77 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 1.5.4\n" +"X-Generator: Poedit 1.8.5\n" "X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-Basepath: .\n" "X-Poedit-KeywordsList: gettext_noopt\n" "X-Poedit-SearchPath-0: /home/tobias/macbookbackup/Entwicklung/rtmidi-beides\n" -#: RtMidi.h:91 +#: RtMidi.h:107 msgid "Automatic selection" msgstr "Automatische Auswahl" -#: RtMidi.h:92 +#: RtMidi.h:108 msgid "Core MIDI" msgstr "Core MIDI" -#: RtMidi.h:93 +#: RtMidi.h:109 msgid "ALSA" msgstr "ALSA" -#: RtMidi.h:94 +#: RtMidi.h:110 msgid "JACK" msgstr "JACK" -#: RtMidi.h:95 +#: RtMidi.h:111 msgid "Windows Multimedia" msgstr "Windows Multimedia" -#: RtMidi.h:96 +#: RtMidi.h:112 msgid "DirectX/Kernel Streaming" msgstr "DirectX/Kernel Streaming" -#: RtMidi.h:97 +#: RtMidi.h:113 msgid "NULL device" msgstr "Keine Funktion." -#: RtMidi.h:98 +#: RtMidi.h:114 msgid "All available MIDI systems" msgstr "Alle verfügbaren MIDI-Systeme." -#: RtMidi.h:450 RtMidi.h:557 RtMidi.h:1070 RtMidi.h:1162 +#: RtMidi.h:530 RtMidi.h:691 RtMidi.h:1220 RtMidi.h:1312 msgid "Passed NULL pointer." msgstr "Nullzeiger übergeben." -#: RtMidi.h:623 RtMidi.cpp:2093 +#: RtMidi.h:723 RtMidi.cpp:2161 msgid "No data in message argument." msgstr "Keine Daten in der MIDI-Nachricht." -#: RtMidi.h:951 +#: RtMidi.h:1082 msgid "A NULL pointer has been passed as port descriptor" msgstr "Ein leerer Zeiger wurde als Schnittstellenbeschreibung übergeben." -#: RtMidi.h:983 RtMidi.h:1195 RtMidi.h:1218 RtMidi.h:1231 +#: RtMidi.h:1114 RtMidi.h:1345 RtMidi.h:1369 RtMidi.h:1382 msgid "No valid MIDI system has been selected." msgstr "Es wurde kein benutzbares MIDI-System ausgewählt." -#: RtMidi.h:1052 +#: RtMidi.h:1184 msgid "Could not find any valid MIDI system." msgstr "Es konnte kein benutzbares MIDI-System gefunden werden." -#: RtMidi.h:1075 +#: RtMidi.h:1225 msgid "No valid MIDI system has been found." msgstr "Es konnte kein benutzbares MIDI-System gefunden werden." -#: RtMidi.h:1212 +#: RtMidi.h:1363 msgid "No data in MIDI message." msgstr "Keine Daten in der MIDI-Nachricht." -#: RtMidi.cpp:71 +#: RtMidi.h:1608 RtMidi.h:1630 +msgid "MidiInDummy: This class provides no functionality." +msgstr "MidiInDummy: Diese Klasse stellt keine Funktionen zur verfügung." + +#: RtMidi.cpp:87 #, c-format msgid "" "Error formatting the error string:\n" @@ -96,11 +99,11 @@ msgstr "" "gefunden in %s::%s bei \n" "%s:%d" -#: RtMidi.cpp:83 +#: RtMidi.cpp:99 msgid "Error: could not format the error message" msgstr "Fehler: Ich konnte eine Fehlermeldung nicht formatieren." -#: RtMidi.cpp:258 RtMidi.cpp:361 +#: RtMidi.cpp:267 RtMidi.cpp:370 #, c-format msgid "" "Support for the selected MIDI system %d has not been compiled into the " @@ -109,23 +112,23 @@ msgstr "" "Die Unterstützung für das gewählte MIDI-System %d wurde nicht in die RtMidi-" "Bibliothek eingebaut." -#: RtMidi.cpp:276 RtMidi.cpp:378 +#: RtMidi.cpp:285 RtMidi.cpp:387 msgid "No supported MIDI system has been found." msgstr "Es konnte kein benutzbares MIDI-System gefunden werden." -#: RtMidi.cpp:457 +#: RtMidi.cpp:474 RtMidi.cpp:491 msgid "A callback function is already set." msgstr "Es wurde schon eine Rückruffunktion gesetzt." -#: RtMidi.cpp:463 +#: RtMidi.cpp:480 RtMidi.cpp:497 msgid "The callback function value is invalid." msgstr "Der Funktionswert einer aufgerufenen Rückruffunktion ist ungültig." -#: RtMidi.cpp:476 +#: RtMidi.cpp:508 msgid "No callback function was set." msgstr "Es wurde keine Rückruffunktion gesetzt." -#: RtMidi.cpp:499 +#: RtMidi.cpp:530 msgid "" "Returning an empty MIDI message as all input is handled by a callback " "function." @@ -133,13 +136,13 @@ msgstr "" "Es wird eine leere MIDI-Nachricht generiert, weil alle Eingaben durch eine " "Rückruf-Funktion (engl. callback) abgefangen werden." -#: RtMidi.cpp:1154 +#: RtMidi.cpp:1183 msgid "Could not get the unique identifier of a midi endpoint." msgstr "" "Konnte die eindeutige Identifikation (UUID) eines MIDI-Endpunktes nicht " "bekommen." -#: RtMidi.cpp:1165 +#: RtMidi.cpp:1193 msgid "" "Could not get the endpoint back from the unique identifier of a midi " "endpoint." @@ -147,64 +150,69 @@ msgstr "" "Konnte den MIDI-Endpunkt einer eindeutige Identifikation (UUID) nicht " "bekommen." -#: RtMidi.cpp:1181 +#: RtMidi.cpp:1208 msgid "Could not get the entity of a midi endpoint." msgstr "Konnte die Geräteeinheit eines MIDI-Endpunktes nicht bekommen." -#: RtMidi.cpp:1258 RtMidi.cpp:1298 +#: RtMidi.cpp:1273 RtMidi.cpp:1313 msgid "Error creating OS X MIDI port because of invalid port flags." msgstr "" "Konnte die OS X-MIDI-Schnittstelle nicht anlegen, da ungültige Eigenschaften " "angegeben wurden." -#: RtMidi.cpp:1262 RtMidi.cpp:1302 RtMidi.cpp:1804 +#: RtMidi.cpp:1277 RtMidi.cpp:1317 RtMidi.cpp:1858 msgid "Error creating OS-X MIDI port." msgstr "Es gab einen Fehler beim Erzeugen der MIDI-Schnittstelle." -#: RtMidi.cpp:1355 +#: RtMidi.cpp:1370 msgid "Error creating OS-X MIDI client object." msgstr "Fehler beim erzeugen des OS-X-MIDI-Klienten." -#: RtMidi.cpp:1693 RtMidi.cpp:1785 RtMidi.cpp:1939 RtMidi.cpp:2035 -#: RtMidi.cpp:3052 RtMidi.cpp:3169 RtMidi.cpp:3419 RtMidi.cpp:3567 -#: RtMidi.cpp:4217 RtMidi.cpp:4492 RtMidi.cpp:4551 RtMidi.cpp:5311 -#: RtMidi.cpp:5600 +#: RtMidi.cpp:1626 RtMidi.cpp:1696 RtMidi.cpp:3006 RtMidi.cpp:4184 +#: RtMidi.cpp:5250 +msgid "Error: Message queue limit reached." +msgstr "Fehler: Die Nachrichten-Warteschlange ist überlang." + +#: RtMidi.cpp:1747 RtMidi.cpp:1839 RtMidi.cpp:1997 RtMidi.cpp:2090 +#: RtMidi.cpp:3149 RtMidi.cpp:3266 RtMidi.cpp:3534 RtMidi.cpp:3682 +#: RtMidi.cpp:4240 RtMidi.cpp:4535 RtMidi.cpp:4594 RtMidi.cpp:5438 +#: RtMidi.cpp:5655 msgid "A valid connection already exists." msgstr "Es existiert schon eine gültige Verbindung." -#: RtMidi.cpp:1701 RtMidi.cpp:3059 RtMidi.cpp:4224 +#: RtMidi.cpp:1755 RtMidi.cpp:3156 RtMidi.cpp:4247 msgid "No MIDI input sources found." msgstr "Keine MIDI-Eingabe-Geräte gefunden." -#: RtMidi.cpp:1710 RtMidi.cpp:1867 RtMidi.cpp:1922 RtMidi.cpp:1956 -#: RtMidi.cpp:3069 RtMidi.cpp:3439 RtMidi.cpp:4392 RtMidi.cpp:4470 -#: RtMidi.cpp:4505 RtMidi.cpp:5411 RtMidi.cpp:5701 +#: RtMidi.cpp:1764 RtMidi.cpp:1922 RtMidi.cpp:1980 RtMidi.cpp:2011 +#: RtMidi.cpp:3166 RtMidi.cpp:3554 RtMidi.cpp:4435 RtMidi.cpp:4513 +#: RtMidi.cpp:4548 RtMidi.cpp:5534 RtMidi.cpp:5746 #, c-format msgid "The 'portNumber' argument (%d) is invalid." msgstr "Die Portnummer %d ist ungültig." -#: RtMidi.cpp:1722 +#: RtMidi.cpp:1776 msgid "Error creating OS-X MIDI input port." msgstr "Fehler beim Erzeugen der OS-X-MIDI-Eingabe-Schnittstelle." -#: RtMidi.cpp:1732 +#: RtMidi.cpp:1786 msgid "Error getting MIDI input source reference." msgstr "Konnte keine Referenz zum MIDI-Eingang bekommen." -#: RtMidi.cpp:1742 +#: RtMidi.cpp:1796 msgid "Error connecting OS-X MIDI input port." msgstr "Fehler beim verbinden mit dem OS-X-MIDI-Eingang." -#: RtMidi.cpp:1764 +#: RtMidi.cpp:1818 msgid "Error creating virtual OS-X MIDI destination." msgstr "Konnte den virtuellen OS-X-MIDI-Ausgang nicht erzeugen." -#: RtMidi.cpp:1780 RtMidi.cpp:2030 RtMidi.cpp:3164 RtMidi.cpp:3562 -#: RtMidi.cpp:5305 RtMidi.cpp:5594 +#: RtMidi.cpp:1834 RtMidi.cpp:2085 RtMidi.cpp:3261 RtMidi.cpp:3677 +#: RtMidi.cpp:5432 RtMidi.cpp:5649 msgid "Data has not been allocated." msgstr "Daten konnten nicht angelegt werden." -#: RtMidi.cpp:1790 RtMidi.cpp:2040 +#: RtMidi.cpp:1844 RtMidi.cpp:2095 msgid "" "Core MIDI has been instructed to open a non-Core MIDI port. This doesn't " "work." @@ -212,153 +220,189 @@ msgstr "" "Core-MIDI wurde angewiesen, eine nicht-Core-MIDI-Schnittstelle zu öffnen. " "Das geht nicht." -#: RtMidi.cpp:1947 +#: RtMidi.cpp:2005 msgid "No MIDI output destinations found." msgstr "Es wurden keine MIDI-Ausgabegeräte gefunden." -#: RtMidi.cpp:1968 +#: RtMidi.cpp:2023 msgid "Error creating OS-X MIDI output port." msgstr "Fehler beim Erzeugen der OS-X-MIDI-Ausgabe-Schnittstelle." -#: RtMidi.cpp:1978 +#: RtMidi.cpp:2033 msgid "Error getting MIDI output destination reference." msgstr "Konnte keine Referenz zum MIDI-Ausgang bekommen." -#: RtMidi.cpp:2003 +#: RtMidi.cpp:2058 msgid "A virtual output port already exists." msgstr "Es gibt schon einen virtuellen MIDI-Ausgang." -#: RtMidi.cpp:2014 +#: RtMidi.cpp:2069 msgid "Error creating OS-X virtual MIDI source." msgstr "Konnte den virtuellen OS-X-MIDI-Eingang nicht erzeugen." -#: RtMidi.cpp:2153 +#: RtMidi.cpp:2221 msgid "Could not allocate packet list." msgstr "Konnte die Paketliste nicht anlegen." -#: RtMidi.cpp:2162 +#: RtMidi.cpp:2230 msgid "Error sending MIDI to virtual destinations." msgstr "Konnte MIDI-Daten nicht zu virtuellen Ausgängen senden." -#: RtMidi.cpp:2171 RtMidi.cpp:3548 +#: RtMidi.cpp:2239 RtMidi.cpp:3663 msgid "Error sending MIDI message to port." msgstr "Fehler beim Senden der MIDI-Nachricht zum Ausgang." -#: RtMidi.cpp:2374 RtMidi.cpp:2636 RtMidi.cpp:3113 RtMidi.cpp:3174 -#: RtMidi.cpp:3465 +#: RtMidi.cpp:2443 RtMidi.cpp:2704 RtMidi.cpp:3210 RtMidi.cpp:3271 +#: RtMidi.cpp:3580 msgid "Could not allocate ALSA port subscription." msgstr "" "Konnte keinen Speicher für das Abonnoment der ALSA-MIDI-Schnittstelle " "bekommen." -#: RtMidi.cpp:2389 RtMidi.cpp:3122 RtMidi.cpp:3475 +#: RtMidi.cpp:2458 RtMidi.cpp:3219 RtMidi.cpp:3590 msgid "Error making ALSA port connection." msgstr "Konnte zwei ALSA-Schnittstellen nicht miteinander verbinden." -#: RtMidi.cpp:2459 RtMidi.cpp:2946 +#: RtMidi.cpp:2528 RtMidi.cpp:3461 msgid "Error creating ALSA sequencer client object." msgstr "Fehler beim erzeugen des ALSA-Klienten." -#: RtMidi.cpp:2698 RtMidi.cpp:3148 RtMidi.cpp:3278 +#: RtMidi.cpp:2766 RtMidi.cpp:3245 RtMidi.cpp:3394 msgid "Error starting MIDI input thread!" msgstr "Konnte den MIDI-Eingabe-Prozess nicht starten." -#: RtMidi.cpp:2964 +#: RtMidi.cpp:2804 RtMidi.cpp:3478 +msgid "Error initializing MIDI event parser." +msgstr "Fehler bei der Initialisierung des MIDI-Ereeignisparsers." + +#: RtMidi.cpp:2817 +msgid "Error initializing buffer memory." +msgstr "Fehler beim Anlegen des Pufferspeichers." + +#: RtMidi.cpp:2851 +msgid "MIDI input buffer overrun." +msgstr "MIDI-Eingabepuffer übergelaufen." + +#: RtMidi.cpp:2861 +msgid "ALSA returned without providing a MIDI event." +msgstr "ALSA kam zurück ohne ein MIDI-Ereignis mitzubringen." + +#: RtMidi.cpp:2871 +#, c-format +msgid "" +"Unknown MIDI input error.\n" +"The system reports:\n" +"%s" +msgstr "" +"Unbekannter MIDI-Eingabefehler.\n" +"Das System meldet:\n" +"%s" + +#: RtMidi.cpp:2929 +msgid "Error resizing buffer memory." +msgstr "Fehler beim Ändern der Grüße des Pufferspeichers." + +#: RtMidi.cpp:2980 +msgid "Event parsing error or not a MIDI event." +msgstr "" +"Analyse eines Ereignisses fehlgeschlagen oder es war kein MIDI-Ereignis." + +#: RtMidi.cpp:3061 msgid "Error creating pipe objects." msgstr "Fehler beim anlegen einer Pipe." -#: RtMidi.cpp:3044 RtMidi.cpp:3411 +#: RtMidi.cpp:3141 RtMidi.cpp:3526 msgid "Error looking for port name." msgstr "Fehler beim Suchen nach einem Schnittstellennamen." -#: RtMidi.cpp:3100 +#: RtMidi.cpp:3197 msgid "Error creating ALSA input port." msgstr "Fehler beim Erzeugen der ALSA-Eingabe-Schnittstelle." -#: RtMidi.cpp:3179 RtMidi.cpp:3577 +#: RtMidi.cpp:3276 RtMidi.cpp:3692 msgid "" "ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work." msgstr "" "ALSA wurde angewiesen, eine nicht-ALSA-MIDI-Schnittstelle zu öffnen. Das " "geht nicht." -#: RtMidi.cpp:3244 RtMidi.cpp:3502 +#: RtMidi.cpp:3360 RtMidi.cpp:3617 msgid "Error creating ALSA virtual port." msgstr "Fehler beim Erzeugen einer virtuellen ALSA-Schnittstelle." -#: RtMidi.cpp:3363 -msgid "Error initializing MIDI event parser." -msgstr "Fehler bei der Initialisierung des MIDI-Ereeignisparsers." - -#: RtMidi.cpp:3370 RtMidi.cpp:3526 +#: RtMidi.cpp:3485 RtMidi.cpp:3641 msgid "Error while allocating buffer memory." msgstr "Fehler beim Anlegen des Pufferspeichers." -#: RtMidi.cpp:3427 +#: RtMidi.cpp:3542 msgid "No MIDI output sinks found." msgstr "Es wurden kiene Midi-Ausgabegeräte gefunden." -#: RtMidi.cpp:3454 +#: RtMidi.cpp:3569 msgid "Error creating ALSA output port." msgstr "Fehler beim Erzeugen der ALSA-Ausgangs." -#: RtMidi.cpp:3519 +#: RtMidi.cpp:3634 msgid "ALSA error resizing MIDI event buffer." msgstr "ALSA-Fehler beim Verändern der Größe des MIDI-Nachrichten-Puffers." -#: RtMidi.cpp:3540 +#: RtMidi.cpp:3655 msgid "Event parsing error." msgstr "Fehler bei der Analyse eines Ereignisses." -#: RtMidi.cpp:3572 +#: RtMidi.cpp:3687 msgid "Error allocating ALSA port subscription." msgstr "" "Konnte keinen Speicher für das Abonnoment der ALSA-MIDI-Schnittstelle " "bekommen." -#: RtMidi.cpp:3709 +#: RtMidi.cpp:3837 #, c-format msgid "The port argument %d is invalid." msgstr "Das Schnittstellenargument %d ist ungültig." -#: RtMidi.cpp:4198 +#: RtMidi.cpp:4159 +msgid "Error sending sysex to Midi device." +msgstr "Fehler beim Senden der SysEx-Nachricht zum MIDI-Gerät." + +#: RtMidi.cpp:4222 msgid "No MIDI input devices currently available." msgstr "Es gibt momentan keine MIDI-Eingabegeräte." -#: RtMidi.cpp:4209 +#: RtMidi.cpp:4232 msgid "Failed to initialize a critical section." msgstr "Konnte kritischen Bereich nicht initialisieren." -#: RtMidi.cpp:4233 +#: RtMidi.cpp:4256 #, c-format msgid "the 'portNumber' argument (%d) is invalid." msgstr "Die Portnummer %d ist ungültig." -#: RtMidi.cpp:4245 +#: RtMidi.cpp:4268 msgid "Error creating Windows MM MIDI input port." msgstr "Konnte den Windows-Multimedia-MIDI-Eingang nicht erzeugen." -#: RtMidi.cpp:4261 +#: RtMidi.cpp:4284 msgid "Error initializing data for Windows MM MIDI input port." msgstr "" "Fehler beim Erzeugen der daten für einen Windows Multimedia MIDI-Eingang." -#: RtMidi.cpp:4270 +#: RtMidi.cpp:4293 msgid "Could not register the input buffer for Windows MM MIDI input port." msgstr "" "Konnte den Eingabe-Puffer eines Windows-Multimedia-MIDI-Eingangs nicht " "erzeugen." -#: RtMidi.cpp:4279 +#: RtMidi.cpp:4302 msgid "Error starting Windows MM MIDI input port." msgstr "Konnte einen Windows-Multimedia-MIDI-Eingang nicht aktivieren." -#: RtMidi.cpp:4290 RtMidi.cpp:4538 +#: RtMidi.cpp:4313 RtMidi.cpp:4581 msgid "Virtual ports are not available Windows Multimedia MIDI API." msgstr "" "Windows Multimedia unterstützt keine virtuellen MIDI-Ein- und -Ausgänge." -#: RtMidi.cpp:4297 RtMidi.cpp:4546 +#: RtMidi.cpp:4320 RtMidi.cpp:4589 msgid "" "Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI " "port. This doesn't work." @@ -366,7 +410,7 @@ msgstr "" "Windows Multimedia (WinMM) wurde angewiesen, eine nicht-WinMM-MIDI-" "Schnittstelle zu öffnen. Das geht nicht." -#: RtMidi.cpp:4302 +#: RtMidi.cpp:4325 msgid "" "We are overwriting an existing connection. This is probably a programming " "error." @@ -374,12 +418,12 @@ msgstr "" "Wir überschreiben eine vorhandene MIDI-Verbindung. Das ist vermutlich ein " "Programmierfehler." -#: RtMidi.cpp:4307 +#: RtMidi.cpp:4330 msgid "Trying to open a non-input port as input MIDI port. This doesn't work." msgstr "" "Versuche eine Nicht-Eingang als MIDI-Eingang zu öffnen. Das geht nicht." -#: RtMidi.cpp:4317 RtMidi.cpp:4566 +#: RtMidi.cpp:4344 RtMidi.cpp:4613 msgid "" "Some change in the arrangement of MIDI input ports invalidated the port " "descriptor." @@ -387,105 +431,105 @@ msgstr "" "Eine Veränderung bei den MIDI-Schnittstellen hat die interne " "Schnittstellenbeschreibung ungültig gemacht." -#: RtMidi.cpp:4332 +#: RtMidi.cpp:4359 msgid "The handle is invalid. Did you disconnect the device?" msgstr "" "Ein Schnittstellenverweis ist ungültig. Haben Sie das zugehörige Gerät " "entfernt?" -#: RtMidi.cpp:4336 RtMidi.cpp:4585 +#: RtMidi.cpp:4363 RtMidi.cpp:4632 msgid "" "The system has no driver for our handle :-(. Did you disconnect the device?" msgstr "" "Das System hat keinen Treiber für unseren Schnittstellenverweis (mehr) :-(. " "Haben Sie das zugehörige Gerät entfernt?" -#: RtMidi.cpp:4340 RtMidi.cpp:4589 +#: RtMidi.cpp:4367 RtMidi.cpp:4636 msgid "Out of memory." msgstr "Hauptspeicher erschöpft." -#: RtMidi.cpp:4370 +#: RtMidi.cpp:4413 msgid "Error closing Windows MM MIDI input port." msgstr "" "Konnte den Windows Multimedia MIDI-Eingang nicht ordnungsgemäß schließen." -#: RtMidi.cpp:4448 +#: RtMidi.cpp:4491 msgid "No MIDI output devices currently available." msgstr "Es gibt momentan keine MIDI-Ausgabegeräte." -#: RtMidi.cpp:4499 +#: RtMidi.cpp:4542 msgid "No MIDI output destinations found!" msgstr "Es wurden keine MIDI-Ausgabegeräte gefunden." -#: RtMidi.cpp:4517 +#: RtMidi.cpp:4560 msgid "Error creating Windows MM MIDI output port." msgstr "Konnte den Windows Multimedia MIDI-Ausgang nicht erzeugen." -#: RtMidi.cpp:4556 +#: RtMidi.cpp:4599 msgid "The port descriptor cannot be used to open an output port." msgstr "" "Eine Schnittstellenbeschreibung kann nicht benutzt werden, um einen MIDI-" "Ausgang zu erzeugen." -#: RtMidi.cpp:4581 +#: RtMidi.cpp:4628 msgid "The internal handle is invalid. Did you disconnect the device?" msgstr "" "Ein interner Schnittstellenverweis ist ungültig. Haben sie das zugehörige " "Gerät entfernt?" -#: RtMidi.cpp:4611 +#: RtMidi.cpp:4664 msgid "Message argument is empty." msgstr "Das Nachrichtenargument ist leer." -#: RtMidi.cpp:4623 +#: RtMidi.cpp:4676 msgid "Error while allocating sysex message memory." msgstr "Fehler beim Anlegen des Speichers für SysEx-Nachrichten." -#: RtMidi.cpp:4639 +#: RtMidi.cpp:4692 msgid "Error preparing sysex header." msgstr "Fehler beim Erstellen des SysEx-Kopfes." -#: RtMidi.cpp:4648 +#: RtMidi.cpp:4701 msgid "Error sending sysex message." msgstr "Fehler beim Senden der SysEx-Nachricht." -#: RtMidi.cpp:4661 +#: RtMidi.cpp:4714 msgid "Message size is greater than 3 bytes (and not sysex)." msgstr "" "Eine MIDI-Nachricht ist größer als 3 Bytes (und keine SysEx-Nachricht)." -#: RtMidi.cpp:4677 +#: RtMidi.cpp:4730 msgid "Error sending MIDI message." msgstr "Fehler beim Senden der MIDI-Nachricht." -#: RtMidi.cpp:4928 +#: RtMidi.cpp:4961 msgid "Could not connect to JACK server. Is it runnig?" msgstr "Ich konnte mich nicht mit dem JACK-Server verbinden. Läuft er?" -#: RtMidi.cpp:5131 +#: RtMidi.cpp:5172 msgid "Error opening JACK port subscription." msgstr "Fehler beim abonnieren einer JACK-Schnittstelle." -#: RtMidi.cpp:5238 RtMidi.cpp:5521 +#: RtMidi.cpp:5356 RtMidi.cpp:5584 msgid "JACK server not running?" msgstr "Läuft der JACK-Server?" -#: RtMidi.cpp:5273 RtMidi.cpp:5338 RtMidi.cpp:5562 RtMidi.cpp:5627 +#: RtMidi.cpp:5400 RtMidi.cpp:5617 msgid "Error creating JACK port." msgstr "Es gab einen Fehler beim Erzeugen der JACK-Schnittstelle." -#: RtMidi.cpp:5293 RtMidi.cpp:5582 +#: RtMidi.cpp:5420 RtMidi.cpp:5637 msgid "Error creating JACK virtual port." msgstr "Fehler beim Erzeugen einer virtuellen JACK-Schnittstelle." -#: RtMidi.cpp:5317 RtMidi.cpp:5606 +#: RtMidi.cpp:5444 RtMidi.cpp:5661 msgid "" "JACK has been instructed to open a non-JACK MIDI port. This doesn't work." msgstr "" "JACK wurde angewiesen, eine nicht-JACK-Schnittstelle zu öffnen. Das geht " "nicht." -#: RtMidi.cpp:5404 RtMidi.cpp:5694 +#: RtMidi.cpp:5527 RtMidi.cpp:5739 msgid "No ports available." msgstr "Keine Schnittstellen verfügbar." diff --git a/po/rtmidi.pot b/po/rtmidi.pot index 31553e53..792245d6 100644 --- a/po/rtmidi.pot +++ b/po/rtmidi.pot @@ -1,15 +1,14 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Gary P. Scavone -# This file is distributed under the same license as the PACKAGE package. +# This file is distributed under the same license as the rtmidi package. # FIRST AUTHOR , YEAR. # -#: RtMidi.cpp:3346 #, fuzzy msgid "" msgstr "" -"Project-Id-Version: rtmidi 2.1.0\n" +"Project-Id-Version: rtmidi 3.0\n" "Report-Msgid-Bugs-To: https://github.com/thestk/rtmidi\n" -"POT-Creation-Date: 2014-06-10 21:00+0200\n" +"POT-Creation-Date: 2015-10-14 22:01+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,67 +17,71 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: RtMidi.h:91 +#: RtMidi.h:107 msgid "Automatic selection" msgstr "" -#: RtMidi.h:92 +#: RtMidi.h:108 msgid "Core MIDI" msgstr "" -#: RtMidi.h:93 +#: RtMidi.h:109 msgid "ALSA" msgstr "" -#: RtMidi.h:94 +#: RtMidi.h:110 msgid "JACK" msgstr "" -#: RtMidi.h:95 +#: RtMidi.h:111 msgid "Windows Multimedia" msgstr "" -#: RtMidi.h:96 +#: RtMidi.h:112 msgid "DirectX/Kernel Streaming" msgstr "" -#: RtMidi.h:97 +#: RtMidi.h:113 msgid "NULL device" msgstr "" -#: RtMidi.h:98 +#: RtMidi.h:114 msgid "All available MIDI systems" msgstr "" -#: RtMidi.h:450 RtMidi.h:557 RtMidi.h:1070 RtMidi.h:1162 +#: RtMidi.h:530 RtMidi.h:691 RtMidi.h:1220 RtMidi.h:1312 msgid "Passed NULL pointer." msgstr "" -#: RtMidi.h:623 RtMidi.cpp:2093 +#: RtMidi.h:723 RtMidi.cpp:2161 msgid "No data in message argument." msgstr "" -#: RtMidi.h:951 +#: RtMidi.h:1082 msgid "A NULL pointer has been passed as port descriptor" msgstr "" -#: RtMidi.h:983 RtMidi.h:1195 RtMidi.h:1218 RtMidi.h:1231 +#: RtMidi.h:1114 RtMidi.h:1345 RtMidi.h:1369 RtMidi.h:1382 msgid "No valid MIDI system has been selected." msgstr "" -#: RtMidi.h:1052 +#: RtMidi.h:1184 msgid "Could not find any valid MIDI system." msgstr "" -#: RtMidi.h:1075 +#: RtMidi.h:1225 msgid "No valid MIDI system has been found." msgstr "" -#: RtMidi.h:1212 +#: RtMidi.h:1363 msgid "No data in MIDI message." msgstr "" -#: RtMidi.cpp:71 +#: RtMidi.h:1608 RtMidi.h:1630 +msgid "MidiInDummy: This class provides no functionality." +msgstr "" + +#: RtMidi.cpp:87 #, c-format msgid "" "Error formatting the error string:\n" @@ -87,354 +90,391 @@ msgid "" "%s:%d" msgstr "" -#: RtMidi.cpp:83 +#: RtMidi.cpp:99 msgid "Error: could not format the error message" msgstr "" -#: RtMidi.cpp:258 RtMidi.cpp:361 +#: RtMidi.cpp:267 RtMidi.cpp:370 #, c-format msgid "" "Support for the selected MIDI system %d has not been compiled into the " "RtMidi library." msgstr "" -#: RtMidi.cpp:276 RtMidi.cpp:378 +#: RtMidi.cpp:285 RtMidi.cpp:387 msgid "No supported MIDI system has been found." msgstr "" -#: RtMidi.cpp:457 +#: RtMidi.cpp:474 RtMidi.cpp:491 msgid "A callback function is already set." msgstr "" -#: RtMidi.cpp:463 +#: RtMidi.cpp:480 RtMidi.cpp:497 msgid "The callback function value is invalid." msgstr "" -#: RtMidi.cpp:476 +#: RtMidi.cpp:508 msgid "No callback function was set." msgstr "" -#: RtMidi.cpp:499 +#: RtMidi.cpp:530 msgid "" "Returning an empty MIDI message as all input is handled by a callback " "function." msgstr "" -#: RtMidi.cpp:1154 +#: RtMidi.cpp:1183 msgid "Could not get the unique identifier of a midi endpoint." msgstr "" -#: RtMidi.cpp:1165 +#: RtMidi.cpp:1193 msgid "" "Could not get the endpoint back from the unique identifier of a midi " "endpoint." msgstr "" -#: RtMidi.cpp:1181 +#: RtMidi.cpp:1208 msgid "Could not get the entity of a midi endpoint." msgstr "" -#: RtMidi.cpp:1258 RtMidi.cpp:1298 +#: RtMidi.cpp:1273 RtMidi.cpp:1313 msgid "Error creating OS X MIDI port because of invalid port flags." msgstr "" -#: RtMidi.cpp:1262 RtMidi.cpp:1302 RtMidi.cpp:1804 +#: RtMidi.cpp:1277 RtMidi.cpp:1317 RtMidi.cpp:1858 msgid "Error creating OS-X MIDI port." msgstr "" -#: RtMidi.cpp:1355 +#: RtMidi.cpp:1370 msgid "Error creating OS-X MIDI client object." msgstr "" -#: RtMidi.cpp:1693 RtMidi.cpp:1785 RtMidi.cpp:1939 RtMidi.cpp:2035 -#: RtMidi.cpp:3052 RtMidi.cpp:3169 RtMidi.cpp:3419 RtMidi.cpp:3567 -#: RtMidi.cpp:4217 RtMidi.cpp:4492 RtMidi.cpp:4551 RtMidi.cpp:5311 -#: RtMidi.cpp:5600 +#: RtMidi.cpp:1626 RtMidi.cpp:1696 RtMidi.cpp:3006 RtMidi.cpp:4184 +#: RtMidi.cpp:5250 +msgid "Error: Message queue limit reached." +msgstr "" + +#: RtMidi.cpp:1747 RtMidi.cpp:1839 RtMidi.cpp:1997 RtMidi.cpp:2090 +#: RtMidi.cpp:3149 RtMidi.cpp:3266 RtMidi.cpp:3534 RtMidi.cpp:3682 +#: RtMidi.cpp:4240 RtMidi.cpp:4535 RtMidi.cpp:4594 RtMidi.cpp:5438 +#: RtMidi.cpp:5655 msgid "A valid connection already exists." msgstr "" -#: RtMidi.cpp:1701 RtMidi.cpp:3059 RtMidi.cpp:4224 +#: RtMidi.cpp:1755 RtMidi.cpp:3156 RtMidi.cpp:4247 msgid "No MIDI input sources found." msgstr "" -#: RtMidi.cpp:1710 RtMidi.cpp:1867 RtMidi.cpp:1922 RtMidi.cpp:1956 -#: RtMidi.cpp:3069 RtMidi.cpp:3439 RtMidi.cpp:4392 RtMidi.cpp:4470 -#: RtMidi.cpp:4505 RtMidi.cpp:5411 RtMidi.cpp:5701 +#: RtMidi.cpp:1764 RtMidi.cpp:1922 RtMidi.cpp:1980 RtMidi.cpp:2011 +#: RtMidi.cpp:3166 RtMidi.cpp:3554 RtMidi.cpp:4435 RtMidi.cpp:4513 +#: RtMidi.cpp:4548 RtMidi.cpp:5534 RtMidi.cpp:5746 #, c-format msgid "The 'portNumber' argument (%d) is invalid." msgstr "" -#: RtMidi.cpp:1722 +#: RtMidi.cpp:1776 msgid "Error creating OS-X MIDI input port." msgstr "" -#: RtMidi.cpp:1732 +#: RtMidi.cpp:1786 msgid "Error getting MIDI input source reference." msgstr "" -#: RtMidi.cpp:1742 +#: RtMidi.cpp:1796 msgid "Error connecting OS-X MIDI input port." msgstr "" -#: RtMidi.cpp:1764 +#: RtMidi.cpp:1818 msgid "Error creating virtual OS-X MIDI destination." msgstr "" -#: RtMidi.cpp:1780 RtMidi.cpp:2030 RtMidi.cpp:3164 RtMidi.cpp:3562 -#: RtMidi.cpp:5305 RtMidi.cpp:5594 +#: RtMidi.cpp:1834 RtMidi.cpp:2085 RtMidi.cpp:3261 RtMidi.cpp:3677 +#: RtMidi.cpp:5432 RtMidi.cpp:5649 msgid "Data has not been allocated." msgstr "" -#: RtMidi.cpp:1790 RtMidi.cpp:2040 +#: RtMidi.cpp:1844 RtMidi.cpp:2095 msgid "" "Core MIDI has been instructed to open a non-Core MIDI port. This doesn't " "work." msgstr "" -#: RtMidi.cpp:1947 +#: RtMidi.cpp:2005 msgid "No MIDI output destinations found." msgstr "" -#: RtMidi.cpp:1968 +#: RtMidi.cpp:2023 msgid "Error creating OS-X MIDI output port." msgstr "" -#: RtMidi.cpp:1978 +#: RtMidi.cpp:2033 msgid "Error getting MIDI output destination reference." msgstr "" -#: RtMidi.cpp:2003 +#: RtMidi.cpp:2058 msgid "A virtual output port already exists." msgstr "" -#: RtMidi.cpp:2014 +#: RtMidi.cpp:2069 msgid "Error creating OS-X virtual MIDI source." msgstr "" -#: RtMidi.cpp:2153 +#: RtMidi.cpp:2221 msgid "Could not allocate packet list." msgstr "" -#: RtMidi.cpp:2162 +#: RtMidi.cpp:2230 msgid "Error sending MIDI to virtual destinations." msgstr "" -#: RtMidi.cpp:2171 RtMidi.cpp:3548 +#: RtMidi.cpp:2239 RtMidi.cpp:3663 msgid "Error sending MIDI message to port." msgstr "" -#: RtMidi.cpp:2374 RtMidi.cpp:2636 RtMidi.cpp:3113 RtMidi.cpp:3174 -#: RtMidi.cpp:3465 +#: RtMidi.cpp:2443 RtMidi.cpp:2704 RtMidi.cpp:3210 RtMidi.cpp:3271 +#: RtMidi.cpp:3580 msgid "Could not allocate ALSA port subscription." msgstr "" -#: RtMidi.cpp:2389 RtMidi.cpp:3122 RtMidi.cpp:3475 +#: RtMidi.cpp:2458 RtMidi.cpp:3219 RtMidi.cpp:3590 msgid "Error making ALSA port connection." msgstr "" -#: RtMidi.cpp:2459 RtMidi.cpp:2946 +#: RtMidi.cpp:2528 RtMidi.cpp:3461 msgid "Error creating ALSA sequencer client object." msgstr "" -#: RtMidi.cpp:2698 RtMidi.cpp:3148 RtMidi.cpp:3278 +#: RtMidi.cpp:2766 RtMidi.cpp:3245 RtMidi.cpp:3394 msgid "Error starting MIDI input thread!" msgstr "" -#: RtMidi.cpp:2964 +#: RtMidi.cpp:2804 RtMidi.cpp:3478 +msgid "Error initializing MIDI event parser." +msgstr "" + +#: RtMidi.cpp:2817 +msgid "Error initializing buffer memory." +msgstr "" + +#: RtMidi.cpp:2851 +msgid "MIDI input buffer overrun." +msgstr "" + +#: RtMidi.cpp:2861 +msgid "ALSA returned without providing a MIDI event." +msgstr "" + +#: RtMidi.cpp:2871 +#, c-format +msgid "" +"Unknown MIDI input error.\n" +"The system reports:\n" +"%s" +msgstr "" + +#: RtMidi.cpp:2929 +msgid "Error resizing buffer memory." +msgstr "" + +#: RtMidi.cpp:2980 +msgid "Event parsing error or not a MIDI event." +msgstr "" + +#: RtMidi.cpp:3061 msgid "Error creating pipe objects." msgstr "" -#: RtMidi.cpp:3044 RtMidi.cpp:3411 +#: RtMidi.cpp:3141 RtMidi.cpp:3526 msgid "Error looking for port name." msgstr "" -#: RtMidi.cpp:3100 +#: RtMidi.cpp:3197 msgid "Error creating ALSA input port." msgstr "" -#: RtMidi.cpp:3179 RtMidi.cpp:3577 +#: RtMidi.cpp:3276 RtMidi.cpp:3692 msgid "" "ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work." msgstr "" -#: RtMidi.cpp:3244 RtMidi.cpp:3502 +#: RtMidi.cpp:3360 RtMidi.cpp:3617 msgid "Error creating ALSA virtual port." msgstr "" -#: RtMidi.cpp:3363 -msgid "Error initializing MIDI event parser." -msgstr "" - -#: RtMidi.cpp:3370 RtMidi.cpp:3526 +#: RtMidi.cpp:3485 RtMidi.cpp:3641 msgid "Error while allocating buffer memory." msgstr "" -#: RtMidi.cpp:3427 +#: RtMidi.cpp:3542 msgid "No MIDI output sinks found." msgstr "" -#: RtMidi.cpp:3454 +#: RtMidi.cpp:3569 msgid "Error creating ALSA output port." msgstr "" -#: RtMidi.cpp:3519 +#: RtMidi.cpp:3634 msgid "ALSA error resizing MIDI event buffer." msgstr "" -#: RtMidi.cpp:3540 +#: RtMidi.cpp:3655 msgid "Event parsing error." msgstr "" -#: RtMidi.cpp:3572 +#: RtMidi.cpp:3687 msgid "Error allocating ALSA port subscription." msgstr "" -#: RtMidi.cpp:3709 +#: RtMidi.cpp:3837 #, c-format msgid "The port argument %d is invalid." msgstr "" -#: RtMidi.cpp:4198 +#: RtMidi.cpp:4159 +msgid "Error sending sysex to Midi device." +msgstr "" + +#: RtMidi.cpp:4222 msgid "No MIDI input devices currently available." msgstr "" -#: RtMidi.cpp:4209 +#: RtMidi.cpp:4232 msgid "Failed to initialize a critical section." msgstr "" -#: RtMidi.cpp:4233 +#: RtMidi.cpp:4256 #, c-format msgid "the 'portNumber' argument (%d) is invalid." msgstr "" -#: RtMidi.cpp:4245 +#: RtMidi.cpp:4268 msgid "Error creating Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4261 +#: RtMidi.cpp:4284 msgid "Error initializing data for Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4270 +#: RtMidi.cpp:4293 msgid "Could not register the input buffer for Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4279 +#: RtMidi.cpp:4302 msgid "Error starting Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4290 RtMidi.cpp:4538 +#: RtMidi.cpp:4313 RtMidi.cpp:4581 msgid "Virtual ports are not available Windows Multimedia MIDI API." msgstr "" -#: RtMidi.cpp:4297 RtMidi.cpp:4546 +#: RtMidi.cpp:4320 RtMidi.cpp:4589 msgid "" "Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI " "port. This doesn't work." msgstr "" -#: RtMidi.cpp:4302 +#: RtMidi.cpp:4325 msgid "" "We are overwriting an existing connection. This is probably a programming " "error." msgstr "" -#: RtMidi.cpp:4307 +#: RtMidi.cpp:4330 msgid "Trying to open a non-input port as input MIDI port. This doesn't work." msgstr "" -#: RtMidi.cpp:4317 RtMidi.cpp:4566 +#: RtMidi.cpp:4344 RtMidi.cpp:4613 msgid "" "Some change in the arrangement of MIDI input ports invalidated the port " "descriptor." msgstr "" -#: RtMidi.cpp:4332 +#: RtMidi.cpp:4359 msgid "The handle is invalid. Did you disconnect the device?" msgstr "" -#: RtMidi.cpp:4336 RtMidi.cpp:4585 +#: RtMidi.cpp:4363 RtMidi.cpp:4632 msgid "" "The system has no driver for our handle :-(. Did you disconnect the device?" msgstr "" -#: RtMidi.cpp:4340 RtMidi.cpp:4589 +#: RtMidi.cpp:4367 RtMidi.cpp:4636 msgid "Out of memory." msgstr "" -#: RtMidi.cpp:4370 +#: RtMidi.cpp:4413 msgid "Error closing Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4448 +#: RtMidi.cpp:4491 msgid "No MIDI output devices currently available." msgstr "" -#: RtMidi.cpp:4499 +#: RtMidi.cpp:4542 msgid "No MIDI output destinations found!" msgstr "" -#: RtMidi.cpp:4517 +#: RtMidi.cpp:4560 msgid "Error creating Windows MM MIDI output port." msgstr "" -#: RtMidi.cpp:4556 +#: RtMidi.cpp:4599 msgid "The port descriptor cannot be used to open an output port." msgstr "" -#: RtMidi.cpp:4581 +#: RtMidi.cpp:4628 msgid "The internal handle is invalid. Did you disconnect the device?" msgstr "" -#: RtMidi.cpp:4611 +#: RtMidi.cpp:4664 msgid "Message argument is empty." msgstr "" -#: RtMidi.cpp:4623 +#: RtMidi.cpp:4676 msgid "Error while allocating sysex message memory." msgstr "" -#: RtMidi.cpp:4639 +#: RtMidi.cpp:4692 msgid "Error preparing sysex header." msgstr "" -#: RtMidi.cpp:4648 +#: RtMidi.cpp:4701 msgid "Error sending sysex message." msgstr "" -#: RtMidi.cpp:4661 +#: RtMidi.cpp:4714 msgid "Message size is greater than 3 bytes (and not sysex)." msgstr "" -#: RtMidi.cpp:4677 +#: RtMidi.cpp:4730 msgid "Error sending MIDI message." msgstr "" -#: RtMidi.cpp:4928 +#: RtMidi.cpp:4961 msgid "Could not connect to JACK server. Is it runnig?" msgstr "" -#: RtMidi.cpp:5131 +#: RtMidi.cpp:5172 msgid "Error opening JACK port subscription." msgstr "" -#: RtMidi.cpp:5238 RtMidi.cpp:5521 +#: RtMidi.cpp:5356 RtMidi.cpp:5584 msgid "JACK server not running?" msgstr "" -#: RtMidi.cpp:5273 RtMidi.cpp:5338 RtMidi.cpp:5562 RtMidi.cpp:5627 +#: RtMidi.cpp:5400 RtMidi.cpp:5617 msgid "Error creating JACK port." msgstr "" -#: RtMidi.cpp:5293 RtMidi.cpp:5582 +#: RtMidi.cpp:5420 RtMidi.cpp:5637 msgid "Error creating JACK virtual port." msgstr "" -#: RtMidi.cpp:5317 RtMidi.cpp:5606 +#: RtMidi.cpp:5444 RtMidi.cpp:5661 msgid "" "JACK has been instructed to open a non-JACK MIDI port. This doesn't work." msgstr "" -#: RtMidi.cpp:5404 RtMidi.cpp:5694 +#: RtMidi.cpp:5527 RtMidi.cpp:5739 msgid "No ports available." msgstr "" From ce0b6cd2e0167cb50914ebcc87d46dfb31fc7181 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 14 Oct 2015 22:18:30 +0200 Subject: [PATCH 099/210] Update pot file --- po/rtmidi-ts.pot | 262 +++++++++++++++++++++++++++-------------------- 1 file changed, 151 insertions(+), 111 deletions(-) diff --git a/po/rtmidi-ts.pot b/po/rtmidi-ts.pot index 31553e53..ce383b81 100644 --- a/po/rtmidi-ts.pot +++ b/po/rtmidi-ts.pot @@ -1,15 +1,14 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Gary P. Scavone -# This file is distributed under the same license as the PACKAGE package. +# This file is distributed under the same license as the rtmidi-ts package. # FIRST AUTHOR , YEAR. # -#: RtMidi.cpp:3346 #, fuzzy msgid "" msgstr "" -"Project-Id-Version: rtmidi 2.1.0\n" +"Project-Id-Version: rtmidi-ts 3.0\n" "Report-Msgid-Bugs-To: https://github.com/thestk/rtmidi\n" -"POT-Creation-Date: 2014-06-10 21:00+0200\n" +"POT-Creation-Date: 2015-10-14 22:01+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,67 +17,71 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: RtMidi.h:91 +#: RtMidi.h:107 msgid "Automatic selection" msgstr "" -#: RtMidi.h:92 +#: RtMidi.h:108 msgid "Core MIDI" msgstr "" -#: RtMidi.h:93 +#: RtMidi.h:109 msgid "ALSA" msgstr "" -#: RtMidi.h:94 +#: RtMidi.h:110 msgid "JACK" msgstr "" -#: RtMidi.h:95 +#: RtMidi.h:111 msgid "Windows Multimedia" msgstr "" -#: RtMidi.h:96 +#: RtMidi.h:112 msgid "DirectX/Kernel Streaming" msgstr "" -#: RtMidi.h:97 +#: RtMidi.h:113 msgid "NULL device" msgstr "" -#: RtMidi.h:98 +#: RtMidi.h:114 msgid "All available MIDI systems" msgstr "" -#: RtMidi.h:450 RtMidi.h:557 RtMidi.h:1070 RtMidi.h:1162 +#: RtMidi.h:530 RtMidi.h:691 RtMidi.h:1220 RtMidi.h:1312 msgid "Passed NULL pointer." msgstr "" -#: RtMidi.h:623 RtMidi.cpp:2093 +#: RtMidi.h:723 RtMidi.cpp:2161 msgid "No data in message argument." msgstr "" -#: RtMidi.h:951 +#: RtMidi.h:1082 msgid "A NULL pointer has been passed as port descriptor" msgstr "" -#: RtMidi.h:983 RtMidi.h:1195 RtMidi.h:1218 RtMidi.h:1231 +#: RtMidi.h:1114 RtMidi.h:1345 RtMidi.h:1369 RtMidi.h:1382 msgid "No valid MIDI system has been selected." msgstr "" -#: RtMidi.h:1052 +#: RtMidi.h:1184 msgid "Could not find any valid MIDI system." msgstr "" -#: RtMidi.h:1075 +#: RtMidi.h:1225 msgid "No valid MIDI system has been found." msgstr "" -#: RtMidi.h:1212 +#: RtMidi.h:1363 msgid "No data in MIDI message." msgstr "" -#: RtMidi.cpp:71 +#: RtMidi.h:1608 RtMidi.h:1630 +msgid "MidiInDummy: This class provides no functionality." +msgstr "" + +#: RtMidi.cpp:87 #, c-format msgid "" "Error formatting the error string:\n" @@ -87,354 +90,391 @@ msgid "" "%s:%d" msgstr "" -#: RtMidi.cpp:83 +#: RtMidi.cpp:99 msgid "Error: could not format the error message" msgstr "" -#: RtMidi.cpp:258 RtMidi.cpp:361 +#: RtMidi.cpp:267 RtMidi.cpp:370 #, c-format msgid "" "Support for the selected MIDI system %d has not been compiled into the " "RtMidi library." msgstr "" -#: RtMidi.cpp:276 RtMidi.cpp:378 +#: RtMidi.cpp:285 RtMidi.cpp:387 msgid "No supported MIDI system has been found." msgstr "" -#: RtMidi.cpp:457 +#: RtMidi.cpp:474 RtMidi.cpp:491 msgid "A callback function is already set." msgstr "" -#: RtMidi.cpp:463 +#: RtMidi.cpp:480 RtMidi.cpp:497 msgid "The callback function value is invalid." msgstr "" -#: RtMidi.cpp:476 +#: RtMidi.cpp:508 msgid "No callback function was set." msgstr "" -#: RtMidi.cpp:499 +#: RtMidi.cpp:530 msgid "" "Returning an empty MIDI message as all input is handled by a callback " "function." msgstr "" -#: RtMidi.cpp:1154 +#: RtMidi.cpp:1183 msgid "Could not get the unique identifier of a midi endpoint." msgstr "" -#: RtMidi.cpp:1165 +#: RtMidi.cpp:1193 msgid "" "Could not get the endpoint back from the unique identifier of a midi " "endpoint." msgstr "" -#: RtMidi.cpp:1181 +#: RtMidi.cpp:1208 msgid "Could not get the entity of a midi endpoint." msgstr "" -#: RtMidi.cpp:1258 RtMidi.cpp:1298 +#: RtMidi.cpp:1273 RtMidi.cpp:1313 msgid "Error creating OS X MIDI port because of invalid port flags." msgstr "" -#: RtMidi.cpp:1262 RtMidi.cpp:1302 RtMidi.cpp:1804 +#: RtMidi.cpp:1277 RtMidi.cpp:1317 RtMidi.cpp:1858 msgid "Error creating OS-X MIDI port." msgstr "" -#: RtMidi.cpp:1355 +#: RtMidi.cpp:1370 msgid "Error creating OS-X MIDI client object." msgstr "" -#: RtMidi.cpp:1693 RtMidi.cpp:1785 RtMidi.cpp:1939 RtMidi.cpp:2035 -#: RtMidi.cpp:3052 RtMidi.cpp:3169 RtMidi.cpp:3419 RtMidi.cpp:3567 -#: RtMidi.cpp:4217 RtMidi.cpp:4492 RtMidi.cpp:4551 RtMidi.cpp:5311 -#: RtMidi.cpp:5600 +#: RtMidi.cpp:1626 RtMidi.cpp:1696 RtMidi.cpp:3006 RtMidi.cpp:4184 +#: RtMidi.cpp:5250 +msgid "Error: Message queue limit reached." +msgstr "" + +#: RtMidi.cpp:1747 RtMidi.cpp:1839 RtMidi.cpp:1997 RtMidi.cpp:2090 +#: RtMidi.cpp:3149 RtMidi.cpp:3266 RtMidi.cpp:3534 RtMidi.cpp:3682 +#: RtMidi.cpp:4240 RtMidi.cpp:4535 RtMidi.cpp:4594 RtMidi.cpp:5438 +#: RtMidi.cpp:5655 msgid "A valid connection already exists." msgstr "" -#: RtMidi.cpp:1701 RtMidi.cpp:3059 RtMidi.cpp:4224 +#: RtMidi.cpp:1755 RtMidi.cpp:3156 RtMidi.cpp:4247 msgid "No MIDI input sources found." msgstr "" -#: RtMidi.cpp:1710 RtMidi.cpp:1867 RtMidi.cpp:1922 RtMidi.cpp:1956 -#: RtMidi.cpp:3069 RtMidi.cpp:3439 RtMidi.cpp:4392 RtMidi.cpp:4470 -#: RtMidi.cpp:4505 RtMidi.cpp:5411 RtMidi.cpp:5701 +#: RtMidi.cpp:1764 RtMidi.cpp:1922 RtMidi.cpp:1980 RtMidi.cpp:2011 +#: RtMidi.cpp:3166 RtMidi.cpp:3554 RtMidi.cpp:4435 RtMidi.cpp:4513 +#: RtMidi.cpp:4548 RtMidi.cpp:5534 RtMidi.cpp:5746 #, c-format msgid "The 'portNumber' argument (%d) is invalid." msgstr "" -#: RtMidi.cpp:1722 +#: RtMidi.cpp:1776 msgid "Error creating OS-X MIDI input port." msgstr "" -#: RtMidi.cpp:1732 +#: RtMidi.cpp:1786 msgid "Error getting MIDI input source reference." msgstr "" -#: RtMidi.cpp:1742 +#: RtMidi.cpp:1796 msgid "Error connecting OS-X MIDI input port." msgstr "" -#: RtMidi.cpp:1764 +#: RtMidi.cpp:1818 msgid "Error creating virtual OS-X MIDI destination." msgstr "" -#: RtMidi.cpp:1780 RtMidi.cpp:2030 RtMidi.cpp:3164 RtMidi.cpp:3562 -#: RtMidi.cpp:5305 RtMidi.cpp:5594 +#: RtMidi.cpp:1834 RtMidi.cpp:2085 RtMidi.cpp:3261 RtMidi.cpp:3677 +#: RtMidi.cpp:5432 RtMidi.cpp:5649 msgid "Data has not been allocated." msgstr "" -#: RtMidi.cpp:1790 RtMidi.cpp:2040 +#: RtMidi.cpp:1844 RtMidi.cpp:2095 msgid "" "Core MIDI has been instructed to open a non-Core MIDI port. This doesn't " "work." msgstr "" -#: RtMidi.cpp:1947 +#: RtMidi.cpp:2005 msgid "No MIDI output destinations found." msgstr "" -#: RtMidi.cpp:1968 +#: RtMidi.cpp:2023 msgid "Error creating OS-X MIDI output port." msgstr "" -#: RtMidi.cpp:1978 +#: RtMidi.cpp:2033 msgid "Error getting MIDI output destination reference." msgstr "" -#: RtMidi.cpp:2003 +#: RtMidi.cpp:2058 msgid "A virtual output port already exists." msgstr "" -#: RtMidi.cpp:2014 +#: RtMidi.cpp:2069 msgid "Error creating OS-X virtual MIDI source." msgstr "" -#: RtMidi.cpp:2153 +#: RtMidi.cpp:2221 msgid "Could not allocate packet list." msgstr "" -#: RtMidi.cpp:2162 +#: RtMidi.cpp:2230 msgid "Error sending MIDI to virtual destinations." msgstr "" -#: RtMidi.cpp:2171 RtMidi.cpp:3548 +#: RtMidi.cpp:2239 RtMidi.cpp:3663 msgid "Error sending MIDI message to port." msgstr "" -#: RtMidi.cpp:2374 RtMidi.cpp:2636 RtMidi.cpp:3113 RtMidi.cpp:3174 -#: RtMidi.cpp:3465 +#: RtMidi.cpp:2443 RtMidi.cpp:2704 RtMidi.cpp:3210 RtMidi.cpp:3271 +#: RtMidi.cpp:3580 msgid "Could not allocate ALSA port subscription." msgstr "" -#: RtMidi.cpp:2389 RtMidi.cpp:3122 RtMidi.cpp:3475 +#: RtMidi.cpp:2458 RtMidi.cpp:3219 RtMidi.cpp:3590 msgid "Error making ALSA port connection." msgstr "" -#: RtMidi.cpp:2459 RtMidi.cpp:2946 +#: RtMidi.cpp:2528 RtMidi.cpp:3461 msgid "Error creating ALSA sequencer client object." msgstr "" -#: RtMidi.cpp:2698 RtMidi.cpp:3148 RtMidi.cpp:3278 +#: RtMidi.cpp:2766 RtMidi.cpp:3245 RtMidi.cpp:3394 msgid "Error starting MIDI input thread!" msgstr "" -#: RtMidi.cpp:2964 +#: RtMidi.cpp:2804 RtMidi.cpp:3478 +msgid "Error initializing MIDI event parser." +msgstr "" + +#: RtMidi.cpp:2817 +msgid "Error initializing buffer memory." +msgstr "" + +#: RtMidi.cpp:2851 +msgid "MIDI input buffer overrun." +msgstr "" + +#: RtMidi.cpp:2861 +msgid "ALSA returned without providing a MIDI event." +msgstr "" + +#: RtMidi.cpp:2871 +#, c-format +msgid "" +"Unknown MIDI input error.\n" +"The system reports:\n" +"%s" +msgstr "" + +#: RtMidi.cpp:2929 +msgid "Error resizing buffer memory." +msgstr "" + +#: RtMidi.cpp:2980 +msgid "Event parsing error or not a MIDI event." +msgstr "" + +#: RtMidi.cpp:3061 msgid "Error creating pipe objects." msgstr "" -#: RtMidi.cpp:3044 RtMidi.cpp:3411 +#: RtMidi.cpp:3141 RtMidi.cpp:3526 msgid "Error looking for port name." msgstr "" -#: RtMidi.cpp:3100 +#: RtMidi.cpp:3197 msgid "Error creating ALSA input port." msgstr "" -#: RtMidi.cpp:3179 RtMidi.cpp:3577 +#: RtMidi.cpp:3276 RtMidi.cpp:3692 msgid "" "ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work." msgstr "" -#: RtMidi.cpp:3244 RtMidi.cpp:3502 +#: RtMidi.cpp:3360 RtMidi.cpp:3617 msgid "Error creating ALSA virtual port." msgstr "" -#: RtMidi.cpp:3363 -msgid "Error initializing MIDI event parser." -msgstr "" - -#: RtMidi.cpp:3370 RtMidi.cpp:3526 +#: RtMidi.cpp:3485 RtMidi.cpp:3641 msgid "Error while allocating buffer memory." msgstr "" -#: RtMidi.cpp:3427 +#: RtMidi.cpp:3542 msgid "No MIDI output sinks found." msgstr "" -#: RtMidi.cpp:3454 +#: RtMidi.cpp:3569 msgid "Error creating ALSA output port." msgstr "" -#: RtMidi.cpp:3519 +#: RtMidi.cpp:3634 msgid "ALSA error resizing MIDI event buffer." msgstr "" -#: RtMidi.cpp:3540 +#: RtMidi.cpp:3655 msgid "Event parsing error." msgstr "" -#: RtMidi.cpp:3572 +#: RtMidi.cpp:3687 msgid "Error allocating ALSA port subscription." msgstr "" -#: RtMidi.cpp:3709 +#: RtMidi.cpp:3837 #, c-format msgid "The port argument %d is invalid." msgstr "" -#: RtMidi.cpp:4198 +#: RtMidi.cpp:4159 +msgid "Error sending sysex to Midi device." +msgstr "" + +#: RtMidi.cpp:4222 msgid "No MIDI input devices currently available." msgstr "" -#: RtMidi.cpp:4209 +#: RtMidi.cpp:4232 msgid "Failed to initialize a critical section." msgstr "" -#: RtMidi.cpp:4233 +#: RtMidi.cpp:4256 #, c-format msgid "the 'portNumber' argument (%d) is invalid." msgstr "" -#: RtMidi.cpp:4245 +#: RtMidi.cpp:4268 msgid "Error creating Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4261 +#: RtMidi.cpp:4284 msgid "Error initializing data for Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4270 +#: RtMidi.cpp:4293 msgid "Could not register the input buffer for Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4279 +#: RtMidi.cpp:4302 msgid "Error starting Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4290 RtMidi.cpp:4538 +#: RtMidi.cpp:4313 RtMidi.cpp:4581 msgid "Virtual ports are not available Windows Multimedia MIDI API." msgstr "" -#: RtMidi.cpp:4297 RtMidi.cpp:4546 +#: RtMidi.cpp:4320 RtMidi.cpp:4589 msgid "" "Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI " "port. This doesn't work." msgstr "" -#: RtMidi.cpp:4302 +#: RtMidi.cpp:4325 msgid "" "We are overwriting an existing connection. This is probably a programming " "error." msgstr "" -#: RtMidi.cpp:4307 +#: RtMidi.cpp:4330 msgid "Trying to open a non-input port as input MIDI port. This doesn't work." msgstr "" -#: RtMidi.cpp:4317 RtMidi.cpp:4566 +#: RtMidi.cpp:4344 RtMidi.cpp:4613 msgid "" "Some change in the arrangement of MIDI input ports invalidated the port " "descriptor." msgstr "" -#: RtMidi.cpp:4332 +#: RtMidi.cpp:4359 msgid "The handle is invalid. Did you disconnect the device?" msgstr "" -#: RtMidi.cpp:4336 RtMidi.cpp:4585 +#: RtMidi.cpp:4363 RtMidi.cpp:4632 msgid "" "The system has no driver for our handle :-(. Did you disconnect the device?" msgstr "" -#: RtMidi.cpp:4340 RtMidi.cpp:4589 +#: RtMidi.cpp:4367 RtMidi.cpp:4636 msgid "Out of memory." msgstr "" -#: RtMidi.cpp:4370 +#: RtMidi.cpp:4413 msgid "Error closing Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4448 +#: RtMidi.cpp:4491 msgid "No MIDI output devices currently available." msgstr "" -#: RtMidi.cpp:4499 +#: RtMidi.cpp:4542 msgid "No MIDI output destinations found!" msgstr "" -#: RtMidi.cpp:4517 +#: RtMidi.cpp:4560 msgid "Error creating Windows MM MIDI output port." msgstr "" -#: RtMidi.cpp:4556 +#: RtMidi.cpp:4599 msgid "The port descriptor cannot be used to open an output port." msgstr "" -#: RtMidi.cpp:4581 +#: RtMidi.cpp:4628 msgid "The internal handle is invalid. Did you disconnect the device?" msgstr "" -#: RtMidi.cpp:4611 +#: RtMidi.cpp:4664 msgid "Message argument is empty." msgstr "" -#: RtMidi.cpp:4623 +#: RtMidi.cpp:4676 msgid "Error while allocating sysex message memory." msgstr "" -#: RtMidi.cpp:4639 +#: RtMidi.cpp:4692 msgid "Error preparing sysex header." msgstr "" -#: RtMidi.cpp:4648 +#: RtMidi.cpp:4701 msgid "Error sending sysex message." msgstr "" -#: RtMidi.cpp:4661 +#: RtMidi.cpp:4714 msgid "Message size is greater than 3 bytes (and not sysex)." msgstr "" -#: RtMidi.cpp:4677 +#: RtMidi.cpp:4730 msgid "Error sending MIDI message." msgstr "" -#: RtMidi.cpp:4928 +#: RtMidi.cpp:4961 msgid "Could not connect to JACK server. Is it runnig?" msgstr "" -#: RtMidi.cpp:5131 +#: RtMidi.cpp:5172 msgid "Error opening JACK port subscription." msgstr "" -#: RtMidi.cpp:5238 RtMidi.cpp:5521 +#: RtMidi.cpp:5356 RtMidi.cpp:5584 msgid "JACK server not running?" msgstr "" -#: RtMidi.cpp:5273 RtMidi.cpp:5338 RtMidi.cpp:5562 RtMidi.cpp:5627 +#: RtMidi.cpp:5400 RtMidi.cpp:5617 msgid "Error creating JACK port." msgstr "" -#: RtMidi.cpp:5293 RtMidi.cpp:5582 +#: RtMidi.cpp:5420 RtMidi.cpp:5637 msgid "Error creating JACK virtual port." msgstr "" -#: RtMidi.cpp:5317 RtMidi.cpp:5606 +#: RtMidi.cpp:5444 RtMidi.cpp:5661 msgid "" "JACK has been instructed to open a non-JACK MIDI port. This doesn't work." msgstr "" -#: RtMidi.cpp:5404 RtMidi.cpp:5694 +#: RtMidi.cpp:5527 RtMidi.cpp:5739 msgid "No ports available." msgstr "" From 065bd06437a5351cf8cc58779150023d37bc2e55 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Thu, 31 Mar 2016 01:00:51 +0200 Subject: [PATCH 100/210] disable trim function as it is unused --- RtMidi.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 5f3ea62e..5e55e9c4 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -569,11 +569,12 @@ static inline std::string &rtrim(std::string &s) { s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); return s; } - +#if 0 // trim from both ends static inline std::string &trim(std::string &s) { return ltrim(rtrim(s)); } +#endif NAMESPACE_RTMIDI_END // *************************************************** // From 12ae7259f4fb0b6877ca85a73540bcee5ef16b22 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Thu, 31 Mar 2016 01:01:06 +0200 Subject: [PATCH 101/210] AlsaMidiData is a struct. --- RtMidi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RtMidi.h b/RtMidi.h index d6234af2..6dbd8699 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -1477,7 +1477,7 @@ class MidiInAlsa: public MidiInApi protected: static void * alsaMidiHandler( void *ptr ) throw(); void initialize( const std::string& clientName ); - friend class AlsaMidiData; + friend struct AlsaMidiData; }; class MidiOutAlsa: public MidiOutApi From cb1e9adab45298977048d85f352eda0a4f2f5d1e Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 28 Feb 2016 19:25:05 +0100 Subject: [PATCH 102/210] Update translations. --- po/de.gmo | Bin 0 -> 13272 bytes po/de.mo | Bin 13272 -> 13440 bytes po/de.po | 216 ++++++++++++++++++++++++++------------------------ po/rtmidi.pot | 212 +++++++++++++++++++++++++------------------------ 4 files changed, 219 insertions(+), 209 deletions(-) create mode 100644 po/de.gmo diff --git a/po/de.gmo b/po/de.gmo new file mode 100644 index 0000000000000000000000000000000000000000..a00aac037ac9e60177b16177f6326b3e08c62126 GIT binary patch literal 13272 zcmcJVdyHJyUB_?Rkfz(b8rq~Oj~vq&+lgoPk%yB>Y-eq+osGTr;Br z&b^cS@MagPf&{3df+8WHYE&vh1pGmZ5GWzSe;`&7NJM~yR6sn6P(VV8_z$E40zSWU z&V9^d*G>>uy8E3w_dI^*_x}B6|NgF;s-BU%YiQf4J0#JZ~P{2YwP< z1HTX41owkq0dE5T0Q`RNO>h}}2W)_k&UoG@z%KZm;O9YJc|Q-H2fqqF0KNm>2j25x z&zl90fU1%Dfq{r()3b9@_o5WN2m zOV=vc;CTQpf-i$I?(e`k@RmF6dXIxb#|xmG@5ezo*BhYl`>O@bjST|1v1^|H!?68F^)GM|l2EZ~>fW5k%*8K{@{r6#8BU<$S;A@NYn&|Gz;w z&jTN`=R6I{K3!1eeGX)4?<=6t^$k$u^OvB=>%Txm;oX0?rT-!D0?$u_Yv7l`XTf(s zq37g1c3uQN!t*bJ$H2Eh1%8;#Ti{{vEZ752gTDjLf&T$M2|kDtt%7|J)_HG$p8?+j zWuFF2`rP|H?+SQ==WlWt(T{r(s>tDt!weKY{|dMS{u+20d8dK@IwwK->-r{0R9{(^ZpT(c@Lp99L>7|%J(mV z=fFP%=fFD<-oxNipzu9+_*L+6p5Ju%KMo&9$zI_56qNJ+1t{ZWGr^X_3=}%Q0Se#$ z+2KBv7Sg>>gYy1IL81G1L80enj9u^uDC_k>(T`WaXTU!JMIY~mSdrH2y(1v3@;adC z)fXJT=H9>Up6}$P(0L3*G+xi)PlJl*uY+>FKXrIBhZKGs1MdZ21Th`&i{OueuYeoi zCpnA;zXU4q-@sGg-7s0~?s@Rj;BSGD;@vurF99D1H^E;5g+F(&ndtcy@EP!DK^gbg z;9cO6hdeI?p8*y4I`}^Dv)pI7_id`t>(JL;dzGwsHpM5Goa|oqujW&kxO*s4(<?-7S^stjU8-f$eDZ<#ZkiyGt=c{O?9ac_1##f(Sb~D#>s|TDbZP;L`>fdvOYAbVG>^ry0W=n z+n&*3sQjyb5c=&<+c)V}n(0C6E#_G~@Ux%;TSChS?_`|VQPrm#pt_u8_%xO3lW`t) zIbwz^!nosSTA8yN0j7D|N)T~1*?D5<5P|AUg-ECV-bqk+_{`$Tvz#Nj3bWO6s)9@< zc@zb`;R)--YGxx zjfh1y#<~gtb(`L)AVD#%%%0UKTd3AD%xHj;c}qs&-AK{8-GpfecEUK7QF{^MMmnQp z@P)O;l}UQtFbK)Yee36$_P%DsO-FiXWPwy8(x?OfI$Rf~6-`IXe z4|jjF=iCcx${pBPMO%0LJk_ExL1bN)`F=h0d-$lajVo^LeS~V<9$c#i?Zvuk)YJo; z*TsRYt;KoL(G#TKfL0XJ8XvkBdBb1`^Nb)T*;UY0oq;HVMxj;WgDi8g9UP?5Gvg49 z(&M>Nyw=Qt{po?3({YYV2_m&WZMF6jXfid!$NgQm0=~pdH^;XOPYn|Y7Q_Y7xni@C zq3&EYnkFX%QIG|GI1zG&eu5(`mK_=8e8NBv;$&;;h_1MU>-h}JoiL6!!~|uuQOw96 zl&2Z^=3V6$s%Ts6D`8LOmnNe|i4t+i@Lf_8&gm?@{W0h($vIKYF07UQt37uU&y{>r4@-5U41pE6s(Rw!O!)RA^^j_BWja*{eSC}X#faq)v(TF5=u|!!Y_%+rosd-6C4bC_ z;xg^UF~~+Hfwqd~ok#B^Gqvhszf4spPw+!oxK-teOdA<$T~>;v`YCvwiWxX{IXVWL}CU;LnTH*?gDg zL-`v0GixCh66s36D)!iD{oV)Jgk0?E0+}2MKw*ljw(_Z$MNRLbDF(!vP#&XTBWIO5 z2~Xg}j0%rBA=|6n%-JG(5k~Iyd`{-(B~(KJQ^*AoSGV0KDh)19j2mTynI`$ z%UIL0&IAh?P@Hgtll!})nP?{-42`){|HWqAi<$A9VbD%|iC~vl>VRx^J|DDoa-fu< zI=H`kNG!`yW`|BH3X+m!er%lOQ2lFlii&Y7&Q&)^%d&&btrZ4s;8 z4k~ytPSqGw5nW`Hc14<4t0bd()oKr3Q&oIKHwo}jMiwL^1-Y%p!RB?3nQV!kA&pwm zT7@4`HTz^VL_L32g~>WC%qGe2#SPA8#!zJUBN$H^;!nMRFV2xf=IKV}7nN|FBwEXwA<( zIJdyKbAFmNF5y|y(5HJtOpDtADzw(=hk7tTMW5Wz!ZrRpg^nj_(}p6Fi=J*qIy=T1 zQ7!b5qnDWfZ^2$=hGhx-qnATGSm0LrOo9UOb z*o^k+xJcG>_@g zg(sB#c=TYT_8nF8hn|?Z(m10domh^n#wc^9=9`Z-AK{ICY^<3Y;-saZr7Q{M+Y^3D z&YbmIs##4rtGDPMb<=ZbeM?EP!C792;&_-Qg%C0h@W!m1NWimZBv?pkb(^ zHhnu1+@Q@WYUdjMyQkY)s;|_|;XMLG`dVGwxz^c8=%(e-hH2~dG~C~o8l9}l*s><( z)MoT{uHg)bVHiOhi)9xxxEHkR<06~Z8;Xn#HWu@=hgR8Eo9Wy&PHQwWp+6D~WVxMJ zBZ`m+l}Xf@WaqV=uSq1J!9se~I8REP1f4#5(^xg_Kj|n+|IaakK)M+~eRS9!Et0{e z_17>9p#Bw?)ON0RURz&}V2nD2arAUQQ)Y@=bp!R@&J*E}iu5td88@$ZqIX; z?hl{2b&I8`K*HYeeN$(`{Z>*WlqA*P~NknmO=hb{YBO)9Z1$5JeaFis< zvu$ClQwYmg1c&Z2S8ZzSp+;OGfF&A^qTNO-68YQJxzXTd*KFJ{?Fn`8^5x}Iha8<# z4~rYzc{S54(bt?q`00o#HsRT_Ve0(r?)~moK<{FwsP>qp3`R5{DE{^r#X)i z=WrOeqYzjTN|uNx5km9VMGvJUG9k-)!Z8_+aIF&Gbyz27t_HtbAyzYuB(b;m#PrE9 zRJl^lZTes~U{)I%QcFcI4nH#QI_B zggw?ZmL~ZeK3UW6>Dez#qA<{*q#LeDTsnS&gXHgYZC7}kfIb-Y9}{lc z1j#8A3d*Yq6)y~l%dT&nmSh*9At7K$zF<4ZV@_bvhD+lETw3Ge^Vq=BB1M(yv7j&} zfQx}%*H4Zb_gYT;$Ip{d8R-qAG^lc;NIK3{Al=@CtCOClh!c2HNTBy2uBi;WJ5M3Ui`QWTux$>ewbxZnR%&otoxnSOv<%n6($Yo?D<6hdNH~;6+rrw@L?C2IF zbnqiQ{O9KmTa52Thdci6{Q=8A>+*=elkT)&(+vz64L^mLsPzo>@2LtT4SuiltTl=F zcP%=7{JGxTd9@$XDS6t@hgn)w)wI(({hil_>%2LihvByE){Hk|f~0GFi*4$R8wHL< zCzyG5nDQ&&e~qNK;EWGm^LxLI+-3i!QE0k4sH0xkEPsGFr2ICSlK94|L^gK#tmvS` zPf4<@dn#HMBiR6*R%#`ju5HBYv1DPS-NaHhr^gOxZS~=Sxa-UEk7jAMbB%rpo0W}+ zf``s2VCM464?TJ-0_T@SyI92jNYOYEw8J2#g}Nd9qfYR1x63Mh?TBCT@LZgRk#t3KnpB{DCSsAfjuGPS8;Em5ng6Z zw;Z}g{v){D+OkRghmV_O7RE5H!A`sf5957!1~c$8T#GYUj|&*W zZP{i)OyE*HhP<*ju+c1O?@-u4#RA@q_b)Ol!-r853?U8eB$nVWxETv`%xbY275H&1 zz_YjxKgRWV0~Oe+JJRECMTch(OPJpdQCLky3JY<@fBp@tc+Oo+P}qp~;$Bo>6SxXL zKu!1^Y9U!m%!)CJ3T!uqa0F{`3f1mcbeZ1@?o1C@j|yY}wZd0X16)F-d=52nR<7Af zEc1N~wKYAs0*|2rm_qgc(tm#gHGV-}I)E4^HK0eK1dpHwnntB=7PYcWHf|Y~p`Pnd zd)|ljIEYI9Mbuu;`2LO?d0s^42-YCGX9-jWMwgL)ML0!;R``+cHPi|g-<4ib47K7` z)I%)@U7+Kzm>uQ6^f`OKi%;FZshq* ztj1Y%a0Ro+unM>15N^W{(Zy^IP!&FaO}Gz9qFut>IE&@@AZgNk&m}30++sF~4^a_h znK~>_oJR%JN+V_HG;YD<6$+av z6zF25W`jr%t0tjuA9 z?*9_P)ah(P?cErv!)4^p=K0Zz*3e7sb|QW42v*=(RJ&`a0G4ufN^v_@;|s_uyMPMd z2h?~)9DoYuw`K~D;48>GyNYG_4`yJ9tI&iI%*U6ItlNa|yI9Zjw^)PgNhAMTtOu#G zVI*mG8g;g=`2LMaHCRWjUOd5%B0Y#~mreP8f)3BuQ7g=2d9neOk%L%>=a7qJpW-Oa zVGnk(8V|3cgO#MW4%=Mox_J*@r{XCp{zQVZrZ6`EM{o$gMrEjl*>u_`u>n6vwOh%Z z%EMvo#iQ7X^XTBN==kN#{y=Z4^0t;hpeHqU`>EXWJ}(|`@A8~y1_t}u6V9`P10B6y zpHo^|>hupJocR8@x6kQ#KH*e5g`i;2Lcw}zwUo3V1m6_ApniYsd2nI(Gc)JR%zyqf zvxi#mwIm*8rJXW9ZG5NljSn+Z!$3MeeEcKKTr9vDSclVb56;B1n1pLJu?GtPyuwI`rq)L52D7;$VvrJgb58;PoV_&qXxQwO5FfzWzR7i^VvYv%TRm1 z0i(DPmHLaQz3%t?2Se0fVGvygVfU;Fm4O}EG*0 z6RO`qWNbT&3hXj!i~dAy*=uAstS~3FfKpsVy$0*>bPoAnLt%&pMYK3K)v+Bz)W5|D z4xk@LF?$7;;BsuiYD}VoFL5CjbC6=V1xcRu;paGjnkPV-4t`+Pkf2aS!(Eo6Lz2hF zYAcp`#!;#M0hi)WSdT-f0IN8Gx;1-|WZ7xd^}2+gVJ|9>EM8J(HsK;XjA2aNq@a{& zd3q4T)p!!s@n2NOQcezwvj$Xq2d=>1(7{ahuM9syrGA%ZHWuVYE#AVQ?tc#9 zYR{sm4qu~I(94fj^cZz|v*}GATZRj;9rfOMQ~-ByE)M7FL~uURWV=uSoI{Ow57mDR z2cd@ft(pRDb^_;NAEx0GjNwzv#YJ2RvTbWU_hFQJ7gpkb$bX8>BApa1j3mo8q0ZJ} z&!4^LgP72Rar`LK2(mra;&}x9)Gwh{c-u3bWhx^P%)<`k0@+bKggw}XGgwVCo\n" "Language-Team: German translation team \n" "Language: de\n" @@ -16,7 +16,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 1.8.5\n" +"X-Generator: Poedit 1.8.6\n" "X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-Basepath: .\n" "X-Poedit-KeywordsList: gettext_noopt\n" @@ -54,35 +54,35 @@ msgstr "Keine Funktion." msgid "All available MIDI systems" msgstr "Alle verfügbaren MIDI-Systeme." -#: RtMidi.h:530 RtMidi.h:691 RtMidi.h:1220 RtMidi.h:1312 +#: RtMidi.h:530 RtMidi.h:692 RtMidi.h:1221 RtMidi.h:1313 msgid "Passed NULL pointer." msgstr "Nullzeiger übergeben." -#: RtMidi.h:723 RtMidi.cpp:2161 +#: RtMidi.h:724 RtMidi.cpp:2165 msgid "No data in message argument." msgstr "Keine Daten in der MIDI-Nachricht." -#: RtMidi.h:1082 +#: RtMidi.h:1083 msgid "A NULL pointer has been passed as port descriptor" msgstr "Ein leerer Zeiger wurde als Schnittstellenbeschreibung übergeben." -#: RtMidi.h:1114 RtMidi.h:1345 RtMidi.h:1369 RtMidi.h:1382 +#: RtMidi.h:1115 RtMidi.h:1346 RtMidi.h:1370 RtMidi.h:1383 msgid "No valid MIDI system has been selected." msgstr "Es wurde kein benutzbares MIDI-System ausgewählt." -#: RtMidi.h:1184 +#: RtMidi.h:1185 msgid "Could not find any valid MIDI system." msgstr "Es konnte kein benutzbares MIDI-System gefunden werden." -#: RtMidi.h:1225 +#: RtMidi.h:1226 msgid "No valid MIDI system has been found." msgstr "Es konnte kein benutzbares MIDI-System gefunden werden." -#: RtMidi.h:1363 +#: RtMidi.h:1364 msgid "No data in MIDI message." msgstr "Keine Daten in der MIDI-Nachricht." -#: RtMidi.h:1608 RtMidi.h:1630 +#: RtMidi.h:1610 RtMidi.h:1632 msgid "MidiInDummy: This class provides no functionality." msgstr "MidiInDummy: Diese Klasse stellt keine Funktionen zur verfügung." @@ -116,19 +116,19 @@ msgstr "" msgid "No supported MIDI system has been found." msgstr "Es konnte kein benutzbares MIDI-System gefunden werden." -#: RtMidi.cpp:474 RtMidi.cpp:491 +#: RtMidi.cpp:476 RtMidi.cpp:493 msgid "A callback function is already set." msgstr "Es wurde schon eine Rückruffunktion gesetzt." -#: RtMidi.cpp:480 RtMidi.cpp:497 +#: RtMidi.cpp:482 RtMidi.cpp:499 msgid "The callback function value is invalid." msgstr "Der Funktionswert einer aufgerufenen Rückruffunktion ist ungültig." -#: RtMidi.cpp:508 +#: RtMidi.cpp:510 msgid "No callback function was set." msgstr "Es wurde keine Rückruffunktion gesetzt." -#: RtMidi.cpp:530 +#: RtMidi.cpp:532 msgid "" "Returning an empty MIDI message as all input is handled by a callback " "function." @@ -136,13 +136,13 @@ msgstr "" "Es wird eine leere MIDI-Nachricht generiert, weil alle Eingaben durch eine " "Rückruf-Funktion (engl. callback) abgefangen werden." -#: RtMidi.cpp:1183 +#: RtMidi.cpp:1187 msgid "Could not get the unique identifier of a midi endpoint." msgstr "" "Konnte die eindeutige Identifikation (UUID) eines MIDI-Endpunktes nicht " "bekommen." -#: RtMidi.cpp:1193 +#: RtMidi.cpp:1197 msgid "" "Could not get the endpoint back from the unique identifier of a midi " "endpoint." @@ -150,69 +150,69 @@ msgstr "" "Konnte den MIDI-Endpunkt einer eindeutige Identifikation (UUID) nicht " "bekommen." -#: RtMidi.cpp:1208 +#: RtMidi.cpp:1212 msgid "Could not get the entity of a midi endpoint." msgstr "Konnte die Geräteeinheit eines MIDI-Endpunktes nicht bekommen." -#: RtMidi.cpp:1273 RtMidi.cpp:1313 +#: RtMidi.cpp:1277 RtMidi.cpp:1317 msgid "Error creating OS X MIDI port because of invalid port flags." msgstr "" "Konnte die OS X-MIDI-Schnittstelle nicht anlegen, da ungültige Eigenschaften " "angegeben wurden." -#: RtMidi.cpp:1277 RtMidi.cpp:1317 RtMidi.cpp:1858 +#: RtMidi.cpp:1281 RtMidi.cpp:1321 RtMidi.cpp:1862 msgid "Error creating OS-X MIDI port." msgstr "Es gab einen Fehler beim Erzeugen der MIDI-Schnittstelle." -#: RtMidi.cpp:1370 +#: RtMidi.cpp:1374 msgid "Error creating OS-X MIDI client object." msgstr "Fehler beim erzeugen des OS-X-MIDI-Klienten." -#: RtMidi.cpp:1626 RtMidi.cpp:1696 RtMidi.cpp:3006 RtMidi.cpp:4184 -#: RtMidi.cpp:5250 +#: RtMidi.cpp:1630 RtMidi.cpp:1700 RtMidi.cpp:2983 RtMidi.cpp:4162 +#: RtMidi.cpp:5236 msgid "Error: Message queue limit reached." msgstr "Fehler: Die Nachrichten-Warteschlange ist überlang." -#: RtMidi.cpp:1747 RtMidi.cpp:1839 RtMidi.cpp:1997 RtMidi.cpp:2090 -#: RtMidi.cpp:3149 RtMidi.cpp:3266 RtMidi.cpp:3534 RtMidi.cpp:3682 -#: RtMidi.cpp:4240 RtMidi.cpp:4535 RtMidi.cpp:4594 RtMidi.cpp:5438 -#: RtMidi.cpp:5655 +#: RtMidi.cpp:1751 RtMidi.cpp:1843 RtMidi.cpp:2001 RtMidi.cpp:2094 +#: RtMidi.cpp:3127 RtMidi.cpp:3244 RtMidi.cpp:3512 RtMidi.cpp:3660 +#: RtMidi.cpp:4218 RtMidi.cpp:4521 RtMidi.cpp:4580 RtMidi.cpp:5424 +#: RtMidi.cpp:5641 msgid "A valid connection already exists." msgstr "Es existiert schon eine gültige Verbindung." -#: RtMidi.cpp:1755 RtMidi.cpp:3156 RtMidi.cpp:4247 +#: RtMidi.cpp:1759 RtMidi.cpp:3134 RtMidi.cpp:4225 msgid "No MIDI input sources found." msgstr "Keine MIDI-Eingabe-Geräte gefunden." -#: RtMidi.cpp:1764 RtMidi.cpp:1922 RtMidi.cpp:1980 RtMidi.cpp:2011 -#: RtMidi.cpp:3166 RtMidi.cpp:3554 RtMidi.cpp:4435 RtMidi.cpp:4513 -#: RtMidi.cpp:4548 RtMidi.cpp:5534 RtMidi.cpp:5746 +#: RtMidi.cpp:1768 RtMidi.cpp:1926 RtMidi.cpp:1984 RtMidi.cpp:2015 +#: RtMidi.cpp:3144 RtMidi.cpp:3532 RtMidi.cpp:4413 RtMidi.cpp:4491 +#: RtMidi.cpp:4534 RtMidi.cpp:5520 RtMidi.cpp:5732 #, c-format msgid "The 'portNumber' argument (%d) is invalid." msgstr "Die Portnummer %d ist ungültig." -#: RtMidi.cpp:1776 +#: RtMidi.cpp:1780 msgid "Error creating OS-X MIDI input port." msgstr "Fehler beim Erzeugen der OS-X-MIDI-Eingabe-Schnittstelle." -#: RtMidi.cpp:1786 +#: RtMidi.cpp:1790 msgid "Error getting MIDI input source reference." msgstr "Konnte keine Referenz zum MIDI-Eingang bekommen." -#: RtMidi.cpp:1796 +#: RtMidi.cpp:1800 msgid "Error connecting OS-X MIDI input port." msgstr "Fehler beim verbinden mit dem OS-X-MIDI-Eingang." -#: RtMidi.cpp:1818 +#: RtMidi.cpp:1822 msgid "Error creating virtual OS-X MIDI destination." msgstr "Konnte den virtuellen OS-X-MIDI-Ausgang nicht erzeugen." -#: RtMidi.cpp:1834 RtMidi.cpp:2085 RtMidi.cpp:3261 RtMidi.cpp:3677 -#: RtMidi.cpp:5432 RtMidi.cpp:5649 +#: RtMidi.cpp:1838 RtMidi.cpp:2089 RtMidi.cpp:3239 RtMidi.cpp:3655 +#: RtMidi.cpp:5418 RtMidi.cpp:5635 msgid "Data has not been allocated." msgstr "Daten konnten nicht angelegt werden." -#: RtMidi.cpp:1844 RtMidi.cpp:2095 +#: RtMidi.cpp:1848 RtMidi.cpp:2099 msgid "" "Core MIDI has been instructed to open a non-Core MIDI port. This doesn't " "work." @@ -220,74 +220,80 @@ msgstr "" "Core-MIDI wurde angewiesen, eine nicht-Core-MIDI-Schnittstelle zu öffnen. " "Das geht nicht." -#: RtMidi.cpp:2005 +#: RtMidi.cpp:2009 msgid "No MIDI output destinations found." msgstr "Es wurden keine MIDI-Ausgabegeräte gefunden." -#: RtMidi.cpp:2023 +#: RtMidi.cpp:2027 msgid "Error creating OS-X MIDI output port." msgstr "Fehler beim Erzeugen der OS-X-MIDI-Ausgabe-Schnittstelle." -#: RtMidi.cpp:2033 +#: RtMidi.cpp:2037 msgid "Error getting MIDI output destination reference." msgstr "Konnte keine Referenz zum MIDI-Ausgang bekommen." -#: RtMidi.cpp:2058 +#: RtMidi.cpp:2062 msgid "A virtual output port already exists." msgstr "Es gibt schon einen virtuellen MIDI-Ausgang." -#: RtMidi.cpp:2069 +#: RtMidi.cpp:2073 msgid "Error creating OS-X virtual MIDI source." msgstr "Konnte den virtuellen OS-X-MIDI-Eingang nicht erzeugen." -#: RtMidi.cpp:2221 +#: RtMidi.cpp:2177 +msgid "message format problem ... not sysex but > 3 bytes?" +msgstr "" +"Nachrichtenformatproblem: Eine MIDI-Nachricht ist größer als 3 Bytes (und " +"keine SysEx-Nachricht)." + +#: RtMidi.cpp:2196 msgid "Could not allocate packet list." msgstr "Konnte die Paketliste nicht anlegen." -#: RtMidi.cpp:2230 +#: RtMidi.cpp:2205 msgid "Error sending MIDI to virtual destinations." msgstr "Konnte MIDI-Daten nicht zu virtuellen Ausgängen senden." -#: RtMidi.cpp:2239 RtMidi.cpp:3663 +#: RtMidi.cpp:2214 RtMidi.cpp:3641 msgid "Error sending MIDI message to port." msgstr "Fehler beim Senden der MIDI-Nachricht zum Ausgang." -#: RtMidi.cpp:2443 RtMidi.cpp:2704 RtMidi.cpp:3210 RtMidi.cpp:3271 -#: RtMidi.cpp:3580 +#: RtMidi.cpp:2418 RtMidi.cpp:2681 RtMidi.cpp:3188 RtMidi.cpp:3249 +#: RtMidi.cpp:3558 msgid "Could not allocate ALSA port subscription." msgstr "" "Konnte keinen Speicher für das Abonnoment der ALSA-MIDI-Schnittstelle " "bekommen." -#: RtMidi.cpp:2458 RtMidi.cpp:3219 RtMidi.cpp:3590 +#: RtMidi.cpp:2433 RtMidi.cpp:3197 RtMidi.cpp:3568 msgid "Error making ALSA port connection." msgstr "Konnte zwei ALSA-Schnittstellen nicht miteinander verbinden." -#: RtMidi.cpp:2528 RtMidi.cpp:3461 +#: RtMidi.cpp:2503 RtMidi.cpp:3439 msgid "Error creating ALSA sequencer client object." msgstr "Fehler beim erzeugen des ALSA-Klienten." -#: RtMidi.cpp:2766 RtMidi.cpp:3245 RtMidi.cpp:3394 +#: RtMidi.cpp:2743 RtMidi.cpp:3223 RtMidi.cpp:3372 msgid "Error starting MIDI input thread!" msgstr "Konnte den MIDI-Eingabe-Prozess nicht starten." -#: RtMidi.cpp:2804 RtMidi.cpp:3478 +#: RtMidi.cpp:2781 RtMidi.cpp:3456 msgid "Error initializing MIDI event parser." msgstr "Fehler bei der Initialisierung des MIDI-Ereeignisparsers." -#: RtMidi.cpp:2817 +#: RtMidi.cpp:2794 msgid "Error initializing buffer memory." msgstr "Fehler beim Anlegen des Pufferspeichers." -#: RtMidi.cpp:2851 +#: RtMidi.cpp:2828 msgid "MIDI input buffer overrun." msgstr "MIDI-Eingabepuffer übergelaufen." -#: RtMidi.cpp:2861 +#: RtMidi.cpp:2838 msgid "ALSA returned without providing a MIDI event." msgstr "ALSA kam zurück ohne ein MIDI-Ereignis mitzubringen." -#: RtMidi.cpp:2871 +#: RtMidi.cpp:2848 #, c-format msgid "" "Unknown MIDI input error.\n" @@ -298,111 +304,111 @@ msgstr "" "Das System meldet:\n" "%s" -#: RtMidi.cpp:2929 +#: RtMidi.cpp:2906 msgid "Error resizing buffer memory." msgstr "Fehler beim Ändern der Grüße des Pufferspeichers." -#: RtMidi.cpp:2980 +#: RtMidi.cpp:2957 msgid "Event parsing error or not a MIDI event." msgstr "" "Analyse eines Ereignisses fehlgeschlagen oder es war kein MIDI-Ereignis." -#: RtMidi.cpp:3061 +#: RtMidi.cpp:3038 msgid "Error creating pipe objects." msgstr "Fehler beim anlegen einer Pipe." -#: RtMidi.cpp:3141 RtMidi.cpp:3526 +#: RtMidi.cpp:3119 RtMidi.cpp:3504 msgid "Error looking for port name." msgstr "Fehler beim Suchen nach einem Schnittstellennamen." -#: RtMidi.cpp:3197 +#: RtMidi.cpp:3175 msgid "Error creating ALSA input port." msgstr "Fehler beim Erzeugen der ALSA-Eingabe-Schnittstelle." -#: RtMidi.cpp:3276 RtMidi.cpp:3692 +#: RtMidi.cpp:3254 RtMidi.cpp:3670 msgid "" "ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work." msgstr "" "ALSA wurde angewiesen, eine nicht-ALSA-MIDI-Schnittstelle zu öffnen. Das " "geht nicht." -#: RtMidi.cpp:3360 RtMidi.cpp:3617 +#: RtMidi.cpp:3338 RtMidi.cpp:3595 msgid "Error creating ALSA virtual port." msgstr "Fehler beim Erzeugen einer virtuellen ALSA-Schnittstelle." -#: RtMidi.cpp:3485 RtMidi.cpp:3641 +#: RtMidi.cpp:3463 RtMidi.cpp:3619 msgid "Error while allocating buffer memory." msgstr "Fehler beim Anlegen des Pufferspeichers." -#: RtMidi.cpp:3542 +#: RtMidi.cpp:3520 msgid "No MIDI output sinks found." msgstr "Es wurden kiene Midi-Ausgabegeräte gefunden." -#: RtMidi.cpp:3569 +#: RtMidi.cpp:3547 msgid "Error creating ALSA output port." msgstr "Fehler beim Erzeugen der ALSA-Ausgangs." -#: RtMidi.cpp:3634 +#: RtMidi.cpp:3612 msgid "ALSA error resizing MIDI event buffer." msgstr "ALSA-Fehler beim Verändern der Größe des MIDI-Nachrichten-Puffers." -#: RtMidi.cpp:3655 +#: RtMidi.cpp:3633 msgid "Event parsing error." msgstr "Fehler bei der Analyse eines Ereignisses." -#: RtMidi.cpp:3687 +#: RtMidi.cpp:3665 msgid "Error allocating ALSA port subscription." msgstr "" "Konnte keinen Speicher für das Abonnoment der ALSA-MIDI-Schnittstelle " "bekommen." -#: RtMidi.cpp:3837 +#: RtMidi.cpp:3815 #, c-format msgid "The port argument %d is invalid." msgstr "Das Schnittstellenargument %d ist ungültig." -#: RtMidi.cpp:4159 +#: RtMidi.cpp:4137 msgid "Error sending sysex to Midi device." msgstr "Fehler beim Senden der SysEx-Nachricht zum MIDI-Gerät." -#: RtMidi.cpp:4222 +#: RtMidi.cpp:4200 msgid "No MIDI input devices currently available." msgstr "Es gibt momentan keine MIDI-Eingabegeräte." -#: RtMidi.cpp:4232 +#: RtMidi.cpp:4210 msgid "Failed to initialize a critical section." msgstr "Konnte kritischen Bereich nicht initialisieren." -#: RtMidi.cpp:4256 +#: RtMidi.cpp:4234 #, c-format msgid "the 'portNumber' argument (%d) is invalid." msgstr "Die Portnummer %d ist ungültig." -#: RtMidi.cpp:4268 +#: RtMidi.cpp:4246 msgid "Error creating Windows MM MIDI input port." msgstr "Konnte den Windows-Multimedia-MIDI-Eingang nicht erzeugen." -#: RtMidi.cpp:4284 +#: RtMidi.cpp:4262 msgid "Error initializing data for Windows MM MIDI input port." msgstr "" "Fehler beim Erzeugen der daten für einen Windows Multimedia MIDI-Eingang." -#: RtMidi.cpp:4293 +#: RtMidi.cpp:4271 msgid "Could not register the input buffer for Windows MM MIDI input port." msgstr "" "Konnte den Eingabe-Puffer eines Windows-Multimedia-MIDI-Eingangs nicht " "erzeugen." -#: RtMidi.cpp:4302 +#: RtMidi.cpp:4280 msgid "Error starting Windows MM MIDI input port." msgstr "Konnte einen Windows-Multimedia-MIDI-Eingang nicht aktivieren." -#: RtMidi.cpp:4313 RtMidi.cpp:4581 +#: RtMidi.cpp:4291 RtMidi.cpp:4567 msgid "Virtual ports are not available Windows Multimedia MIDI API." msgstr "" "Windows Multimedia unterstützt keine virtuellen MIDI-Ein- und -Ausgänge." -#: RtMidi.cpp:4320 RtMidi.cpp:4589 +#: RtMidi.cpp:4298 RtMidi.cpp:4575 msgid "" "Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI " "port. This doesn't work." @@ -410,7 +416,7 @@ msgstr "" "Windows Multimedia (WinMM) wurde angewiesen, eine nicht-WinMM-MIDI-" "Schnittstelle zu öffnen. Das geht nicht." -#: RtMidi.cpp:4325 +#: RtMidi.cpp:4303 msgid "" "We are overwriting an existing connection. This is probably a programming " "error." @@ -418,12 +424,12 @@ msgstr "" "Wir überschreiben eine vorhandene MIDI-Verbindung. Das ist vermutlich ein " "Programmierfehler." -#: RtMidi.cpp:4330 +#: RtMidi.cpp:4308 msgid "Trying to open a non-input port as input MIDI port. This doesn't work." msgstr "" "Versuche eine Nicht-Eingang als MIDI-Eingang zu öffnen. Das geht nicht." -#: RtMidi.cpp:4344 RtMidi.cpp:4613 +#: RtMidi.cpp:4322 RtMidi.cpp:4599 msgid "" "Some change in the arrangement of MIDI input ports invalidated the port " "descriptor." @@ -431,105 +437,105 @@ msgstr "" "Eine Veränderung bei den MIDI-Schnittstellen hat die interne " "Schnittstellenbeschreibung ungültig gemacht." -#: RtMidi.cpp:4359 +#: RtMidi.cpp:4337 msgid "The handle is invalid. Did you disconnect the device?" msgstr "" "Ein Schnittstellenverweis ist ungültig. Haben Sie das zugehörige Gerät " "entfernt?" -#: RtMidi.cpp:4363 RtMidi.cpp:4632 +#: RtMidi.cpp:4341 RtMidi.cpp:4618 msgid "" "The system has no driver for our handle :-(. Did you disconnect the device?" msgstr "" "Das System hat keinen Treiber für unseren Schnittstellenverweis (mehr) :-(. " "Haben Sie das zugehörige Gerät entfernt?" -#: RtMidi.cpp:4367 RtMidi.cpp:4636 +#: RtMidi.cpp:4345 RtMidi.cpp:4622 msgid "Out of memory." msgstr "Hauptspeicher erschöpft." -#: RtMidi.cpp:4413 +#: RtMidi.cpp:4391 msgid "Error closing Windows MM MIDI input port." msgstr "" "Konnte den Windows Multimedia MIDI-Eingang nicht ordnungsgemäß schließen." -#: RtMidi.cpp:4491 +#: RtMidi.cpp:4469 msgid "No MIDI output devices currently available." msgstr "Es gibt momentan keine MIDI-Ausgabegeräte." -#: RtMidi.cpp:4542 +#: RtMidi.cpp:4528 msgid "No MIDI output destinations found!" msgstr "Es wurden keine MIDI-Ausgabegeräte gefunden." -#: RtMidi.cpp:4560 +#: RtMidi.cpp:4546 msgid "Error creating Windows MM MIDI output port." msgstr "Konnte den Windows Multimedia MIDI-Ausgang nicht erzeugen." -#: RtMidi.cpp:4599 +#: RtMidi.cpp:4585 msgid "The port descriptor cannot be used to open an output port." msgstr "" "Eine Schnittstellenbeschreibung kann nicht benutzt werden, um einen MIDI-" "Ausgang zu erzeugen." -#: RtMidi.cpp:4628 +#: RtMidi.cpp:4614 msgid "The internal handle is invalid. Did you disconnect the device?" msgstr "" "Ein interner Schnittstellenverweis ist ungültig. Haben sie das zugehörige " "Gerät entfernt?" -#: RtMidi.cpp:4664 +#: RtMidi.cpp:4650 msgid "Message argument is empty." msgstr "Das Nachrichtenargument ist leer." -#: RtMidi.cpp:4676 +#: RtMidi.cpp:4662 msgid "Error while allocating sysex message memory." msgstr "Fehler beim Anlegen des Speichers für SysEx-Nachrichten." -#: RtMidi.cpp:4692 +#: RtMidi.cpp:4678 msgid "Error preparing sysex header." msgstr "Fehler beim Erstellen des SysEx-Kopfes." -#: RtMidi.cpp:4701 +#: RtMidi.cpp:4687 msgid "Error sending sysex message." msgstr "Fehler beim Senden der SysEx-Nachricht." -#: RtMidi.cpp:4714 +#: RtMidi.cpp:4700 msgid "Message size is greater than 3 bytes (and not sysex)." msgstr "" "Eine MIDI-Nachricht ist größer als 3 Bytes (und keine SysEx-Nachricht)." -#: RtMidi.cpp:4730 +#: RtMidi.cpp:4716 msgid "Error sending MIDI message." msgstr "Fehler beim Senden der MIDI-Nachricht." -#: RtMidi.cpp:4961 +#: RtMidi.cpp:4947 msgid "Could not connect to JACK server. Is it runnig?" msgstr "Ich konnte mich nicht mit dem JACK-Server verbinden. Läuft er?" -#: RtMidi.cpp:5172 +#: RtMidi.cpp:5158 msgid "Error opening JACK port subscription." msgstr "Fehler beim abonnieren einer JACK-Schnittstelle." -#: RtMidi.cpp:5356 RtMidi.cpp:5584 +#: RtMidi.cpp:5342 RtMidi.cpp:5570 msgid "JACK server not running?" msgstr "Läuft der JACK-Server?" -#: RtMidi.cpp:5400 RtMidi.cpp:5617 +#: RtMidi.cpp:5386 RtMidi.cpp:5603 msgid "Error creating JACK port." msgstr "Es gab einen Fehler beim Erzeugen der JACK-Schnittstelle." -#: RtMidi.cpp:5420 RtMidi.cpp:5637 +#: RtMidi.cpp:5406 RtMidi.cpp:5623 msgid "Error creating JACK virtual port." msgstr "Fehler beim Erzeugen einer virtuellen JACK-Schnittstelle." -#: RtMidi.cpp:5444 RtMidi.cpp:5661 +#: RtMidi.cpp:5430 RtMidi.cpp:5647 msgid "" "JACK has been instructed to open a non-JACK MIDI port. This doesn't work." msgstr "" "JACK wurde angewiesen, eine nicht-JACK-Schnittstelle zu öffnen. Das geht " "nicht." -#: RtMidi.cpp:5527 RtMidi.cpp:5739 +#: RtMidi.cpp:5513 RtMidi.cpp:5725 msgid "No ports available." msgstr "Keine Schnittstellen verfügbar." diff --git a/po/rtmidi.pot b/po/rtmidi.pot index 792245d6..60eb9ba2 100644 --- a/po/rtmidi.pot +++ b/po/rtmidi.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: rtmidi 3.0\n" +"Project-Id-Version: rtmidi 2.1.0\n" "Report-Msgid-Bugs-To: https://github.com/thestk/rtmidi\n" -"POT-Creation-Date: 2015-10-14 22:01+0200\n" +"POT-Creation-Date: 2016-02-28 19:22+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -49,35 +49,35 @@ msgstr "" msgid "All available MIDI systems" msgstr "" -#: RtMidi.h:530 RtMidi.h:691 RtMidi.h:1220 RtMidi.h:1312 +#: RtMidi.h:530 RtMidi.h:692 RtMidi.h:1221 RtMidi.h:1313 msgid "Passed NULL pointer." msgstr "" -#: RtMidi.h:723 RtMidi.cpp:2161 +#: RtMidi.h:724 RtMidi.cpp:2165 msgid "No data in message argument." msgstr "" -#: RtMidi.h:1082 +#: RtMidi.h:1083 msgid "A NULL pointer has been passed as port descriptor" msgstr "" -#: RtMidi.h:1114 RtMidi.h:1345 RtMidi.h:1369 RtMidi.h:1382 +#: RtMidi.h:1115 RtMidi.h:1346 RtMidi.h:1370 RtMidi.h:1383 msgid "No valid MIDI system has been selected." msgstr "" -#: RtMidi.h:1184 +#: RtMidi.h:1185 msgid "Could not find any valid MIDI system." msgstr "" -#: RtMidi.h:1225 +#: RtMidi.h:1226 msgid "No valid MIDI system has been found." msgstr "" -#: RtMidi.h:1363 +#: RtMidi.h:1364 msgid "No data in MIDI message." msgstr "" -#: RtMidi.h:1608 RtMidi.h:1630 +#: RtMidi.h:1610 RtMidi.h:1632 msgid "MidiInDummy: This class provides no functionality." msgstr "" @@ -105,166 +105,170 @@ msgstr "" msgid "No supported MIDI system has been found." msgstr "" -#: RtMidi.cpp:474 RtMidi.cpp:491 +#: RtMidi.cpp:476 RtMidi.cpp:493 msgid "A callback function is already set." msgstr "" -#: RtMidi.cpp:480 RtMidi.cpp:497 +#: RtMidi.cpp:482 RtMidi.cpp:499 msgid "The callback function value is invalid." msgstr "" -#: RtMidi.cpp:508 +#: RtMidi.cpp:510 msgid "No callback function was set." msgstr "" -#: RtMidi.cpp:530 +#: RtMidi.cpp:532 msgid "" "Returning an empty MIDI message as all input is handled by a callback " "function." msgstr "" -#: RtMidi.cpp:1183 +#: RtMidi.cpp:1187 msgid "Could not get the unique identifier of a midi endpoint." msgstr "" -#: RtMidi.cpp:1193 +#: RtMidi.cpp:1197 msgid "" "Could not get the endpoint back from the unique identifier of a midi " "endpoint." msgstr "" -#: RtMidi.cpp:1208 +#: RtMidi.cpp:1212 msgid "Could not get the entity of a midi endpoint." msgstr "" -#: RtMidi.cpp:1273 RtMidi.cpp:1313 +#: RtMidi.cpp:1277 RtMidi.cpp:1317 msgid "Error creating OS X MIDI port because of invalid port flags." msgstr "" -#: RtMidi.cpp:1277 RtMidi.cpp:1317 RtMidi.cpp:1858 +#: RtMidi.cpp:1281 RtMidi.cpp:1321 RtMidi.cpp:1862 msgid "Error creating OS-X MIDI port." msgstr "" -#: RtMidi.cpp:1370 +#: RtMidi.cpp:1374 msgid "Error creating OS-X MIDI client object." msgstr "" -#: RtMidi.cpp:1626 RtMidi.cpp:1696 RtMidi.cpp:3006 RtMidi.cpp:4184 -#: RtMidi.cpp:5250 +#: RtMidi.cpp:1630 RtMidi.cpp:1700 RtMidi.cpp:2983 RtMidi.cpp:4162 +#: RtMidi.cpp:5236 msgid "Error: Message queue limit reached." msgstr "" -#: RtMidi.cpp:1747 RtMidi.cpp:1839 RtMidi.cpp:1997 RtMidi.cpp:2090 -#: RtMidi.cpp:3149 RtMidi.cpp:3266 RtMidi.cpp:3534 RtMidi.cpp:3682 -#: RtMidi.cpp:4240 RtMidi.cpp:4535 RtMidi.cpp:4594 RtMidi.cpp:5438 -#: RtMidi.cpp:5655 +#: RtMidi.cpp:1751 RtMidi.cpp:1843 RtMidi.cpp:2001 RtMidi.cpp:2094 +#: RtMidi.cpp:3127 RtMidi.cpp:3244 RtMidi.cpp:3512 RtMidi.cpp:3660 +#: RtMidi.cpp:4218 RtMidi.cpp:4521 RtMidi.cpp:4580 RtMidi.cpp:5424 +#: RtMidi.cpp:5641 msgid "A valid connection already exists." msgstr "" -#: RtMidi.cpp:1755 RtMidi.cpp:3156 RtMidi.cpp:4247 +#: RtMidi.cpp:1759 RtMidi.cpp:3134 RtMidi.cpp:4225 msgid "No MIDI input sources found." msgstr "" -#: RtMidi.cpp:1764 RtMidi.cpp:1922 RtMidi.cpp:1980 RtMidi.cpp:2011 -#: RtMidi.cpp:3166 RtMidi.cpp:3554 RtMidi.cpp:4435 RtMidi.cpp:4513 -#: RtMidi.cpp:4548 RtMidi.cpp:5534 RtMidi.cpp:5746 +#: RtMidi.cpp:1768 RtMidi.cpp:1926 RtMidi.cpp:1984 RtMidi.cpp:2015 +#: RtMidi.cpp:3144 RtMidi.cpp:3532 RtMidi.cpp:4413 RtMidi.cpp:4491 +#: RtMidi.cpp:4534 RtMidi.cpp:5520 RtMidi.cpp:5732 #, c-format msgid "The 'portNumber' argument (%d) is invalid." msgstr "" -#: RtMidi.cpp:1776 +#: RtMidi.cpp:1780 msgid "Error creating OS-X MIDI input port." msgstr "" -#: RtMidi.cpp:1786 +#: RtMidi.cpp:1790 msgid "Error getting MIDI input source reference." msgstr "" -#: RtMidi.cpp:1796 +#: RtMidi.cpp:1800 msgid "Error connecting OS-X MIDI input port." msgstr "" -#: RtMidi.cpp:1818 +#: RtMidi.cpp:1822 msgid "Error creating virtual OS-X MIDI destination." msgstr "" -#: RtMidi.cpp:1834 RtMidi.cpp:2085 RtMidi.cpp:3261 RtMidi.cpp:3677 -#: RtMidi.cpp:5432 RtMidi.cpp:5649 +#: RtMidi.cpp:1838 RtMidi.cpp:2089 RtMidi.cpp:3239 RtMidi.cpp:3655 +#: RtMidi.cpp:5418 RtMidi.cpp:5635 msgid "Data has not been allocated." msgstr "" -#: RtMidi.cpp:1844 RtMidi.cpp:2095 +#: RtMidi.cpp:1848 RtMidi.cpp:2099 msgid "" "Core MIDI has been instructed to open a non-Core MIDI port. This doesn't " "work." msgstr "" -#: RtMidi.cpp:2005 +#: RtMidi.cpp:2009 msgid "No MIDI output destinations found." msgstr "" -#: RtMidi.cpp:2023 +#: RtMidi.cpp:2027 msgid "Error creating OS-X MIDI output port." msgstr "" -#: RtMidi.cpp:2033 +#: RtMidi.cpp:2037 msgid "Error getting MIDI output destination reference." msgstr "" -#: RtMidi.cpp:2058 +#: RtMidi.cpp:2062 msgid "A virtual output port already exists." msgstr "" -#: RtMidi.cpp:2069 +#: RtMidi.cpp:2073 msgid "Error creating OS-X virtual MIDI source." msgstr "" -#: RtMidi.cpp:2221 +#: RtMidi.cpp:2177 +msgid "message format problem ... not sysex but > 3 bytes?" +msgstr "" + +#: RtMidi.cpp:2196 msgid "Could not allocate packet list." msgstr "" -#: RtMidi.cpp:2230 +#: RtMidi.cpp:2205 msgid "Error sending MIDI to virtual destinations." msgstr "" -#: RtMidi.cpp:2239 RtMidi.cpp:3663 +#: RtMidi.cpp:2214 RtMidi.cpp:3641 msgid "Error sending MIDI message to port." msgstr "" -#: RtMidi.cpp:2443 RtMidi.cpp:2704 RtMidi.cpp:3210 RtMidi.cpp:3271 -#: RtMidi.cpp:3580 +#: RtMidi.cpp:2418 RtMidi.cpp:2681 RtMidi.cpp:3188 RtMidi.cpp:3249 +#: RtMidi.cpp:3558 msgid "Could not allocate ALSA port subscription." msgstr "" -#: RtMidi.cpp:2458 RtMidi.cpp:3219 RtMidi.cpp:3590 +#: RtMidi.cpp:2433 RtMidi.cpp:3197 RtMidi.cpp:3568 msgid "Error making ALSA port connection." msgstr "" -#: RtMidi.cpp:2528 RtMidi.cpp:3461 +#: RtMidi.cpp:2503 RtMidi.cpp:3439 msgid "Error creating ALSA sequencer client object." msgstr "" -#: RtMidi.cpp:2766 RtMidi.cpp:3245 RtMidi.cpp:3394 +#: RtMidi.cpp:2743 RtMidi.cpp:3223 RtMidi.cpp:3372 msgid "Error starting MIDI input thread!" msgstr "" -#: RtMidi.cpp:2804 RtMidi.cpp:3478 +#: RtMidi.cpp:2781 RtMidi.cpp:3456 msgid "Error initializing MIDI event parser." msgstr "" -#: RtMidi.cpp:2817 +#: RtMidi.cpp:2794 msgid "Error initializing buffer memory." msgstr "" -#: RtMidi.cpp:2851 +#: RtMidi.cpp:2828 msgid "MIDI input buffer overrun." msgstr "" -#: RtMidi.cpp:2861 +#: RtMidi.cpp:2838 msgid "ALSA returned without providing a MIDI event." msgstr "" -#: RtMidi.cpp:2871 +#: RtMidi.cpp:2848 #, c-format msgid "" "Unknown MIDI input error.\n" @@ -272,209 +276,209 @@ msgid "" "%s" msgstr "" -#: RtMidi.cpp:2929 +#: RtMidi.cpp:2906 msgid "Error resizing buffer memory." msgstr "" -#: RtMidi.cpp:2980 +#: RtMidi.cpp:2957 msgid "Event parsing error or not a MIDI event." msgstr "" -#: RtMidi.cpp:3061 +#: RtMidi.cpp:3038 msgid "Error creating pipe objects." msgstr "" -#: RtMidi.cpp:3141 RtMidi.cpp:3526 +#: RtMidi.cpp:3119 RtMidi.cpp:3504 msgid "Error looking for port name." msgstr "" -#: RtMidi.cpp:3197 +#: RtMidi.cpp:3175 msgid "Error creating ALSA input port." msgstr "" -#: RtMidi.cpp:3276 RtMidi.cpp:3692 +#: RtMidi.cpp:3254 RtMidi.cpp:3670 msgid "" "ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work." msgstr "" -#: RtMidi.cpp:3360 RtMidi.cpp:3617 +#: RtMidi.cpp:3338 RtMidi.cpp:3595 msgid "Error creating ALSA virtual port." msgstr "" -#: RtMidi.cpp:3485 RtMidi.cpp:3641 +#: RtMidi.cpp:3463 RtMidi.cpp:3619 msgid "Error while allocating buffer memory." msgstr "" -#: RtMidi.cpp:3542 +#: RtMidi.cpp:3520 msgid "No MIDI output sinks found." msgstr "" -#: RtMidi.cpp:3569 +#: RtMidi.cpp:3547 msgid "Error creating ALSA output port." msgstr "" -#: RtMidi.cpp:3634 +#: RtMidi.cpp:3612 msgid "ALSA error resizing MIDI event buffer." msgstr "" -#: RtMidi.cpp:3655 +#: RtMidi.cpp:3633 msgid "Event parsing error." msgstr "" -#: RtMidi.cpp:3687 +#: RtMidi.cpp:3665 msgid "Error allocating ALSA port subscription." msgstr "" -#: RtMidi.cpp:3837 +#: RtMidi.cpp:3815 #, c-format msgid "The port argument %d is invalid." msgstr "" -#: RtMidi.cpp:4159 +#: RtMidi.cpp:4137 msgid "Error sending sysex to Midi device." msgstr "" -#: RtMidi.cpp:4222 +#: RtMidi.cpp:4200 msgid "No MIDI input devices currently available." msgstr "" -#: RtMidi.cpp:4232 +#: RtMidi.cpp:4210 msgid "Failed to initialize a critical section." msgstr "" -#: RtMidi.cpp:4256 +#: RtMidi.cpp:4234 #, c-format msgid "the 'portNumber' argument (%d) is invalid." msgstr "" -#: RtMidi.cpp:4268 +#: RtMidi.cpp:4246 msgid "Error creating Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4284 +#: RtMidi.cpp:4262 msgid "Error initializing data for Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4293 +#: RtMidi.cpp:4271 msgid "Could not register the input buffer for Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4302 +#: RtMidi.cpp:4280 msgid "Error starting Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4313 RtMidi.cpp:4581 +#: RtMidi.cpp:4291 RtMidi.cpp:4567 msgid "Virtual ports are not available Windows Multimedia MIDI API." msgstr "" -#: RtMidi.cpp:4320 RtMidi.cpp:4589 +#: RtMidi.cpp:4298 RtMidi.cpp:4575 msgid "" "Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI " "port. This doesn't work." msgstr "" -#: RtMidi.cpp:4325 +#: RtMidi.cpp:4303 msgid "" "We are overwriting an existing connection. This is probably a programming " "error." msgstr "" -#: RtMidi.cpp:4330 +#: RtMidi.cpp:4308 msgid "Trying to open a non-input port as input MIDI port. This doesn't work." msgstr "" -#: RtMidi.cpp:4344 RtMidi.cpp:4613 +#: RtMidi.cpp:4322 RtMidi.cpp:4599 msgid "" "Some change in the arrangement of MIDI input ports invalidated the port " "descriptor." msgstr "" -#: RtMidi.cpp:4359 +#: RtMidi.cpp:4337 msgid "The handle is invalid. Did you disconnect the device?" msgstr "" -#: RtMidi.cpp:4363 RtMidi.cpp:4632 +#: RtMidi.cpp:4341 RtMidi.cpp:4618 msgid "" "The system has no driver for our handle :-(. Did you disconnect the device?" msgstr "" -#: RtMidi.cpp:4367 RtMidi.cpp:4636 +#: RtMidi.cpp:4345 RtMidi.cpp:4622 msgid "Out of memory." msgstr "" -#: RtMidi.cpp:4413 +#: RtMidi.cpp:4391 msgid "Error closing Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4491 +#: RtMidi.cpp:4469 msgid "No MIDI output devices currently available." msgstr "" -#: RtMidi.cpp:4542 +#: RtMidi.cpp:4528 msgid "No MIDI output destinations found!" msgstr "" -#: RtMidi.cpp:4560 +#: RtMidi.cpp:4546 msgid "Error creating Windows MM MIDI output port." msgstr "" -#: RtMidi.cpp:4599 +#: RtMidi.cpp:4585 msgid "The port descriptor cannot be used to open an output port." msgstr "" -#: RtMidi.cpp:4628 +#: RtMidi.cpp:4614 msgid "The internal handle is invalid. Did you disconnect the device?" msgstr "" -#: RtMidi.cpp:4664 +#: RtMidi.cpp:4650 msgid "Message argument is empty." msgstr "" -#: RtMidi.cpp:4676 +#: RtMidi.cpp:4662 msgid "Error while allocating sysex message memory." msgstr "" -#: RtMidi.cpp:4692 +#: RtMidi.cpp:4678 msgid "Error preparing sysex header." msgstr "" -#: RtMidi.cpp:4701 +#: RtMidi.cpp:4687 msgid "Error sending sysex message." msgstr "" -#: RtMidi.cpp:4714 +#: RtMidi.cpp:4700 msgid "Message size is greater than 3 bytes (and not sysex)." msgstr "" -#: RtMidi.cpp:4730 +#: RtMidi.cpp:4716 msgid "Error sending MIDI message." msgstr "" -#: RtMidi.cpp:4961 +#: RtMidi.cpp:4947 msgid "Could not connect to JACK server. Is it runnig?" msgstr "" -#: RtMidi.cpp:5172 +#: RtMidi.cpp:5158 msgid "Error opening JACK port subscription." msgstr "" -#: RtMidi.cpp:5356 RtMidi.cpp:5584 +#: RtMidi.cpp:5342 RtMidi.cpp:5570 msgid "JACK server not running?" msgstr "" -#: RtMidi.cpp:5400 RtMidi.cpp:5617 +#: RtMidi.cpp:5386 RtMidi.cpp:5603 msgid "Error creating JACK port." msgstr "" -#: RtMidi.cpp:5420 RtMidi.cpp:5637 +#: RtMidi.cpp:5406 RtMidi.cpp:5623 msgid "Error creating JACK virtual port." msgstr "" -#: RtMidi.cpp:5444 RtMidi.cpp:5661 +#: RtMidi.cpp:5430 RtMidi.cpp:5647 msgid "" "JACK has been instructed to open a non-JACK MIDI port. This doesn't work." msgstr "" -#: RtMidi.cpp:5527 RtMidi.cpp:5739 +#: RtMidi.cpp:5513 RtMidi.cpp:5725 msgid "No ports available." msgstr "" From af49a244fd00cc0ff7fca9a5d3357dd9114cae1c Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Thu, 31 Mar 2016 15:34:49 +0200 Subject: [PATCH 103/210] Fix compilation with gettext support. --- RtMidi.cpp | 6 +++--- RtMidi.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index ccce89f4..4a587585 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -51,7 +51,7 @@ const char * rtmidi_gettext (const char * s) { } void init_rtmidi_gettext() { - static initialized = false; + static bool initialized = false; if (initialized) return; bindtextdomain("rtmidi",LOCALEDIR); @@ -86,7 +86,7 @@ Error::Error( const char * message, } else { const char * fmt = gettext_noopt("Error formatting the error string:\n'%s'\nFound in %s::%s at \n%s:%d"); #ifdef RTMIDI_GETTEXT - fmt = gettext(fmt); + fmt = rtmidi_gettext(fmt); #endif length = snprintf(NULL,0,fmt,message,class_name,function_name,file_name,line); @@ -98,7 +98,7 @@ Error::Error( const char * message, const char * msg = gettext_noopt("Error: could not format the error message"); #ifdef RTMIDI_GETTEXT - msg = gettext(msg); + msg = rtmidi_gettext(msg); #endif message_ = msg; } diff --git a/RtMidi.h b/RtMidi.h index c38cc0a3..ea792111 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -77,7 +77,7 @@ #include #ifdef RTMIDI_GETTEXT -#include "gettext.h" +#include "libintl.h" #endif #define gettext_noopt(str) (str) From 40575896be2f617f45c312b895a1138cfae9ac04 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Thu, 31 Mar 2016 15:35:07 +0200 Subject: [PATCH 104/210] Fix compilation of dummy midi device. --- RtMidi.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index ea792111..4fc17f7c 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -1607,6 +1607,7 @@ class MidiOutWinMM: public MidiOutApi #if defined(__RTMIDI_DUMMY__) +#define RTMIDI_CLASSNAME "MidiInDummy" class MidiInDummy: public MidiInApi { public: @@ -1615,11 +1616,11 @@ class MidiInDummy: public MidiInApi error( RTMIDI_ERROR(_("MidiInDummy: This class provides no functionality."), Error::WARNING) ); } - ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } + ApiType getCurrentApi( void ) throw() { return DUMMY; } bool hasVirtualPorts() const { return false; } - void openPort( unsigned int /*portNumber*/, const & std::string /*portName*/ ) {} + void openPort( unsigned int portNumber, const &std::string portName ) {} void openVirtualPort( const std::string /*portName*/ ) {} - void openPort( const PortDescriptor & port, const & std::string portName) {} + void openPort( const PortDescriptor & port, const &std::string portName) {} Pointer getDescriptor(bool local=false) { return 0; } PortList getPortList(int capabilities) { return PortList(); } void closePort( void ) {} @@ -1629,7 +1630,9 @@ class MidiInDummy: public MidiInApi protected: void initialize( const std::string& /*clientName*/ ) {} }; +#undef RTMIDI_CLASSNAME +#define RTMIDI_CLASSNAME "MidiOutDummy" class MidiOutDummy: public MidiOutApi { public: @@ -1637,7 +1640,7 @@ class MidiOutDummy: public MidiOutApi error( RTMIDI_ERROR(_("MidiInDummy: This class provides no functionality."), Error::WARNING) ); } - ApiType getCurrentApi( void ) { return RTMIDI_DUMMY; } + ApiType getCurrentApi( void ) { return DUMMY; } bool hasVirtualPorts() const { return false; } void openPort( unsigned int /*portNumber*/, const & std::string /*portName*/ ) {} void openVirtualPort( const std::string /*portName*/ ) {} From b6bb480b32f6ca2244b482cbaded92c364809b18 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 1 Apr 2016 17:12:08 +0200 Subject: [PATCH 105/210] Avoid triggering of warnings in RtMidi.h when the functions are not actually used. --- RtMidi.h | 154 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 91 insertions(+), 63 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index 4fc17f7c..3ef31939 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -150,33 +150,6 @@ struct MidiInterface { virtual void delete_me() {} }; -//! C style user callback function type definition. -/*! - This interface type has been replaced by a MidiInterface class. - - \param timeStamp timestamp indicating when the event has been received - \param message a pointer to the binary MIDI message - \param userData a pointer that can be set using setUserdata - \sa MidiIn - \sa MidiInApi - \sa MidiInterface - \deprecated -*/ -RTMIDI_DEPRECATED(typedef void (*MidiCallback)( double timeStamp, std::vector *message, void *userData),"RtMidi now provides a class MidiInterface for MIDI callbacks"); - -//! Compatibility interface to hold a C style callback function -struct CompatibilityMidiInterface: MidiInterface { - CompatibilityMidiInterface(MidiCallback cb, void * ud): - callback(cb), - userData(ud) {} - void rtmidi_midi_in(double timestamp, std::vector *message) { - callback (timestamp, message, userData); - } - void delete_me() { delete this; } - MidiCallback callback; - void * userData; -}; - /************************************************************************/ /*! \class Error \brief Exception handling class for RtMidi. @@ -215,11 +188,11 @@ class Error : public std::exception //! The constructor. Error( const char * message, - Type type, - const char * class_name, - const char * function_name, - const char * file_name, - int line_number, ...) throw(); + Type type, + const char * class_name, + const char * function_name, + const char * file_name, + int line_number, ...) throw(); //! The destructor. virtual ~Error( void ) throw() {} @@ -250,36 +223,13 @@ class Error : public std::exception Type type_; }; -//! RtMidi error callback function prototype. -/*! - \param type Type of error. - \param errorText Error description. - Note that class behaviour is undefined after a critical error (not - a warning) is reported. -*/ -typedef void (*ErrorCallback)( Error::Type type, const std::string &errorText, void * userdata ); struct ErrorInterface { virtual ~ErrorInterface() {} virtual void rtmidi_error (Error e) = 0; virtual void delete_me() {}; }; -struct CompatibilityErrorInterface: ErrorInterface { - CompatibilityErrorInterface(ErrorCallback cb, void * ud): callback(cb), - userdata(ud) {} - void rtmidi_error(Error e) { - callback(e.getType(),e.getMessage(),userdata); - } - - void delete_me() { delete this; } -private: - ErrorCallback callback; - void * userdata; -}; - - - #if !RTMIDI_SUPPORTS_CPP11 class PortDescriptor; @@ -462,6 +412,29 @@ class PortDescriptor { typedef std::list > PortList; +//! RtMidi error callback function prototype. +/*! + \param type Type of error. + \param errorText Error description. + + Note that class behaviour is undefined after a critical error (not + a warning) is reported. +*/ +RTMIDI_DEPRECATED(typedef void (*ErrorCallback)( Error::Type type, const std::string &errorText, void * userdata ),"RtMidi now provides a class MidiInterface for error callbacks"); + +//! C style user callback function type definition. +/*! + This interface type has been replaced by a MidiInterface class. + + \param timeStamp timestamp indicating when the event has been received + \param message a pointer to the binary MIDI message + \param userData a pointer that can be set using setUserdata + \sa MidiIn + \sa MidiInApi + \sa MidiInterface + \deprecated +*/ +RTMIDI_DEPRECATED(typedef void (*MidiCallback)( double timeStamp, std::vector *message, void *userData),"RtMidi now provides a class MidiInterface for MIDI callbacks"); // **************************************************************** // // @@ -635,6 +608,9 @@ class MidiApi */ void error( Error e ); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + //! Virtual function to set an error callback function to be invoked when an error has occured. /*! The callback function will be called whenever an error has occured. It is best @@ -642,6 +618,7 @@ class MidiApi */ RTMIDI_DEPRECATED(virtual void setErrorCallback( ErrorCallback errorCallback = NULL, void * userData = 0 ), "RtMidi now provides a typesafe ErrorInterface class"); +#pragma GCC diagnostic pop protected: virtual void initialize( const std::string& clientName ) = 0; @@ -688,6 +665,10 @@ class MidiInApi : public MidiApi :front(0), back(0), size(0), ringSize(0) {} }; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + + RTMIDI_DEPRECATED(void setCallback( MidiCallback callback, void *userData = 0 ), "RtMidi now provides a type-safe MidiInterface class."); RTMIDI_DEPRECATED(double getMessage( std::vector *message ), @@ -700,6 +681,8 @@ class MidiInApi : public MidiApi return getMessage(*message); } +#pragma GCC diagnostic pop + protected: // The RtMidiInData structure is used to pass private class data to // the MIDI input handling function or thread. @@ -822,10 +805,10 @@ class Midi { if (list && !list->empty()) { PortList retval; for (MidiApiList::iterator i = list->begin(); - i != list->end(); - ++i) { - PortList tmp = (*i)->getPortList(capabilities); - retval.splice(retval.end(), tmp); + i != list->end(); + ++i) { + PortList tmp = (*i)->getPortList(capabilities); + retval.splice(retval.end(), tmp); } return retval; } @@ -863,6 +846,8 @@ class Midi { //! A basic error reporting function for RtMidi classes. void error( Error e ); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" /* old functions */ RTMIDI_DEPRECATED(enum, @@ -985,7 +970,7 @@ inline std::string getApiName(Midi::Api type) return getApiName((ApiType)type); } - +#pragma GCC diagnostic pop #undef RTMIDI_CLASSNAME /**********************************************************************/ @@ -1110,8 +1095,8 @@ class MidiIn : public Midi std::vector< ApiType > apis; getCompiledApi( apis ); for (size_t i = 0 ; i < apis.size() ; i++) { - openMidiApi( apis[0] ); - if (rtapi_ && rtapi_->hasVirtualPorts()) break; + openMidiApi( apis[0] ); + if (rtapi_ && rtapi_->hasVirtualPorts()) break; } } @@ -1192,6 +1177,9 @@ class MidiIn : public Midi return 0.0; } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + //! Set a callback function to be invoked for incoming MIDI messages. /*! The callback function will be called whenever an incoming MIDI @@ -1232,7 +1220,7 @@ class MidiIn : public Midi Error::WARNING)); return 0.0; } - +#pragma GCC diagnostic pop protected: static MidiApiList queryApis; int queueSizeLimit; @@ -1658,6 +1646,42 @@ class MidiOutDummy: public MidiOutApi #endif +// old API + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + +//! Compatibility interface to hold a C style callback function +struct CompatibilityMidiInterface: MidiInterface { + CompatibilityMidiInterface(MidiCallback cb, void * ud): + callback(cb), + userData(ud) {} + void rtmidi_midi_in(double timestamp, std::vector *message) { + callback (timestamp, message, userData); + } + void delete_me() { delete this; } + MidiCallback callback; + void * userData; +}; + + +struct CompatibilityErrorInterface: ErrorInterface { + CompatibilityErrorInterface(ErrorCallback cb, void * ud): callback(cb), + userdata(ud) {} + void rtmidi_error(Error e) { + callback(e.getType(),e.getMessage(),userdata); + } + + void delete_me() { delete this; } +private: + ErrorCallback callback; + void * userdata; +}; + + + NAMESPACE_RTMIDI_END typedef rtmidi::Midi RTMIDI_DEPRECATED(RtMidi,"RtMidi has been replaced by rtmidi::Midi"); @@ -1679,4 +1703,8 @@ class RtMidiOut: public rtmidi::MidiOut { clientName) {} }; typedef rtmidi::Error RtMidiError; +#ifdef GCC +#pragma GCC diagnostic pop +#endif + #endif From cc0f6d18824595bc439728d956772e6e7c2debaf Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 1 Apr 2016 17:13:06 +0200 Subject: [PATCH 106/210] Add PortPointer as Pointer type for increasing readablity of source code. --- RtMidi.h | 1 + 1 file changed, 1 insertion(+) diff --git a/RtMidi.h b/RtMidi.h index 3ef31939..e1ff8a05 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -409,6 +409,7 @@ class PortDescriptor { /*! Port descriptors are stored as shared pointers. This avoids unnecessary duplication of the data structure and handles automatic deletion if all references have been removed. */ +typedef Pointer PortPointer; typedef std::list > PortList; From 0058095605e1c7fb54dd7eb39df742272f8605be Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 1 Apr 2016 17:13:32 +0200 Subject: [PATCH 107/210] Add some missing operators to for the Pointer Class. --- RtMidi.h | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index e1ff8a05..8c99d135 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -280,15 +280,26 @@ class Pointer { else return (*ptr->descriptor); } + const datatype & operator * () const { + if (!ptr || !ptr->descriptor) { + throw std::invalid_argument("rtmidi::Pointer: trying to dereference a NULL pointer."); + } + else return (*ptr->descriptor); + } + bool operator ! () { return (!ptr || !ptr->descriptor); } + operator bool () { + return (ptr && ptr->descriptor); + } + Pointer & operator = (const Pointer & other) { if (ptr) { if (!(--ptr->count)) { - delete ptr->descriptor; - delete ptr; + delete ptr->descriptor; + delete ptr; } } ptr = other.ptr; @@ -298,6 +309,16 @@ class Pointer { protected: countPointer * ptr; }; + +template +bool operator==(const Pointer& lhs, const Pointer& rhs) { + return (&(*lhs)) == (&(*rhs)); +} + +template +bool operator!=(const Pointer& lhs, const Pointer& rhs) { + return (&(*lhs)) != (&(*rhs)); +} #else template using Pointer = std::shared_ptr; From 0161cab8ac802b308842cb12070f19fef09e292f Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 2 Apr 2016 14:48:24 +0200 Subject: [PATCH 108/210] Write sub-constructors in the correct order for MidiApi::MidiApi(). --- RtMidi.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 52176015..17752ce7 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -397,8 +397,8 @@ MidiOut :: ~MidiOut() throw() MidiApi :: MidiApi( void ) : apiData_( 0 ), connected_( false ), - errorCallback_(0), - firstErrorOccurred_ (false) + firstErrorOccurred_ (false), + errorCallback_(0) { } From 86aac099da20b17c07abd0cf9507f4427c26f2d2 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 2 Apr 2016 16:13:15 +0200 Subject: [PATCH 109/210] Fix issuing of deprication warnings. Some warnings were not generated properly. --- RtMidi.h | 73 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index 099102a0..91d6b5f9 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -433,7 +433,10 @@ class PortDescriptor { typedef Pointer PortPointer; typedef std::list > PortList; - +/* A depricated type. See below for the documentation. We + split the definiton into several pieces to work around some + intended warnings. */ +typedef void (*ErrorCallback_t)( Error::Type type, const std::string &errorText, void * userdata ); //! RtMidi error callback function prototype. /*! \param type Type of error. @@ -441,9 +444,17 @@ typedef std::list > PortList; Note that class behaviour is undefined after a critical error (not a warning) is reported. + \sa ErrorInterface + \depricated */ -RTMIDI_DEPRECATED(typedef void (*ErrorCallback)( Error::Type type, const std::string &errorText, void * userdata ),"RtMidi now provides a class MidiInterface for error callbacks"); +RTMIDI_DEPRECATED(typedef ErrorCallback_t ErrorCallback,"RtMidi now provides a class MidiInterface for error callbacks"); + +/* A depricated type. See below for the documentation. We + split the definiton into several pieces to work around some + intended warnings. */ +#define ErrorCallback ErrorCallback_t +typedef void (*MidiCallback_t)( double timeStamp, std::vector *message, void *userData); //! C style user callback function type definition. /*! This interface type has been replaced by a MidiInterface class. @@ -456,7 +467,8 @@ RTMIDI_DEPRECATED(typedef void (*ErrorCallback)( Error::Type type, const std::st \sa MidiInterface \deprecated */ -RTMIDI_DEPRECATED(typedef void (*MidiCallback)( double timeStamp, std::vector *message, void *userData),"RtMidi now provides a class MidiInterface for MIDI callbacks"); +RTMIDI_DEPRECATED(typedef MidiCallback_t MidiCallback,"RtMidi now provides a class MidiInterface for MIDI callbacks"); +#define MidiCallback MidiCallback_t // **************************************************************** // // @@ -630,8 +642,6 @@ class MidiApi */ void error( Error e ); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" //! Virtual function to set an error callback function to be invoked when an error has occured. /*! @@ -640,7 +650,6 @@ class MidiApi */ RTMIDI_DEPRECATED(virtual void setErrorCallback( ErrorCallback errorCallback = NULL, void * userData = 0 ), "RtMidi now provides a typesafe ErrorInterface class"); -#pragma GCC diagnostic pop protected: virtual void initialize( const std::string& clientName ) = 0; @@ -687,8 +696,6 @@ class MidiInApi : public MidiApi :front(0), back(0), size(0), ringSize(0) {} }; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" RTMIDI_DEPRECATED(void setCallback( MidiCallback callback, void *userData = 0 ), @@ -703,8 +710,6 @@ class MidiInApi : public MidiApi return getMessage(*message); } -#pragma GCC diagnostic pop - protected: // The RtMidiInData structure is used to pass private class data to // the MIDI input handling function or thread. @@ -868,19 +873,20 @@ class Midi { //! A basic error reporting function for RtMidi classes. void error( Error e ); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - /* old functions */ - RTMIDI_DEPRECATED(enum, - "enum RtMidi::Api has been replaced by enum rtmidi::ApiType") Api { + enum Api_t { UNSPECIFIED = rtmidi::UNSPECIFIED, - MACOSX_CORE = rtmidi::MACOSX_CORE, - LINUX_ALSA = rtmidi::LINUX_ALSA, - UNIX_JACK = rtmidi::UNIX_JACK, - WINDOWS_MM = rtmidi::WINDOWS_MM, - RTMIDI_DUMMY = rtmidi::DUMMY - }; + MACOSX_CORE = rtmidi::MACOSX_CORE, + LINUX_ALSA = rtmidi::LINUX_ALSA, + UNIX_JACK = rtmidi::UNIX_JACK, + WINDOWS_MM = rtmidi::WINDOWS_MM, + RTMIDI_DUMMY = rtmidi::DUMMY + }; + + /* old functions */ + RTMIDI_DEPRECATED(typedef Api_t Api, + "enum RtMidi::Api has been replaced by enum rtmidi::ApiType"); +#define Api Api_t RTMIDI_DEPRECATED(static void getCompiledApi( std::vector &apis, bool preferSystem = true ) throw(), "enum RtMidi::Api has been replaced by enum rtmidi::ApiType" ) { @@ -961,7 +967,14 @@ class Midi { */ RTMIDI_DEPRECATED(void setErrorCallback( ErrorCallback errorCallback = NULL, void * userData = 0 ), "setErrorCallback now expects an object of type ErrorInterface") { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif if (rtapi_) rtapi_->setErrorCallback(errorCallback, userData); +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif } @@ -992,7 +1005,6 @@ inline std::string getApiName(Midi::Api type) return getApiName((ApiType)type); } -#pragma GCC diagnostic pop #undef RTMIDI_CLASSNAME /**********************************************************************/ @@ -1199,8 +1211,6 @@ class MidiIn : public Midi return 0.0; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" //! Set a callback function to be invoked for incoming MIDI messages. /*! @@ -1216,8 +1226,15 @@ class MidiIn : public Midi RTMIDI_DEPRECATED(void setCallback( MidiCallback callback, void *userData = 0 ), "RtMidi now provides a type-safe MidiInterface class.") { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif if (rtapi_) static_cast(rtapi_)->setCallback(callback,userData); +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif } //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. /*! @@ -1242,7 +1259,6 @@ class MidiIn : public Midi Error::WARNING)); return 0.0; } -#pragma GCC diagnostic pop protected: static MidiApiList queryApis; int queueSizeLimit; @@ -1670,10 +1686,6 @@ class MidiOutDummy: public MidiOutApi // old API -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif //! Compatibility interface to hold a C style callback function struct CompatibilityMidiInterface: MidiInterface { @@ -1725,8 +1737,5 @@ class RtMidiOut: public rtmidi::MidiOut { clientName) {} }; typedef rtmidi::Error RtMidiError; -#ifdef GCC -#pragma GCC diagnostic pop -#endif #endif From 5abe1ee798fabd51190cb0b52265c16f13fd2122 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 2 Apr 2016 16:32:09 +0200 Subject: [PATCH 110/210] Constistently use references to strings. This avoids several constructions of temporary strings. --- RtMidi.cpp | 28 ++++++++++++------------ RtMidi.h | 64 +++++++++++++++++++++++++++--------------------------- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 17752ce7..47c8dd08 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -233,7 +233,7 @@ void MidiIn :: openMidiApi( ApiType api ) MidiApiList MidiIn::queryApis; MidiIn :: MidiIn( ApiType api, - const std::string clientName, + const std::string & clientName, unsigned int queueSize, bool pfsystem ) : Midi(&queryApis,pfsystem,clientName), @@ -250,8 +250,8 @@ MidiIn :: MidiIn( ApiType api, for ( unsigned int i=0; i (apiData_); if ( !data->local.client ) { @@ -3409,7 +3409,7 @@ void MidiInAlsa :: closePort( void ) //*********************************************************************// #define RTMIDI_CLASSNAME "MidiOutAlsa" -MidiOutAlsa :: MidiOutAlsa( const std::string clientName ) : MidiOutApi() +MidiOutAlsa :: MidiOutAlsa( const std::string & clientName ) : MidiOutApi() { initialize( clientName ); } @@ -3581,7 +3581,7 @@ void MidiOutAlsa :: closePort( void ) } } -void MidiOutAlsa :: openVirtualPort( std::string portName ) +void MidiOutAlsa :: openVirtualPort(const std::string & portName ) { AlsaMidiData *data = static_cast (apiData_); if ( !data->local.client ) { @@ -5309,7 +5309,7 @@ int JackBackendCallbacks::jackProcessOut( jack_nframes_t nframes, void *arg ) #undef RTMIDI_CLASSNAME #define RTMIDI_CLASSNAME "MidiInJack" -MidiInJack :: MidiInJack( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) +MidiInJack :: MidiInJack( const std::string & clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { initialize( clientName ); } @@ -5391,7 +5391,7 @@ void MidiInJack :: openPort( unsigned int portNumber, const std::string & portNa jack_connect( *(data->seq), name.c_str(), jack_port_name( data->local ) ); } -void MidiInJack :: openVirtualPort( const std::string portName ) +void MidiInJack :: openVirtualPort( const std::string & portName ) { JackMidiData *data = static_cast (apiData_); @@ -5541,7 +5541,7 @@ void MidiInJack :: closePort() #define RTMIDI_CLASSNAME "MidiOutJack" -MidiOutJack :: MidiOutJack( const std::string clientName ) : MidiOutApi() +MidiOutJack :: MidiOutJack( const std::string & clientName ) : MidiOutApi() { initialize( clientName ); } @@ -5608,7 +5608,7 @@ void MidiOutJack :: openPort( unsigned int portNumber, const std::string & portN jack_connect( *(data->seq), jack_port_name( data->local ), name.c_str() ); } -void MidiOutJack :: openVirtualPort( const std::string portName ) +void MidiOutJack :: openVirtualPort( const std::string & portName ) { JackMidiData *data = static_cast (apiData_); diff --git a/RtMidi.h b/RtMidi.h index 91d6b5f9..7d8ec02a 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -511,7 +511,7 @@ class MidiApi \sa hasVirtualPorts */ - virtual void openVirtualPort( const std::string portName = std::string( "RtMidi virtual port" ) ) = 0; + virtual void openVirtualPort( const std::string & portName = std::string( "RtMidi virtual port" ) ) = 0; //! Pure virtual function to open a MIDI connection given by enumeration number. /*! \param portNumber An optional port number greater than 0 @@ -901,8 +901,8 @@ class Midi { //! Compatibilty function for older code virtual - RTMIDI_DEPRECATED(void openVirtualPort( const - std::string portName = std::string( "RtMidi virtual port" ) ), + RTMIDI_DEPRECATED(void openVirtualPort( const std::string & portName + = std::string( "RtMidi virtual port" ) ), "For better usability you should call this function from a derived class") = 0; //! Pure virtual function to open a MIDI connection given by enumeration number. @@ -917,7 +917,7 @@ class Midi { \deprecated */ RTMIDI_DEPRECATED(void openPort( unsigned int portNumber = 0, - const std::string portName = std::string( "RtMidi" ) + const std::string & portName = std::string( "RtMidi" ) ),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)") { if (rtapi_) rtapi_->openPort(portNumber,portName); @@ -1073,7 +1073,7 @@ class MidiIn : public Midi versa. */ MidiIn( ApiType api=rtmidi::UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Input Client"), + const std::string & clientName = std::string( "RtMidi Input Client"), unsigned int queueSizeLimit = 100, bool pfsystem = true); @@ -1121,7 +1121,7 @@ class MidiIn : public Midi \param portName An optional name for the application port that is used to connect to portId can be specified. */ - void openVirtualPort( const std::string portName = std::string( "RtMidi virtual input port" ) ) + void openVirtualPort( const std::string & portName = std::string( "RtMidi virtual input port" ) ) { if (!rtapi_ && list && !list->empty()) { Pointer api = list->front(); @@ -1312,7 +1312,7 @@ class MidiOut : public Midi versa. */ MidiOut( ApiType api=rtmidi::UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Output Client"), + const std::string & clientName = std::string( "RtMidi Output Client"), bool pfsystem = true); //! The destructor closes any open MIDI connections. @@ -1359,7 +1359,7 @@ class MidiOut : public Midi \param portName An optional name for the applicaction port that is used to connect to portId can be specified. */ - void openVirtualPort( const std::string portName = std::string( "RtMidi virtual output port" ) ) + void openVirtualPort( const std::string & portName = std::string( "RtMidi virtual output port" ) ) { if (!rtapi_ && list && !list->empty()) { Pointer api = list->front(); @@ -1367,8 +1367,8 @@ class MidiOut : public Midi std::vector< ApiType > apis; getCompiledApi( apis ); for (size_t i = 0 ; i < apis.size() ; i++) { - openMidiApi( apis[0] ); - if (rtapi_ && rtapi_->hasVirtualPorts()) break; + openMidiApi( apis[0] ); + if (rtapi_ && rtapi_->hasVirtualPorts()) break; } } @@ -1441,12 +1441,12 @@ NAMESPACE_RTMIDI_START class MidiInCore: public MidiInApi { public: - MidiInCore( const std::string clientName, unsigned int queueSizeLimit ); + MidiInCore( const std::string & clientName, unsigned int queueSizeLimit ); ~MidiInCore( void ); ApiType getCurrentApi( void ) throw() { return MACOSX_CORE; }; bool hasVirtualPorts() const { return true; } void openPort( unsigned int portNumber, const std::string & portName ); - void openVirtualPort( const std::string portName ); + void openVirtualPort( const std::string & portName ); void openPort( const PortDescriptor & port, const std::string & portName); Pointer getDescriptor(bool local=false); PortList getPortList(int capabilities); @@ -1466,12 +1466,12 @@ class MidiInCore: public MidiInApi class MidiOutCore: public MidiOutApi { public: - MidiOutCore( const std::string clientName ); + MidiOutCore( const std::string & clientName ); ~MidiOutCore( void ); ApiType getCurrentApi( void ) throw() { return MACOSX_CORE; }; bool hasVirtualPorts() const { return true; } void openPort( unsigned int portNumber, const std::string & portName ); - void openVirtualPort( const std::string portName ); + void openVirtualPort( const std::string & portName ); void openPort( const PortDescriptor & port, const std::string & portName); Pointer getDescriptor(bool local=false); PortList getPortList(int capabilities); @@ -1491,12 +1491,12 @@ class MidiOutCore: public MidiOutApi class MidiInJack: public MidiInApi { public: - MidiInJack( const std::string clientName, unsigned int queueSizeLimit ); + MidiInJack( const std::string & clientName, unsigned int queueSizeLimit ); ~MidiInJack( void ); ApiType getCurrentApi( void ) throw() { return UNIX_JACK; }; bool hasVirtualPorts() const { return true; } void openPort( unsigned int portNumber, const std::string & portName ); - void openVirtualPort( const std::string portName ); + void openVirtualPort( const std::string & portName ); void openPort( const PortDescriptor & port, const std::string & portName); Pointer getDescriptor(bool local=false); PortList getPortList(int capabilities); @@ -1514,12 +1514,12 @@ class MidiInJack: public MidiInApi class MidiOutJack: public MidiOutApi { public: - MidiOutJack( const std::string clientName ); + MidiOutJack( const std::string & clientName ); ~MidiOutJack( void ); ApiType getCurrentApi( void ) throw() { return UNIX_JACK; }; bool hasVirtualPorts() const { return true; } void openPort( unsigned int portNumber, const std::string & portName ); - void openVirtualPort( const std::string portName ); + void openVirtualPort( const std::string & portName ); void openPort( const PortDescriptor & port, const std::string & portName); Pointer getDescriptor(bool local=false); PortList getPortList(int capabilities); @@ -1542,12 +1542,12 @@ class MidiOutJack: public MidiOutApi class MidiInAlsa: public MidiInApi { public: - MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit ); + MidiInAlsa( const std::string & clientName, unsigned int queueSizeLimit ); ~MidiInAlsa( void ); ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; bool hasVirtualPorts() const { return true; } void openPort( unsigned int portNumber, const std::string & portName ); - void openVirtualPort( const std::string portName ); + void openVirtualPort( const std::string & portName ); void openPort( const PortDescriptor & port, const std::string & portName); Pointer getDescriptor(bool local=false); PortList getPortList(int capabilities); @@ -1564,12 +1564,12 @@ class MidiInAlsa: public MidiInApi class MidiOutAlsa: public MidiOutApi { public: - MidiOutAlsa( const std::string clientName ); + MidiOutAlsa( const std::string & clientName ); ~MidiOutAlsa( void ); ApiType getCurrentApi( void ) throw() { return LINUX_ALSA; }; bool hasVirtualPorts() const { return true; } void openPort( unsigned int portNumber, const std::string & portName ); - void openVirtualPort( const std::string portName ); + void openVirtualPort( const std::string & portName ); void openPort( const PortDescriptor & port, const std::string & portName); Pointer getDescriptor(bool local=false); PortList getPortList(int capabilities); @@ -1589,12 +1589,12 @@ class MidiOutAlsa: public MidiOutApi class MidiInWinMM: public MidiInApi { public: - MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ); + MidiInWinMM( const std::string & clientName, unsigned int queueSizeLimit ); ~MidiInWinMM( void ); ApiType getCurrentApi( void ) throw() { return WINDOWS_MM; }; bool hasVirtualPorts() const { return false; } void openPort( unsigned int portNumber, const std::string & portName ); - void openVirtualPort( const std::string portName ); + void openVirtualPort( const std::string & portName ); void openPort( const PortDescriptor & port, const std::string & portName); Pointer getDescriptor(bool local=false); PortList getPortList(int capabilities); @@ -1611,12 +1611,12 @@ class MidiInWinMM: public MidiInApi class MidiOutWinMM: public MidiOutApi { public: - MidiOutWinMM( const std::string clientName ); + MidiOutWinMM( const std::string & clientName ); ~MidiOutWinMM( void ); ApiType getCurrentApi( void ) throw() { return WINDOWS_MM; }; bool hasVirtualPorts() const { return false; } void openPort( unsigned int portNumber, const std::string & portName ); - void openVirtualPort( const std::string portName ); + void openVirtualPort( const std::string & portName ); void openPort( const PortDescriptor & port, const std::string & portName); Pointer getDescriptor(bool local=false); PortList getPortList(int capabilities); @@ -1637,7 +1637,7 @@ class MidiOutWinMM: public MidiOutApi class MidiInDummy: public MidiInApi { public: - MidiInDummy( const std::string /*clientName*/, unsigned int queueSizeLimit ) + MidiInDummy( const std::string & /*clientName*/, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { error( RTMIDI_ERROR(_("MidiInDummy: This class provides no functionality."), Error::WARNING) ); @@ -1645,7 +1645,7 @@ class MidiInDummy: public MidiInApi ApiType getCurrentApi( void ) throw() { return DUMMY; } bool hasVirtualPorts() const { return false; } void openPort( unsigned int portNumber, const &std::string portName ) {} - void openVirtualPort( const std::string /*portName*/ ) {} + void openVirtualPort( const std::string & /*portName*/ ) {} void openPort( const PortDescriptor & port, const &std::string portName) {} Pointer getDescriptor(bool local=false) { return 0; } PortList getPortList(int capabilities) { return PortList(); } @@ -1662,14 +1662,14 @@ class MidiInDummy: public MidiInApi class MidiOutDummy: public MidiOutApi { public: - MidiOutDummy( const std::string /*clientName*/ ) { + MidiOutDummy( const std::string & /*clientName*/ ) { error( RTMIDI_ERROR(_("MidiInDummy: This class provides no functionality."), Error::WARNING) ); } ApiType getCurrentApi( void ) { return DUMMY; } bool hasVirtualPorts() const { return false; } void openPort( unsigned int /*portNumber*/, const & std::string /*portName*/ ) {} - void openVirtualPort( const std::string /*portName*/ ) {} + void openVirtualPort( const std::string & /*portName*/ ) {} void openPort( const PortDescriptor & port, const & std::string portName) {} Pointer getDescriptor(bool local=false) { return 0; } PortList getPortList(int capabilities) { return PortList(); } @@ -1723,7 +1723,7 @@ typedef rtmidi::Midi RTMIDI_DEPRECATED(RtMidi,"RtMidi has been replaced by rtmid class RtMidiIn: public rtmidi::MidiIn { public: RTMIDI_DEPRECATED(RtMidiIn( RtMidi::Api api = RtMidi::UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Input Client")), + const std::string & clientName = std::string( "RtMidi Input Client")), "Class RtMidiIn has been replaced by rtmidi::MidiIn"): MidiIn((rtmidi::ApiType)api, clientName) {} @@ -1731,7 +1731,7 @@ class RtMidiIn: public rtmidi::MidiIn { class RtMidiOut: public rtmidi::MidiOut { public: RTMIDI_DEPRECATED(RtMidiOut( RtMidi::Api api = RtMidi::UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Output Client")), + const std::string & clientName = std::string( "RtMidi Output Client")), "Class RtMidiOut has been replaced by rtmidi::MidiOut"): MidiOut((rtmidi::ApiType)api, clientName) {} From c02a15b187f778a097b50eedb7f3dc79023b93a8 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 2 Apr 2016 22:14:45 +0200 Subject: [PATCH 111/210] Use a Reference rather than a pointer to the message object in the MIDI callback. Passing the object by reference avoids certain checks in user code as we cannot pass a null pointer. --- RtMidi.cpp | 114 ++++++++++++++++++++++++++--------------------------- RtMidi.h | 6 +-- 2 files changed, 60 insertions(+), 60 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 47c8dd08..12cc1e71 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -2959,7 +2959,7 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() // don't bother ALSA with an unhandled exception } #endif - } + } } } @@ -2967,23 +2967,23 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() if ( message.bytes.size() == 0 || continueSysex ) continue; if ( data->userCallback ) { - data->userCallback->rtmidi_midi_in( message.timeStamp, &message.bytes); + data->userCallback->rtmidi_midi_in( message.timeStamp, message.bytes); } else { // As long as we haven't reached our queue size limit, push the message. if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; } else { - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother ALSA with an unhandled exception - } + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } } } } @@ -4091,18 +4091,18 @@ struct WinMMCallbacks { else if ( status < 0xE0 ) nBytes = 2; else if ( status < 0xF0 ) nBytes = 3; else if ( status == 0xF1 ) { - if ( data->ignoreFlags & 0x02 ) return; - else nBytes = 2; + if ( data->ignoreFlags & 0x02 ) return; + else nBytes = 2; } else if ( status == 0xF2 ) nBytes = 3; else if ( status == 0xF3 ) nBytes = 2; else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) { - // A MIDI timing tick message and we're ignoring it. - return; + // A MIDI timing tick message and we're ignoring it. + return; } else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { - // A MIDI active sensing message and we're ignoring it. - return; + // A MIDI active sensing message and we're ignoring it. + return; } // Copy bytes to our MIDI message. @@ -4112,9 +4112,9 @@ struct WinMMCallbacks { else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) MIDIHDR *sysex = ( MIDIHDR *) midiMessage; if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { - // Sysex message and we're not ignoring it - for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) - apiData->message.bytes.push_back( sysex->lpData[i] ); + // Sysex message and we're not ignoring it + for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) + apiData->message.bytes.push_back( sysex->lpData[i] ); } // The WinMM API requires that the sysex buffer be requeued after @@ -4126,42 +4126,42 @@ struct WinMMCallbacks { // avoid requeueing it, else the computer suddenly reboots after // one or two minutes. if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { - //if ( sysex->dwBytesRecorded > 0 ) { - EnterCriticalSection( &(apiData->_mutex) ); - MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); - LeaveCriticalSection( &(apiData->_mutex) ); - if ( result != MMSYSERR_NOERROR ){ - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error sending sysex to Midi device."), + //if ( sysex->dwBytesRecorded > 0 ) { + EnterCriticalSection( &(apiData->_mutex) ); + MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); + LeaveCriticalSection( &(apiData->_mutex) ); + if ( result != MMSYSERR_NOERROR ){ + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error sending sysex to Midi device."), Error::WARNING)); - } catch (Error e) { - // don't bother WinMM with an unhandled exception - } - } + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } + } - if ( data->ignoreFlags & 0x01 ) return; + if ( data->ignoreFlags & 0x01 ) return; } else return; } if ( data->userCallback ) { - data->userCallback->rtmidi_midi_in( apiData->message.timeStamp, &apiData->message.bytes ); + data->userCallback->rtmidi_midi_in( apiData->message.timeStamp, apiData->message.bytes ); } else { // As long as we haven't reached our queue size limit, push the message. if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = apiData->message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; + data->queue.ring[data->queue.back++] = apiData->message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; } else { - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother WinMM with an unhandled exception - } + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } } } @@ -5219,24 +5219,24 @@ int JackBackendCallbacks::jackProcessIn( jack_nframes_t nframes, void *arg ) if ( !rtData->continueSysex ) { if ( rtData->userCallback ) { - rtData->userCallback->rtmidi_midi_in( message.timeStamp, &message.bytes); + rtData->userCallback->rtmidi_midi_in( message.timeStamp, message.bytes); } else { - // As long as we haven't reached our queue size limit, push the message. - if ( rtData->queue.size < rtData->queue.ringSize ) { - rtData->queue.ring[rtData->queue.back++] = message; - if ( rtData->queue.back == rtData->queue.ringSize ) - rtData->queue.back = 0; - rtData->queue.size++; - } - else { - try { - rtData->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + // As long as we haven't reached our queue size limit, push the message. + if ( rtData->queue.size < rtData->queue.ringSize ) { + rtData->queue.ring[rtData->queue.back++] = message; + if ( rtData->queue.back == rtData->queue.ringSize ) + rtData->queue.back = 0; + rtData->queue.size++; + } + else { + try { + rtData->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother WinMM with an unhandled exception - } - } + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } + } } } } diff --git a/RtMidi.h b/RtMidi.h index 7d8ec02a..eb7b607d 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -137,7 +137,7 @@ struct MidiInterface { \param timestamp the timestamp when the MIDI message has been received \param message the message itself. */ - virtual void rtmidi_midi_in(double timestamp, std::vector *message) = 0; + virtual void rtmidi_midi_in(double timestamp, std::vector &message) = 0; //! Delete the object if necessary. /*! This function allows the user to delete the Midi callback object, @@ -1692,8 +1692,8 @@ struct CompatibilityMidiInterface: MidiInterface { CompatibilityMidiInterface(MidiCallback cb, void * ud): callback(cb), userData(ud) {} - void rtmidi_midi_in(double timestamp, std::vector *message) { - callback (timestamp, message, userData); + void rtmidi_midi_in(double timestamp, std::vector &message) { + callback (timestamp, &message, userData); } void delete_me() { delete this; } MidiCallback callback; From cca569dcb8e067e6ec92fc887f08c325ca5c492e Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Thu, 14 Apr 2016 21:01:12 +0200 Subject: [PATCH 112/210] Fix the error detection in sendMessage. --- RtMidi.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index eb7b607d..eb031bcc 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -1411,8 +1411,9 @@ class MidiOut : public Midi void sendMessage( std::vector &message ) { if (rtapi_) static_cast(rtapi_)->sendMessage(message); - error( RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), - Error::WARNING)); + else + error( RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), + Error::WARNING)); } protected: static MidiApiList queryApis; From 159145422ccef785c5b8817127c774b396cb1970 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 14 Jan 2018 13:55:11 +0100 Subject: [PATCH 113/210] update gettext --- ABOUT-NLS | 2411 ++++++++++++++++++++++-------------------- po/ChangeLog | 5 + po/Makefile.in.in | 71 +- po/Makevars.template | 78 ++ po/Rules-quot | 15 +- 5 files changed, 1400 insertions(+), 1180 deletions(-) create mode 100644 po/Makevars.template diff --git a/ABOUT-NLS b/ABOUT-NLS index b1de1b68..3cc82865 100644 --- a/ABOUT-NLS +++ b/ABOUT-NLS @@ -1,16 +1,16 @@ 1 Notes on the Free Translation Project *************************************** -Free software is going international! The Free Translation Project is -a way to get maintainers of free software, translators, and users all +Free software is going international! The Free Translation Project is a +way to get maintainers of free software, translators, and users all together, so that free software will gradually become able to speak many languages. A few packages already provide translations for their messages. - If you found this `ABOUT-NLS' file inside a distribution, you may -assume that the distributed package does use GNU `gettext' internally, + If you found this 'ABOUT-NLS' file inside a distribution, you may +assume that the distributed package does use GNU 'gettext' internally, itself available at your nearest GNU archive site. But you do _not_ -need to install GNU `gettext' prior to configuring, installing or using +need to install GNU 'gettext' prior to configuring, installing or using this package with messages translated. Installers will find here some useful hints. These notes also @@ -23,12 +23,12 @@ work on translations can contact the appropriate team. Some packages are "localizable" when properly installed; the programs they contain can be made to speak your own native language. Most such -packages use GNU `gettext'. Other packages have their own ways to -internationalization, predating GNU `gettext'. +packages use GNU 'gettext'. Other packages have their own ways to +internationalization, predating GNU 'gettext'. By default, this package will be installed to allow translation of messages. It will automatically detect whether the system already -provides the GNU `gettext' functions. Installers may use special +provides the GNU 'gettext' functions. Installers may use special options at configuration time for changing the default behaviour. The command: @@ -36,72 +36,71 @@ command: will _totally_ disable translation of messages. - When you already have GNU `gettext' installed on your system and run -configure without an option for your new package, `configure' will -probably detect the previously built and installed `libintl' library -and will decide to use it. If not, you may have to to use the -`--with-libintl-prefix' option to tell `configure' where to look for it. + When you already have GNU 'gettext' installed on your system and run +configure without an option for your new package, 'configure' will +probably detect the previously built and installed 'libintl' library and +will decide to use it. If not, you may have to to use the +'--with-libintl-prefix' option to tell 'configure' where to look for it. - Internationalized packages usually have many `po/LL.po' files, where + Internationalized packages usually have many 'po/LL.po' files, where LL gives an ISO 639 two-letter code identifying the language. Unless -translations have been forbidden at `configure' time by using the -`--disable-nls' switch, all available translations are installed -together with the package. However, the environment variable `LINGUAS' +translations have been forbidden at 'configure' time by using the +'--disable-nls' switch, all available translations are installed +together with the package. However, the environment variable 'LINGUAS' may be set, prior to configuration, to limit the installed set. -`LINGUAS' should then contain a space separated list of two-letter +'LINGUAS' should then contain a space separated list of two-letter codes, stating which languages are allowed. 1.2 Using This Package ====================== As a user, if your language has been installed for this package, you -only have to set the `LANG' environment variable to the appropriate -`LL_CC' combination. If you happen to have the `LC_ALL' or some other -`LC_xxx' environment variables set, you should unset them before -setting `LANG', otherwise the setting of `LANG' will not have the -desired effect. Here `LL' is an ISO 639 two-letter language code, and -`CC' is an ISO 3166 two-letter country code. For example, let's -suppose that you speak German and live in Germany. At the shell -prompt, merely execute `setenv LANG de_DE' (in `csh'), -`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). -This can be done from your `.login' or `.profile' file, once and for -all. +only have to set the 'LANG' environment variable to the appropriate +'LL_CC' combination. If you happen to have the 'LC_ALL' or some other +'LC_xxx' environment variables set, you should unset them before setting +'LANG', otherwise the setting of 'LANG' will not have the desired +effect. Here 'LL' is an ISO 639 two-letter language code, and 'CC' is +an ISO 3166 two-letter country code. For example, let's suppose that +you speak German and live in Germany. At the shell prompt, merely +execute 'setenv LANG de_DE' (in 'csh'), 'export LANG; LANG=de_DE' (in +'sh') or 'export LANG=de_DE' (in 'bash'). This can be done from your +'.login' or '.profile' file, once and for all. You might think that the country code specification is redundant. But in fact, some languages have dialects in different countries. For -example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The +example, 'de_AT' is used for Austria, and 'pt_BR' for Brazil. The country code serves to distinguish the dialects. - The locale naming convention of `LL_CC', with `LL' denoting the -language and `CC' denoting the country, is the one use on systems based -on GNU libc. On other systems, some variations of this scheme are -used, such as `LL' or `LL_CC.ENCODING'. You can get the list of -locales supported by your system for your language by running the -command `locale -a | grep '^LL''. + The locale naming convention of 'LL_CC', with 'LL' denoting the +language and 'CC' denoting the country, is the one use on systems based +on GNU libc. On other systems, some variations of this scheme are used, +such as 'LL' or 'LL_CC.ENCODING'. You can get the list of locales +supported by your system for your language by running the command +'locale -a | grep '^LL''. Not all programs have translations for all languages. By default, an English message is shown in place of a nonexistent translation. If you understand other languages, you can set up a priority list of languages. This is done through a different environment variable, called -`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' -for the purpose of message handling, but you still need to have `LANG' +'LANGUAGE'. GNU 'gettext' gives preference to 'LANGUAGE' over 'LANG' +for the purpose of message handling, but you still need to have 'LANG' set to the primary language; this is required by other parts of the -system libraries. For example, some Swedish users who would rather -read translations in German than English for when Swedish is not -available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. +system libraries. For example, some Swedish users who would rather read +translations in German than English for when Swedish is not available, +set 'LANGUAGE' to 'sv:de' while leaving 'LANG' to 'sv_SE'. Special advice for Norwegian users: The language code for Norwegian -bokma*l changed from `no' to `nb' recently (in 2003). During the +bokma*l changed from 'no' to 'nb' recently (in 2003). During the transition period, while some message catalogs for this language are -installed under `nb' and some older ones under `no', it's recommended -for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and +installed under 'nb' and some older ones under 'no', it's recommended +for Norwegian users to set 'LANGUAGE' to 'nb:no' so that both newer and older translations are used. - In the `LANGUAGE' environment variable, but not in the `LANG' -environment variable, `LL_CC' combinations can be abbreviated as `LL' -to denote the language's main dialect. For example, `de' is equivalent -to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' -(Portuguese as spoken in Portugal) in this context. + In the 'LANGUAGE' environment variable, but not in the 'LANG' +environment variable, 'LL_CC' combinations can be abbreviated as 'LL' to +denote the language's main dialect. For example, 'de' is equivalent to +'de_DE' (German as spoken in Germany), and 'pt' to 'pt_PT' (Portuguese +as spoken in Portugal) in this context. 1.3 Translating Teams ===================== @@ -111,22 +110,22 @@ people who like their own language and write it well, and who are also able to synergize with other translators speaking the same language. Each translation team has its own mailing list. The up-to-date list of teams can be found at the Free Translation Project's homepage, -`http://translationproject.org/', in the "Teams" area. +'http://translationproject.org/', in the "Teams" area. If you'd like to volunteer to _work_ at translating messages, you should become a member of the translating team for your own language. The subscribing address is _not_ the same as the list itself, it has -`-request' appended. For example, speakers of Swedish can send a -message to `sv-request@li.org', having this message body: +'-request' appended. For example, speakers of Swedish can send a +message to 'sv-request@li.org', having this message body: subscribe - Keep in mind that team members are expected to participate -_actively_ in translations, or at solving translational difficulties, -rather than merely lurking around. If your team does not exist yet and -you want to start one, or if you are unsure about what to do or how to -get started, please write to `coordinator@translationproject.org' to -reach the coordinator for all translator teams. + Keep in mind that team members are expected to participate _actively_ +in translations, or at solving translational difficulties, rather than +merely lurking around. If your team does not exist yet and you want to +start one, or if you are unsure about what to do or how to get started, +please write to 'coordinator@translationproject.org' to reach the +coordinator for all translator teams. The English team is special. It works at improving and uniformizing the terminology in use. Proven linguistic skills are praised more than @@ -136,1114 +135,1214 @@ programming skills, here. ====================== Languages are not equally supported in all packages. The following -matrix shows the current state of internationalization, as of June -2010. The matrix shows, in regard of each package, for which languages -PO files have been submitted to translation coordination, with a +matrix shows the current state of internationalization, as of Jun 2014. +The matrix shows, in regard of each package, for which languages PO +files have been submitted to translation coordination, with a translation percentage of at least 50%. - Ready PO files af am an ar as ast az be be@latin bg bn_IN bs ca + Ready PO files af am an ar as ast az be bg bn bn_IN bs ca crh cs + +---------------------------------------------------+ + a2ps | [] [] [] | + aegis | | + anubis | | + aspell | [] [] [] | + bash | [] [] [] | + bfd | | + binutils | [] | + bison | | + bison-runtime | [] | + buzztrax | [] | + ccd2cue | | + ccide | | + cflow | | + clisp | | + coreutils | [] [] | + cpio | | + cppi | | + cpplib | [] | + cryptsetup | [] | + datamash | | + denemo | [] [] | + dfarc | [] | + dialog | [] [] [] | + dico | | + diffutils | [] | + dink | [] | + direvent | | + doodle | [] | + dos2unix | | + dos2unix-man | | + e2fsprogs | [] [] | + enscript | [] | + exif | [] | + fetchmail | [] [] | + findutils | [] | + flex | [] | + freedink | [] [] | + fusionforge | | + gas | | + gawk | [] | + gcal | [] | + gcc | | + gdbm | | + gettext-examples | [] [] [] [] [] | + gettext-runtime | [] [] [] | + gettext-tools | [] [] | + gjay | | + glunarclock | [] [] [] | + gnubiff | [] | + gnubik | [] | + gnucash | () () [] | + gnuchess | | + gnulib | [] | + gnunet | | + gnunet-gtk | | + gold | | + gphoto2 | [] | + gprof | [] | + gramadoir | | + grep | [] [] [] | + grub | [] | + gsasl | | + gss | | + gst-plugins-bad | [] [] | + gst-plugins-base | [] [] [] | + gst-plugins-good | [] [] [] | + gst-plugins-ugly | [] [] [] | + gstreamer | [] [] [] [] | + gtick | [] | + gtkam | [] [] | + gtkspell | [] [] [] [] [] | + guix | | + guix-packages | | + gutenprint | [] | + hello | [] | + help2man | | + help2man-texi | | + hylafax | | + idutils | | + iso_15924 | [] | + iso_3166 | [] [] [] [] [] [] [] [] [] [] | + iso_3166_2 | | + iso_4217 | [] | + iso_639 | [] [] [] [] [] [] [] [] [] | + iso_639_3 | [] [] | + iso_639_5 | | + jwhois | | + kbd | [] | + klavaro | [] [] [] [] [] | + ld | [] | + leafpad | [] [] [] [] | + libc | [] [] [] | + libexif | () | + libextractor | | + libgnutls | [] | + libgphoto2 | [] | + libgphoto2_port | [] | + libgsasl | | + libiconv | [] [] | + libidn | [] | + liferea | [] [] [] [] | + lilypond | [] [] | + lordsawar | [] | + lprng | | + lynx | [] [] | + m4 | [] | + mailfromd | | + mailutils | | + make | [] | + man-db | [] [] | + man-db-manpages | | + midi-instruments | [] [] [] | + minicom | [] | + mkisofs | [] | + myserver | [] | + nano | [] [] [] | + opcodes | | + parted | [] | + pies | | + pnmixer | | + popt | [] | + procps-ng | | + procps-ng-man | | + psmisc | [] | + pspp | [] | + pushover | [] | + pwdutils | | + pyspread | | + radius | [] | + recode | [] [] [] | + recutils | | + rpm | | + rush | | + sarg | | + sed | [] [] [] [] | + sharutils | [] | + shishi | | + skribilo | | + solfege | [] [] | + solfege-manual | | + spotmachine | | + sudo | [] [] | + sudoers | [] [] | + sysstat | [] | + tar | [] [] [] | + texinfo | [] [] | + texinfo_document | [] [] | + tigervnc | [] | + tin | | + tin-man | | + tracgoogleappsa... | | + trader | | + util-linux | [] | + ve | | + vice | | + vmm | | + vorbis-tools | [] | + wastesedge | | + wcd | | + wcd-man | | + wdiff | [] [] | + wget | [] | + wyslij-po | | + xboard | | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] | + +---------------------------------------------------+ + af am an ar as ast az be bg bn bn_IN bs ca crh cs + 4 0 2 5 3 11 0 8 25 3 3 1 55 4 74 + + da de el en en_GB en_ZA eo es et eu fa fi fr + +--------------------------------------------------+ + a2ps | [] [] [] [] [] [] [] [] [] | + aegis | [] [] [] [] | + anubis | [] [] [] [] [] | + aspell | [] [] [] [] [] [] [] | + bash | [] [] [] | + bfd | [] [] [] [] | + binutils | [] [] [] | + bison | [] [] [] [] [] [] [] [] | + bison-runtime | [] [] [] [] [] [] [] [] | + buzztrax | [] [] [] [] | + ccd2cue | [] [] [] [] | + ccide | [] [] [] [] [] [] | + cflow | [] [] [] [] [] | + clisp | [] [] [] [] [] | + coreutils | [] [] [] [] [] | + cpio | [] [] [] [] [] | + cppi | [] [] [] [] [] | + cpplib | [] [] [] [] [] [] | + cryptsetup | [] [] [] [] [] | + datamash | [] [] [] [] | + denemo | [] | + dfarc | [] [] [] [] [] [] | + dialog | [] [] [] [] [] [] [] [] [] | + dico | [] [] [] [] | + diffutils | [] [] [] [] [] [] | + dink | [] [] [] [] [] [] | + direvent | [] [] [] [] | + doodle | [] [] [] [] | + dos2unix | [] [] [] [] [] | + dos2unix-man | [] [] [] | + e2fsprogs | [] [] [] [] [] | + enscript | [] [] [] [] [] [] | + exif | [] [] [] [] [] [] | + fetchmail | [] () [] [] [] [] [] | + findutils | [] [] [] [] [] [] [] [] | + flex | [] [] [] [] [] [] | + freedink | [] [] [] [] [] [] [] [] | + fusionforge | [] [] [] | + gas | [] [] [] | + gawk | [] [] [] [] [] | + gcal | [] [] [] [] | + gcc | [] | + gdbm | [] [] [] [] [] | + gettext-examples | [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] | + gettext-tools | [] [] [] [] [] | + gjay | [] [] [] [] | + glunarclock | [] [] [] [] [] | + gnubiff | () [] [] () | + gnubik | [] [] [] [] [] | + gnucash | [] () () () () () () | + gnuchess | [] [] [] [] | + gnulib | [] [] [] [] [] [] [] | + gnunet | [] | + gnunet-gtk | [] | + gold | [] [] [] | + gphoto2 | [] () [] [] | + gprof | [] [] [] [] [] [] | + gramadoir | [] [] [] [] [] | + grep | [] [] [] [] [] [] [] | + grub | [] [] [] [] [] | + gsasl | [] [] [] [] [] | + gss | [] [] [] [] [] | + gst-plugins-bad | [] [] [] | + gst-plugins-base | [] [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] [] [] | + gtick | [] () [] [] [] | + gtkam | [] () [] [] [] [] | + gtkspell | [] [] [] [] [] [] [] [] | + guix | [] [] | + guix-packages | | + gutenprint | [] [] [] [] | + hello | [] [] [] [] [] [] [] [] | + help2man | [] [] [] [] [] [] [] | + help2man-texi | [] [] [] | + hylafax | [] [] | + idutils | [] [] [] [] [] | + iso_15924 | [] () [] [] () [] () | + iso_3166 | [] () [] [] [] [] () [] () | + iso_3166_2 | [] () () () | + iso_4217 | [] () [] [] [] () [] () | + iso_639 | [] () [] [] () [] () | + iso_639_3 | () () () | + iso_639_5 | () () () | + jwhois | [] [] [] [] [] | + kbd | [] [] [] [] [] [] | + klavaro | [] [] [] [] [] [] [] | + ld | [] [] [] [] | + leafpad | [] [] [] [] [] [] [] [] | + libc | [] [] [] [] [] | + libexif | [] [] () [] [] | + libextractor | [] | + libgnutls | [] [] [] [] | + libgphoto2 | [] () [] | + libgphoto2_port | [] () [] [] [] [] | + libgsasl | [] [] [] [] [] | + libiconv | [] [] [] [] [] [] [] | + libidn | [] [] [] [] [] | + liferea | [] () [] [] [] [] [] | + lilypond | [] [] [] [] [] [] | + lordsawar | [] [] | + lprng | | + lynx | [] [] [] [] [] [] | + m4 | [] [] [] [] [] [] | + mailfromd | [] | + mailutils | [] [] [] [] | + make | [] [] [] [] [] | + man-db | [] [] [] [] | + man-db-manpages | [] [] | + midi-instruments | [] [] [] [] [] [] [] [] [] | + minicom | [] [] [] [] [] | + mkisofs | [] [] [] | + myserver | [] [] [] [] | + nano | [] [] [] [] [] [] [] | + opcodes | [] [] [] [] [] | + parted | [] [] [] | + pies | [] | + pnmixer | [] [] | + popt | [] [] [] [] [] [] | + procps-ng | [] [] | + procps-ng-man | [] [] | + psmisc | [] [] [] [] [] [] [] | + pspp | [] [] [] | + pushover | () [] [] [] | + pwdutils | [] [] [] | + pyspread | [] [] [] | + radius | [] [] | + recode | [] [] [] [] [] [] [] | + recutils | [] [] [] [] | + rpm | [] [] [] [] [] | + rush | [] [] [] | + sarg | [] [] | + sed | [] [] [] [] [] [] [] [] | + sharutils | [] [] [] [] | + shishi | [] [] [] | + skribilo | [] [] [] | + solfege | [] [] [] [] [] [] [] [] | + solfege-manual | [] [] [] [] [] | + spotmachine | [] [] [] [] [] | + sudo | [] [] [] [] [] [] | + sudoers | [] [] [] [] [] [] | + sysstat | [] [] [] [] [] [] | + tar | [] [] [] [] [] [] [] | + texinfo | [] [] [] [] [] | + texinfo_document | [] [] [] [] | + tigervnc | [] [] [] [] [] [] | + tin | [] [] [] [] | + tin-man | [] | + tracgoogleappsa... | [] [] [] [] [] | + trader | [] [] [] [] [] [] | + util-linux | [] [] [] [] | + ve | [] [] [] [] [] | + vice | () () () | + vmm | [] [] | + vorbis-tools | [] [] [] [] | + wastesedge | [] | + wcd | [] [] [] [] | + wcd-man | [] | + wdiff | [] [] [] [] [] [] [] | + wget | [] [] [] [] [] [] | + wyslij-po | [] [] [] [] | + xboard | [] [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] [] [] [] | + +--------------------------------------------------+ + da de el en en_GB en_ZA eo es et eu fa fi fr + 119 131 32 1 6 0 94 95 22 13 4 102 139 + + ga gd gl gu he hi hr hu hy ia id is it ja ka kk + +-------------------------------------------------+ + a2ps | [] [] [] [] | + aegis | [] | + anubis | [] [] [] [] | + aspell | [] [] [] [] [] | + bash | [] [] [] [] | + bfd | [] [] | + binutils | [] [] [] | + bison | [] | + bison-runtime | [] [] [] [] [] [] [] [] | + buzztrax | | + ccd2cue | [] | + ccide | [] [] | + cflow | [] [] [] | + clisp | | + coreutils | [] [] | + cpio | [] [] [] [] [] [] | + cppi | [] [] [] [] [] | + cpplib | [] [] | + cryptsetup | [] | + datamash | | + denemo | [] | + dfarc | [] [] [] | + dialog | [] [] [] [] [] [] [] [] [] [] | + dico | | + diffutils | [] [] [] [] | + dink | [] | + direvent | [] | + doodle | [] [] | + dos2unix | [] [] | + dos2unix-man | | + e2fsprogs | [] [] | + enscript | [] [] [] | + exif | [] [] [] [] [] [] | + fetchmail | [] [] [] | + findutils | [] [] [] [] [] [] [] | + flex | [] | + freedink | [] [] [] [] | + fusionforge | | + gas | [] | + gawk | [] () [] | + gcal | | + gcc | | + gdbm | | + gettext-examples | [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] [] | + gettext-tools | [] [] [] | + gjay | [] | + glunarclock | [] [] [] [] [] [] | + gnubiff | [] [] () | + gnubik | [] [] [] | + gnucash | () () () () () | + gnuchess | | + gnulib | [] [] [] [] [] | + gnunet | | + gnunet-gtk | | + gold | [] [] | + gphoto2 | [] [] [] [] | + gprof | [] [] [] [] | + gramadoir | [] [] [] | + grep | [] [] [] [] [] [] [] | + grub | [] [] [] | + gsasl | [] [] [] [] [] | + gss | [] [] [] [] [] | + gst-plugins-bad | [] [] [] | + gst-plugins-base | [] [] [] [] | + gst-plugins-good | [] [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] | + gtick | [] [] [] [] [] | + gtkam | [] [] [] [] [] | + gtkspell | [] [] [] [] [] [] [] [] [] [] | + guix | | + guix-packages | | + gutenprint | [] [] [] | + hello | [] [] [] [] [] | + help2man | [] [] [] | + help2man-texi | | + hylafax | [] | + idutils | [] [] | + iso_15924 | [] [] [] [] [] [] | + iso_3166 | [] [] [] [] [] [] [] [] [] [] [] [] [] | + iso_3166_2 | [] [] | + iso_4217 | [] [] [] [] [] [] | + iso_639 | [] [] [] [] [] [] [] [] [] | + iso_639_3 | [] [] | + iso_639_5 | | + jwhois | [] [] [] [] | + kbd | [] [] [] | + klavaro | [] [] [] [] [] | + ld | [] [] [] [] | + leafpad | [] [] [] [] [] [] [] () | + libc | [] [] [] [] [] | + libexif | [] | + libextractor | | + libgnutls | [] | + libgphoto2 | [] [] | + libgphoto2_port | [] [] | + libgsasl | [] [] [] [] | + libiconv | [] [] [] [] [] [] [] | + libidn | [] [] [] [] | + liferea | [] [] [] [] [] | + lilypond | [] | + lordsawar | | + lprng | [] | + lynx | [] [] [] [] | + m4 | [] [] [] [] [] | + mailfromd | | + mailutils | | + make | [] [] [] [] | + man-db | [] [] | + man-db-manpages | [] [] | + midi-instruments | [] [] [] [] [] [] [] [] [] | + minicom | [] [] [] | + mkisofs | [] [] | + myserver | [] | + nano | [] [] [] [] [] [] | + opcodes | [] [] [] | + parted | [] [] [] [] [] | + pies | | + pnmixer | [] [] | + popt | [] [] [] [] [] [] [] [] [] [] | + procps-ng | | + procps-ng-man | | + psmisc | [] [] [] [] | + pspp | [] [] | + pushover | [] | + pwdutils | [] | + pyspread | | + radius | [] | + recode | [] [] [] [] [] [] [] | + recutils | | + rpm | [] | + rush | [] | + sarg | | + sed | [] [] [] [] [] [] [] | + sharutils | | + shishi | | + skribilo | [] | + solfege | [] [] | + solfege-manual | | + spotmachine | | + sudo | [] [] [] [] | + sudoers | [] [] [] | + sysstat | [] [] [] [] | + tar | [] [] [] [] [] [] | + texinfo | [] [] [] | + texinfo_document | [] [] [] | + tigervnc | | + tin | | + tin-man | | + tracgoogleappsa... | [] [] [] [] | + trader | [] [] | + util-linux | [] | + ve | [] | + vice | () () | + vmm | | + vorbis-tools | [] [] | + wastesedge | [] | + wcd | | + wcd-man | | + wdiff | [] [] [] | + wget | [] [] [] [] | + wyslij-po | [] [] [] | + xboard | | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] [] [] | + +-------------------------------------------------+ + ga gd gl gu he hi hr hu hy ia id is it ja ka kk + 35 2 47 4 8 2 60 71 2 6 81 11 87 57 0 3 + + kn ko ku ky lg lt lv mk ml mn mr ms mt nb ne nl +--------------------------------------------------+ - a2ps | [] [] | - aegis | | - ant-phone | | - anubis | | - aspell | [] [] | - bash | | + a2ps | [] [] | + aegis | [] | + anubis | [] [] [] | + aspell | [] [] | + bash | [] [] | bfd | | - bibshelf | [] | binutils | | - bison | | - bison-runtime | [] | - bluez-pin | [] [] | - bombono-dvd | | - buzztard | | - cflow | | - clisp | | - coreutils | [] [] | - cpio | | + bison | [] | + bison-runtime | [] [] [] [] [] [] | + buzztrax | | + ccd2cue | | + ccide | [] [] | + cflow | [] | + clisp | [] | + coreutils | [] [] | + cpio | [] | cppi | | - cpplib | [] | - cryptsetup | | - dfarc | | - dialog | [] [] | + cpplib | [] | + cryptsetup | [] | + datamash | [] [] | + denemo | | + dfarc | [] [] | + dialog | [] [] [] [] [] [] | dico | | - diffutils | [] | - dink | | - doodle | | - e2fsprogs | [] | - enscript | [] | - exif | | - fetchmail | [] | - findutils | [] | - flex | [] | - freedink | | + diffutils | [] [] [] | + dink | [] | + direvent | [] | + doodle | [] | + dos2unix | [] [] | + dos2unix-man | [] | + e2fsprogs | [] | + enscript | [] | + exif | [] [] [] | + fetchmail | [] | + findutils | [] [] | + flex | [] | + freedink | [] [] | + fusionforge | | gas | | - gawk | [] [] | - gcal | [] | + gawk | [] | + gcal | | gcc | | - gettext-examples | [] [] [] [] | - gettext-runtime | [] [] | - gettext-tools | [] [] | - gip | [] | + gdbm | | + gettext-examples | [] [] [] [] [] [] | + gettext-runtime | [] [] [] | + gettext-tools | [] | gjay | | - gliv | [] | - glunarclock | [] [] | - gnubiff | | - gnucash | [] | - gnuedu | | - gnulib | | + glunarclock | [] [] | + gnubiff | [] | + gnubik | [] [] | + gnucash | () () () () () () () [] | + gnuchess | [] [] | + gnulib | [] | gnunet | | gnunet-gtk | | - gnutls | | gold | | - gpe-aerial | | - gpe-beam | | - gpe-bluetooth | | - gpe-calendar | | - gpe-clock | [] | - gpe-conf | | - gpe-contacts | | - gpe-edit | | - gpe-filemanager | | - gpe-go | | - gpe-login | | - gpe-ownerinfo | [] | - gpe-package | | - gpe-sketchbook | | - gpe-su | [] | - gpe-taskmanager | [] | - gpe-timesheet | [] | - gpe-today | [] | - gpe-todo | | - gphoto2 | | - gprof | [] | - gpsdrive | | - gramadoir | | - grep | | - grub | [] [] | - gsasl | | + gphoto2 | [] | + gprof | [] [] | + gramadoir | [] | + grep | [] [] | + grub | [] [] [] | + gsasl | [] | gss | | - gst-plugins-bad | [] | - gst-plugins-base | [] | - gst-plugins-good | [] | - gst-plugins-ugly | [] | - gstreamer | [] [] [] | - gtick | | - gtkam | [] | - gtkorphan | [] | - gtkspell | [] [] [] | - gutenprint | | - hello | [] | - help2man | | - hylafax | | - idutils | | - indent | [] [] | - iso_15924 | | - iso_3166 | [] [] [] [] [] [] [] | - iso_3166_2 | | - iso_4217 | | - iso_639 | [] [] [] [] | - iso_639_3 | | - jwhois | | - kbd | | - keytouch | [] | - keytouch-editor | | - keytouch-keyboa... | [] | - klavaro | [] | - latrine | | - ld | [] | - leafpad | [] [] | - libc | [] [] | - libexif | () | - libextractor | | - libgnutls | | - libgpewidget | | - libgpg-error | | - libgphoto2 | | - libgphoto2_port | | - libgsasl | | - libiconv | [] | - libidn | | - lifelines | | - liferea | [] [] | - lilypond | | - linkdr | [] | + gst-plugins-bad | [] [] [] | + gst-plugins-base | [] [] [] | + gst-plugins-good | [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] | + gstreamer | [] [] [] | + gtick | [] | + gtkam | [] [] | + gtkspell | [] [] [] [] [] [] [] | + guix | | + guix-packages | | + gutenprint | [] | + hello | [] [] [] | + help2man | [] | + help2man-texi | | + hylafax | [] | + idutils | [] | + iso_15924 | () [] [] | + iso_3166 | [] [] [] () [] [] [] [] [] [] | + iso_3166_2 | () [] | + iso_4217 | () [] [] [] | + iso_639 | [] [] () [] [] [] [] | + iso_639_3 | [] () [] | + iso_639_5 | () | + jwhois | [] [] | + kbd | [] | + klavaro | [] [] | + ld | | + leafpad | [] [] [] [] [] | + libc | [] [] | + libexif | [] | + libextractor | [] | + libgnutls | [] [] | + libgphoto2 | [] | + libgphoto2_port | [] | + libgsasl | [] | + libiconv | [] [] | + libidn | [] | + liferea | [] [] [] | + lilypond | [] | lordsawar | | lprng | | - lynx | [] | - m4 | | + lynx | [] | + m4 | [] | mailfromd | | mailutils | | - make | | - man-db | | - man-db-manpages | | - minicom | | - mkisofs | | + make | [] [] | + man-db | [] | + man-db-manpages | [] | + midi-instruments | [] [] [] [] [] [] [] | + minicom | [] | + mkisofs | [] | myserver | | - nano | [] [] | - opcodes | | - parted | | + nano | [] [] [] | + opcodes | [] | + parted | [] [] | pies | | - popt | | - psmisc | | - pspp | [] | - pwdutils | | - radius | [] | - recode | [] [] | - rosegarden | | - rpm | | - rush | | + pnmixer | [] | + popt | [] [] [] [] [] | + procps-ng | | + procps-ng-man | | + psmisc | [] | + pspp | [] [] | + pushover | | + pwdutils | [] | + pyspread | | + radius | [] | + recode | [] [] | + recutils | [] | + rpm | [] | + rush | [] | sarg | | - screem | | - scrollkeeper | [] [] [] | - sed | [] [] | - sharutils | [] [] | + sed | [] [] | + sharutils | [] | shishi | | - skencil | | - solfege | | - solfege-manual | | - soundtracker | | - sp | | - sysstat | | - tar | [] | - texinfo | | + skribilo | | + solfege | [] [] | + solfege-manual | [] | + spotmachine | [] | + sudo | [] [] [] | + sudoers | [] [] [] | + sysstat | [] [] | + tar | [] [] [] | + texinfo | [] | + texinfo_document | [] | + tigervnc | [] | tin | | - unicode-han-tra... | | - unicode-transla... | | - util-linux-ng | [] | - vice | | - vmm | | - vorbis-tools | | - wastesedge | | - wdiff | | - wget | [] [] | - wyslij-po | | - xchat | [] [] [] [] | - xdg-user-dirs | [] [] [] [] [] [] [] [] [] | - xkeyboard-config | [] [] | + tin-man | | + tracgoogleappsa... | [] [] [] | + trader | [] | + util-linux | [] | + ve | [] | + vice | [] | + vmm | [] | + vorbis-tools | [] | + wastesedge | [] | + wcd | [] | + wcd-man | [] | + wdiff | [] | + wget | [] [] | + wyslij-po | [] | + xboard | [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] | +--------------------------------------------------+ - af am an ar as ast az be be@latin bg bn_IN bs ca - 6 0 1 2 3 19 1 10 3 28 3 1 38 + kn ko ku ky lg lt lv mk ml mn mr ms mt nb ne nl + 5 15 4 6 0 13 23 3 3 3 4 11 2 42 1 125 - crh cs da de el en en_GB en_ZA eo es et eu fa - +-------------------------------------------------+ - a2ps | [] [] [] [] [] [] [] | - aegis | [] [] [] | - ant-phone | [] () | - anubis | [] [] | - aspell | [] [] [] [] [] | - bash | [] [] [] | - bfd | [] | - bibshelf | [] [] [] | - binutils | [] | - bison | [] [] | - bison-runtime | [] [] [] [] | - bluez-pin | [] [] [] [] [] [] | - bombono-dvd | [] | - buzztard | [] [] [] | - cflow | [] [] | - clisp | [] [] [] [] | - coreutils | [] [] [] [] | - cpio | | - cppi | | - cpplib | [] [] [] | - cryptsetup | [] | - dfarc | [] [] [] | - dialog | [] [] [] [] [] | - dico | | - diffutils | [] [] [] [] [] [] | - dink | [] [] [] | - doodle | [] | - e2fsprogs | [] [] [] | - enscript | [] [] [] | - exif | () [] [] | - fetchmail | [] [] () [] [] [] | - findutils | [] [] [] | - flex | [] [] | - freedink | [] [] [] | - gas | [] | - gawk | [] [] [] | - gcal | [] | - gcc | [] [] | - gettext-examples | [] [] [] [] | - gettext-runtime | [] [] [] [] | - gettext-tools | [] [] [] | - gip | [] [] [] [] | - gjay | [] | - gliv | [] [] [] | - glunarclock | [] [] | - gnubiff | () | - gnucash | [] () () () () | - gnuedu | [] [] | - gnulib | [] [] | - gnunet | | - gnunet-gtk | [] | - gnutls | [] [] | - gold | [] | - gpe-aerial | [] [] [] [] | - gpe-beam | [] [] [] [] | - gpe-bluetooth | [] [] | - gpe-calendar | [] | - gpe-clock | [] [] [] [] | - gpe-conf | [] [] [] | - gpe-contacts | [] [] [] | - gpe-edit | [] [] | - gpe-filemanager | [] [] [] | - gpe-go | [] [] [] [] | - gpe-login | [] [] | - gpe-ownerinfo | [] [] [] [] | - gpe-package | [] [] [] | - gpe-sketchbook | [] [] [] [] | - gpe-su | [] [] [] [] | - gpe-taskmanager | [] [] [] [] | - gpe-timesheet | [] [] [] [] | - gpe-today | [] [] [] [] | - gpe-todo | [] [] [] | - gphoto2 | [] [] () [] [] [] | - gprof | [] [] [] | - gpsdrive | [] [] [] | - gramadoir | [] [] [] | - grep | [] | - grub | [] [] | - gsasl | [] | - gss | | - gst-plugins-bad | [] [] [] [] [] | - gst-plugins-base | [] [] [] [] [] | - gst-plugins-good | [] [] [] [] [] [] | - gst-plugins-ugly | [] [] [] [] [] [] | - gstreamer | [] [] [] [] [] | - gtick | [] () [] | - gtkam | [] [] () [] [] | - gtkorphan | [] [] [] [] | - gtkspell | [] [] [] [] [] [] [] | - gutenprint | [] [] [] | - hello | [] [] [] [] | - help2man | [] | - hylafax | [] [] | - idutils | [] [] | - indent | [] [] [] [] [] [] [] | - iso_15924 | [] () [] [] | - iso_3166 | [] [] [] [] () [] [] [] () | - iso_3166_2 | () | - iso_4217 | [] [] [] () [] [] | - iso_639 | [] [] [] [] () [] [] | - iso_639_3 | [] | - jwhois | [] | - kbd | [] [] [] [] [] | - keytouch | [] [] | - keytouch-editor | [] [] | - keytouch-keyboa... | [] | - klavaro | [] [] [] [] | - latrine | [] () | - ld | [] [] | - leafpad | [] [] [] [] [] [] | - libc | [] [] [] [] | - libexif | [] [] () | - libextractor | | - libgnutls | [] | - libgpewidget | [] [] | - libgpg-error | [] [] | - libgphoto2 | [] () | - libgphoto2_port | [] () [] | - libgsasl | | - libiconv | [] [] [] [] [] | - libidn | [] [] [] | - lifelines | [] () | - liferea | [] [] [] [] [] | - lilypond | [] [] [] | - linkdr | [] [] [] | - lordsawar | [] | - lprng | | - lynx | [] [] [] [] | - m4 | [] [] [] [] | - mailfromd | | - mailutils | [] | - make | [] [] [] | - man-db | | - man-db-manpages | | - minicom | [] [] [] [] | - mkisofs | | - myserver | | - nano | [] [] [] | - opcodes | [] [] | - parted | [] [] | - pies | | - popt | [] [] [] [] [] | - psmisc | [] [] [] | - pspp | [] | - pwdutils | [] | - radius | [] | - recode | [] [] [] [] [] [] | - rosegarden | () () () | - rpm | [] [] [] | - rush | | - sarg | | - screem | | - scrollkeeper | [] [] [] [] [] | - sed | [] [] [] [] [] [] | - sharutils | [] [] [] [] | - shishi | | - skencil | [] () [] | - solfege | [] [] [] | - solfege-manual | [] [] | - soundtracker | [] [] [] | - sp | [] | - sysstat | [] [] [] | - tar | [] [] [] [] | - texinfo | [] [] [] | - tin | [] [] | - unicode-han-tra... | | - unicode-transla... | | - util-linux-ng | [] [] [] [] | - vice | () () | - vmm | [] | - vorbis-tools | [] [] | - wastesedge | [] | - wdiff | [] [] | - wget | [] [] [] | - wyslij-po | | - xchat | [] [] [] [] [] | - xdg-user-dirs | [] [] [] [] [] [] [] [] [] | - xkeyboard-config | [] [] [] [] [] [] | - +-------------------------------------------------+ - crh cs da de el en en_GB en_ZA eo es et eu fa - 5 64 105 117 18 1 8 0 28 89 18 19 0 + nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr + +------------------------------------------------+ + a2ps | [] [] [] [] [] [] [] | + aegis | [] [] | + anubis | [] [] [] | + aspell | [] [] [] [] [] [] [] | + bash | [] [] [] [] [] [] | + bfd | [] [] | + binutils | [] [] | + bison | [] [] [] | + bison-runtime | [] [] [] [] [] [] [] [] | + buzztrax | [] | + ccd2cue | [] [] | + ccide | [] [] [] | + cflow | [] [] [] | + clisp | [] | + coreutils | [] [] [] [] | + cpio | [] [] [] | + cppi | [] [] [] | + cpplib | [] [] [] | + cryptsetup | [] [] [] | + datamash | [] [] | + denemo | | + dfarc | [] [] [] | + dialog | [] [] [] [] [] [] [] | + dico | [] | + diffutils | [] [] [] | + dink | | + direvent | [] [] [] | + doodle | [] [] | + dos2unix | [] [] [] [] | + dos2unix-man | [] [] | + e2fsprogs | [] | + enscript | [] [] [] [] [] [] | + exif | [] [] [] [] [] [] | + fetchmail | [] [] [] | + findutils | [] [] [] [] [] [] | + flex | [] [] [] [] [] | + freedink | [] [] [] [] [] | + fusionforge | | + gas | | + gawk | [] | + gcal | | + gcc | | + gdbm | [] [] [] | + gettext-examples | [] [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] [] [] [] | + gettext-tools | [] [] [] [] [] [] [] | + gjay | [] | + glunarclock | [] [] [] [] [] [] | + gnubiff | [] | + gnubik | [] [] [] [] | + gnucash | () () () () () [] | + gnuchess | [] [] | + gnulib | [] [] [] [] [] | + gnunet | | + gnunet-gtk | | + gold | | + gphoto2 | [] [] [] [] [] | + gprof | [] [] [] [] | + gramadoir | [] [] | + grep | [] [] [] [] [] [] | + grub | [] [] [] [] [] | + gsasl | [] [] [] | + gss | [] [] [] [] | + gst-plugins-bad | [] [] [] [] [] | + gst-plugins-base | [] [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] [] [] | + gtick | [] [] [] [] [] | + gtkam | [] [] [] [] [] [] | + gtkspell | [] [] [] [] [] [] [] [] [] | + guix | | + guix-packages | | + gutenprint | [] [] | + hello | [] [] [] [] [] [] | + help2man | [] [] [] [] | + help2man-texi | [] | + hylafax | | + idutils | [] [] [] | + iso_15924 | [] () [] [] [] [] | + iso_3166 | [] [] [] [] () [] [] [] [] [] [] [] [] | + iso_3166_2 | [] () [] | + iso_4217 | [] [] () [] [] [] [] [] | + iso_639 | [] [] [] () [] [] [] [] [] [] | + iso_639_3 | [] () | + iso_639_5 | () [] | + jwhois | [] [] [] [] | + kbd | [] [] | + klavaro | [] [] [] [] [] | + ld | | + leafpad | [] [] [] [] [] [] [] [] | + libc | [] [] [] | + libexif | [] () [] | + libextractor | [] | + libgnutls | [] | + libgphoto2 | [] | + libgphoto2_port | [] [] [] [] [] | + libgsasl | [] [] [] [] | + libiconv | [] [] [] [] [] | + libidn | [] [] [] | + liferea | [] [] [] [] () [] [] | + lilypond | | + lordsawar | | + lprng | [] | + lynx | [] [] | + m4 | [] [] [] [] [] | + mailfromd | [] | + mailutils | [] | + make | [] [] [] | + man-db | [] [] [] | + man-db-manpages | [] [] [] | + midi-instruments | [] [] [] [] [] [] [] [] | + minicom | [] [] [] [] | + mkisofs | [] [] [] | + myserver | [] [] | + nano | [] [] [] [] [] [] | + opcodes | | + parted | [] [] [] [] [] [] | + pies | [] | + pnmixer | [] | + popt | [] [] [] [] [] [] | + procps-ng | [] | + procps-ng-man | [] | + psmisc | [] [] [] [] | + pspp | [] [] | + pushover | | + pwdutils | [] | + pyspread | [] [] | + radius | [] [] | + recode | [] [] [] [] [] [] [] [] | + recutils | [] [] | + rpm | [] | + rush | [] [] [] | + sarg | [] [] | + sed | [] [] [] [] [] [] [] [] | + sharutils | [] [] [] | + shishi | [] [] | + skribilo | [] | + solfege | [] [] [] | + solfege-manual | [] [] | + spotmachine | [] [] | + sudo | [] [] [] [] [] [] | + sudoers | [] [] [] [] | + sysstat | [] [] [] [] [] | + tar | [] [] [] [] [] | + texinfo | [] [] [] | + texinfo_document | [] [] | + tigervnc | [] [] [] | + tin | [] | + tin-man | | + tracgoogleappsa... | [] [] [] [] | + trader | [] [] | + util-linux | [] [] | + ve | [] [] [] | + vice | | + vmm | | + vorbis-tools | [] [] [] | + wastesedge | | + wcd | | + wcd-man | | + wdiff | [] [] [] [] [] | + wget | [] [] [] [] [] | + wyslij-po | [] [] [] [] | + xboard | [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] | + +------------------------------------------------+ + nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr + 7 3 6 114 1 12 88 32 82 3 40 45 7 101 - fi fr ga gl gu he hi hr hu hy id is it ja ka kn - +----------------------------------------------------+ - a2ps | [] [] [] [] | - aegis | [] [] | - ant-phone | [] [] | - anubis | [] [] [] [] | - aspell | [] [] [] [] | - bash | [] [] [] [] | - bfd | [] [] [] | - bibshelf | [] [] [] [] [] | - binutils | [] [] [] | - bison | [] [] [] [] | - bison-runtime | [] [] [] [] [] [] | - bluez-pin | [] [] [] [] [] [] [] [] | - bombono-dvd | [] | - buzztard | [] | - cflow | [] [] [] | - clisp | [] | - coreutils | [] [] [] [] [] | - cpio | [] [] [] [] | - cppi | [] [] | - cpplib | [] [] [] | - cryptsetup | [] [] [] | - dfarc | [] [] [] | - dialog | [] [] [] [] [] [] [] | - dico | | - diffutils | [] [] [] [] [] [] [] [] [] | - dink | [] | - doodle | [] [] | - e2fsprogs | [] [] | - enscript | [] [] [] [] | - exif | [] [] [] [] [] [] | - fetchmail | [] [] [] [] | - findutils | [] [] [] [] [] [] | - flex | [] [] [] | - freedink | [] [] [] | - gas | [] [] | - gawk | [] [] [] [] () [] | - gcal | [] | - gcc | [] | - gettext-examples | [] [] [] [] [] [] [] | - gettext-runtime | [] [] [] [] [] [] | - gettext-tools | [] [] [] [] | - gip | [] [] [] [] [] [] | - gjay | [] | - gliv | [] () | - glunarclock | [] [] [] [] | - gnubiff | () [] () | - gnucash | () () () () () [] | - gnuedu | [] [] | - gnulib | [] [] [] [] [] [] | - gnunet | | - gnunet-gtk | [] | - gnutls | [] [] | - gold | [] [] | - gpe-aerial | [] [] [] | - gpe-beam | [] [] [] [] | - gpe-bluetooth | [] [] [] [] | - gpe-calendar | [] [] | - gpe-clock | [] [] [] [] [] | - gpe-conf | [] [] [] [] | - gpe-contacts | [] [] [] [] | - gpe-edit | [] [] [] | - gpe-filemanager | [] [] [] [] | - gpe-go | [] [] [] [] [] | - gpe-login | [] [] [] | - gpe-ownerinfo | [] [] [] [] [] | - gpe-package | [] [] [] | - gpe-sketchbook | [] [] [] [] | - gpe-su | [] [] [] [] [] [] | - gpe-taskmanager | [] [] [] [] [] | - gpe-timesheet | [] [] [] [] [] | - gpe-today | [] [] [] [] [] [] [] | - gpe-todo | [] [] [] | - gphoto2 | [] [] [] [] [] [] | - gprof | [] [] [] [] | - gpsdrive | [] [] [] | - gramadoir | [] [] [] | - grep | [] [] | - grub | [] [] [] [] | - gsasl | [] [] [] [] [] | - gss | [] [] [] [] [] | - gst-plugins-bad | [] [] [] [] [] [] | - gst-plugins-base | [] [] [] [] [] [] | - gst-plugins-good | [] [] [] [] [] [] | - gst-plugins-ugly | [] [] [] [] [] [] | - gstreamer | [] [] [] [] [] | - gtick | [] [] [] [] [] | - gtkam | [] [] [] [] [] | - gtkorphan | [] [] [] | - gtkspell | [] [] [] [] [] [] [] [] [] | - gutenprint | [] [] [] [] | - hello | [] [] [] | - help2man | [] [] | - hylafax | [] | - idutils | [] [] [] [] [] [] | - indent | [] [] [] [] [] [] [] [] | - iso_15924 | [] () [] [] | - iso_3166 | [] () [] [] [] [] [] [] [] [] [] [] | - iso_3166_2 | () [] [] [] | - iso_4217 | [] () [] [] [] [] | - iso_639 | [] () [] [] [] [] [] [] [] | - iso_639_3 | () [] [] | - jwhois | [] [] [] [] [] | - kbd | [] [] | - keytouch | [] [] [] [] [] [] | - keytouch-editor | [] [] [] [] [] | - keytouch-keyboa... | [] [] [] [] [] | - klavaro | [] [] | - latrine | [] [] [] | - ld | [] [] [] [] | - leafpad | [] [] [] [] [] [] [] () | - libc | [] [] [] [] [] | - libexif | [] | - libextractor | | - libgnutls | [] [] | - libgpewidget | [] [] [] [] | - libgpg-error | [] [] | - libgphoto2 | [] [] [] | - libgphoto2_port | [] [] [] | - libgsasl | [] [] [] [] [] | - libiconv | [] [] [] [] [] [] | - libidn | [] [] [] [] | - lifelines | () | - liferea | [] [] [] [] | - lilypond | [] [] | - linkdr | [] [] [] [] [] | - lordsawar | | - lprng | [] | - lynx | [] [] [] [] [] | - m4 | [] [] [] [] [] [] | - mailfromd | | - mailutils | [] [] | - make | [] [] [] [] [] [] [] [] [] | - man-db | [] [] | - man-db-manpages | [] | - minicom | [] [] [] [] [] | - mkisofs | [] [] [] [] | - myserver | | - nano | [] [] [] [] [] [] | - opcodes | [] [] [] [] | - parted | [] [] [] [] | - pies | | - popt | [] [] [] [] [] [] [] [] [] | - psmisc | [] [] [] | - pspp | | - pwdutils | [] [] | - radius | [] [] | - recode | [] [] [] [] [] [] [] [] | - rosegarden | () () () () () | - rpm | [] [] | - rush | | - sarg | [] | - screem | [] [] | - scrollkeeper | [] [] [] [] | - sed | [] [] [] [] [] [] [] [] | - sharutils | [] [] [] [] [] [] [] | - shishi | [] | - skencil | [] | - solfege | [] [] [] [] | - solfege-manual | [] [] | - soundtracker | [] [] | - sp | [] () | - sysstat | [] [] [] [] [] | - tar | [] [] [] [] [] [] [] | - texinfo | [] [] [] [] | - tin | [] | - unicode-han-tra... | | - unicode-transla... | [] [] | - util-linux-ng | [] [] [] [] [] [] | - vice | () () () | - vmm | [] | - vorbis-tools | [] | - wastesedge | () () | - wdiff | [] | - wget | [] [] [] [] [] [] [] [] | - wyslij-po | [] [] [] | - xchat | [] [] [] [] [] [] [] [] [] | - xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] | - xkeyboard-config | [] [] [] [] [] | - +----------------------------------------------------+ - fi fr ga gl gu he hi hr hu hy id is it ja ka kn - 105 121 53 20 4 8 3 5 53 2 120 5 84 67 0 4 + sv sw ta te tg th tr uk ur vi wa wo zh_CN + +----------------------------------------------+ + a2ps | [] [] [] [] [] | + aegis | [] | + anubis | [] [] [] [] | + aspell | [] [] [] [] [] | + bash | [] [] [] [] | + bfd | [] [] [] | + binutils | [] [] [] | + bison | [] [] [] [] | + bison-runtime | [] [] [] [] [] [] | + buzztrax | [] [] [] | + ccd2cue | [] [] [] | + ccide | [] [] [] [] | + cflow | [] [] [] [] | + clisp | | + coreutils | [] [] [] | + cpio | [] [] [] [] [] | + cppi | [] [] [] [] | + cpplib | [] [] [] [] [] | + cryptsetup | [] [] [] | + datamash | [] [] [] | + denemo | [] | + dfarc | [] [] | + dialog | [] [] [] [] [] [] | + dico | [] | + diffutils | [] [] [] [] [] | + dink | [] | + direvent | [] [] | + doodle | [] [] | + dos2unix | [] [] [] [] | + dos2unix-man | [] [] [] | + e2fsprogs | [] [] [] [] | + enscript | [] [] [] [] | + exif | [] [] [] [] [] | + fetchmail | [] [] [] [] | + findutils | [] [] [] [] [] | + flex | [] [] [] [] | + freedink | [] [] [] | + fusionforge | | + gas | [] | + gawk | [] [] [] | + gcal | [] [] [] | + gcc | [] | + gdbm | [] [] | + gettext-examples | [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] | + gettext-tools | [] [] [] [] [] | + gjay | [] [] [] | + glunarclock | [] [] [] [] | + gnubiff | [] [] | + gnubik | [] [] [] [] | + gnucash | () () () () [] | + gnuchess | [] [] [] | + gnulib | [] [] [] [] | + gnunet | | + gnunet-gtk | | + gold | [] [] | + gphoto2 | [] [] [] [] | + gprof | [] [] [] [] | + gramadoir | [] [] [] | + grep | [] [] [] [] [] | + grub | [] [] [] [] | + gsasl | [] [] [] [] | + gss | [] [] [] | + gst-plugins-bad | [] [] [] [] [] | + gst-plugins-base | [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] | + gstreamer | [] [] [] [] [] | + gtick | [] [] [] | + gtkam | [] [] [] [] | + gtkspell | [] [] [] [] [] [] [] | + guix | | + guix-packages | | + gutenprint | [] [] [] [] | + hello | [] [] [] [] [] [] | + help2man | [] [] [] | + help2man-texi | [] | + hylafax | [] | + idutils | [] [] [] | + iso_15924 | [] () [] [] () [] | + iso_3166 | [] [] () [] [] () [] [] | + iso_3166_2 | () [] [] () [] | + iso_4217 | [] () [] [] () [] | + iso_639 | [] [] [] () [] [] () [] [] | + iso_639_3 | [] () [] [] () | + iso_639_5 | () [] () | + jwhois | [] [] [] [] | + kbd | [] [] [] [] | + klavaro | [] [] [] [] [] [] | + ld | [] [] [] [] [] | + leafpad | [] [] [] [] [] [] | + libc | [] [] [] [] [] | + libexif | [] [] () | + libextractor | [] [] | + libgnutls | [] [] [] [] | + libgphoto2 | [] [] [] | + libgphoto2_port | [] [] [] [] | + libgsasl | [] [] [] [] | + libiconv | [] [] [] [] [] | + libidn | () [] [] [] | + liferea | [] [] [] [] [] | + lilypond | [] | + lordsawar | | + lprng | [] | + lynx | [] [] [] [] | + m4 | [] [] [] | + mailfromd | [] [] | + mailutils | [] | + make | [] [] [] [] | + man-db | [] [] [] | + man-db-manpages | [] [] | + midi-instruments | [] [] [] [] [] [] | + minicom | [] [] | + mkisofs | [] [] [] | + myserver | [] | + nano | [] [] [] [] | + opcodes | [] [] [] | + parted | [] [] [] [] [] | + pies | [] [] | + pnmixer | [] [] [] | + popt | [] [] [] [] [] [] [] | + procps-ng | [] [] | + procps-ng-man | [] | + psmisc | [] [] [] [] | + pspp | [] [] [] | + pushover | [] | + pwdutils | [] [] | + pyspread | [] | + radius | [] [] | + recode | [] [] [] [] | + recutils | [] [] [] | + rpm | [] [] [] [] | + rush | [] [] | + sarg | | + sed | [] [] [] [] [] | + sharutils | [] [] [] [] | + shishi | [] [] | + skribilo | [] [] | + solfege | [] [] [] [] | + solfege-manual | [] | + spotmachine | [] [] [] | + sudo | [] [] [] [] [] | + sudoers | [] [] [] [] | + sysstat | [] [] [] [] [] | + tar | [] [] [] [] [] | + texinfo | [] [] [] | + texinfo_document | [] | + tigervnc | [] [] [] | + tin | [] | + tin-man | | + tracgoogleappsa... | [] [] [] [] [] | + trader | [] | + util-linux | [] [] [] [] | + ve | [] [] [] [] | + vice | () () | + vmm | | + vorbis-tools | [] [] | + wastesedge | | + wcd | [] [] [] | + wcd-man | [] | + wdiff | [] [] [] [] | + wget | [] [] [] | + wyslij-po | [] [] | + xboard | [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] | + +----------------------------------------------+ + sv sw ta te tg th tr uk ur vi wa wo zh_CN + 106 1 4 3 0 13 51 115 1 125 7 1 100 - ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne - +-----------------------------------------------+ - a2ps | [] | - aegis | | - ant-phone | | - anubis | [] [] | - aspell | [] | - bash | | - bfd | | - bibshelf | [] [] | - binutils | | - bison | [] | - bison-runtime | [] [] [] [] [] | - bluez-pin | [] [] [] [] [] | - bombono-dvd | | - buzztard | | - cflow | | - clisp | | - coreutils | [] | - cpio | | - cppi | | - cpplib | | - cryptsetup | | - dfarc | [] | - dialog | [] [] [] [] [] | - dico | | - diffutils | [] [] | - dink | | - doodle | | - e2fsprogs | | - enscript | | - exif | [] | - fetchmail | | - findutils | | - flex | | - freedink | [] | - gas | | - gawk | | - gcal | | - gcc | | - gettext-examples | [] [] [] [] | - gettext-runtime | [] | - gettext-tools | [] | - gip | [] [] | - gjay | | - gliv | | - glunarclock | [] | - gnubiff | | - gnucash | () () () () | - gnuedu | | - gnulib | | - gnunet | | - gnunet-gtk | | - gnutls | [] | - gold | | - gpe-aerial | [] | - gpe-beam | [] | - gpe-bluetooth | [] [] | - gpe-calendar | [] | - gpe-clock | [] [] [] [] [] | - gpe-conf | [] [] | - gpe-contacts | [] [] | - gpe-edit | [] | - gpe-filemanager | [] [] | - gpe-go | [] [] [] | - gpe-login | [] | - gpe-ownerinfo | [] [] | - gpe-package | [] [] | - gpe-sketchbook | [] [] | - gpe-su | [] [] [] [] [] [] | - gpe-taskmanager | [] [] [] [] [] [] | - gpe-timesheet | [] [] | - gpe-today | [] [] [] [] | - gpe-todo | [] [] | - gphoto2 | | - gprof | [] | - gpsdrive | | - gramadoir | | - grep | | - grub | | - gsasl | | - gss | | - gst-plugins-bad | [] [] [] [] | - gst-plugins-base | [] [] | - gst-plugins-good | [] [] | - gst-plugins-ugly | [] [] [] [] [] | - gstreamer | | - gtick | | - gtkam | [] | - gtkorphan | [] [] | - gtkspell | [] [] [] [] [] [] [] | - gutenprint | | - hello | [] [] [] | - help2man | | - hylafax | | - idutils | | - indent | | - iso_15924 | [] [] | - iso_3166 | [] [] () [] [] [] [] [] | - iso_3166_2 | | - iso_4217 | [] [] | - iso_639 | [] [] | - iso_639_3 | [] | - jwhois | [] | - kbd | | - keytouch | [] | - keytouch-editor | [] | - keytouch-keyboa... | [] | - klavaro | [] | - latrine | [] | - ld | | - leafpad | [] [] [] | - libc | [] | - libexif | | - libextractor | | - libgnutls | [] | - libgpewidget | [] [] | - libgpg-error | | - libgphoto2 | | - libgphoto2_port | | - libgsasl | | - libiconv | | - libidn | | - lifelines | | - liferea | | - lilypond | | - linkdr | | - lordsawar | | - lprng | | - lynx | | - m4 | | - mailfromd | | - mailutils | | - make | [] | - man-db | | - man-db-manpages | | - minicom | [] | - mkisofs | | - myserver | | - nano | [] [] | - opcodes | | - parted | | - pies | | - popt | [] [] [] | - psmisc | | - pspp | | - pwdutils | | - radius | | - recode | | - rosegarden | | - rpm | | - rush | | - sarg | | - screem | | - scrollkeeper | [] [] | - sed | | - sharutils | | - shishi | | - skencil | | - solfege | [] | - solfege-manual | | - soundtracker | | - sp | | - sysstat | [] | - tar | [] | - texinfo | [] | - tin | | - unicode-han-tra... | | - unicode-transla... | | - util-linux-ng | | - vice | | - vmm | | - vorbis-tools | | - wastesedge | | - wdiff | | - wget | [] | - wyslij-po | | - xchat | [] [] [] | - xdg-user-dirs | [] [] [] [] [] [] [] [] | - xkeyboard-config | [] [] [] | - +-----------------------------------------------+ - ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne - 20 5 10 1 13 48 4 2 2 4 24 10 20 3 1 - - nl nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr - +---------------------------------------------------+ - a2ps | [] [] [] [] [] [] [] [] | - aegis | [] [] [] | - ant-phone | [] [] | - anubis | [] [] [] | - aspell | [] [] [] [] [] | - bash | [] [] | - bfd | [] | - bibshelf | [] [] | - binutils | [] [] | - bison | [] [] [] | - bison-runtime | [] [] [] [] [] [] [] | - bluez-pin | [] [] [] [] [] [] [] [] | - bombono-dvd | [] () | - buzztard | [] [] | - cflow | [] | - clisp | [] [] | - coreutils | [] [] [] [] [] [] | - cpio | [] [] [] | - cppi | [] | - cpplib | [] | - cryptsetup | [] | - dfarc | [] | - dialog | [] [] [] [] | - dico | [] | - diffutils | [] [] [] [] [] [] | - dink | () | - doodle | [] [] | - e2fsprogs | [] [] | - enscript | [] [] [] [] [] | - exif | [] [] [] () [] | - fetchmail | [] [] [] [] | - findutils | [] [] [] [] [] | - flex | [] [] [] [] [] | - freedink | [] [] | - gas | | - gawk | [] [] [] [] | - gcal | | - gcc | [] | - gettext-examples | [] [] [] [] [] [] [] [] | - gettext-runtime | [] [] [] [] [] [] [] [] [] | - gettext-tools | [] [] [] [] [] [] | - gip | [] [] [] [] [] | - gjay | | - gliv | [] [] [] [] [] [] | - glunarclock | [] [] [] [] [] | - gnubiff | [] () | - gnucash | [] () () () | - gnuedu | [] | - gnulib | [] [] [] [] | - gnunet | | - gnunet-gtk | | - gnutls | [] [] | - gold | | - gpe-aerial | [] [] [] [] [] [] [] | - gpe-beam | [] [] [] [] [] [] [] | - gpe-bluetooth | [] [] | - gpe-calendar | [] [] [] [] | - gpe-clock | [] [] [] [] [] [] [] [] | - gpe-conf | [] [] [] [] [] [] [] | - gpe-contacts | [] [] [] [] [] | - gpe-edit | [] [] [] | - gpe-filemanager | [] [] [] | - gpe-go | [] [] [] [] [] [] [] [] | - gpe-login | [] [] | - gpe-ownerinfo | [] [] [] [] [] [] [] [] | - gpe-package | [] [] | - gpe-sketchbook | [] [] [] [] [] [] [] | - gpe-su | [] [] [] [] [] [] [] [] | - gpe-taskmanager | [] [] [] [] [] [] [] [] | - gpe-timesheet | [] [] [] [] [] [] [] [] | - gpe-today | [] [] [] [] [] [] [] [] | - gpe-todo | [] [] [] [] [] | - gphoto2 | [] [] [] [] [] [] [] [] | - gprof | [] [] [] | - gpsdrive | [] [] | - gramadoir | [] [] | - grep | [] [] [] [] | - grub | [] [] [] | - gsasl | [] [] [] [] | - gss | [] [] [] | - gst-plugins-bad | [] [] [] [] [] [] | - gst-plugins-base | [] [] [] [] [] | - gst-plugins-good | [] [] [] [] [] | - gst-plugins-ugly | [] [] [] [] [] [] | - gstreamer | [] [] [] [] [] | - gtick | [] [] [] | - gtkam | [] [] [] [] [] [] | - gtkorphan | [] | - gtkspell | [] [] [] [] [] [] [] [] [] [] | - gutenprint | [] [] | - hello | [] [] [] [] | - help2man | [] [] | - hylafax | [] | - idutils | [] [] [] [] [] | - indent | [] [] [] [] [] [] [] | - iso_15924 | [] [] [] [] | - iso_3166 | [] [] [] [] [] () [] [] [] [] [] [] [] [] | - iso_3166_2 | [] [] [] | - iso_4217 | [] [] [] [] [] [] [] [] | - iso_639 | [] [] [] [] [] [] [] [] [] | - iso_639_3 | [] [] | - jwhois | [] [] [] [] | - kbd | [] [] [] | - keytouch | [] [] [] | - keytouch-editor | [] [] [] | - keytouch-keyboa... | [] [] [] | - klavaro | [] [] | - latrine | [] [] | - ld | | - leafpad | [] [] [] [] [] [] [] [] [] | - libc | [] [] [] [] | - libexif | [] [] () [] | - libextractor | | - libgnutls | [] [] | - libgpewidget | [] [] [] | - libgpg-error | [] [] | - libgphoto2 | [] [] | - libgphoto2_port | [] [] [] [] [] | - libgsasl | [] [] [] [] [] | - libiconv | [] [] [] [] [] | - libidn | [] [] | - lifelines | [] [] | - liferea | [] [] [] [] [] () () [] | - lilypond | [] | - linkdr | [] [] [] | - lordsawar | | - lprng | [] | - lynx | [] [] [] | - m4 | [] [] [] [] [] | - mailfromd | [] | - mailutils | [] | - make | [] [] [] [] | - man-db | [] [] [] | - man-db-manpages | [] [] [] | - minicom | [] [] [] [] | - mkisofs | [] [] [] | - myserver | | - nano | [] [] [] [] | - opcodes | [] [] | - parted | [] [] [] [] | - pies | [] | - popt | [] [] [] [] | - psmisc | [] [] [] | - pspp | [] [] | - pwdutils | [] | - radius | [] [] [] | - recode | [] [] [] [] [] [] [] [] | - rosegarden | () () | - rpm | [] [] [] | - rush | [] [] | - sarg | | - screem | | - scrollkeeper | [] [] [] [] [] [] [] [] | - sed | [] [] [] [] [] [] [] [] [] | - sharutils | [] [] [] [] | - shishi | [] | - skencil | [] [] | - solfege | [] [] [] [] | - solfege-manual | [] [] [] | - soundtracker | [] | - sp | | - sysstat | [] [] [] [] | - tar | [] [] [] [] | - texinfo | [] [] [] [] | - tin | [] | - unicode-han-tra... | | - unicode-transla... | | - util-linux-ng | [] [] [] [] [] | - vice | [] | - vmm | [] | - vorbis-tools | [] [] | - wastesedge | [] | - wdiff | [] [] | - wget | [] [] [] [] [] [] [] | - wyslij-po | [] [] [] | - xchat | [] [] [] [] [] [] [] [] [] | - xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] [] | - xkeyboard-config | [] [] [] | - +---------------------------------------------------+ - nl nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr - 135 10 4 7 105 1 29 62 47 91 3 54 46 9 37 - - sv sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW - +---------------------------------------------------+ - a2ps | [] [] [] [] [] | 27 - aegis | [] | 9 - ant-phone | [] [] [] [] | 9 - anubis | [] [] [] [] | 15 - aspell | [] [] [] | 20 - bash | [] [] [] | 12 - bfd | [] | 6 - bibshelf | [] [] [] | 16 - binutils | [] [] | 8 - bison | [] [] | 12 - bison-runtime | [] [] [] [] [] [] | 29 - bluez-pin | [] [] [] [] [] [] [] [] | 37 - bombono-dvd | [] | 4 - buzztard | [] | 7 - cflow | [] [] [] | 9 - clisp | | 10 - coreutils | [] [] [] [] | 22 - cpio | [] [] [] [] [] [] | 13 - cppi | [] [] | 5 - cpplib | [] [] [] [] [] [] | 14 - cryptsetup | [] [] | 7 - dfarc | [] | 9 - dialog | [] [] [] [] [] [] [] | 30 - dico | [] | 2 - diffutils | [] [] [] [] [] [] | 30 - dink | | 4 - doodle | [] [] | 7 - e2fsprogs | [] [] [] | 11 - enscript | [] [] [] [] | 17 - exif | [] [] [] | 16 - fetchmail | [] [] [] | 17 - findutils | [] [] [] [] [] | 20 - flex | [] [] [] [] | 15 - freedink | [] | 10 - gas | [] | 4 - gawk | [] [] [] [] | 18 - gcal | [] [] | 5 - gcc | [] [] [] | 7 - gettext-examples | [] [] [] [] [] [] [] | 34 - gettext-runtime | [] [] [] [] [] [] [] | 29 - gettext-tools | [] [] [] [] [] [] | 22 - gip | [] [] [] [] | 22 - gjay | [] | 3 - gliv | [] [] [] | 14 - glunarclock | [] [] [] [] [] | 19 - gnubiff | [] [] | 4 - gnucash | () [] () [] () | 10 - gnuedu | [] [] | 7 - gnulib | [] [] [] [] | 16 - gnunet | [] | 1 - gnunet-gtk | [] [] [] | 5 - gnutls | [] [] [] | 10 - gold | [] | 4 - gpe-aerial | [] [] [] | 18 - gpe-beam | [] [] [] | 19 - gpe-bluetooth | [] [] [] | 13 - gpe-calendar | [] [] [] [] | 12 - gpe-clock | [] [] [] [] [] | 28 - gpe-conf | [] [] [] [] | 20 - gpe-contacts | [] [] [] | 17 - gpe-edit | [] [] [] | 12 - gpe-filemanager | [] [] [] [] | 16 - gpe-go | [] [] [] [] [] | 25 - gpe-login | [] [] [] | 11 - gpe-ownerinfo | [] [] [] [] [] | 25 - gpe-package | [] [] [] | 13 - gpe-sketchbook | [] [] [] | 20 - gpe-su | [] [] [] [] [] | 30 - gpe-taskmanager | [] [] [] [] [] | 29 - gpe-timesheet | [] [] [] [] [] | 25 - gpe-today | [] [] [] [] [] [] | 30 - gpe-todo | [] [] [] [] | 17 - gphoto2 | [] [] [] [] [] | 24 - gprof | [] [] [] | 15 - gpsdrive | [] [] [] | 11 - gramadoir | [] [] [] | 11 - grep | [] [] [] | 10 - grub | [] [] [] | 14 - gsasl | [] [] [] [] | 14 - gss | [] [] [] | 11 - gst-plugins-bad | [] [] [] [] | 26 - gst-plugins-base | [] [] [] [] [] | 24 - gst-plugins-good | [] [] [] [] | 24 - gst-plugins-ugly | [] [] [] [] [] | 29 - gstreamer | [] [] [] [] | 22 - gtick | [] [] [] | 13 - gtkam | [] [] [] | 20 - gtkorphan | [] [] [] | 14 - gtkspell | [] [] [] [] [] [] [] [] [] | 45 - gutenprint | [] | 10 - hello | [] [] [] [] [] [] | 21 - help2man | [] [] | 7 - hylafax | [] | 5 - idutils | [] [] [] [] | 17 - indent | [] [] [] [] [] [] | 30 - iso_15924 | () [] () [] [] | 16 - iso_3166 | [] [] () [] [] () [] [] [] () | 53 - iso_3166_2 | () [] () [] | 9 - iso_4217 | [] () [] [] () [] [] | 26 - iso_639 | [] [] [] () [] () [] [] [] [] | 38 - iso_639_3 | [] () | 8 - jwhois | [] [] [] [] [] | 16 - kbd | [] [] [] [] [] | 15 - keytouch | [] [] [] | 16 - keytouch-editor | [] [] [] | 14 - keytouch-keyboa... | [] [] [] | 14 - klavaro | [] | 11 - latrine | [] [] [] | 10 - ld | [] [] [] [] | 11 - leafpad | [] [] [] [] [] [] | 33 - libc | [] [] [] [] [] | 21 - libexif | [] () | 7 - libextractor | [] | 1 - libgnutls | [] [] [] | 9 - libgpewidget | [] [] [] | 14 - libgpg-error | [] [] [] | 9 - libgphoto2 | [] [] | 8 - libgphoto2_port | [] [] [] [] | 14 - libgsasl | [] [] [] | 13 - libiconv | [] [] [] [] | 21 - libidn | () [] [] | 11 - lifelines | [] | 4 - liferea | [] [] [] | 21 - lilypond | [] | 7 - linkdr | [] [] [] [] [] | 17 - lordsawar | | 1 - lprng | [] | 3 - lynx | [] [] [] [] | 17 - m4 | [] [] [] [] | 19 - mailfromd | [] [] | 3 - mailutils | [] | 5 - make | [] [] [] [] | 21 - man-db | [] [] [] | 8 - man-db-manpages | | 4 - minicom | [] [] | 16 - mkisofs | [] [] | 9 - myserver | | 0 - nano | [] [] [] [] | 21 - opcodes | [] [] [] | 11 - parted | [] [] [] [] [] | 15 - pies | [] [] | 3 - popt | [] [] [] [] [] [] | 27 - psmisc | [] [] | 11 - pspp | | 4 - pwdutils | [] [] | 6 - radius | [] [] | 9 - recode | [] [] [] [] | 28 - rosegarden | () | 0 - rpm | [] [] [] | 11 - rush | [] [] | 4 - sarg | | 1 - screem | [] | 3 - scrollkeeper | [] [] [] [] [] | 27 - sed | [] [] [] [] [] | 30 - sharutils | [] [] [] [] [] | 22 - shishi | [] | 3 - skencil | [] [] | 7 - solfege | [] [] [] [] | 16 - solfege-manual | [] | 8 - soundtracker | [] [] [] | 9 - sp | [] | 3 - sysstat | [] [] | 15 - tar | [] [] [] [] [] [] | 23 - texinfo | [] [] [] [] [] | 17 - tin | | 4 - unicode-han-tra... | | 0 - unicode-transla... | | 2 - util-linux-ng | [] [] [] [] | 20 - vice | () () | 1 - vmm | [] | 4 - vorbis-tools | [] | 6 - wastesedge | | 2 - wdiff | [] [] | 7 - wget | [] [] [] [] [] | 26 - wyslij-po | [] [] | 8 - xchat | [] [] [] [] [] [] | 36 - xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] | 63 - xkeyboard-config | [] [] [] | 22 - +---------------------------------------------------+ - 85 teams sv sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW - 178 domains 119 1 3 3 0 10 65 51 155 17 98 7 41 2618 + zh_HK zh_TW + +-------------+ + a2ps | | 30 + aegis | | 9 + anubis | | 19 + aspell | | 29 + bash | [] | 23 + bfd | | 11 + binutils | | 12 + bison | [] | 18 + bison-runtime | [] | 38 + buzztrax | | 9 + ccd2cue | | 10 + ccide | | 17 + cflow | | 16 + clisp | | 10 + coreutils | | 18 + cpio | | 20 + cppi | | 17 + cpplib | [] | 19 + cryptsetup | | 14 + datamash | | 11 + denemo | | 5 + dfarc | | 17 + dialog | [] | 42 + dico | | 6 + diffutils | | 22 + dink | | 10 + direvent | | 11 + doodle | | 12 + dos2unix | [] | 18 + dos2unix-man | | 9 + e2fsprogs | | 15 + enscript | | 21 + exif | | 27 + fetchmail | | 19 + findutils | | 29 + flex | [] | 19 + freedink | | 24 + fusionforge | | 3 + gas | | 5 + gawk | | 13 + gcal | | 8 + gcc | | 2 + gdbm | | 10 + gettext-examples | [] [] | 40 + gettext-runtime | [] [] | 35 + gettext-tools | [] | 24 + gjay | | 9 + glunarclock | [] | 27 + gnubiff | | 9 + gnubik | | 19 + gnucash | () | 6 + gnuchess | | 11 + gnulib | | 23 + gnunet | | 1 + gnunet-gtk | | 1 + gold | | 7 + gphoto2 | [] | 19 + gprof | | 21 + gramadoir | | 14 + grep | [] | 31 + grub | | 21 + gsasl | [] | 19 + gss | | 17 + gst-plugins-bad | | 21 + gst-plugins-base | | 27 + gst-plugins-good | | 32 + gst-plugins-ugly | | 34 + gstreamer | [] | 32 + gtick | | 19 + gtkam | | 24 + gtkspell | [] [] | 48 + guix | | 2 + guix-packages | | 0 + gutenprint | | 15 + hello | [] | 30 + help2man | | 18 + help2man-texi | | 5 + hylafax | | 5 + idutils | | 14 + iso_15924 | [] | 23 + iso_3166 | [] [] | 58 + iso_3166_2 | | 9 + iso_4217 | [] [] | 28 + iso_639 | [] [] | 46 + iso_639_3 | | 10 + iso_639_5 | | 2 + jwhois | [] | 20 + kbd | | 17 + klavaro | | 30 + ld | [] | 15 + leafpad | [] | 39 + libc | [] | 24 + libexif | | 10 + libextractor | | 5 + libgnutls | | 13 + libgphoto2 | | 10 + libgphoto2_port | [] | 19 + libgsasl | | 18 + libiconv | [] | 29 + libidn | | 17 + liferea | | 29 + lilypond | | 11 + lordsawar | | 3 + lprng | | 3 + lynx | | 19 + m4 | [] | 22 + mailfromd | | 4 + mailutils | | 6 + make | | 19 + man-db | | 15 + man-db-manpages | | 10 + midi-instruments | [] | 43 + minicom | [] | 17 + mkisofs | | 13 + myserver | | 9 + nano | [] | 30 + opcodes | | 12 + parted | [] | 23 + pies | | 4 + pnmixer | | 9 + popt | [] | 36 + procps-ng | | 5 + procps-ng-man | | 4 + psmisc | [] | 22 + pspp | | 13 + pushover | | 6 + pwdutils | | 8 + pyspread | | 6 + radius | | 9 + recode | | 31 + recutils | | 10 + rpm | [] | 13 + rush | | 10 + sarg | | 4 + sed | [] | 35 + sharutils | | 13 + shishi | | 7 + skribilo | | 7 + solfege | | 21 + solfege-manual | | 9 + spotmachine | | 11 + sudo | | 26 + sudoers | | 22 + sysstat | | 23 + tar | [] | 30 + texinfo | | 17 + texinfo_document | | 13 + tigervnc | | 14 + tin | [] | 7 + tin-man | | 1 + tracgoogleappsa... | [] | 22 + trader | | 12 + util-linux | | 13 + ve | | 14 + vice | | 1 + vmm | | 3 + vorbis-tools | | 13 + wastesedge | | 3 + wcd | | 8 + wcd-man | | 3 + wdiff | [] | 23 + wget | | 21 + wyslij-po | | 14 + xboard | | 10 + xdg-user-dirs | [] [] | 68 + xkeyboard-config | [] | 28 + +-------------+ + 89 teams zh_HK zh_TW + 166 domains 7 42 2809 Some counters in the preceding matrix are higher than the number of visible blocks let us expect. This is because a few extra PO files are @@ -1251,32 +1350,30 @@ used for implementing regional variants of languages, or language dialects. For a PO file in the matrix above to be effective, the package to -which it applies should also have been internationalized and -distributed as such by its maintainer. There might be an observable -lag between the mere existence a PO file and its wide availability in a -distribution. +which it applies should also have been internationalized and distributed +as such by its maintainer. There might be an observable lag between the +mere existence a PO file and its wide availability in a distribution. - If June 2010 seems to be old, you may fetch a more recent copy of -this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date -matrix with full percentage details can be found at -`http://translationproject.org/extra/matrix.html'. + If Jun 2014 seems to be old, you may fetch a more recent copy of this +'ABOUT-NLS' file on most GNU archive sites. The most up-to-date matrix +with full percentage details can be found at +'http://translationproject.org/extra/matrix.html'. -1.5 Using `gettext' in new packages +1.5 Using 'gettext' in new packages =================================== If you are writing a freely available program and want to -internationalize it you are welcome to use GNU `gettext' in your -package. Of course you have to respect the GNU Library General Public -License which covers the use of the GNU `gettext' library. This means -in particular that even non-free programs can use `libintl' as a shared -library, whereas only free software can use `libintl' as a static -library or use modified versions of `libintl'. +internationalize it you are welcome to use GNU 'gettext' in your +package. Of course you have to respect the GNU Lesser General Public +License which covers the use of the GNU 'gettext' library. This means +in particular that even non-free programs can use 'libintl' as a shared +library, whereas only free software can use 'libintl' as a static +library or use modified versions of 'libintl'. Once the sources are changed appropriately and the setup can handle -the use of `gettext' the only thing missing are the translations. The +the use of 'gettext' the only thing missing are the translations. The Free Translation Project is also available for packages which are not developed inside the GNU project. Therefore the information given above applies also for every other Free Software Project. Contact -`coordinator@translationproject.org' to make the `.pot' files available +'coordinator@translationproject.org' to make the '.pot' files available to the translation teams. - diff --git a/po/ChangeLog b/po/ChangeLog index 55e4e4dd..000012d2 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,8 @@ +2018-01-07 gettextize + + * Makefile.in.in: Upgrade to gettext-0.19.8.1. + * Rules-quot: Upgrade to gettext-0.19.8.1. + 2014-06-08 gettextize * Makefile.in.in: New file, from gettext-0.18.3. diff --git a/po/Makefile.in.in b/po/Makefile.in.in index fabdc76c..38c293d2 100644 --- a/po/Makefile.in.in +++ b/po/Makefile.in.in @@ -1,15 +1,13 @@ # Makefile for PO directory in any package using GNU gettext. # Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper # -# This file can be copied and used freely without restrictions. It can -# be used in projects which are not available under the GNU General Public -# License but which still want to provide support for the GNU gettext -# functionality. -# Please note that the actual code of GNU gettext is covered by the GNU -# General Public License and is *not* in the public domain. +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. This file is offered as-is, +# without any warranty. # -# Origin: gettext-0.18.3 -GETTEXT_MACRO_VERSION = 0.18 +# Origin: gettext-0.19.8 +GETTEXT_MACRO_VERSION = 0.19 PACKAGE = @PACKAGE@ VERSION = @VERSION@ @@ -45,6 +43,11 @@ install_sh = $(SHELL) @install_sh@ MKDIR_P = @MKDIR_P@ mkdir_p = @mkdir_p@ +# When building gettext-tools, we prefer to use the built programs +# rather than installed programs. However, we can't do that when we +# are cross compiling. +CROSS_COMPILING = @CROSS_COMPILING@ + GMSGFMT_ = @GMSGFMT@ GMSGFMT_no = @GMSGFMT@ GMSGFMT_yes = @GMSGFMT_015@ @@ -77,6 +80,16 @@ POTFILES = \ CATALOGS = @CATALOGS@ +POFILESDEPS_ = $(srcdir)/$(DOMAIN).pot +POFILESDEPS_yes = $(POFILESDEPS_) +POFILESDEPS_no = +POFILESDEPS = $(POFILESDEPS_$(PO_DEPENDS_ON_POT)) + +DISTFILESDEPS_ = update-po +DISTFILESDEPS_yes = $(DISTFILESDEPS_) +DISTFILESDEPS_no = +DISTFILESDEPS = $(DISTFILESDEPS_$(DIST_DEPENDS_ON_UPDATE_PO)) + # Makevars gets inserted here. (Don't remove this line!) .SUFFIXES: @@ -143,15 +156,25 @@ stamp-po: $(srcdir)/$(DOMAIN).pot # heuristic whether some file in the top level directory mentions "GNU xyz". # If GNU 'find' is available, we avoid grepping through monster files. $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed - if { if (LC_ALL=C find --version) 2>/dev/null | grep GNU >/dev/null; then \ - LC_ALL=C find -L $(top_srcdir) -maxdepth 1 -type f -size -10000000c -exec grep 'GNU @PACKAGE@' /dev/null '{}' ';' 2>/dev/null; \ - else \ - LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null; \ - fi; \ - } | grep -v 'libtool:' >/dev/null; then \ - package_gnu='GNU '; \ + package_gnu="$(PACKAGE_GNU)"; \ + test -n "$$package_gnu" || { \ + if { if (LC_ALL=C find --version) 2>/dev/null | grep GNU >/dev/null; then \ + LC_ALL=C find -L $(top_srcdir) -maxdepth 1 -type f \ + -size -10000000c -exec grep 'GNU @PACKAGE@' \ + /dev/null '{}' ';' 2>/dev/null; \ + else \ + LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null; \ + fi; \ + } | grep -v 'libtool:' >/dev/null; then \ + package_gnu=yes; \ + else \ + package_gnu=no; \ + fi; \ + }; \ + if test "$$package_gnu" = "yes"; then \ + package_prefix='GNU '; \ else \ - package_gnu=''; \ + package_prefix=''; \ fi; \ if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \ msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \ @@ -171,12 +194,17 @@ $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ --files-from=$(srcdir)/POTFILES.in \ --copyright-holder='$(COPYRIGHT_HOLDER)' \ - --package-name="$${package_gnu}@PACKAGE@" \ + --package-name="$${package_prefix}@PACKAGE@" \ --package-version='@VERSION@' \ --msgid-bugs-address="$$msgid_bugs_address" \ ;; \ esac test ! -f $(DOMAIN).po || { \ + if test -f $(srcdir)/$(DOMAIN).pot-header; then \ + sed -e '1,/^#$$/d' < $(DOMAIN).po > $(DOMAIN).1po && \ + cat $(srcdir)/$(DOMAIN).pot-header $(DOMAIN).1po > $(DOMAIN).po; \ + rm -f $(DOMAIN).1po; \ + fi; \ if test -f $(srcdir)/$(DOMAIN).pot; then \ sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ @@ -199,13 +227,14 @@ $(srcdir)/$(DOMAIN).pot: # This target rebuilds a PO file if $(DOMAIN).pot has changed. # Note that a PO file is not touched if it doesn't need to be changed. -$(POFILES): $(srcdir)/$(DOMAIN).pot +$(POFILES): $(POFILESDEPS) @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ if test -f "$(srcdir)/$${lang}.po"; then \ + test -f $(srcdir)/$(DOMAIN).pot || $(MAKE) $(srcdir)/$(DOMAIN).pot; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot"; \ cd $(srcdir) \ - && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + && { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \ *) \ @@ -362,7 +391,7 @@ maintainer-clean: distclean distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) dist distdir: - $(MAKE) update-po + test -z "$(DISTFILESDEPS)" || $(MAKE) $(DISTFILESDEPS) @$(MAKE) dist2 # This is a separate target because 'update-po' must be executed before. dist2: stamp-po $(DISTFILES) @@ -406,7 +435,7 @@ update-po: Makefile .nop.po-update: @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ - if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \ + if test "$(PACKAGE)" = "gettext-tools" && test "$(CROSS_COMPILING)" != "yes"; then PATH=`pwd`/../src:$$PATH; fi; \ tmpdir=`pwd`; \ echo "$$lang:"; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ diff --git a/po/Makevars.template b/po/Makevars.template new file mode 100644 index 00000000..0648ec75 --- /dev/null +++ b/po/Makevars.template @@ -0,0 +1,78 @@ +# Makefile variables for PO directory in any package using GNU gettext. + +# Usually the message domain is the same as the package name. +DOMAIN = $(PACKAGE) + +# These two variables depend on the location of this directory. +subdir = po +top_builddir = .. + +# These options get passed to xgettext. +XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ + +# This is the copyright holder that gets inserted into the header of the +# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding +# package. (Note that the msgstr strings, extracted from the package's +# sources, belong to the copyright holder of the package.) Translators are +# expected to transfer the copyright for their translations to this person +# or entity, or to disclaim their copyright. The empty string stands for +# the public domain; in this case the translators are expected to disclaim +# their copyright. +COPYRIGHT_HOLDER = Free Software Foundation, Inc. + +# This tells whether or not to prepend "GNU " prefix to the package +# name that gets inserted into the header of the $(DOMAIN).pot file. +# Possible values are "yes", "no", or empty. If it is empty, try to +# detect it automatically by scanning the files in $(top_srcdir) for +# "GNU packagename" string. +PACKAGE_GNU = + +# This is the email address or URL to which the translators shall report +# bugs in the untranslated strings: +# - Strings which are not entire sentences, see the maintainer guidelines +# in the GNU gettext documentation, section 'Preparing Strings'. +# - Strings which use unclear terms or require additional context to be +# understood. +# - Strings which make invalid assumptions about notation of date, time or +# money. +# - Pluralisation problems. +# - Incorrect English spelling. +# - Incorrect formatting. +# It can be your email address, or a mailing list address where translators +# can write to without being subscribed, or the URL of a web page through +# which the translators can contact you. +MSGID_BUGS_ADDRESS = + +# This is the list of locale categories, beyond LC_MESSAGES, for which the +# message catalogs shall be used. It is usually empty. +EXTRA_LOCALE_CATEGORIES = + +# This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt' +# context. Possible values are "yes" and "no". Set this to yes if the +# package uses functions taking also a message context, like pgettext(), or +# if in $(XGETTEXT_OPTIONS) you define keywords with a context argument. +USE_MSGCTXT = no + +# These options get passed to msgmerge. +# Useful options are in particular: +# --previous to keep previous msgids of translated messages, +# --quiet to reduce the verbosity. +MSGMERGE_OPTIONS = + +# These options get passed to msginit. +# If you want to disable line wrapping when writing PO files, add +# --no-wrap to MSGMERGE_OPTIONS, XGETTEXT_OPTIONS, and +# MSGINIT_OPTIONS. +MSGINIT_OPTIONS = + +# This tells whether or not to regenerate a PO file when $(DOMAIN).pot +# has changed. Possible values are "yes" and "no". Set this to no if +# the POT file is checked in the repository and the version control +# program ignores timestamps. +PO_DEPENDS_ON_POT = yes + +# This tells whether or not to forcibly update $(DOMAIN).pot and +# regenerate PO files on "make dist". Possible values are "yes" and +# "no". Set this to no if the POT file and PO files are maintained +# externally. +DIST_DEPENDS_ON_UPDATE_PO = yes diff --git a/po/Rules-quot b/po/Rules-quot index 5931e539..baf65285 100644 --- a/po/Rules-quot +++ b/po/Rules-quot @@ -1,3 +1,4 @@ +# This file, Rules-quot, can be copied and used freely without restrictions. # Special Makefile rules for English message catalogs with quotation marks. DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot @@ -14,13 +15,23 @@ en@boldquot.po-update: en@boldquot.po-update-en .insert-header.po-update-en: @lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \ - if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \ + if test "$(PACKAGE)" = "gettext-tools" && test "$(CROSS_COMPILING)" != "yes"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \ tmpdir=`pwd`; \ echo "$$lang:"; \ ll=`echo $$lang | sed -e 's/@.*//'`; \ LC_ALL=C; export LC_ALL; \ cd $(srcdir); \ - if $(MSGINIT) -i $(DOMAIN).pot --no-translator -l $$lang -o - 2>/dev/null | sed -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | $(MSGFILTER) $(SED) -f `echo $$lang | sed -e 's/.*@//'`.sed 2>/dev/null > $$tmpdir/$$lang.new.po; then \ + if $(MSGINIT) $(MSGINIT_OPTIONS) -i $(DOMAIN).pot --no-translator -l $$lang -o - 2>/dev/null \ + | $(SED) -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | \ + { case `$(MSGFILTER) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-8] | 0.1[0-8].*) \ + $(MSGFILTER) $(SED) -f `echo $$lang | sed -e 's/.*@//'`.sed \ + ;; \ + *) \ + $(MSGFILTER) `echo $$lang | sed -e 's/.*@//'` \ + ;; \ + esac } 2>/dev/null > $$tmpdir/$$lang.new.po \ + ; then \ if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ From f17180adb8ec2f8f0f08c98a353c5ff52a92a7d0 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 14 Jan 2018 13:56:34 +0100 Subject: [PATCH 114/210] allow to include configure.library as well as Makefile.am into other projects --- Makefile.am | 17 ++- configure.ac | 250 +------------------------------------- configure.library | 300 ++++++++++++++++++++++++++++++++++++++++++++++ tests/Makefile.am | 141 ++++++++++++++-------- 4 files changed, 403 insertions(+), 305 deletions(-) create mode 100644 configure.library diff --git a/Makefile.am b/Makefile.am index 141ea74d..b1c4da70 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,8 +1,15 @@ -SUBDIRS = po . tests -lib_LTLIBRARIES = %D%/librtmidi.la -%C%_librtmidi_la_LDFLAGS = -no-undefined -%C%_librtmidi_la_SOURCES = \ +SUBDIRS += %D%/po +RTMIDITESTCXXFLAGS += -I$(top_srcdir)/%D% +RTMIDITESTLDFLAGS += -L%D% -lrtmidi-ts +lib_LTLIBRARIES += %D%/librtmidi-ts.la +%C%_librtmidi_ts_la_LDFLAGS = -no-undefined $(RTMIDI__TS_LIBS) +%C%_librtmidi_ts_la_CXXFLAGS = $(CXXFLAGS) $(CPPFLAGS) $(RTMIDI_TS_API) +%C%_librtmidi_ts_la_SOURCES = \ %D%/RtMidi.cpp \ %D%/RtMidi.h -EXTRA_DIST = config/config.rpath m4/ChangeLog +EXTRA_DIST += config/config.rpath m4/ChangeLog + +include %D%/tests/Makefile.am + + diff --git a/configure.ac b/configure.ac index 78f679f1..56b2b4e2 100644 --- a/configure.ac +++ b/configure.ac @@ -6,257 +6,9 @@ AC_CONFIG_SRCDIR(RtMidi.cpp) AC_CONFIG_FILES([rtmidi-config librtmidi.pc Makefile tests/Makefile po/Makefile.in]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) -# Fill GXX with something before test. -AC_SUBST( GXX, ["no"] ) -AC_SUBST(noinst_LIBRARIES) - -# Checks for programs. -AC_PROG_CXX(g++ CC c++ cxx) -AM_PROG_AR -AC_PATH_PROG(AR, ar, no) -if [[ $AR = "no" ]] ; then - AC_MSG_ERROR("Could not find ar - needed to create a library"); -fi - -LT_INIT([win32-dll]) AC_CONFIG_MACRO_DIR([m4]) -# Checks for header files. -AC_HEADER_STDC -#AC_CHECK_HEADERS(sys/ioctl.h unistd.h) - -# Check for debug -AC_MSG_CHECKING(whether to compile debug version) -AC_ARG_ENABLE(debug, - [ --enable-debug = enable various debug output], - [AC_SUBST( cppflag, [-D__RTMIDI_DEBUG__] ) AC_SUBST( cxxflag, [-g] ) AC_SUBST( object_path, [Debug] ) AC_MSG_RESULT(yes)], - [AC_SUBST( cppflag, [] ) AC_SUBST( cxxflag, [-O3] ) AC_SUBST( object_path, [Release] ) AC_MSG_RESULT(no)]) - -# Set paths if prefix is defined -if test "x$prefix" != "x" && test "x$prefix" != "xNONE"; then - LIBS="$LIBS -L$prefix/lib" - CPPFLAGS="$CPPFLAGS -I$prefix/include" -fi - -# For -I and -D flags -CPPFLAGS="$CPPFLAGS $cppflag" - -# For debugging and optimization ... overwrite default because it has both -g and -O2 -#CXXFLAGS="$CXXFLAGS $cxxflag" -CXXFLAGS="$cxxflag" - -# Check compiler and use -Wall if gnu. -if [test $GXX = "yes" ;] then - AC_SUBST( cxxflag, ["-Wall -Wextra"] ) -fi - -CXXFLAGS="$CXXFLAGS $cxxflag" - -AC_ARG_ENABLE(address-sanitizer, - AS_HELP_STRING([--enable-address-sanitizer],[Enable gcc/clang address santizer]), - [AS_IF(test "$enableval" = yes, - - AC_LANG_PUSH(C++) - for flag in -fsanitize=address -fno-omit-frame-pointer -fno-common - do - tmpcxxflags="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $flag" - AC_MSG_CHECKING([whether $CXX supports $flag]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], - [AC_MSG_RESULT([yes])], - [CXXFLAGS="$tmpcxxflags" - AC_MSG_RESULT([no])]) - AC_LANG_PUSH(C) - tmpcflags="$CFLAGS" - CFLAGS="$CFLAGS $flag" - AC_MSG_CHECKING([whether $CC supports $flag]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], - [AC_MSG_RESULT([yes])], - [CFLAGS="$tmpcflags" - AC_MSG_RESULT([no])]) - AC_LANG_POP(C) - done - AC_LANG_POP(C++) - ) - ] -) - -AC_ARG_ENABLE(thread-sanitizer, - AS_HELP_STRING([--enable-thread-sanitizer],[Enable gcc/clang thread santizer]), - [AS_IF(test "$enableval" = yes, - AC_LANG_PUSH(C++) - for flag in -fsanitize=thread -fno-omit-frame-pointer -fno-common -fPIC - do - tmpcxxflags="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $flag" - AC_MSG_CHECKING([whether $CXX supports $flag]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], - [AC_MSG_RESULT([yes])], - [CXXFLAGS="$tmpcxxflags" - AC_MSG_RESULT([no])]) - AC_LANG_PUSH(C) - tmpcflags="$CFLAGS" - CFLAGS="$CFLAGS $flag" - AC_MSG_CHECKING([whether $CC supports $flag]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], - [AC_MSG_RESULT([yes])], - [CFLAGS="$tmpcflags" - AC_MSG_RESULT([no])]) - AC_LANG_POP(C) - done - for flag in -pie - do - tmpldflags="$LDFLAGS" - LDFLAGS="$LDFLAGS $flag" - AC_MSG_CHECKING([whether $LD supports $flag]) - AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])], - [AC_MSG_RESULT([yes])], - [LDFLAGS="$tmpldflags" - AC_MSG_RESULT([no])]) - done - AC_LANG_POP(C++) - ) - ] -) - - -# Checks for package options and external software -AC_CANONICAL_HOST - -AC_SUBST( sharedlib, ["librtmidi.so"] ) -AC_SUBST( sharedname, ["librtmidi.so.\$(RELEASE)"] ) -AC_SUBST( libflags, ["-shared -Wl,-soname,\$(SHARED).\$(MAJOR) -o \$(SHARED).\$(RELEASE)"] ) -case $host in - *-apple*) - AC_SUBST( sharedlib, ["librtmidi.dylib"] ) - AC_SUBST( sharedname, ["librtmidi.\$(RELEASE).dylib"] ) - AC_SUBST( libflags, ["-dynamiclib -o librtmidi.\$(RELEASE).dylib"] ) -esac - -AC_SUBST( api, [""] ) -AC_SUBST( req, [""] ) -AC_MSG_CHECKING(for MIDI API) -have_virtual_devices=no -case $host in - *-*-linux*) - AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (mac and linux only)], [ - have_virtual_devices=yes - api="$api -D__UNIX_JACK__" - AC_MSG_RESULT(using JACK) - AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], ) - AC_LANG_PUSH(C++) - AC_TRY_COMPILE([ -#include - ],[ -return jack_port_uuid(NULL); - ],api="$api -D__UNIX_JACK_HAS_UUID__") - AC_LANG_POP(C++) - - # Look for ALSA flag - AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA sequencer API support (linux only)], [ - have_virtual_devices=yes - api="$api -D__LINUX_ALSA__" - req="$req alsa" - AC_MSG_RESULT(using ALSA) - AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(ALSA support requires the asound library!))], ) - - if [test "$api" == "";] then - AC_MSG_RESULT(using ALSA) - AC_SUBST( api, [-D__LINUX_ALSA__] ) - req="$req alsa" - have_virtual_devices=yes - AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(ALSA sequencer support requires the asound library!)) - fi - - # Checks for pthread library. - AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtMidi requires the pthread library!)) - ;; - - *-apple*) - AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (mac and linux only)], [ - have_virtual_devices=yes - api="$api -D__UNIX_JACK__" - AC_MSG_RESULT(using JACK) - AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], ) - AC_LANG_PUSH(C++) - AC_TRY_COMPILE([ -#include - ],[ -return jack_port_uuid(NULL); - ],api="$api -D__UNIX_JACK_HAS_UUID__") - AC_LANG_POP(C++) - - # Look for Core flag - AC_ARG_WITH(core, [ --with-core = choose CoreMidi API support (mac only)], [ - have_virtual_devices=yes - api="$api -D__MACOSX_CORE__" - AC_MSG_RESULT(using CoreMidi) - AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, [], [AC_MSG_ERROR(CoreMIDI header files not found!)] ) - LIBS="$LIBS -framework CoreMIDI -framework CoreFoundation -framework CoreAudio" ], ) - - # If no api flags specified, use CoreMidi - if [test "$api" == ""; ] then - have_virtual_devices=yes - AC_SUBST( api, [-D__MACOSX_CORE__] ) - AC_MSG_RESULT(using CoreMidi) - AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, - [], - [AC_MSG_ERROR(CoreMIDI header files not found!)] ) - AC_SUBST( LIBS, ["-framework CoreMIDI -framework CoreFoundation -framework CoreAudio"] ) - fi - ;; - - *-mingw32*) - # Look for WinMM flag - AC_ARG_WITH(winmm, [ --with-winmm = choose Windows MultiMedia (MM) API support (windoze only)], [ - api="$api -D__WINDOWS_MM__" - AC_MSG_RESULT(using WinMM) - AC_SUBST( LIBS, [-lwinmm] )], ) - - AC_ARG_WITH(winks, [ --with-winks = choose kernel streaming support (windoze only)], [ - api="$api -D__WINDOWS_KS__" - AC_SUBST( LIBS, ["-lsetupapi -lksuser"] ) - AC_MSG_RESULT(using kernel streaming) ], ) - - # I can't get the following check to work so just manually add the library - # or could try the following? AC_LIB_WINMM([midiOutGetNumDevs]) - # AC_CHECK_LIB(winmm, midiInGetNumDevs, , AC_MSG_ERROR(Windows MIDI support requires the winmm library!) )],) - - # If no api flags specified, use WinMM - if [test "$api" == "";] then - AC_SUBST( api, [-D__WINDOWS_MM__] ) - AC_MSG_RESULT(using WinMM) - AC_SUBST( LIBS, [-lwinmm] ) - fi - - AC_CACHE_CHECK([where to find support dlls], [ac_cv_mingw_dll_dirs], - [ - gccsearchdirs=`$CXX $CXXFLAGS -print-search-dirs|\ - sed -e '/^libraries:/ { s/^libraries: *=\?//;s/:/ /g; p } ; d'` - SEARCHDIRS="" - for d in $gccsearchdirs /usr/share/doc/mingw32-runtime /mingw/lib /mingw/bin /usr/lib /lib /usr/bin /bin - do - AS_IF(test -d $d, - [ SEARCHDIRS="$SEARCHDIRS $d" ]) - done - ac_cv_mingw_dll_dirs="$SEARCHDIRS" - ]) - - AC_SUBST(DLLSEARCHPATH,"$ac_cv_mingw_dll_dirs") - - ;; - - *) - # Default case for unknown realtime systems. - AC_MSG_ERROR(Unknown system type for MIDI support!) - ;; -esac -AM_CONDITIONAL(COPYDLLS,test -n "$DLLSEARCHPATH") -AM_CONDITIONAL(HAVE_VIRTUAL_DEVICES,test "$have_virtual_devices" == yes) -AM_GNU_GETTEXT([external]) -AM_GNU_GETTEXT_VERSION([0.18]) - -CPPFLAGS="$CPPFLAGS $api" +m4_include(configure.library) AC_OUTPUT diff --git a/configure.library b/configure.library new file mode 100644 index 00000000..254b1b72 --- /dev/null +++ b/configure.library @@ -0,0 +1,300 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + + +# initialize the variables for the makefile +AC_SUBST(noinst_LIBRARIES) +AC_SUBST(noinst_PROGRAMS) +AC_SUBST(TESTS) +AC_SUBST(SUBDIRS) +AC_SUBST(lib_LTLIBRARIES) +AC_SUBST(EXTRA_DIST) +AC_SUBST(RTMIDI_TS_SUFFIX,[ts]) + +# Checks for programs. +AC_PROG_CXX +dnl AM_PROG_AR +dnl AC_PATH_PROG(AR, ar, no) +dnl if [[ $AR = "no" ]] ; then +dnl AC_MSG_ERROR("Could not find ar - needed to create a library"); +dnl fi + +LT_INIT([win32-dll]) + +# Checks for header files. +AC_HEADER_STDC +#AC_CHECK_HEADERS(sys/ioctl.h unistd.h) + +# Check for debug +AC_MSG_CHECKING(whether to compile debug version) +AC_ARG_ENABLE(debug, + [ --enable-debug = enable various debug output], + [ + AC_SUBST( RTMIDI_CPPFLAGS, [-D__RTMIDI_DEBUG__] ) + AC_SUBST( RTMIDI_CXXFLAGS, [-g] ) + AC_MSG_RESULT(yes)], + [AC_SUBST( RTMIDI_CPPFLAGS, [] ) + AC_SUBST( RTMIDI_CXXFLAGS, [-O3] ) + AC_MSG_RESULT(no)]) + +dnl # Set paths if prefix is defined +dnl if test "x$prefix" != "x" && test "x$prefix" != "xNONE"; then +dnl LIBS="$LIBS -L$prefix/lib" +dnl CPPFLAGS="$CPPFLAGS -I$prefix/include" +dnl fi + +# Check compiler and use -Wall if supported. +for flag in -Wall -Wextra +do + tmpcxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $flag" + AC_MSG_CHECKING([whether $CXX supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CXXFLAGS="$tmpcxxflags" + AC_MSG_RESULT([no])]) + AC_LANG_PUSH(C) + tmpcflags="$CFLAGS" + CFLAGS="$CFLAGS $flag" + AC_MSG_CHECKING([whether $CC supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CFLAGS="$tmpcflags" + AC_MSG_RESULT([no])]) + AC_LANG_POP(C) +done +dnl mudflap is not possible with g++ 4.7.1 and wxWidgets 2.8 +dnl tmpcxxflags="$CXXFLAGS" +dnl tmplibs="$LIBS" +dnl CXXFLAGS="$CXXFLAGS -fmudflapth" +dnl LIBS="-lmudflapth" +dnl AC_MSG_CHECKING([whether $CXX supports -fmudflapth -lmudflapth]) +dnl AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], +dnl [AC_MSG_RESULT([yes])], +dnl [CXXFLAGS="$tmpcxxflags" +dnl LIBS="$tmplibs"] +dnl [AC_MSG_RESULT([no])]) +dnl + +AC_ARG_ENABLE(address-sanitizer, + AS_HELP_STRING([--enable-address-sanitizer],[Enable gcc/clang address santizer]), + [AS_IF(test "$enableval" = yes, + + AC_LANG_PUSH(C++) + for flag in -fsanitize=address -fno-omit-frame-pointer -fno-common + do + tmpcxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $flag" + AC_MSG_CHECKING([whether $CXX supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CXXFLAGS="$tmpcxxflags" + AC_MSG_RESULT([no])]) + AC_LANG_PUSH(C) + tmpcflags="$CFLAGS" + CFLAGS="$CFLAGS $flag" + AC_MSG_CHECKING([whether $CC supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CFLAGS="$tmpcflags" + AC_MSG_RESULT([no])]) + AC_LANG_POP(C) + done + AC_LANG_POP(C++) + ) + ] +) + +AC_ARG_ENABLE(thread-sanitizer, + AS_HELP_STRING([--enable-thread-sanitizer],[Enable gcc/clang thread santizer]), + [AS_IF(test "$enableval" = yes, + AC_LANG_PUSH(C++) + for flag in -fsanitize=thread -fno-omit-frame-pointer -fno-common -fPIC + do + tmpcxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $flag" + AC_MSG_CHECKING([whether $CXX supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CXXFLAGS="$tmpcxxflags" + AC_MSG_RESULT([no])]) + AC_LANG_PUSH(C) + tmpcflags="$CFLAGS" + CFLAGS="$CFLAGS $flag" + AC_MSG_CHECKING([whether $CC supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CFLAGS="$tmpcflags" + AC_MSG_RESULT([no])]) + AC_LANG_POP(C) + done + for flag in -pie + do + tmpldflags="$LDFLAGS" + LDFLAGS="$LDFLAGS $flag" + AC_MSG_CHECKING([whether $LD supports $flag]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [LDFLAGS="$tmpldflags" + AC_MSG_RESULT([no])]) + done + AC_LANG_POP(C++) + ) + ] +) + +dnl AC_SUBST( sharedlib, ["librtmidi.so"] ) +dnl AC_SUBST( sharedname, ["librtmidi.so.\$(RELEASE)"] ) +dnl AC_SUBST( libflags, ["-shared -Wl,-soname,\$(SHARED).\$(MAJOR) -o \$(SHARED).\$(RELEASE)"] ) +dnl case $host in +dnl *-apple*) +dnl AC_SUBST( sharedlib, ["librtmidi.dylib"] ) +dnl AC_SUBST( sharedname, ["librtmidi.\$(RELEASE).dylib"] ) +dnl AC_SUBST( libflags, ["-dynamiclib -o librtmidi.\$(RELEASE).dylib"] ) +dnl esac + +AC_SUBST( RTMIDI_TS_API, [""] ) +AC_SUBST( req, [""] ) +AC_MSG_CHECKING(for MIDI API) +have_virtual_devices=no +case $host in + *-*-linux*) + AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (mac and linux only)], [ + have_virtual_devices=yes + RTMIDI_TS_API="$RTMIDI_TS_API -D__UNIX_JACK__" + AC_MSG_RESULT(using JACK) + AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], ) + AC_LANG_PUSH(C++) + AC_TRY_COMPILE([ +#include + ],[ +return jack_port_uuid(NULL); + ],RTMIDI_TS_API="$RTMIDI_TS_API -D__UNIX_JACK_HAS_UUID__") + AC_LANG_POP(C++) + + # Look for ALSA flag + AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA sequencer API support (linux only)], [ + have_virtual_devices=yes + RTMIDI_TS_API="$RTMIDI_TS_API -D__LINUX_ALSA__" + req="$req alsa" + AC_MSG_RESULT(using ALSA) + AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(ALSA support requires the asound library!))], ) + + if [test "$RTMIDI_TS_API" == "";] then + AC_MSG_RESULT(using ALSA) + AC_SUBST( RTMIDI_TS_API, [-D__LINUX_ALSA__] ) + req="$req alsa" + have_virtual_devices=yes + AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(ALSA sequencer support requires the asound library!)) + fi + + # Checks for pthread library. + AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtMidi requires the pthread library!)) + ;; + + *-apple*) + AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (mac and linux only)], [ + have_virtual_devices=yes + RTMIDI_TS_API="$RTMIDI_TS_API -D__UNIX_JACK__" + AC_MSG_RESULT(using JACK) + AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], ) + AC_LANG_PUSH(C++) + AC_TRY_COMPILE([ +#include + ],[ +return jack_port_uuid(NULL); + ],RTMIDI_TS_API="$RTMIDI_TS_API -D__UNIX_JACK_HAS_UUID__") + AC_LANG_POP(C++) + + # Look for Core flag + AC_ARG_WITH(core, [ --with-core = choose CoreMidi API support (mac only)], [ + have_virtual_devices=yes + RTMIDI_TS_API="$RTMIDI_TS_API -D__MACOSX_CORE__" + AC_MSG_RESULT(using CoreMidi) + AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, [], [AC_MSG_ERROR(CoreMIDI header files not found!)] ) + RTMIDI_TS_LIBS="$RTMIDI_TS_LIBS -framework CoreMIDI -framework CoreFoundation -framework CoreAudio" ], ) + + # If no api flags specified, use CoreMidi + if [test "$RTMIDI_TS_API" == ""; ] then + have_virtual_devices=yes + AC_SUBST( RTMIDI_TS_API, [-D__MACOSX_CORE__] ) + AC_MSG_RESULT(using CoreMidi) + AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, + [], + [AC_MSG_ERROR(CoreMIDI header files not found!)] ) + AC_SUBST( RTMIDI_TS_LIBS, ["-framework CoreMIDI -framework CoreFoundation -framework CoreAudio"] ) + fi + ;; + + *-mingw32*) + + # Look for WinMM flag + AC_ARG_WITH(winmm, [ --with-winmm = choose Windows MultiMedia (MM) API support (windoze only)], [ + RTMIDI_TS_API="$RTMIDI_TS_API -D__WINDOWS_MM__" + AC_MSG_RESULT(using WinMM) + AC_SUBST( RTMIDI_TS_LIBS, [-lwinmm] )], ) + + AC_ARG_WITH(winks, [ --with-winks = choose kernel streaming support (windoze only)], [ + api="$RTMIDI_TS_API -D__WINDOWS_KS__" + AC_SUBST( RTMIDI_TS_LIBS, ["-lsetupapi -lksuser"] ) + AC_MSG_RESULT(using kernel streaming) ], ) + + # I can't get the following check to work so just manually add the library + # or could try the following? AC_LIB_WINMM([midiOutGetNumDevs]) + # AC_CHECK_LIB(winmm, midiInGetNumDevs, , AC_MSG_ERROR(Windows MIDI support requires the winmm library!) )],) + + # If no RTMIDI_TS_API flags specified, use WinMM + if [test "$RTMIDI_TS_API" == "";] then + AC_SUBST( RTMIDI_TS_API, [-D__WINDOWS_MM__] ) + AC_MSG_RESULT(using WinMM) + AC_SUBST( RTMIDI_TS_LIBS, [-lwinmm] ) + fi + + AC_CACHE_CHECK([where to find support dlls], [ac_cv_rtmidi_ts_mingw_dll_dirs], + [ + gccsearchdirs=`$CXX $CXXFLAGS -print-search-dirs|\ + sed -e '/^libraries:/ { s/^libraries: *=\?//;s/:/ /g; p } ; d'` + SEARCHDIRS="$DLLSEARCHPATH" + for d in \ + $gccsearchdirs \ + /usr/share/doc/mingw32-runtime \ + /usr/$host/bin \ + /usr/$host/lib \ + /usr/bin/$host/ \ + /usr/lib/$host/ \ + /usr/lib/$host/lib \ + /usr/lib/$host/bin \ + /usr/bin/$host/lib \ + /usr/bin/$host/bin \ + /mingw/lib \ + /mingw/bin \ + /usr/lib \ + /lib \ + /usr/bin \ + /bin + do + AS_IF(test -d $d, + [ SEARCHDIRS="$SEARCHDIRS $d" ]) + done + ac_cv_rtmidi_ts_mingw_dll_dirs="$SEARCHDIRS" + ]) + + AC_SUBST(DLLSEARCHPATH,"$ac_cv_rtmidi_ts_mingw_dll_dirs") + + ;; + + *) + # Default case for unknown realtime systems. + AC_MSG_ERROR(Unknown system type for MIDI support!) + ;; +esac +AM_CONDITIONAL(HAVE_VIRTUAL_DEVICES,test "$have_virtual_devices" == yes) +AM_GNU_GETTEXT([external]) +AM_GNU_GETTEXT_VERSION([0.19.8]) + +if test "x$rtmidicopydlls" = "x" +then + rtmidicopydlls=false +fi + +AM_CONDITIONAL(RTMIDICOPYDLLS,$rtmidicopydlls && test -n "$DLLSEARCHPATH") diff --git a/tests/Makefile.am b/tests/Makefile.am index 048563c5..efbd90e1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,63 +1,83 @@ ### RtMidi tests Makefile - for various flavors of unix -AM_CPPFLAGS = -I$(top_srcdir) -LDADD = -L$(top_builddir) -lrtmidi @LIBS@ - -noinst_PROGRAMS = \ - midiprobe \ - midiout \ - qmidiin \ - cmidiin \ - sysextest \ - midiprobe2 \ - midiprobe-all \ - cmidiin2 \ - qmidiin2 \ - midiout2 \ - loopback \ - errors - -TESTS = \ - midiprobe \ - midiprobe2 \ - midiprobe-all \ - errors +#RTMIDITESTCXXFLAGS += -I$(top_srcdir)/%D% +#RTMIDITESTLDFLAGS += -L$(top_builddir)/%D% -lrtmidi-ts @LIBS@ + +noinst_PROGRAMS += \ + %D%/midiprobe \ + %D%/midiout \ + %D%/qmidiin \ + %D%/cmidiin \ + %D%/sysextest \ + %D%/midiprobe2 \ + %D%/midiprobe-all \ + %D%/cmidiin2 \ + %D%/qmidiin2 \ + %D%/midiout2 \ + %D%/loopback \ + %D%/errors + +TESTS += \ + %D%/midiprobe \ + %D%/midiprobe2 \ + %D%/midiprobe-all \ + %D%/errors if HAVE_VIRTUAL_DEVICES -TESTS += loopback +TESTS += %D%/loopback endif -midiprobe_SOURCES = midiprobe.cpp -midiout_SOURCES = midiout.cpp -qmidiin_SOURCES = qmidiin.cpp -cmidiin_SOURCES = cmidiin.cpp -sysextest_SOURCES = sysextest.cpp -midiprobe2_SOURCES = midiprobe2.cpp -midiprobe_all_SOURCES = midiprobe-all.cpp -cmidiin2_SOURCES = cmidiin2.cpp -qmidiin2_SOURCES = qmidiin2.cpp -midiout2_SOURCES = midiout2.cpp -loopback_SOURCES = loopback.cpp -errors_SOURCES = errors.cpp +%C%_midiprobe_SOURCES = %D%/midiprobe.cpp +%C%_midiout_SOURCES = %D%/midiout.cpp +%C%_qmidiin_SOURCES = %D%/qmidiin.cpp +%C%_cmidiin_SOURCES = %D%/cmidiin.cpp +%C%_sysextest_SOURCES = %D%/sysextest.cpp +%C%_midiprobe2_SOURCES = %D%/midiprobe2.cpp +%C%_midiprobe_all_SOURCES = %D%/midiprobe-all.cpp +%C%_cmidiin2_SOURCES = %D%/cmidiin2.cpp +%C%_qmidiin2_SOURCES = %D%/qmidiin2.cpp +%C%_midiout2_SOURCES = %D%/midiout2.cpp +%C%_loopback_SOURCES = %D%/loopback.cpp +%C%_errors_SOURCES = %D%/errors.cpp -if COPYDLLS -check-am: check-dll +# When a nonstandard gettext library or wrapper is used, +# we need extra flags. +%C%_midiprobe_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) +%C%_midiout_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) +%C%_qmidiin_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) +%C%_cmidiin_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) +%C%_sysextest_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) +%C%_midiprobe2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) +%C%_midiprobe_all_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) +%C%_cmidiin2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) +%C%_qmidiin2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) +%C%_midiout2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) +%C%_loopback_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) +%C%_errors_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -check-dll: all-am - $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) - $(MAKE) $(AM_MAKEFLAGS) linkchecks +%C%_midiprobe_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_midiout_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_qmidiin_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_cmidiin_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_sysextest_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_midiprobe2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_midiprobe_all_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_cmidiin2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_qmidiin2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_midiout2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_loopback_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_errors_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -linkchecks: - for d in `echo $(TESTS)| tr ' ' '\n' | grep -i -e '$(EXEEXT)$$'` ; \ - do \ - ls -l "$$d" ; \ - $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$d" DLLEXEDIR="." installdll ; \ - test -f ".libs/$$d" && \ - $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE=".libs/$$d" DLLEXEDIR="." installdll ; \ - done -installdll: +if RTMIDICOPYDLLS + +#------------------------------------------------------------------------------------- +# Installing DLLs +#------------------------------------------------------------------------------------- + + +rtmidi_installdll: @echo 'solving references for $(DLLLINKFILE)... ' DLLSEARCHPATH="$(DLLSEARCHPATH)" ; \ for d in `LANG=C $(OBJDUMP) -p $(DLLEXEDIR)/$(DLLLINKFILE) |sed '/^\s*DLL Name:.*\(lib\|thread\|wx\|mingw\|gcc\|stdc++\)/ { s/^\s*DLL Name:\s*//; p } ; d '` ; \ @@ -74,7 +94,7 @@ installdll: case "$$f" in \ *.gz) GZIP=$(GZIP_ENV) gzip -dc $(DLLEXEDIR)/`basename "$$f"` >$(DLLEXEDIR)/"$$d" ;; \ esac ; \ - $(MAKE) DLLLINKFILE="$$d" DLLEXEDIR="$(DLLEXEDIR)" installdll ; \ + $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$d" DLLEXEDIR="$(DLLEXEDIR)" rtmidi_installdll ; \ else \ echo "not found." ; \ fi ; \ @@ -82,5 +102,24 @@ installdll: echo "done." ;\ done ; -endif +#------------------------------------------------------------------------------------- +# Certain fixed files +#------------------------------------------------------------------------------------- + + +check-am: check-dll + +check-dll: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) linkchecks + +linkchecks: + for d in `echo $(TESTS)| tr ' ' '\n' | grep -i -e '$(EXEEXT)$$'` ; \ + do \ + ls -l "$$d" ; \ + $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$d" DLLEXEDIR="." rtmidi_installdll ; \ + test -f ".libs/$$d" && \ + $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE=".libs/$$d" DLLEXEDIR="." rtmidi_installdll ; \ + done +endif From 7c773cb7f097ad595a6fe0667571d2f444f7b05d Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 14 Jan 2018 13:59:51 +0100 Subject: [PATCH 115/210] Fix Constant names so that they do not clash with windows predefined macros --- RtMidi.cpp | 173 ++++++++++++++++++++-------------------- RtMidi.h | 15 ++-- tests/cmidiin2.cpp | 2 +- tests/midiout2.cpp | 4 +- tests/midiprobe-all.cpp | 16 ++-- tests/midiprobe2.cpp | 16 ++-- tests/qmidiin2.cpp | 10 +-- 7 files changed, 120 insertions(+), 116 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 12cc1e71..d26651ce 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -151,7 +151,7 @@ void Midi :: getCompiledApi( std::vector &apis, bool preferSystem ) thr // DUMMY is a no-backend class so we add it at // the very end. #if defined(__RTMIDI_DUMMY__) - apis.push_back( rtmidi::RTMIDI_DUMMY ); + apis.push_back( rtmidi::DUMMY ); #endif } @@ -250,8 +250,8 @@ MidiIn :: MidiIn( ApiType api, for ( unsigned int i=0; iqueue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; } else { - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother ALSA with an unhandled exception - } + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } } } } @@ -3740,9 +3742,9 @@ NAMESPACE_RTMIDI_END #define RT_SYSEX_BUFFER_COUNT 4 NAMESPACE_RTMIDI_START -/* some header defines UNIQUE_NAME as a macro */ -#ifdef UNIQUE_NAME -#undef UNIQUE_NAME +/* some header defines UNIQUE_PORT_NAME as a macro */ +#ifdef UNIQUE_PORT_NAME +#undef UNIQUE_PORT_NAME #endif /*! An abstraction layer for the ALSA sequencer layer. It provides the following functionality: @@ -3865,14 +3867,14 @@ class WinMMSequencer { if (flags & PortDescriptor::INCLUDE_API) os << "WinMM:"; os << name.c_str(); - if (flags & PortDescriptor::UNIQUE_NAME) + if (flags & PortDescriptor::UNIQUE_PORT_NAME) os << ";" << port; break; case PortDescriptor::LONG_NAME: case PortDescriptor::SHORT_NAME: default: os << name.c_str(); - if (flags & PortDescriptor::UNIQUE_NAME) { + if (flags & PortDescriptor::UNIQUE_PORT_NAME) { os << " "; os << port; } @@ -3943,7 +3945,7 @@ struct WinMMPortDescriptor:public PortDescriptor else return 0; } - std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) { + std::string getName(int flags = SHORT_NAME | UNIQUE_PORT_NAME) { return seq.getPortName(port,is_input,flags); } @@ -4091,18 +4093,18 @@ struct WinMMCallbacks { else if ( status < 0xE0 ) nBytes = 2; else if ( status < 0xF0 ) nBytes = 3; else if ( status == 0xF1 ) { - if ( data->ignoreFlags & 0x02 ) return; - else nBytes = 2; + if ( data->ignoreFlags & 0x02 ) return; + else nBytes = 2; } else if ( status == 0xF2 ) nBytes = 3; else if ( status == 0xF3 ) nBytes = 2; else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) { - // A MIDI timing tick message and we're ignoring it. - return; + // A MIDI timing tick message and we're ignoring it. + return; } else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { - // A MIDI active sensing message and we're ignoring it. - return; + // A MIDI active sensing message and we're ignoring it. + return; } // Copy bytes to our MIDI message. @@ -4112,9 +4114,9 @@ struct WinMMCallbacks { else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) MIDIHDR *sysex = ( MIDIHDR *) midiMessage; if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { - // Sysex message and we're not ignoring it - for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) - apiData->message.bytes.push_back( sysex->lpData[i] ); + // Sysex message and we're not ignoring it + for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) + apiData->message.bytes.push_back( sysex->lpData[i] ); } // The WinMM API requires that the sysex buffer be requeued after @@ -4126,20 +4128,20 @@ struct WinMMCallbacks { // avoid requeueing it, else the computer suddenly reboots after // one or two minutes. if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { - //if ( sysex->dwBytesRecorded > 0 ) { - EnterCriticalSection( &(apiData->_mutex) ); - MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); - LeaveCriticalSection( &(apiData->_mutex) ); - if ( result != MMSYSERR_NOERROR ){ - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error sending sysex to Midi device."), + //if ( sysex->dwBytesRecorded > 0 ) { + EnterCriticalSection( &(apiData->_mutex) ); + MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); + LeaveCriticalSection( &(apiData->_mutex) ); + if ( result != MMSYSERR_NOERROR ){ + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error sending sysex to Midi device."), Error::WARNING)); - } catch (Error e) { - // don't bother WinMM with an unhandled exception - } - } + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } + } - if ( data->ignoreFlags & 0x01 ) return; + if ( data->ignoreFlags & 0x01 ) return; } else return; } @@ -4150,18 +4152,18 @@ struct WinMMCallbacks { else { // As long as we haven't reached our queue size limit, push the message. if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = apiData->message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; + data->queue.ring[data->queue.back++] = apiData->message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; } else { - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother WinMM with an unhandled exception - } + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } } } @@ -4172,7 +4174,8 @@ struct WinMMCallbacks { #undef RTMIDI_CLASSNAME #define RTMIDI_CLASSNAME "MidiInWinMM" -MidiInWinMM :: MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) +MidiInWinMM :: MidiInWinMM( const std::string & clientName, + unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { initialize( clientName ); } @@ -4283,7 +4286,7 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string & /*por connected_ = true; } -void MidiInWinMM :: openVirtualPort( std::string /*portName*/ ) +void MidiInWinMM :: openVirtualPort(const std::string & /*portName*/ ) { // This function cannot be implemented for the Windows MM MIDI API. error(RTMIDI_ERROR(gettext_noopt("Virtual ports are not available Windows Multimedia MIDI API."), @@ -4443,7 +4446,7 @@ std::string MidiInWinMM :: getPortName( unsigned int portNumber ) //*********************************************************************// #define RTMIDI_CLASSNAME "MidiOutWinMM" -MidiOutWinMM :: MidiOutWinMM( const std::string clientName ) : MidiOutApi() +MidiOutWinMM :: MidiOutWinMM( const std::string & clientName ) : MidiOutApi() { initialize( clientName ); } @@ -4559,7 +4562,7 @@ void MidiOutWinMM :: closePort( void ) } } -void MidiOutWinMM :: openVirtualPort( std::string /*portName*/ ) +void MidiOutWinMM :: openVirtualPort(const std::string & /*portName*/ ) { // This function cannot be implemented for the Windows MM MIDI API. error(RTMIDI_ERROR(gettext_noopt("Virtual ports are not available Windows Multimedia MIDI API."), @@ -5004,7 +5007,7 @@ struct JackPortDescriptor:public PortDescriptor } - std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) { + std::string getName(int flags = SHORT_NAME | UNIQUE_PORT_NAME) { return seq.getPortName(port,flags); } @@ -5219,24 +5222,24 @@ int JackBackendCallbacks::jackProcessIn( jack_nframes_t nframes, void *arg ) if ( !rtData->continueSysex ) { if ( rtData->userCallback ) { - rtData->userCallback->rtmidi_midi_in( message.timeStamp, message.bytes); + rtData->userCallback->rtmidi_midi_in( message.timeStamp, message.bytes); } else { - // As long as we haven't reached our queue size limit, push the message. - if ( rtData->queue.size < rtData->queue.ringSize ) { - rtData->queue.ring[rtData->queue.back++] = message; - if ( rtData->queue.back == rtData->queue.ringSize ) - rtData->queue.back = 0; - rtData->queue.size++; - } - else { - try { - rtData->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + // As long as we haven't reached our queue size limit, push the message. + if ( rtData->queue.size < rtData->queue.ringSize ) { + rtData->queue.ring[rtData->queue.back++] = message; + if ( rtData->queue.back == rtData->queue.ringSize ) + rtData->queue.back = 0; + rtData->queue.size++; + } + else { + try { + rtData->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother WinMM with an unhandled exception - } - } + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } + } } } } diff --git a/RtMidi.h b/RtMidi.h index eb031bcc..8352862d 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -357,11 +357,11 @@ class PortDescriptor { that is concerned with naming. */ - UNIQUE_NAME = 0x10, /*!< Make all names uniqe. This - is usually done by adding - numbers to the end of the - string \note: use #undef UNIQUE_NAME - on windows in case of any errors */ + UNIQUE_PORT_NAME = 0x10, /*!< Make all names uniqe. This + is usually done by adding + numbers to the end of the + string \note: use #undef UNIQUE_PORT_NAME + on windows in case of any errors */ INCLUDE_API = 0x20 /*!< Add a string describing the API at the beginning of the string. */ @@ -417,7 +417,7 @@ class PortDescriptor { * \return A name that is formatted according to \ref flags. * \sa NamingTypes */ - virtual std::string getName(int flags = SHORT_NAME | UNIQUE_NAME) = 0; + virtual std::string getName(int flags = SHORT_NAME | UNIQUE_PORT_NAME) = 0; //! Get capabilities /*! \return a capabilities flag describing the capabilities of the port. @@ -1590,7 +1590,8 @@ class MidiOutAlsa: public MidiOutApi class MidiInWinMM: public MidiInApi { public: - MidiInWinMM( const std::string & clientName, unsigned int queueSizeLimit ); + MidiInWinMM( const std::string & clientName, + unsigned int queueSizeLimit ); ~MidiInWinMM( void ); ApiType getCurrentApi( void ) throw() { return WINDOWS_MM; }; bool hasVirtualPorts() const { return false; } diff --git a/tests/cmidiin2.cpp b/tests/cmidiin2.cpp index 9bd0bb93..06459df4 100644 --- a/tests/cmidiin2.cpp +++ b/tests/cmidiin2.cpp @@ -94,7 +94,7 @@ bool chooseMidiPort( rtmidi::MidiIn &midi ) std::copy(list.begin(),list.end(),pointers.begin()); for (nr = 0 ; nr < (int)pointers.size(); nr++) { portName = pointers[nr]->getName(rtmidi::PortDescriptor::LONG_NAME - | rtmidi::PortDescriptor::UNIQUE_NAME + | rtmidi::PortDescriptor::UNIQUE_PORT_NAME | rtmidi::PortDescriptor::INCLUDE_API); std::cout << " Input port #" << nr << ": " << portName << '\n'; } diff --git a/tests/midiout2.cpp b/tests/midiout2.cpp index 8df61ea2..c68e045c 100644 --- a/tests/midiout2.cpp +++ b/tests/midiout2.cpp @@ -18,7 +18,7 @@ #if defined(__WINDOWS_MM__) #include #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) -#undef UNIQUE_NAME +#undef UNIQUE_PORT_NAME #else // Unix variants #include #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) @@ -151,7 +151,7 @@ bool chooseMidiPort( rtmidi::MidiOut &midi ) std::copy(list.begin(),list.end(),pointers.begin()); for (nr = 0 ; nr < (int)pointers.size(); nr++) { portName = pointers[nr]->getName(rtmidi::PortDescriptor::LONG_NAME - | rtmidi::PortDescriptor::UNIQUE_NAME + | rtmidi::PortDescriptor::UNIQUE_PORT_NAME | rtmidi::PortDescriptor::INCLUDE_API); std::cout << " Output port #" << nr << ": " << portName << '\n'; } diff --git a/tests/midiprobe-all.cpp b/tests/midiprobe-all.cpp index ba24e5aa..90839fe0 100644 --- a/tests/midiprobe-all.cpp +++ b/tests/midiprobe-all.cpp @@ -36,9 +36,9 @@ int main() std::cout << " Input Port: " << (*i)->getName() << std::endl; for (int j = 0 ; j < 4 ; j++ ) { std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; - std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME) << std::endl; std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; - std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; std::cout << std::endl; } @@ -62,9 +62,9 @@ int main() std::cout << " Output Port: " << (*i)->getName() << std::endl; for (int j = 0 ; j < 4 ; j++ ) { std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; - std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME) << std::endl; std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; - std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; std::cout << std::endl; } @@ -84,9 +84,9 @@ int main() std::cout << " Input Port: " << (*i)->getName() << std::endl; for (int j = 0 ; j < 4 ; j++ ) { std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; - std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME) << std::endl; std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; - std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; std::cout << std::endl; } @@ -105,9 +105,9 @@ int main() std::cout << " Output Port: " << (*i)->getName() << std::endl; for (int j = 0 ; j < 4 ; j++ ) { std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; - std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME) << std::endl; std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; - std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; std::cout << std::endl; } diff --git a/tests/midiprobe2.cpp b/tests/midiprobe2.cpp index a0c8c260..0fae3d8e 100644 --- a/tests/midiprobe2.cpp +++ b/tests/midiprobe2.cpp @@ -48,9 +48,9 @@ int main() std::cout << " Input Port: " << (*i)->getName() << std::endl; for (int j = 0 ; j < 4 ; j++ ) { std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; - std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME) << std::endl; std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; - std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; std::cout << std::endl; } @@ -75,9 +75,9 @@ int main() std::cout << " Output Port: " << (*i)->getName() << std::endl; for (int j = 0 ; j < 4 ; j++ ) { std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; - std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME) << std::endl; std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; - std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; std::cout << std::endl; } @@ -97,9 +97,9 @@ int main() std::cout << " Input Port: " << (*i)->getName() << std::endl; for (int j = 0 ; j < 4 ; j++ ) { std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; - std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME) << std::endl; std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; - std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; std::cout << std::endl; } @@ -118,9 +118,9 @@ int main() std::cout << " Output Port: " << (*i)->getName() << std::endl; for (int j = 0 ; j < 4 ; j++ ) { std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; - std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME) << std::endl; std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; - std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_NAME + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; std::cout << std::endl; } diff --git a/tests/qmidiin2.cpp b/tests/qmidiin2.cpp index 9c0671fb..20956c8d 100644 --- a/tests/qmidiin2.cpp +++ b/tests/qmidiin2.cpp @@ -17,8 +17,8 @@ // Platform-dependent sleep routines. #if defined(__WINDOWS_MM__) #include -#define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) -#undef UNIQUE_NAME +#define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) +#undef UNIQUE_PORT_NAME #else // Unix variants #include #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) @@ -35,13 +35,13 @@ void usage( rtmidi::PortList list ) { std::cout << "Available ports:" << std::endl; int flags = rtmidi::PortDescriptor::SESSION_PATH | - rtmidi::PortDescriptor::UNIQUE_NAME | + rtmidi::PortDescriptor::UNIQUE_PORT_NAME | rtmidi::PortDescriptor::INCLUDE_API; for (rtmidi::PortList::iterator i = list.begin(); i != list.end(); i++) { std::cout << "\"" << (*i)->getName(rtmidi::PortDescriptor::SESSION_PATH | - rtmidi::PortDescriptor::UNIQUE_NAME | + rtmidi::PortDescriptor::UNIQUE_PORT_NAME | rtmidi::PortDescriptor::INCLUDE_API) << "\""; std::cout << "\t"; @@ -74,7 +74,7 @@ int main( int argc, char *argv[] ) for (rtmidi::PortList::iterator i = list.begin(); i != list.end(); i++) { if (argv[1] == (*i)->getName(rtmidi::PortDescriptor::SESSION_PATH | - rtmidi::PortDescriptor::UNIQUE_NAME | + rtmidi::PortDescriptor::UNIQUE_PORT_NAME | rtmidi::PortDescriptor::INCLUDE_API)) { port = *i; break; From 6d9bc8c4918551ec9c815f1e9f77a382f343a26b Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 14 Jan 2018 14:01:00 +0100 Subject: [PATCH 116/210] Specialize getPortList for MIDI input as well as MIDI output to select a conveniant pattern --- RtMidi.h | 49 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index 8352862d..f04b2804 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -1141,15 +1141,32 @@ class MidiIn : public Midi } } + //! Return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that + describes which capabilities the returned devices + must support. The returned devices may have + additional capabilities to those which have been + requested, but not less. - //! Pure virtual function to return a port descirptor if the port is open - Pointer getDescriptor(bool local=false) - { - if (rtapi_) return rtapi_->getDescriptor(local); - return 0; + \return This function returns a list of port descriptors. + + \note Each API will request additonal + capabilites. An output API will set always add \ref + PortDescriptor::OUTPUT to the mask while an input + device will always add \ref PortDescriptor::OUTPUT. + + \note An input API may but need not necessarily + report output devices which cannot be used as input + if \ref PortDescriptor::OUTPUT is passed as \ref + capabilities parameter. + */ + PortList getPortList(int capabilities = PortDescriptor::INPUT) { + return Midi::getPortList(capabilities); } + //! Set a callback function to be invoked for incoming MIDI messages. /*! The callback function will be called whenever an incoming MIDI @@ -1379,7 +1396,29 @@ class MidiOut : public Midi } } + //! Return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that + describes which capabilities the returned devices + must support. The returned devices may have + additional capabilities to those which have been + requested, but not less. + + \return This function returns a list of port descriptors. + + \note Each API will request additonal + capabilites. An output API will set always add \ref + PortDescriptor::OUTPUT to the mask while an input + device will always add \ref PortDescriptor::OUTPUT. + \note An input API may but need not necessarily + report output devices which cannot be used as input + if \ref PortDescriptor::OUTPUT is passed as \ref + capabilities parameter. + */ + PortList getPortList(int capabilities = PortDescriptor::OUTPUT) { + return Midi::getPortList(capabilities); + } //! Immediately send a single message out an open MIDI output port. /*! From 8e0dd4913070b8ae727569e1fae8c1ec79b8da9d Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 14 Jan 2018 14:01:55 +0100 Subject: [PATCH 117/210] fix gettext-enabled compilation --- RtMidi.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index f04b2804..5d04aed4 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -1680,7 +1680,7 @@ class MidiInDummy: public MidiInApi public: MidiInDummy( const std::string & /*clientName*/, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { - error( RTMIDI_ERROR(_("MidiInDummy: This class provides no functionality."), + error( RTMIDI_ERROR(rtmidi_gettext("MidiInDummy: This class provides no functionality."), Error::WARNING) ); } ApiType getCurrentApi( void ) throw() { return DUMMY; } @@ -1704,7 +1704,7 @@ class MidiOutDummy: public MidiOutApi { public: MidiOutDummy( const std::string & /*clientName*/ ) { - error( RTMIDI_ERROR(_("MidiInDummy: This class provides no functionality."), + error( RTMIDI_ERROR(rtmidi_gettext("MidiInDummy: This class provides no functionality."), Error::WARNING) ); } ApiType getCurrentApi( void ) { return DUMMY; } From 147d4bb864ea254bfb98dab50bc419a924ca47b0 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 14 Jan 2018 14:02:26 +0100 Subject: [PATCH 118/210] fix warnings about unused arguments --- RtMidi.h | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index 5d04aed4..f18e438d 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -1685,10 +1685,14 @@ class MidiInDummy: public MidiInApi } ApiType getCurrentApi( void ) throw() { return DUMMY; } bool hasVirtualPorts() const { return false; } - void openPort( unsigned int portNumber, const &std::string portName ) {} + void openPort( unsigned int /* portNumber*/, + const std::string & /*portName*/ ) {} void openVirtualPort( const std::string & /*portName*/ ) {} - void openPort( const PortDescriptor & port, const &std::string portName) {} - Pointer getDescriptor(bool local=false) { return 0; } + void openPort( const PortDescriptor & /* port */, + const std::string & /* portName */) {} + Pointer getDescriptor(bool /* local=false */) { + return 0; + } PortList getPortList(int capabilities) { return PortList(); } void closePort( void ) {} unsigned int getPortCount( void ) { return 0; } @@ -1707,13 +1711,15 @@ class MidiOutDummy: public MidiOutApi error( RTMIDI_ERROR(rtmidi_gettext("MidiInDummy: This class provides no functionality."), Error::WARNING) ); } - ApiType getCurrentApi( void ) { return DUMMY; } + ApiType getCurrentApi( void ) throw() { return DUMMY; } bool hasVirtualPorts() const { return false; } - void openPort( unsigned int /*portNumber*/, const & std::string /*portName*/ ) {} + void openPort( unsigned int /*portNumber*/, const std::string & /*portName*/ ) {} void openVirtualPort( const std::string & /*portName*/ ) {} - void openPort( const PortDescriptor & port, const & std::string portName) {} - Pointer getDescriptor(bool local=false) { return 0; } - PortList getPortList(int capabilities) { return PortList(); } + void openPort( const PortDescriptor & port, const std::string & portName) {} + Pointer getDescriptor(bool /* local=false */) { return 0; } + PortList getPortList(int /*capabilities*/) { + return PortList(); + } void closePort( void ) {} unsigned int getPortCount( void ) { return 0; } std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } @@ -1722,6 +1728,7 @@ class MidiOutDummy: public MidiOutApi protected: void initialize( const std::string& /*clientName*/ ) {} }; +>>>>>>> 5aa160b... fix warnings about unused arguments #endif From 0e210ab9062296d99f24c0c3c96ac5346f52190e Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 14 Jan 2018 14:02:48 +0100 Subject: [PATCH 119/210] Fix warning about redefined macro --- RtMidi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RtMidi.h b/RtMidi.h index f18e438d..6d66f3d8 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -1728,7 +1728,7 @@ class MidiOutDummy: public MidiOutApi protected: void initialize( const std::string& /*clientName*/ ) {} }; ->>>>>>> 5aa160b... fix warnings about unused arguments +#undef RTMIDI_CLASSNAME #endif From 321164be49a73bac6a93cbb7926c5239a2cecdbe Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 14 Jan 2018 14:03:11 +0100 Subject: [PATCH 120/210] Fix warning about signed/unsigned comparison --- tests/errors.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/errors.cpp b/tests/errors.cpp index af8d3cba..31281486 100644 --- a/tests/errors.cpp +++ b/tests/errors.cpp @@ -33,7 +33,7 @@ int main( int /* argc */, char * /*argv*/[] ) std::vector types = Midi::getCompiledApi(); if (types.size() > 1) { - for (int i = 0 ; i < types.size() ; i++) { + for (size_t i = 0 ; i < types.size() ; i++) { try { MidiIn in (types[i]); PortList ports = in.getPortList(PortDescriptor::INPUT); From fef3603df96bdc36e6848c53a7953bb4515c4fad Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 14 Jan 2018 14:03:25 +0100 Subject: [PATCH 121/210] fix compilation of loopback --- tests/loopback.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/loopback.cpp b/tests/loopback.cpp index be7e14ec..7bc1fc38 100644 --- a/tests/loopback.cpp +++ b/tests/loopback.cpp @@ -89,9 +89,9 @@ int main( int /* argc */, char * /*argv*/[] ) { // avoid problems with wrong destruction order /* use smart pointers to handle deletion */ - rtmidi::Pointer midiin = outdescriptor->getInputApi(); + rtmidi::Pointer midiin(outdescriptor->getInputApi()); if (!midiin) abort(); - rtmidi::Pointer midiout = indescriptor->getOutputApi(); + rtmidi::Pointer midiout(indescriptor->getOutputApi()); if (!midiout) abort(); From f1b3a8ba5e4f732ce6d24d338c7b3782e8d87788 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 26 Jan 2018 13:33:59 +0100 Subject: [PATCH 122/210] configure suffix, build and test as part of another project --- Makefile.am | 16 ++++++-------- configure.ac | 6 ++++- configure.library | 9 ++++++++ po/Makevars | 4 ++++ tests/Makefile.am | 56 +++++++++++++++++++++++++++++------------------ 5 files changed, 60 insertions(+), 31 deletions(-) diff --git a/Makefile.am b/Makefile.am index b1c4da70..5de9f221 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,15 +1,13 @@ -SUBDIRS += %D%/po -RTMIDITESTCXXFLAGS += -I$(top_srcdir)/%D% -RTMIDITESTLDFLAGS += -L%D% -lrtmidi-ts -lib_LTLIBRARIES += %D%/librtmidi-ts.la -%C%_librtmidi_ts_la_LDFLAGS = -no-undefined $(RTMIDI__TS_LIBS) -%C%_librtmidi_ts_la_CXXFLAGS = $(CXXFLAGS) $(CPPFLAGS) $(RTMIDI_TS_API) -%C%_librtmidi_ts_la_SOURCES = \ +RTMIDITESTCXXFLAGS = $(EXTRA_RTMIDITESTCXXFLAGS) -I$(top_srcdir)/%D% +RTMIDILIBRARYNAME = %D%/librtmidi@rtmidi_suffix@.la +RTMIDITESTLDFLAGS = $(EXTRA_RTMIDITESTLDFLAGS) $(RTMIDILIBRARYNAME) +lib_LTLIBRARIES += %D%/librtmidi@rtmidi_suffix@.la +%C%_librtmidi@rtmidi_suffix@_la_LDFLAGS = -no-undefined $(RTMIDI__TS_LIBS) +%C%_librtmidi@rtmidi_suffix@_la_CXXFLAGS = $(CXXFLAGS) $(CPPFLAGS) $(RTMIDI_TS_API) -DRTMIDI_NO_WARN_DEPRECATED +%C%_librtmidi@rtmidi_suffix@_la_SOURCES = \ %D%/RtMidi.cpp \ %D%/RtMidi.h EXTRA_DIST += config/config.rpath m4/ChangeLog include %D%/tests/Makefile.am - - diff --git a/configure.ac b/configure.ac index 56b2b4e2..8b825ef3 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ # Process this file with autoconf to produce a configure script. #AC_INIT(RtMidi, 2.1.0, gary@music.mcgill.ca, rtmidi) -AC_INIT(RtMidi-ts, 3.0, keinstein_junoir@gmx.net, rtmidi-ts) +AC_INIT(RtMidi-ts, 3.0, keinstein_junior@gmx.net, rtmidi-ts) AC_CONFIG_AUX_DIR(config) AC_CONFIG_SRCDIR(RtMidi.cpp) AC_CONFIG_FILES([rtmidi-config librtmidi.pc Makefile tests/Makefile po/Makefile.in]) @@ -8,8 +8,12 @@ AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) AC_CONFIG_MACRO_DIR([m4]) +rtmidi_suffix="-ts" m4_include(configure.library) +SUBDIRS="$SUBDIRS %D%/po" + + AC_OUTPUT chmod oug+x rtmidi-config diff --git a/configure.library b/configure.library index 254b1b72..4c6e9a34 100644 --- a/configure.library +++ b/configure.library @@ -25,6 +25,13 @@ LT_INIT([win32-dll]) AC_HEADER_STDC #AC_CHECK_HEADERS(sys/ioctl.h unistd.h) +AC_ARG_ENABLE(suffix, +AS_HELP_STRING([--with-suffix],[add a suffix to the library. Default is $rtmidi_suffix]), +[AS_IF(test "x$enableval" = "xno", + [ rtmidi_suffix=""], + [ rtmidi_suffix="$enableval"])]) +AC_SUBST(rtmidi_suffix) + # Check for debug AC_MSG_CHECKING(whether to compile debug version) AC_ARG_ENABLE(debug, @@ -63,6 +70,8 @@ do AC_MSG_RESULT([no])]) AC_LANG_POP(C) done + + dnl mudflap is not possible with g++ 4.7.1 and wxWidgets 2.8 dnl tmpcxxflags="$CXXFLAGS" dnl tmplibs="$LIBS" diff --git a/po/Makevars b/po/Makevars index f1d4cd38..c8a877e3 100644 --- a/po/Makevars +++ b/po/Makevars @@ -51,3 +51,7 @@ USE_MSGCTXT = no # --previous to keep previous msgids of translated messages, # --quiet to reduce the verbosity. MSGMERGE_OPTIONS = + +all: + +tags: diff --git a/tests/Makefile.am b/tests/Makefile.am index efbd90e1..476d6fc1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,6 +1,6 @@ ### RtMidi tests Makefile - for various flavors of unix #RTMIDITESTCXXFLAGS += -I$(top_srcdir)/%D% -#RTMIDITESTLDFLAGS += -L$(top_builddir)/%D% -lrtmidi-ts @LIBS@ +#RTMIDITESTLDFLAGS += -L$(top_builddir)/%D% -lrtmidi@rtmidi_suffix@ @LIBS@ noinst_PROGRAMS += \ %D%/midiprobe \ @@ -27,7 +27,6 @@ TESTS += %D%/loopback endif - %C%_midiprobe_SOURCES = %D%/midiprobe.cpp %C%_midiout_SOURCES = %D%/midiout.cpp %C%_qmidiin_SOURCES = %D%/qmidiin.cpp @@ -43,31 +42,46 @@ endif # When a nonstandard gettext library or wrapper is used, # we need extra flags. -%C%_midiprobe_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -%C%_midiout_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -%C%_qmidiin_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -%C%_cmidiin_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -%C%_sysextest_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) +%C%_midiprobe_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_midiout_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_qmidiin_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_cmidiin_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_sysextest_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED %C%_midiprobe2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) %C%_midiprobe_all_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) %C%_cmidiin2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) %C%_qmidiin2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) %C%_midiout2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) %C%_loopback_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -%C%_errors_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) - -%C%_midiprobe_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -%C%_midiout_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -%C%_qmidiin_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -%C%_cmidiin_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -%C%_sysextest_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -%C%_midiprobe2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -%C%_midiprobe_all_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -%C%_cmidiin2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -%C%_qmidiin2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -%C%_midiout2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -%C%_loopback_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -%C%_errors_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_errors_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED + +# +#%C%_midiprobe_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +#%C%_midiout_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +#%C%_qmidiin_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +#%C%_cmidiin_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +#%C%_sysextest_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +#%C%_midiprobe2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +#%C%_midiprobe_all_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +#%C%_cmidiin2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +#%C%_qmidiin2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +#%C%_midiout2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +#%C%_loopback_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +#%C%_errors_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +# + +%C%_midiprobe_LDADD = $(RTMIDILIBRARYNAME) +%C%_midiout_LDADD = $(RTMIDILIBRARYNAME) +%C%_qmidiin_LDADD = $(RTMIDILIBRARYNAME) +%C%_cmidiin_LDADD = $(RTMIDILIBRARYNAME) +%C%_sysextest_LDADD = $(RTMIDILIBRARYNAME) +%C%_midiprobe2_LDADD = $(RTMIDILIBRARYNAME) +%C%_midiprobe_all_LDADD = $(RTMIDILIBRARYNAME) +%C%_cmidiin2_LDADD = $(RTMIDILIBRARYNAME) +%C%_qmidiin2_LDADD = $(RTMIDILIBRARYNAME) +%C%_midiout2_LDADD = $(RTMIDILIBRARYNAME) +%C%_loopback_LDADD = $(RTMIDILIBRARYNAME) +%C%_errors_LDADD = $(RTMIDILIBRARYNAME) if RTMIDICOPYDLLS From 13873da9a1f3357592b9f9bbd256b294e931b268 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 26 Jan 2018 13:36:35 +0100 Subject: [PATCH 123/210] Fix exception handling for multiple APIs when jack cannot connect to the server. --- RtMidi.cpp | 92 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 33 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index d26651ce..961373a5 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -225,8 +225,9 @@ void MidiIn :: openMidiApi( ApiType api ) default: break; } - } catch (Error e) { - error(e); + } catch (const Error & e) { + rtapi_ = 0; + throw; } } @@ -248,10 +249,15 @@ MidiIn :: MidiIn( ApiType api, std::vector< ApiType > apis; getCompiledApi( apis ); for ( unsigned int i=0; i apis; getCompiledApi( apis ); for ( unsigned int i=0; iclientName = clientName; try { data->init(true); - } catch (Error e) { - error(e); + } catch (const Error & e) { + delete data; + apiData_ = 0; + throw; } } @@ -5530,6 +5549,7 @@ std::string MidiInJack :: getPortName( unsigned int portNumber ) void MidiInJack :: closePort() { JackMidiData *data = static_cast (apiData_); + if (!data) return; if ( data->local == NULL ) return; jack_port_unregister( *(data->seq), data->local ); @@ -5555,7 +5575,13 @@ void MidiOutJack :: initialize( const std::string& clientName ) apiData_ = (void *) data; this->clientName = clientName; // init is the last as it may throw an exception - data->init(false); + try { + data->init(false); + } catch (const Error & e) { + delete data; + apiData_ = 0; + throw; + } } void MidiOutJack :: connect() From dce42b0e362edf8ba0562058d82ae584624f4518 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 26 Jan 2018 13:38:06 +0100 Subject: [PATCH 124/210] Silence some compiler warnings when they do not apply. --- RtMidi.cpp | 90 +++++++++++++++++++++++------------------------ RtMidi.h | 16 ++++++--- configure.library | 26 ++++++++++++++ 3 files changed, 83 insertions(+), 49 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 961373a5..9183bc74 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -2915,21 +2915,21 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() case SND_SEQ_EVENT_SYSEX: if ( (data->ignoreFlags & 0x01) ) break; if ( ev->data.ext.len > apiData->bufferSize ) { - apiData->bufferSize = ev->data.ext.len; - free( buffer ); - buffer = (unsigned char *) malloc( apiData->bufferSize ); - if ( buffer == NULL ) { - data->doInput = false; - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error resizing buffer memory."), + apiData->bufferSize = ev->data.ext.len; + free( buffer ); + buffer = (unsigned char *) malloc( apiData->bufferSize ); + if ( buffer == NULL ) { + data->doInput = false; + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error resizing buffer memory."), Error::WARNING)); - } catch (Error e) { - // don't bother ALSA with an unhandled exception - } - break; - } + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } + break; + } } - + FALLTHROUGH; default: doDecode = true; } @@ -2938,38 +2938,38 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() nBytes = snd_midi_event_decode( apiData->coder, buffer, apiData->bufferSize, ev ); if ( nBytes > 0 ) { - // The ALSA sequencer has a maximum buffer size for MIDI sysex - // events of 256 bytes. If a device sends sysex messages larger - // than this, they are segmented into 256 byte chunks. So, - // we'll watch for this and concatenate sysex chunks into a - // single sysex message if necessary. - if ( !continueSysex ) - message.bytes.assign( buffer, &buffer[nBytes] ); - else - message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] ); - - continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) ); - if ( !continueSysex ) { - - // Calculate the time stamp: - message.timeStamp = 0.0; - - // Method 1: Use the system time. - //(void)gettimeofday(&tv, (struct timezone *)NULL); - //time = (tv.tv_sec * 1000000) + tv.tv_usec; - - // Method 2: Use the ALSA sequencer event time data. - // (thanks to Pedro Lopez-Cabanillas!). - time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 ); - lastTime = time; - time -= apiData->lastTime; - apiData->lastTime = lastTime; - if ( data->firstMessage == true ) - data->firstMessage = false; - else - message.timeStamp = time * 0.000001; - } - else { + // The ALSA sequencer has a maximum buffer size for MIDI sysex + // events of 256 bytes. If a device sends sysex messages larger + // than this, they are segmented into 256 byte chunks. So, + // we'll watch for this and concatenate sysex chunks into a + // single sysex message if necessary. + if ( !continueSysex ) + message.bytes.assign( buffer, &buffer[nBytes] ); + else + message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] ); + + continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) ); + if ( !continueSysex ) { + + // Calculate the time stamp: + message.timeStamp = 0.0; + + // Method 1: Use the system time. + //(void)gettimeofday(&tv, (struct timezone *)NULL); + //time = (tv.tv_sec * 1000000) + tv.tv_usec; + + // Method 2: Use the ALSA sequencer event time data. + // (thanks to Pedro Lopez-Cabanillas!). + time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 ); + lastTime = time; + time -= apiData->lastTime; + apiData->lastTime = lastTime; + if ( data->firstMessage == true ) + data->firstMessage = false; + else + message.timeStamp = time * 0.000001; + } + else { #if defined(__RTMIDI_DEBUG__) try { data->error(RTMIDI_ERROR(rtmidi_gettext("Event parsing error or not a MIDI event."), diff --git a/RtMidi.h b/RtMidi.h index 6d66f3d8..41e2d02c 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -45,6 +45,9 @@ #define RTMIDI_VERSION "3.0.0alpha" +#ifdef RTMIDI_NO_WARN_DEPRECATED +#define RTMIDI_DEPRECATED(func,message) func +#else #ifdef __GNUC__ #define RTMIDI_DEPRECATED(func,message) func __attribute__ ((deprecated(message))) #elif defined(_MSC_VER) @@ -53,6 +56,9 @@ #pragma message("WARNING: You need to implement the macro RTMIDI_DEPRECATED for this compiler if this code doesn't compile") #define RTMIDI_DEPRECATED(func,message) func [[deprecated(message)]] #endif +#endif + +#define rtmidiUnused(x) do { (void)x; } while (0) // Check for C++11 support #if defined(_MSC_VER) && _MSC_VER >= 1800 @@ -1693,13 +1699,15 @@ class MidiInDummy: public MidiInApi Pointer getDescriptor(bool /* local=false */) { return 0; } - PortList getPortList(int capabilities) { return PortList(); } + PortList getPortList(int /* capabilities */) { + return PortList(); + } void closePort( void ) {} unsigned int getPortCount( void ) { return 0; } - std::string getPortName( unsigned int portNumber ) { return ""; } + std::string getPortName( unsigned int /* portNumber */ ) { return ""; } protected: - void initialize( const std::string& /*clientName*/ ) {} + void initialize( const std::string& /* clientName */ ) {} }; #undef RTMIDI_CLASSNAME @@ -1715,7 +1723,7 @@ class MidiOutDummy: public MidiOutApi bool hasVirtualPorts() const { return false; } void openPort( unsigned int /*portNumber*/, const std::string & /*portName*/ ) {} void openVirtualPort( const std::string & /*portName*/ ) {} - void openPort( const PortDescriptor & port, const std::string & portName) {} + void openPort( const PortDescriptor & /* port */, const std::string & /* portName */) {} Pointer getDescriptor(bool /* local=false */) { return 0; } PortList getPortList(int /*capabilities*/) { return PortList(); diff --git a/configure.library b/configure.library index 4c6e9a34..81cf6fc2 100644 --- a/configure.library +++ b/configure.library @@ -307,3 +307,29 @@ then fi AM_CONDITIONAL(RTMIDICOPYDLLS,$rtmidicopydlls && test -n "$DLLSEARCHPATH") + + +AC_LANG(C++) +AC_CACHE_CHECK([fallthrough syntax in the C++ language], ac_cv_cxx_fallthrough, +[ +AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([ + int j; + void test(int i) { switch (i) { case 1: j = 3; [[[fallthrough]]] ; case 2: j++; }} + ],[])],[ac_cv_cxx_fallthrough="[[[fallthrough]]]"],[ + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([ + int j; + void test(int i) { switch (i) { case 1: j = 3; [[[gnu::fallthrough]]] ; case 2: j++; }} + ],[])],[ac_cv_cxx_fallthrough="[[[gnu::fallthrough]]]"],[ + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([ + int j; + void test(int i) { switch (i) { case 1: j = 3; __attribute__((fallthrough)) ; case 2: j++; }} + ],[])],[ac_cv_cxx_fallthrough="__attribute__((fallthrough))"],[ + ac_cv_cxx_fallthrough="" + ]); + ]); +]); +]) +AC_DEFINE_UNQUOTED(mutfallthrough,[$ac_cv_cxx_fallthrough],[syntax for swtich case fallthrough attributes in C++]) From f504f04538e75d57d4272081a140750d273c2c3a Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 26 Jan 2018 13:38:31 +0100 Subject: [PATCH 125/210] Fix internal pointer class. --- RtMidi.h | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index 41e2d02c..b28d5554 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -259,14 +259,13 @@ class Pointer { if (ptr) ptr->count++; } + Pointer(const Pointer && other): + ptr(other.ptr) { + } ~Pointer() { if (!ptr) return; - if (!ptr->descriptor) { - delete ptr; - return; - } - if (!(--ptr->count)) { + if (!(--(ptr->count))) { delete ptr->descriptor; delete ptr; } @@ -308,8 +307,8 @@ class Pointer { delete ptr; } } - ptr = other.ptr; - ptr->count++; + if ((ptr = other.ptr)) + ptr->count++; return *this; } protected: @@ -321,6 +320,16 @@ bool operator==(const Pointer& lhs, const Pointer& rhs) { return (&(*lhs)) == (&(*rhs)); } +template +bool operator!=(const Pointer& lhs, const Pointer& rhs) { + return (&(*lhs)) != (&(*rhs)); +} + +template +bool operator==(const Pointer& lhs, const Pointer& rhs) { + return (&(*lhs)) == (&(*rhs)); +} + template bool operator!=(const Pointer& lhs, const Pointer& rhs) { return (&(*lhs)) != (&(*rhs)); From d7edd3e8b66300683e67da1df5f36d4719f10677 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 26 Jan 2018 13:38:45 +0100 Subject: [PATCH 126/210] Fix some spelling errors. --- RtMidi.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index b28d5554..e8bff778 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -448,7 +448,7 @@ class PortDescriptor { typedef Pointer PortPointer; typedef std::list > PortList; -/* A depricated type. See below for the documentation. We +/* A deprecated type. See below for the documentation. We split the definiton into several pieces to work around some intended warnings. */ typedef void (*ErrorCallback_t)( Error::Type type, const std::string &errorText, void * userdata ); @@ -460,11 +460,11 @@ typedef void (*ErrorCallback_t)( Error::Type type, const std::string &errorText, Note that class behaviour is undefined after a critical error (not a warning) is reported. \sa ErrorInterface - \depricated + \deprecated */ RTMIDI_DEPRECATED(typedef ErrorCallback_t ErrorCallback,"RtMidi now provides a class MidiInterface for error callbacks"); -/* A depricated type. See below for the documentation. We +/* A deprecated type. See below for the documentation. We split the definiton into several pieces to work around some intended warnings. */ #define ErrorCallback ErrorCallback_t From 160635ac4aab759ec24a4a507a91ffacbc322f54 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 26 Jan 2018 13:52:02 +0100 Subject: [PATCH 127/210] add m4 directory We cannot assume that all tests are available on every build machine --- .gitignore | 1 - m4/ChangeLog | 11 + m4/codeset.m4 | 21 + m4/fcntl-o.m4 | 81 + m4/gettext.m4 | 420 +++ m4/glibc2.m4 | 30 + m4/glibc21.m4 | 30 + m4/iconv.m4 | 271 ++ m4/intdiv0.m4 | 84 + m4/intl.m4 | 294 ++ m4/intldir.m4 | 19 + m4/intlmacosx.m4 | 51 + m4/intmax.m4 | 33 + m4/inttypes-pri.m4 | 36 + m4/inttypes_h.m4 | 26 + m4/lcmessage.m4 | 31 + m4/lib-ld.m4 | 119 + m4/lib-link.m4 | 777 ++++ m4/lib-prefix.m4 | 224 ++ m4/libtool.m4 | 8387 ++++++++++++++++++++++++++++++++++++++++++++ m4/lock.m4 | 37 + m4/longlong.m4 | 106 + m4/ltoptions.m4 | 437 +++ m4/ltsugar.m4 | 124 + m4/ltversion.m4 | 23 + m4/lt~obsolete.m4 | 99 + m4/nls.m4 | 32 + m4/po.m4 | 453 +++ m4/printf-posix.m4 | 45 + m4/progtest.m4 | 91 + m4/size_max.m4 | 75 + m4/stdint_h.m4 | 26 + m4/threadlib.m4 | 347 ++ m4/uintmax_t.m4 | 30 + m4/visibility.m4 | 74 + m4/wchar_t.m4 | 20 + m4/wint_t.m4 | 28 + m4/xsize.m4 | 13 + 38 files changed, 13005 insertions(+), 1 deletion(-) create mode 100644 m4/ChangeLog create mode 100644 m4/codeset.m4 create mode 100644 m4/fcntl-o.m4 create mode 100644 m4/gettext.m4 create mode 100644 m4/glibc2.m4 create mode 100644 m4/glibc21.m4 create mode 100644 m4/iconv.m4 create mode 100644 m4/intdiv0.m4 create mode 100644 m4/intl.m4 create mode 100644 m4/intldir.m4 create mode 100644 m4/intlmacosx.m4 create mode 100644 m4/intmax.m4 create mode 100644 m4/inttypes-pri.m4 create mode 100644 m4/inttypes_h.m4 create mode 100644 m4/lcmessage.m4 create mode 100644 m4/lib-ld.m4 create mode 100644 m4/lib-link.m4 create mode 100644 m4/lib-prefix.m4 create mode 100644 m4/libtool.m4 create mode 100644 m4/lock.m4 create mode 100644 m4/longlong.m4 create mode 100644 m4/ltoptions.m4 create mode 100644 m4/ltsugar.m4 create mode 100644 m4/ltversion.m4 create mode 100644 m4/lt~obsolete.m4 create mode 100644 m4/nls.m4 create mode 100644 m4/po.m4 create mode 100644 m4/printf-posix.m4 create mode 100644 m4/progtest.m4 create mode 100644 m4/size_max.m4 create mode 100644 m4/stdint_h.m4 create mode 100644 m4/threadlib.m4 create mode 100644 m4/uintmax_t.m4 create mode 100644 m4/visibility.m4 create mode 100644 m4/wchar_t.m4 create mode 100644 m4/wint_t.m4 create mode 100644 m4/xsize.m4 diff --git a/.gitignore b/.gitignore index 755dd8da..05d91727 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,5 @@ Makefile.in /aclocal.m4 /autom4te.cache /configure -/m4 *.orig *~ diff --git a/m4/ChangeLog b/m4/ChangeLog new file mode 100644 index 00000000..33ccb9bb --- /dev/null +++ b/m4/ChangeLog @@ -0,0 +1,11 @@ +2018-01-07 gettextize + + * gettext.m4: Upgrade to gettext-0.19.8.1. + * iconv.m4: Upgrade to gettext-0.19.8.1. + * lib-ld.m4: Upgrade to gettext-0.19.8.1. + * lib-link.m4: Upgrade to gettext-0.19.8.1. + * lib-prefix.m4: Upgrade to gettext-0.19.8.1. + * nls.m4: Upgrade to gettext-0.19.8.1. + * po.m4: Upgrade to gettext-0.19.8.1. + * progtest.m4: Upgrade to gettext-0.19.8.1. + diff --git a/m4/codeset.m4 b/m4/codeset.m4 new file mode 100644 index 00000000..a53c0426 --- /dev/null +++ b/m4/codeset.m4 @@ -0,0 +1,21 @@ +# codeset.m4 serial 4 (gettext-0.18) +dnl Copyright (C) 2000-2002, 2006, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([AM_LANGINFO_CODESET], +[ + AC_CACHE_CHECK([for nl_langinfo and CODESET], [am_cv_langinfo_codeset], + [AC_TRY_LINK([#include ], + [char* cs = nl_langinfo(CODESET); return !cs;], + [am_cv_langinfo_codeset=yes], + [am_cv_langinfo_codeset=no]) + ]) + if test $am_cv_langinfo_codeset = yes; then + AC_DEFINE([HAVE_LANGINFO_CODESET], [1], + [Define if you have and nl_langinfo(CODESET).]) + fi +]) diff --git a/m4/fcntl-o.m4 b/m4/fcntl-o.m4 new file mode 100644 index 00000000..d416a61c --- /dev/null +++ b/m4/fcntl-o.m4 @@ -0,0 +1,81 @@ +# fcntl-o.m4 serial 1 +dnl Copyright (C) 2006, 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Written by Paul Eggert. + +# Test whether the flags O_NOATIME and O_NOFOLLOW actually work. +# Define HAVE_WORKING_O_NOATIME to 1 if O_NOATIME works, or to 0 otherwise. +# Define HAVE_WORKING_O_NOFOLLOW to 1 if O_NOFOLLOW works, or to 0 otherwise. +AC_DEFUN([gl_FCNTL_O_FLAGS], +[ + dnl Persuade glibc to define O_NOATIME and O_NOFOLLOW. + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + AC_CACHE_CHECK([for working fcntl.h], [gl_cv_header_working_fcntl_h], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + #include + #include + #ifndef O_NOATIME + #define O_NOATIME 0 + #endif + #ifndef O_NOFOLLOW + #define O_NOFOLLOW 0 + #endif + static int const constants[] = + { + O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC, O_APPEND, + O_NONBLOCK, O_SYNC, O_ACCMODE, O_RDONLY, O_RDWR, O_WRONLY + }; + ]], + [[ + int status = !constants; + { + static char const sym[] = "conftest.sym"; + if (symlink (".", sym) != 0 + || close (open (sym, O_RDONLY | O_NOFOLLOW)) == 0) + status |= 32; + unlink (sym); + } + { + static char const file[] = "confdefs.h"; + int fd = open (file, O_RDONLY | O_NOATIME); + char c; + struct stat st0, st1; + if (fd < 0 + || fstat (fd, &st0) != 0 + || sleep (1) != 0 + || read (fd, &c, 1) != 1 + || close (fd) != 0 + || stat (file, &st1) != 0 + || st0.st_atime != st1.st_atime) + status |= 64; + } + return status;]])], + [gl_cv_header_working_fcntl_h=yes], + [case $? in #( + 32) gl_cv_header_working_fcntl_h='no (bad O_NOFOLLOW)';; #( + 64) gl_cv_header_working_fcntl_h='no (bad O_NOATIME)';; #( + 96) gl_cv_header_working_fcntl_h='no (bad O_NOATIME, O_NOFOLLOW)';; #( + *) gl_cv_header_working_fcntl_h='no';; + esac], + [gl_cv_header_working_fcntl_h=cross-compiling])]) + + case $gl_cv_header_working_fcntl_h in #( + *O_NOATIME* | no | cross-compiling) ac_val=0;; #( + *) ac_val=1;; + esac + AC_DEFINE_UNQUOTED([HAVE_WORKING_O_NOATIME], [$ac_val], + [Define to 1 if O_NOATIME works.]) + + case $gl_cv_header_working_fcntl_h in #( + *O_NOFOLLOW* | no | cross-compiling) ac_val=0;; #( + *) ac_val=1;; + esac + AC_DEFINE_UNQUOTED([HAVE_WORKING_O_NOFOLLOW], [$ac_val], + [Define to 1 if O_NOFOLLOW works.]) +]) diff --git a/m4/gettext.m4 b/m4/gettext.m4 new file mode 100644 index 00000000..eef5073b --- /dev/null +++ b/m4/gettext.m4 @@ -0,0 +1,420 @@ +# gettext.m4 serial 68 (gettext-0.19.8) +dnl Copyright (C) 1995-2014, 2016 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2006, 2008-2010. + +dnl Macro to add for using GNU gettext. + +dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]). +dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The +dnl default (if it is not specified or empty) is 'no-libtool'. +dnl INTLSYMBOL should be 'external' for packages with no intl directory, +dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory. +dnl If INTLSYMBOL is 'use-libtool', then a libtool library +dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, +dnl depending on --{enable,disable}-{shared,static} and on the presence of +dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library +dnl $(top_builddir)/intl/libintl.a will be created. +dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext +dnl implementations (in libc or libintl) without the ngettext() function +dnl will be ignored. If NEEDSYMBOL is specified and is +dnl 'need-formatstring-macros', then GNU gettext implementations that don't +dnl support the ISO C 99 formatstring macros will be ignored. +dnl INTLDIR is used to find the intl libraries. If empty, +dnl the value '$(top_builddir)/intl/' is used. +dnl +dnl The result of the configuration is one of three cases: +dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled +dnl and used. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 2) GNU gettext has been found in the system's C library. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 3) No internationalization, always use English msgid. +dnl Catalog format: none +dnl Catalog extension: none +dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur. +dnl The use of .gmo is historical (it was needed to avoid overwriting the +dnl GNU format catalogs when building on a platform with an X/Open gettext), +dnl but we keep it in order not to force irrelevant filename changes on the +dnl maintainers. +dnl +AC_DEFUN([AM_GNU_GETTEXT], +[ + dnl Argument checking. + ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , + [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT +])])])])]) + ifelse(ifelse([$1], [], [old])[]ifelse([$1], [no-libtool], [old]), [old], + [AC_DIAGNOSE([obsolete], [Use of AM_GNU_GETTEXT without [external] argument is deprecated.])]) + ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , + [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT +])])])]) + define([gt_included_intl], + ifelse([$1], [external], + ifdef([AM_GNU_GETTEXT_][INTL_SUBDIR], [yes], [no]), + [yes])) + define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], [])) + gt_NEEDS_INIT + AM_GNU_GETTEXT_NEED([$2]) + + AC_REQUIRE([AM_PO_SUBDIRS])dnl + ifelse(gt_included_intl, yes, [ + AC_REQUIRE([AM_INTL_SUBDIR])dnl + ]) + + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Sometimes libintl requires libiconv, so first search for libiconv. + dnl Ideally we would do this search only after the + dnl if test "$USE_NLS" = "yes"; then + dnl if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT + dnl the configure script would need to contain the same shell code + dnl again, outside any 'if'. There are two solutions: + dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'. + dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE. + dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not + dnl documented, we avoid it. + ifelse(gt_included_intl, yes, , [ + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + ]) + + dnl Sometimes, on Mac OS X, libintl requires linking with CoreFoundation. + gt_INTL_MACOSX + + dnl Set USE_NLS. + AC_REQUIRE([AM_NLS]) + + ifelse(gt_included_intl, yes, [ + BUILD_INCLUDED_LIBINTL=no + USE_INCLUDED_LIBINTL=no + ]) + LIBINTL= + LTLIBINTL= + POSUB= + + dnl Add a version number to the cache macros. + case " $gt_needs " in + *" need-formatstring-macros "*) gt_api_version=3 ;; + *" need-ngettext "*) gt_api_version=2 ;; + *) gt_api_version=1 ;; + esac + gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" + gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" + + dnl If we use NLS figure out what method + if test "$USE_NLS" = "yes"; then + gt_use_preinstalled_gnugettext=no + ifelse(gt_included_intl, yes, [ + AC_MSG_CHECKING([whether included gettext is requested]) + AC_ARG_WITH([included-gettext], + [ --with-included-gettext use the GNU gettext library included here], + nls_cv_force_use_gnu_gettext=$withval, + nls_cv_force_use_gnu_gettext=no) + AC_MSG_RESULT([$nls_cv_force_use_gnu_gettext]) + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + ]) + dnl User does not insist on using GNU NLS library. Figure out what + dnl to use. If GNU gettext is available we use this. Else we have + dnl to fall back to GNU NLS library. + + if test $gt_api_version -ge 3; then + gt_revision_test_code=' +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +changequote(,)dnl +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +changequote([,])dnl +' + else + gt_revision_test_code= + fi + if test $gt_api_version -ge 2; then + gt_expression_test_code=' + * ngettext ("", "", 0)' + else + gt_expression_test_code= + fi + + AC_CACHE_CHECK([for GNU gettext in libc], [$gt_func_gnugettext_libc], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings; +#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_domain_bindings) +#else +#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0 +#endif +$gt_revision_test_code + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION + ]])], + [eval "$gt_func_gnugettext_libc=yes"], + [eval "$gt_func_gnugettext_libc=no"])]) + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + dnl Sometimes libintl requires libiconv, so first search for libiconv. + ifelse(gt_included_intl, yes, , [ + AM_ICONV_LINK + ]) + dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL + dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv]) + dnl because that would add "-liconv" to LIBINTL and LTLIBINTL + dnl even if libiconv doesn't exist. + AC_LIB_LINKFLAGS_BODY([intl]) + AC_CACHE_CHECK([for GNU gettext in libintl], + [$gt_func_gnugettext_libintl], + [gt_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCINTL" + gt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBINTL" + dnl Now see whether libintl exists and does not depend on libiconv. + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); +#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_expand_alias ("")) +#else +#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0 +#endif +$gt_revision_test_code + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION + ]])], + [eval "$gt_func_gnugettext_libintl=yes"], + [eval "$gt_func_gnugettext_libintl=no"]) + dnl Now see whether libintl exists and depends on libiconv. + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); +#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_expand_alias ("")) +#else +#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0 +#endif +$gt_revision_test_code + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION + ]])], + [LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + eval "$gt_func_gnugettext_libintl=yes" + ]) + fi + CPPFLAGS="$gt_save_CPPFLAGS" + LIBS="$gt_save_LIBS"]) + fi + + dnl If an already present or preinstalled GNU gettext() is found, + dnl use it. But if this macro is used in GNU gettext, and GNU + dnl gettext is already preinstalled in libintl, we update this + dnl libintl. (Cf. the install rule in intl/Makefile.in.) + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ + || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ + && test "$PACKAGE" != gettext-runtime \ + && test "$PACKAGE" != gettext-tools; }; then + gt_use_preinstalled_gnugettext=yes + else + dnl Reset the values set by searching for libintl. + LIBINTL= + LTLIBINTL= + INCINTL= + fi + + ifelse(gt_included_intl, yes, [ + if test "$gt_use_preinstalled_gnugettext" != "yes"; then + dnl GNU gettext is not found in the C library. + dnl Fall back on included GNU gettext library. + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions used to generate GNU NLS library. + BUILD_INCLUDED_LIBINTL=yes + USE_INCLUDED_LIBINTL=yes + LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV $LIBTHREAD" + LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV $LTLIBTHREAD" + LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` + fi + + CATOBJEXT= + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions to use GNU gettext tools. + CATOBJEXT=.gmo + fi + ]) + + if test -n "$INTL_MACOSX_LIBS"; then + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Some extra flags are needed during linking. + LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" + LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" + fi + fi + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + AC_DEFINE([ENABLE_NLS], [1], + [Define to 1 if translation of program messages to the user's native language + is requested.]) + else + USE_NLS=no + fi + fi + + AC_MSG_CHECKING([whether to use NLS]) + AC_MSG_RESULT([$USE_NLS]) + if test "$USE_NLS" = "yes"; then + AC_MSG_CHECKING([where the gettext function comes from]) + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + gt_source="external libintl" + else + gt_source="libc" + fi + else + gt_source="included intl directory" + fi + AC_MSG_RESULT([$gt_source]) + fi + + if test "$USE_NLS" = "yes"; then + + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + AC_MSG_CHECKING([how to link with libintl]) + AC_MSG_RESULT([$LIBINTL]) + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) + fi + + dnl For backward compatibility. Some packages may be using this. + AC_DEFINE([HAVE_GETTEXT], [1], + [Define if the GNU gettext() function is already present or preinstalled.]) + AC_DEFINE([HAVE_DCGETTEXT], [1], + [Define if the GNU dcgettext() function is already present or preinstalled.]) + fi + + dnl We need to process the po/ directory. + POSUB=po + fi + + ifelse(gt_included_intl, yes, [ + dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL + dnl to 'yes' because some of the testsuite requires it. + if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then + BUILD_INCLUDED_LIBINTL=yes + fi + + dnl Make all variables we use known to autoconf. + AC_SUBST([BUILD_INCLUDED_LIBINTL]) + AC_SUBST([USE_INCLUDED_LIBINTL]) + AC_SUBST([CATOBJEXT]) + + dnl For backward compatibility. Some configure.ins may be using this. + nls_cv_header_intl= + nls_cv_header_libgt= + + dnl For backward compatibility. Some Makefiles may be using this. + DATADIRNAME=share + AC_SUBST([DATADIRNAME]) + + dnl For backward compatibility. Some Makefiles may be using this. + INSTOBJEXT=.mo + AC_SUBST([INSTOBJEXT]) + + dnl For backward compatibility. Some Makefiles may be using this. + GENCAT=gencat + AC_SUBST([GENCAT]) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLOBJS= + if test "$USE_INCLUDED_LIBINTL" = yes; then + INTLOBJS="\$(GETTOBJS)" + fi + AC_SUBST([INTLOBJS]) + + dnl Enable libtool support if the surrounding package wishes it. + INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix + AC_SUBST([INTL_LIBTOOL_SUFFIX_PREFIX]) + ]) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLLIBS="$LIBINTL" + AC_SUBST([INTLLIBS]) + + dnl Make all documented variables known to autoconf. + AC_SUBST([LIBINTL]) + AC_SUBST([LTLIBINTL]) + AC_SUBST([POSUB]) +]) + + +dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized. +m4_define([gt_NEEDS_INIT], +[ + m4_divert_text([DEFAULTS], [gt_needs=]) + m4_define([gt_NEEDS_INIT], []) +]) + + +dnl Usage: AM_GNU_GETTEXT_NEED([NEEDSYMBOL]) +AC_DEFUN([AM_GNU_GETTEXT_NEED], +[ + m4_divert_text([INIT_PREPARE], [gt_needs="$gt_needs $1"]) +]) + + +dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) +AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) + + +dnl Usage: AM_GNU_GETTEXT_REQUIRE_VERSION([gettext-version]) +AC_DEFUN([AM_GNU_GETTEXT_REQUIRE_VERSION], []) diff --git a/m4/glibc2.m4 b/m4/glibc2.m4 new file mode 100644 index 00000000..f148c12c --- /dev/null +++ b/m4/glibc2.m4 @@ -0,0 +1,30 @@ +# glibc2.m4 serial 2 +dnl Copyright (C) 2000-2002, 2004, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Test for the GNU C Library, version 2.0 or newer. +# From Bruno Haible. + +AC_DEFUN([gt_GLIBC2], + [ + AC_CACHE_CHECK([whether we are using the GNU C Library 2 or newer], + [ac_cv_gnu_library_2], + [AC_EGREP_CPP([Lucky GNU user], + [ +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ >= 2) + Lucky GNU user + #endif +#endif + ], + [ac_cv_gnu_library_2=yes], + [ac_cv_gnu_library_2=no]) + ] + ) + AC_SUBST([GLIBC2]) + GLIBC2="$ac_cv_gnu_library_2" + ] +) diff --git a/m4/glibc21.m4 b/m4/glibc21.m4 new file mode 100644 index 00000000..68ada9d4 --- /dev/null +++ b/m4/glibc21.m4 @@ -0,0 +1,30 @@ +# glibc21.m4 serial 4 +dnl Copyright (C) 2000-2002, 2004, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Test for the GNU C Library, version 2.1 or newer. +# From Bruno Haible. + +AC_DEFUN([gl_GLIBC21], + [ + AC_CACHE_CHECK([whether we are using the GNU C Library 2.1 or newer], + [ac_cv_gnu_library_2_1], + [AC_EGREP_CPP([Lucky GNU user], + [ +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) + Lucky GNU user + #endif +#endif + ], + [ac_cv_gnu_library_2_1=yes], + [ac_cv_gnu_library_2_1=no]) + ] + ) + AC_SUBST([GLIBC21]) + GLIBC21="$ac_cv_gnu_library_2_1" + ] +) diff --git a/m4/iconv.m4 b/m4/iconv.m4 new file mode 100644 index 00000000..aa159c53 --- /dev/null +++ b/m4/iconv.m4 @@ -0,0 +1,271 @@ +# iconv.m4 serial 19 (gettext-0.18.2) +dnl Copyright (C) 2000-2002, 2007-2014, 2016 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], +[ + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([iconv]) +]) + +AC_DEFUN([AM_ICONV_LINK], +[ + dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and + dnl those with the standalone portable GNU libiconv installed). + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + + dnl Add $INCICONV to CPPFLAGS before performing the following checks, + dnl because if the user has installed libiconv and not disabled its use + dnl via --without-libiconv-prefix, he wants to use it. The first + dnl AC_LINK_IFELSE will then fail, the second AC_LINK_IFELSE will succeed. + am_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) + + AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [ + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);]])], + [am_cv_func_iconv=yes]) + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);]])], + [am_cv_lib_iconv=yes] + [am_cv_func_iconv=yes]) + LIBS="$am_save_LIBS" + fi + ]) + if test "$am_cv_func_iconv" = yes; then + AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [ + dnl This tests against bugs in AIX 5.1, AIX 6.1..7.1, HP-UX 11.11, + dnl Solaris 10. + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + am_cv_func_iconv_works=no + for ac_iconv_const in '' 'const'; do + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + +#ifndef ICONV_CONST +# define ICONV_CONST $ac_iconv_const +#endif + ]], + [[int result = 0; + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 1; + iconv_close (cd_utf8_to_88591); + } + } + /* Test against Solaris 10 bug: Failures are not distinguishable from + successful returns. */ + { + iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); + if (cd_ascii_to_88591 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\263"; + char buf[10]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_ascii_to_88591, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 2; + iconv_close (cd_ascii_to_88591); + } + } + /* Test against AIX 6.1..7.1 bug: Buffer overrun. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\304"; + static char buf[2] = { (char)0xDE, (char)0xAD }; + ICONV_CONST char *inptr = input; + size_t inbytesleft = 1; + char *outptr = buf; + size_t outbytesleft = 1; + size_t res = iconv (cd_88591_to_utf8, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) + result |= 4; + iconv_close (cd_88591_to_utf8); + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + result |= 8; + iconv_close (cd_88591_to_utf8); + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + result |= 16; + return result; +]])], + [am_cv_func_iconv_works=yes], , + [case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac]) + test "$am_cv_func_iconv_works" = no || break + done + LIBS="$am_save_LIBS" + ]) + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + AC_DEFINE([HAVE_ICONV], [1], + [Define if you have the iconv() function and it works.]) + fi + if test "$am_cv_lib_iconv" = yes; then + AC_MSG_CHECKING([how to link with libiconv]) + AC_MSG_RESULT([$LIBICONV]) + else + dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV + dnl either. + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + AC_SUBST([LIBICONV]) + AC_SUBST([LTLIBICONV]) +]) + +dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to +dnl avoid warnings like +dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required". +dnl This is tricky because of the way 'aclocal' is implemented: +dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN. +dnl Otherwise aclocal's initial scan pass would miss the macro definition. +dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions. +dnl Otherwise aclocal would emit many "Use of uninitialized value $1" +dnl warnings. +m4_define([gl_iconv_AC_DEFUN], + m4_version_prereq([2.64], + [[AC_DEFUN_ONCE( + [$1], [$2])]], + [m4_ifdef([gl_00GNULIB], + [[AC_DEFUN_ONCE( + [$1], [$2])]], + [[AC_DEFUN( + [$1], [$2])]])])) +gl_iconv_AC_DEFUN([AM_ICONV], +[ + AM_ICONV_LINK + if test "$am_cv_func_iconv" = yes; then + AC_MSG_CHECKING([for iconv declaration]) + AC_CACHE_VAL([am_cv_proto_iconv], [ + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) +size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +#else +size_t iconv(); +#endif + ]], + [[]])], + [am_cv_proto_iconv_arg1=""], + [am_cv_proto_iconv_arg1="const"]) + am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) + am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` + AC_MSG_RESULT([ + $am_cv_proto_iconv]) + AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1], + [Define as const if the declaration of iconv() needs const.]) + dnl Also substitute ICONV_CONST in the gnulib generated . + m4_ifdef([gl_ICONV_H_DEFAULTS], + [AC_REQUIRE([gl_ICONV_H_DEFAULTS]) + if test -n "$am_cv_proto_iconv_arg1"; then + ICONV_CONST="const" + fi + ]) + fi +]) diff --git a/m4/intdiv0.m4 b/m4/intdiv0.m4 new file mode 100644 index 00000000..289c4df5 --- /dev/null +++ b/m4/intdiv0.m4 @@ -0,0 +1,84 @@ +# intdiv0.m4 serial 3 (gettext-0.18) +dnl Copyright (C) 2002, 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gt_INTDIV0], +[ + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + + AC_CACHE_CHECK([whether integer division by zero raises SIGFPE], + gt_cv_int_divbyzero_sigfpe, + [ + gt_cv_int_divbyzero_sigfpe= +changequote(,)dnl + case "$host_os" in + macos* | darwin[6-9]* | darwin[1-9][0-9]*) + # On MacOS X 10.2 or newer, just assume the same as when cross- + # compiling. If we were to perform the real test, 1 Crash Report + # dialog window would pop up. + case "$host_cpu" in + i[34567]86 | x86_64) + gt_cv_int_divbyzero_sigfpe="guessing yes" ;; + esac + ;; + esac +changequote([,])dnl + if test -z "$gt_cv_int_divbyzero_sigfpe"; then + AC_TRY_RUN([ +#include +#include + +static void +sigfpe_handler (int sig) +{ + /* Exit with code 0 if SIGFPE, with code 1 if any other signal. */ + exit (sig != SIGFPE); +} + +int x = 1; +int y = 0; +int z; +int nan; + +int main () +{ + signal (SIGFPE, sigfpe_handler); +/* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP. */ +#if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP) + signal (SIGTRAP, sigfpe_handler); +#endif +/* Linux/SPARC yields signal SIGILL. */ +#if defined (__sparc__) && defined (__linux__) + signal (SIGILL, sigfpe_handler); +#endif + + z = x / y; + nan = y / y; + exit (1); +} +], [gt_cv_int_divbyzero_sigfpe=yes], [gt_cv_int_divbyzero_sigfpe=no], + [ + # Guess based on the CPU. +changequote(,)dnl + case "$host_cpu" in + alpha* | i[34567]86 | x86_64 | m68k | s390*) + gt_cv_int_divbyzero_sigfpe="guessing yes";; + *) + gt_cv_int_divbyzero_sigfpe="guessing no";; + esac +changequote([,])dnl + ]) + fi + ]) + case "$gt_cv_int_divbyzero_sigfpe" in + *yes) value=1;; + *) value=0;; + esac + AC_DEFINE_UNQUOTED([INTDIV0_RAISES_SIGFPE], [$value], + [Define if integer division by zero raises signal SIGFPE.]) +]) diff --git a/m4/intl.m4 b/m4/intl.m4 new file mode 100644 index 00000000..335b23c2 --- /dev/null +++ b/m4/intl.m4 @@ -0,0 +1,294 @@ +# intl.m4 serial 17 (gettext-0.18) +dnl Copyright (C) 1995-2009 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2009. + +AC_PREREQ([2.52]) + +dnl Checks for all prerequisites of the intl subdirectory, +dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS, +dnl USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL. +AC_DEFUN([AM_INTL_SUBDIR], +[ + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + AC_REQUIRE([gt_GLIBC2])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([gl_VISIBILITY])dnl + AC_REQUIRE([gt_INTL_SUBDIR_CORE])dnl + AC_REQUIRE([AC_TYPE_LONG_LONG_INT])dnl + AC_REQUIRE([gt_TYPE_WCHAR_T])dnl + AC_REQUIRE([gt_TYPE_WINT_T])dnl + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gt_TYPE_INTMAX_T]) + AC_REQUIRE([gt_PRINTF_POSIX]) + AC_REQUIRE([gl_GLIBC21])dnl + AC_REQUIRE([gl_XSIZE])dnl + AC_REQUIRE([gl_FCNTL_O_FLAGS])dnl + AC_REQUIRE([gt_INTL_MACOSX])dnl + + dnl Support for automake's --enable-silent-rules. + case "$enable_silent_rules" in + yes) INTL_DEFAULT_VERBOSITY=0;; + no) INTL_DEFAULT_VERBOSITY=1;; + *) INTL_DEFAULT_VERBOSITY=1;; + esac + AC_SUBST([INTL_DEFAULT_VERBOSITY]) + + AC_CHECK_TYPE([ptrdiff_t], , + [AC_DEFINE([ptrdiff_t], [long], + [Define as the type of the result of subtracting two pointers, if the system doesn't define it.]) + ]) + AC_CHECK_HEADERS([stddef.h stdlib.h string.h]) + AC_CHECK_FUNCS([asprintf fwprintf newlocale putenv setenv setlocale \ + snprintf strnlen wcslen wcsnlen mbrtowc wcrtomb]) + + dnl Use the _snprintf function only if it is declared (because on NetBSD it + dnl is defined as a weak alias of snprintf; we prefer to use the latter). + gt_CHECK_DECL(_snprintf, [#include ]) + gt_CHECK_DECL(_snwprintf, [#include ]) + + dnl Use the *_unlocked functions only if they are declared. + dnl (because some of them were defined without being declared in Solaris + dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built + dnl on Solaris 2.5.1 to run on Solaris 2.6). + dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. + gt_CHECK_DECL(getc_unlocked, [#include ]) + + case $gt_cv_func_printf_posix in + *yes) HAVE_POSIX_PRINTF=1 ;; + *) HAVE_POSIX_PRINTF=0 ;; + esac + AC_SUBST([HAVE_POSIX_PRINTF]) + if test "$ac_cv_func_asprintf" = yes; then + HAVE_ASPRINTF=1 + else + HAVE_ASPRINTF=0 + fi + AC_SUBST([HAVE_ASPRINTF]) + if test "$ac_cv_func_snprintf" = yes; then + HAVE_SNPRINTF=1 + else + HAVE_SNPRINTF=0 + fi + AC_SUBST([HAVE_SNPRINTF]) + if test "$ac_cv_func_newlocale" = yes; then + HAVE_NEWLOCALE=1 + else + HAVE_NEWLOCALE=0 + fi + AC_SUBST([HAVE_NEWLOCALE]) + if test "$ac_cv_func_wprintf" = yes; then + HAVE_WPRINTF=1 + else + HAVE_WPRINTF=0 + fi + AC_SUBST([HAVE_WPRINTF]) + + AM_LANGINFO_CODESET + gt_LC_MESSAGES + + dnl Compilation on mingw and Cygwin needs special Makefile rules, because + dnl 1. when we install a shared library, we must arrange to export + dnl auxiliary pointer variables for every exported variable, + dnl 2. when we install a shared library and a static library simultaneously, + dnl the include file specifies __declspec(dllimport) and therefore we + dnl must arrange to define the auxiliary pointer variables for the + dnl exported variables _also_ in the static library. + if test "$enable_shared" = yes; then + case "$host_os" in + mingw* | cygwin*) is_woe32dll=yes ;; + *) is_woe32dll=no ;; + esac + else + is_woe32dll=no + fi + WOE32DLL=$is_woe32dll + AC_SUBST([WOE32DLL]) + + dnl On mingw and Cygwin, we can activate special Makefile rules which add + dnl version information to the shared libraries and executables. + case "$host_os" in + mingw* | cygwin*) is_woe32=yes ;; + *) is_woe32=no ;; + esac + WOE32=$is_woe32 + AC_SUBST([WOE32]) + if test $WOE32 = yes; then + dnl Check for a program that compiles Windows resource files. + AC_CHECK_TOOL([WINDRES], [windres]) + fi + + dnl Determine whether when creating a library, "-lc" should be passed to + dnl libtool or not. On many platforms, it is required for the libtool option + dnl -no-undefined to work. On HP-UX, however, the -lc - stored by libtool + dnl in the *.la files - makes it impossible to create multithreaded programs, + dnl because libtool also reorders the -lc to come before the -pthread, and + dnl this disables pthread_create() . + case "$host_os" in + hpux*) LTLIBC="" ;; + *) LTLIBC="-lc" ;; + esac + AC_SUBST([LTLIBC]) + + dnl Rename some macros and functions used for locking. + AH_BOTTOM([ +#define __libc_lock_t gl_lock_t +#define __libc_lock_define gl_lock_define +#define __libc_lock_define_initialized gl_lock_define_initialized +#define __libc_lock_init gl_lock_init +#define __libc_lock_lock gl_lock_lock +#define __libc_lock_unlock gl_lock_unlock +#define __libc_lock_recursive_t gl_recursive_lock_t +#define __libc_lock_define_recursive gl_recursive_lock_define +#define __libc_lock_define_initialized_recursive gl_recursive_lock_define_initialized +#define __libc_lock_init_recursive gl_recursive_lock_init +#define __libc_lock_lock_recursive gl_recursive_lock_lock +#define __libc_lock_unlock_recursive gl_recursive_lock_unlock +#define glthread_in_use libintl_thread_in_use +#define glthread_lock_init_func libintl_lock_init_func +#define glthread_lock_lock_func libintl_lock_lock_func +#define glthread_lock_unlock_func libintl_lock_unlock_func +#define glthread_lock_destroy_func libintl_lock_destroy_func +#define glthread_rwlock_init_multithreaded libintl_rwlock_init_multithreaded +#define glthread_rwlock_init_func libintl_rwlock_init_func +#define glthread_rwlock_rdlock_multithreaded libintl_rwlock_rdlock_multithreaded +#define glthread_rwlock_rdlock_func libintl_rwlock_rdlock_func +#define glthread_rwlock_wrlock_multithreaded libintl_rwlock_wrlock_multithreaded +#define glthread_rwlock_wrlock_func libintl_rwlock_wrlock_func +#define glthread_rwlock_unlock_multithreaded libintl_rwlock_unlock_multithreaded +#define glthread_rwlock_unlock_func libintl_rwlock_unlock_func +#define glthread_rwlock_destroy_multithreaded libintl_rwlock_destroy_multithreaded +#define glthread_rwlock_destroy_func libintl_rwlock_destroy_func +#define glthread_recursive_lock_init_multithreaded libintl_recursive_lock_init_multithreaded +#define glthread_recursive_lock_init_func libintl_recursive_lock_init_func +#define glthread_recursive_lock_lock_multithreaded libintl_recursive_lock_lock_multithreaded +#define glthread_recursive_lock_lock_func libintl_recursive_lock_lock_func +#define glthread_recursive_lock_unlock_multithreaded libintl_recursive_lock_unlock_multithreaded +#define glthread_recursive_lock_unlock_func libintl_recursive_lock_unlock_func +#define glthread_recursive_lock_destroy_multithreaded libintl_recursive_lock_destroy_multithreaded +#define glthread_recursive_lock_destroy_func libintl_recursive_lock_destroy_func +#define glthread_once_func libintl_once_func +#define glthread_once_singlethreaded libintl_once_singlethreaded +#define glthread_once_multithreaded libintl_once_multithreaded +]) +]) + + +dnl Checks for the core files of the intl subdirectory: +dnl dcigettext.c +dnl eval-plural.h +dnl explodename.c +dnl finddomain.c +dnl gettextP.h +dnl gmo.h +dnl hash-string.h hash-string.c +dnl l10nflist.c +dnl libgnuintl.h.in (except the *printf stuff) +dnl loadinfo.h +dnl loadmsgcat.c +dnl localealias.c +dnl log.c +dnl plural-exp.h plural-exp.c +dnl plural.y +dnl Used by libglocale. +AC_DEFUN([gt_INTL_SUBDIR_CORE], +[ + AC_REQUIRE([AC_C_INLINE])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + AC_REQUIRE([gt_INTDIV0])dnl + AC_REQUIRE([gl_AC_TYPE_UINTMAX_T])dnl + AC_REQUIRE([gt_INTTYPES_PRI])dnl + AC_REQUIRE([gl_LOCK])dnl + + AC_TRY_LINK( + [int foo (int a) { a = __builtin_expect (a, 10); return a == 10 ? 0 : 1; }], + [], + [AC_DEFINE([HAVE_BUILTIN_EXPECT], [1], + [Define to 1 if the compiler understands __builtin_expect.])]) + + AC_CHECK_HEADERS([argz.h inttypes.h limits.h unistd.h sys/param.h]) + AC_CHECK_FUNCS([getcwd getegid geteuid getgid getuid mempcpy munmap \ + stpcpy strcasecmp strdup strtoul tsearch uselocale argz_count \ + argz_stringify argz_next __fsetlocking]) + + dnl Use the *_unlocked functions only if they are declared. + dnl (because some of them were defined without being declared in Solaris + dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built + dnl on Solaris 2.5.1 to run on Solaris 2.6). + dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. + gt_CHECK_DECL([feof_unlocked], [#include ]) + gt_CHECK_DECL([fgets_unlocked], [#include ]) + + AM_ICONV + + dnl intl/plural.c is generated from intl/plural.y. It requires bison, + dnl because plural.y uses bison specific features. It requires at least + dnl bison-1.26 because earlier versions generate a plural.c that doesn't + dnl compile. + dnl bison is only needed for the maintainer (who touches plural.y). But in + dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put + dnl the rule in general Makefile. Now, some people carelessly touch the + dnl files or have a broken "make" program, hence the plural.c rule will + dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not + dnl present or too old. + AC_CHECK_PROGS([INTLBISON], [bison]) + if test -z "$INTLBISON"; then + ac_verc_fail=yes + else + dnl Found it, now check the version. + AC_MSG_CHECKING([version of bison]) +changequote(<<,>>)dnl + ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` + case $ac_prog_version in + '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; + 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) +changequote([,])dnl + ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; + *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; + esac + AC_MSG_RESULT([$ac_prog_version]) + fi + if test $ac_verc_fail = yes; then + INTLBISON=: + fi +]) + + +dnl gt_CHECK_DECL(FUNC, INCLUDES) +dnl Check whether a function is declared. +AC_DEFUN([gt_CHECK_DECL], +[ + AC_CACHE_CHECK([whether $1 is declared], [ac_cv_have_decl_$1], + [AC_TRY_COMPILE([$2], [ +#ifndef $1 + char *p = (char *) $1; +#endif +], ac_cv_have_decl_$1=yes, ac_cv_have_decl_$1=no)]) + if test $ac_cv_have_decl_$1 = yes; then + gt_value=1 + else + gt_value=0 + fi + AC_DEFINE_UNQUOTED([HAVE_DECL_]translit($1, [a-z], [A-Z]), [$gt_value], + [Define to 1 if you have the declaration of `$1', and to 0 if you don't.]) +]) diff --git a/m4/intldir.m4 b/m4/intldir.m4 new file mode 100644 index 00000000..ebae76d3 --- /dev/null +++ b/m4/intldir.m4 @@ -0,0 +1,19 @@ +# intldir.m4 serial 2 (gettext-0.18) +dnl Copyright (C) 2006, 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +AC_PREREQ([2.52]) + +dnl Tells the AM_GNU_GETTEXT macro to consider an intl/ directory. +AC_DEFUN([AM_GNU_GETTEXT_INTL_SUBDIR], []) diff --git a/m4/intlmacosx.m4 b/m4/intlmacosx.m4 new file mode 100644 index 00000000..dd910259 --- /dev/null +++ b/m4/intlmacosx.m4 @@ -0,0 +1,51 @@ +# intlmacosx.m4 serial 3 (gettext-0.18) +dnl Copyright (C) 2004-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Checks for special options needed on MacOS X. +dnl Defines INTL_MACOSX_LIBS. +AC_DEFUN([gt_INTL_MACOSX], +[ + dnl Check for API introduced in MacOS X 10.2. + AC_CACHE_CHECK([for CFPreferencesCopyAppValue], + [gt_cv_func_CFPreferencesCopyAppValue], + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_TRY_LINK([#include ], + [CFPreferencesCopyAppValue(NULL, NULL)], + [gt_cv_func_CFPreferencesCopyAppValue=yes], + [gt_cv_func_CFPreferencesCopyAppValue=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], [1], + [Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) + fi + dnl Check for API introduced in MacOS X 10.3. + AC_CACHE_CHECK([for CFLocaleCopyCurrent], [gt_cv_func_CFLocaleCopyCurrent], + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_TRY_LINK([#include ], [CFLocaleCopyCurrent();], + [gt_cv_func_CFLocaleCopyCurrent=yes], + [gt_cv_func_CFLocaleCopyCurrent=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], [1], + [Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + AC_SUBST([INTL_MACOSX_LIBS]) +]) diff --git a/m4/intmax.m4 b/m4/intmax.m4 new file mode 100644 index 00000000..74aaaf5e --- /dev/null +++ b/m4/intmax.m4 @@ -0,0 +1,33 @@ +# intmax.m4 serial 5 (gettext-0.18) +dnl Copyright (C) 2002-2005, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether the system has the 'intmax_t' type, but don't attempt to +dnl find a replacement if it is lacking. + +AC_DEFUN([gt_TYPE_INTMAX_T], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + AC_CACHE_CHECK([for intmax_t], [gt_cv_c_intmax_t], + [AC_TRY_COMPILE([ +#include +#include +#if HAVE_STDINT_H_WITH_UINTMAX +#include +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +#include +#endif +], [intmax_t x = -1; + return !x;], + [gt_cv_c_intmax_t=yes], + [gt_cv_c_intmax_t=no])]) + if test $gt_cv_c_intmax_t = yes; then + AC_DEFINE([HAVE_INTMAX_T], [1], + [Define if you have the 'intmax_t' type in or .]) + fi +]) diff --git a/m4/inttypes-pri.m4 b/m4/inttypes-pri.m4 new file mode 100644 index 00000000..718a4f4e --- /dev/null +++ b/m4/inttypes-pri.m4 @@ -0,0 +1,36 @@ +# inttypes-pri.m4 serial 6 (gettext-0.18) +dnl Copyright (C) 1997-2002, 2006, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_PREREQ([2.52]) + +# Define PRI_MACROS_BROKEN if exists and defines the PRI* +# macros to non-string values. This is the case on AIX 4.3.3. + +AC_DEFUN([gt_INTTYPES_PRI], +[ + AC_CHECK_HEADERS([inttypes.h]) + if test $ac_cv_header_inttypes_h = yes; then + AC_CACHE_CHECK([whether the inttypes.h PRIxNN macros are broken], + [gt_cv_inttypes_pri_broken], + [ + AC_TRY_COMPILE([#include +#ifdef PRId32 +char *p = PRId32; +#endif +], [], [gt_cv_inttypes_pri_broken=no], [gt_cv_inttypes_pri_broken=yes]) + ]) + fi + if test "$gt_cv_inttypes_pri_broken" = yes; then + AC_DEFINE_UNQUOTED([PRI_MACROS_BROKEN], [1], + [Define if exists and defines unusable PRI* macros.]) + PRI_MACROS_BROKEN=1 + else + PRI_MACROS_BROKEN=0 + fi + AC_SUBST([PRI_MACROS_BROKEN]) +]) diff --git a/m4/inttypes_h.m4 b/m4/inttypes_h.m4 new file mode 100644 index 00000000..782d77ed --- /dev/null +++ b/m4/inttypes_h.m4 @@ -0,0 +1,26 @@ +# inttypes_h.m4 serial 9 +dnl Copyright (C) 1997-2004, 2006, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_INTTYPES_H_WITH_UINTMAX if exists, +# doesn't clash with , and declares uintmax_t. + +AC_DEFUN([gl_AC_HEADER_INTTYPES_H], +[ + AC_CACHE_CHECK([for inttypes.h], [gl_cv_header_inttypes_h], + [AC_TRY_COMPILE( + [#include +#include ], + [uintmax_t i = (uintmax_t) -1; return !i;], + [gl_cv_header_inttypes_h=yes], + [gl_cv_header_inttypes_h=no])]) + if test $gl_cv_header_inttypes_h = yes; then + AC_DEFINE_UNQUOTED([HAVE_INTTYPES_H_WITH_UINTMAX], [1], + [Define if exists, doesn't clash with , + and declares uintmax_t. ]) + fi +]) diff --git a/m4/lcmessage.m4 b/m4/lcmessage.m4 new file mode 100644 index 00000000..1a705431 --- /dev/null +++ b/m4/lcmessage.m4 @@ -0,0 +1,31 @@ +# lcmessage.m4 serial 6 (gettext-0.18) +dnl Copyright (C) 1995-2002, 2004-2005, 2008-2010 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995. + +# Check whether LC_MESSAGES is available in . + +AC_DEFUN([gt_LC_MESSAGES], +[ + AC_CACHE_CHECK([for LC_MESSAGES], [gt_cv_val_LC_MESSAGES], + [AC_TRY_LINK([#include ], [return LC_MESSAGES], + [gt_cv_val_LC_MESSAGES=yes], [gt_cv_val_LC_MESSAGES=no])]) + if test $gt_cv_val_LC_MESSAGES = yes; then + AC_DEFINE([HAVE_LC_MESSAGES], [1], + [Define if your file defines LC_MESSAGES.]) + fi +]) diff --git a/m4/lib-ld.m4 b/m4/lib-ld.m4 new file mode 100644 index 00000000..6209de65 --- /dev/null +++ b/m4/lib-ld.m4 @@ -0,0 +1,119 @@ +# lib-ld.m4 serial 6 +dnl Copyright (C) 1996-2003, 2009-2016 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Subroutines of libtool.m4, +dnl with replacements s/_*LT_PATH/AC_LIB_PROG/ and s/lt_/acl_/ to avoid +dnl collision with libtool.m4. + +dnl From libtool-2.4. Sets the variable with_gnu_ld to yes or no. +AC_DEFUN([AC_LIB_PROG_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], [acl_cv_prog_gnu_ld], +[# I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 /dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo "$ac_prog"| sed 's%\\\\%/%g'` + while echo "$ac_prog" | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL([acl_cv_path_LD], +[if test -z "$LD"; then + acl_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$acl_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 = 1.10 to complain if config.rpath is missing. + m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) + AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS + AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld + AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host + AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir + AC_CACHE_CHECK([for shared library run path origin], [acl_cv_rpath], [ + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + ]) + wl="$acl_cv_wl" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" + dnl Determine whether the user wants rpath handling at all. + AC_ARG_ENABLE([rpath], + [ --disable-rpath do not hardcode runtime library paths], + :, enable_rpath=yes) +]) + +dnl AC_LIB_FROMPACKAGE(name, package) +dnl declares that libname comes from the given package. The configure file +dnl will then not have a --with-libname-prefix option but a +dnl --with-package-prefix option. Several libraries can come from the same +dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar +dnl macro call that searches for libname. +AC_DEFUN([AC_LIB_FROMPACKAGE], +[ + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_frompackage_]NAME, [$2]) + popdef([NAME]) + pushdef([PACK],[$2]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_libsinpackage_]PACKUP, + m4_ifdef([acl_libsinpackage_]PACKUP, [m4_defn([acl_libsinpackage_]PACKUP)[, ]],)[lib$1]) + popdef([PACKUP]) + popdef([PACK]) +]) + +dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. +dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found +dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_LINKFLAGS_BODY], +[ + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])]) + dnl Autoconf >= 2.61 supports dots in --with options. + pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[m4_translit(PACK,[.],[_])],PACK)]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_ARG_WITH(P_A_C_K[-prefix], +[[ --with-]]P_A_C_K[[-prefix[=DIR] search for ]PACKLIBS[ in DIR/include and DIR/lib + --without-]]P_A_C_K[[-prefix don't search for ]PACKLIBS[ in includedir and libdir]], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi +]) + dnl Search the library and its dependencies in $additional_libdir and + dnl $LDFLAGS. Using breadth-first-seach. + LIB[]NAME= + LTLIB[]NAME= + INC[]NAME= + LIB[]NAME[]_PREFIX= + dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been + dnl computed. So it has to be reset here. + HAVE_LIB[]NAME= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='$1 $2' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + dnl See if it was already located by an earlier AC_LIB_LINKFLAGS + dnl or AC_LIB_HAVE_LINKFLAGS call. + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" + else + dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined + dnl that this library doesn't exist. So just drop it. + : + fi + else + dnl Search the library lib$name in $additional_libdir and $LDFLAGS + dnl and the already constructed $LIBNAME/$LTLIBNAME. + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + dnl The same code as in the loop below: + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + dnl Found the library. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + dnl Linking with a shared library. We attempt to hardcode its + dnl directory into the executable's runpath, unless it's the + dnl standard /usr/lib. + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + dnl No hardcoding is needed. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + dnl The hardcoding into $LIBNAME is system dependent. + if test "$acl_hardcode_direct" = yes; then + dnl Using DIR/libNAME.so during linking hardcodes DIR into the + dnl resulting binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + dnl Rely on "-L$found_dir". + dnl But don't add it if it's already contained in the LDFLAGS + dnl or the already constructed $LIBNAME + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH + dnl here, because this doesn't fit in flags passed to the + dnl compiler. So give up. No hardcoding. This affects only + dnl very old systems. + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + dnl Linking with a static library. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" + else + dnl We shouldn't come here, but anyway it's good to have a + dnl fallback. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" + fi + fi + dnl Assume the include files are nearby. + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + dnl Potentially add $additional_includedir to $INCNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's /usr/local/include and we are using GCC on Linux, + dnl 3. if it's already present in $CPPFLAGS or the already + dnl constructed $INCNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INC[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $INCNAME. + INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + dnl Look for dependencies. + if test -n "$found_la"; then + dnl Read the .la file. It defines the variables + dnl dlname, library_names, old_library, dependency_libs, current, + dnl age, revision, installed, dlopen, dlpreopen, libdir. + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + dnl We use only dependency_libs. + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's /usr/local/lib and we are using GCC on Linux, + dnl 3. if it's already present in $LDFLAGS or the already + dnl constructed $LIBNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LIBNAME. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LTLIBNAME. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + dnl Handle this in the next round. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + dnl Handle this in the next round. Throw away the .la's + dnl directory; it is already contained in a preceding -L + dnl option. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + dnl Most likely an immediate library name. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" + ;; + esac + done + fi + else + dnl Didn't find the library; assume it is in the system directories + dnl known to the linker and runtime loader. (All the system + dnl directories known to the linker should also be known to the + dnl runtime loader, otherwise the system is severely misconfigured.) + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user must + dnl pass all path elements in one option. We can arrange that for a + dnl single library, but not when more than one $LIBNAMEs are used. + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl. + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + else + dnl The -rpath options are cumulative. + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + dnl When using libtool, the option that works for both libraries and + dnl executables is -R. The -R options are cumulative. + for found_dir in $ltrpathdirs; do + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" + done + fi + popdef([P_A_C_K]) + popdef([PACKLIBS]) + popdef([PACKUP]) + popdef([PACK]) + popdef([NAME]) +]) + +dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, +dnl unless already present in VAR. +dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes +dnl contains two or three consecutive elements that belong together. +AC_DEFUN([AC_LIB_APPENDTOVAR], +[ + for element in [$2]; do + haveit= + for x in $[$1]; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + [$1]="${[$1]}${[$1]:+ }$element" + fi + done +]) + +dnl For those cases where a variable contains several -L and -l options +dnl referring to unknown libraries and directories, this macro determines the +dnl necessary additional linker options for the runtime path. +dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL]) +dnl sets LDADDVAR to linker options needed together with LIBSVALUE. +dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed, +dnl otherwise linking without libtool is assumed. +AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], +[ + AC_REQUIRE([AC_LIB_RPATH]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + $1= + if test "$enable_rpath" != no; then + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode directories into the resulting + dnl binary. + rpathdirs= + next= + for opt in $2; do + if test -n "$next"; then + dir="$next" + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then + rpathdirs="$rpathdirs $dir" + fi + next= + else + case $opt in + -L) next=yes ;; + -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'` + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then + rpathdirs="$rpathdirs $dir" + fi + next= ;; + *) next= ;; + esac + fi + done + if test "X$rpathdirs" != "X"; then + if test -n ""$3""; then + dnl libtool is used for linking. Use -R options. + for dir in $rpathdirs; do + $1="${$1}${$1:+ }-R$dir" + done + else + dnl The linker is used for linking directly. + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user + dnl must pass all path elements in one option. + alldirs= + for dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="$flag" + else + dnl The -rpath options are cumulative. + for dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="${$1}${$1:+ }$flag" + done + fi + fi + fi + fi + fi + AC_SUBST([$1]) +]) diff --git a/m4/lib-prefix.m4 b/m4/lib-prefix.m4 new file mode 100644 index 00000000..6851031d --- /dev/null +++ b/m4/lib-prefix.m4 @@ -0,0 +1,224 @@ +# lib-prefix.m4 serial 7 (gettext-0.18) +dnl Copyright (C) 2001-2005, 2008-2016 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and +dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't +dnl require excessive bracketing. +ifdef([AC_HELP_STRING], +[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], +[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) + +dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed +dnl to access previously installed libraries. The basic assumption is that +dnl a user will want packages to use other packages he previously installed +dnl with the same --prefix option. +dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate +dnl libraries, but is otherwise very convenient. +AC_DEFUN([AC_LIB_PREFIX], +[ + AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_LIB_ARG_WITH([lib-prefix], +[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib + --without-lib-prefix don't search for libraries in includedir and libdir], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi +]) + if test $use_additional = yes; then + dnl Potentially add $additional_includedir to $CPPFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's already present in $CPPFLAGS, + dnl 3. if it's /usr/local/include and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + for x in $CPPFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $CPPFLAGS. + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" + fi + fi + fi + fi + dnl Potentially add $additional_libdir to $LDFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's already present in $LDFLAGS, + dnl 3. if it's /usr/local/lib and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + for x in $LDFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LDFLAGS. + LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" + fi + fi + fi + fi + fi +]) + +dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, +dnl acl_final_exec_prefix, containing the values to which $prefix and +dnl $exec_prefix will expand at the end of the configure script. +AC_DEFUN([AC_LIB_PREPARE_PREFIX], +[ + dnl Unfortunately, prefix and exec_prefix get only finally determined + dnl at the end of configure. + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the +dnl variables prefix and exec_prefix bound to the values they will have +dnl at the end of the configure script. +AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], +[ + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + $1 + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_PREPARE_MULTILIB creates +dnl - a variable acl_libdirstem, containing the basename of the libdir, either +dnl "lib" or "lib64" or "lib/64", +dnl - a variable acl_libdirstem2, as a secondary possible value for +dnl acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or +dnl "lib/amd64". +AC_DEFUN([AC_LIB_PREPARE_MULTILIB], +[ + dnl There is no formal standard regarding lib and lib64. + dnl On glibc systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine + dnl the compiler's default mode by looking at the compiler's library search + dnl path. If at least one of its elements ends in /lib64 or points to a + dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI. + dnl Otherwise we use the default, namely "lib". + dnl On Solaris systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or + dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib. + AC_REQUIRE([AC_CANONICAL_HOST]) + acl_libdirstem=lib + acl_libdirstem2= + case "$host_os" in + solaris*) + dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development Environment + dnl . + dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link." + dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the + dnl symlink is missing, so we set acl_libdirstem2 too. + AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit], + [AC_EGREP_CPP([sixtyfour bits], [ +#ifdef _LP64 +sixtyfour bits +#endif + ], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no]) + ]) + if test $gl_cv_solaris_64bit = yes; then + acl_libdirstem=lib/64 + case "$host_cpu" in + sparc*) acl_libdirstem2=lib/sparcv9 ;; + i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; + esac + fi + ;; + *) + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + */../ | */.. ) + # Better ignore directories of this form. They are misleading. + ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi + ;; + esac + test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" +]) diff --git a/m4/libtool.m4 b/m4/libtool.m4 new file mode 100644 index 00000000..ee80844b --- /dev/null +++ b/m4/libtool.m4 @@ -0,0 +1,8387 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +]) + +# serial 58 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + +# _LT_CC_BASENAME(CC) +# ------------------- +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. +m4_defun([_LT_CC_BASENAME], +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from 'configure', and 'config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain=$ac_aux_dir/ltmain.sh +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the 'libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags='_LT_TAGS'dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# '#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test 0 = "$lt_write_fail" && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +'$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test 0 != $[#] +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try '$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try '$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test yes = "$silent" && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +_LT_COPYING +_LT_LIBTOOL_TAGS + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS=$save_LDFLAGS + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[[012]][[,.]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + m4_if([$1], [CXX], +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case $ECHO in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([$with_sysroot]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and where our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test yes = "[$]$2"; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS +]) + +if test yes = "[$]$2"; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n "$lt_cv_sys_max_cmd_len"; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes = "$cross_compiling"; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen=shl_load], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen=dlopen], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then + + # We can hardcode non-existent directories. + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program that can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac]) +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program that can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test no = "$withval" || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + +# _LT_CHECK_MAGIC_METHOD +# ---------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_MAGIC_METHOD], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +AC_CACHE_CHECK([how to recognize dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[[4-9]]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[[45]]*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi]) +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM=-lm) + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test yes = "$GCC"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + _LT_TAGVAR(link_all_deplibs, $1)=no + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + osf3*) + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting $shlibpath_var if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC=$CC +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report what library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC=$lt_save_CC +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)=$prev$p + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)=$p + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)=$p + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test no = "$F77"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_F77"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test no = "$FC"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_FC"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_FC" + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code=$lt_simple_compile_test_code + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f "$lt_ac_sed" && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test 10 -lt "$lt_ac_count" && break + lt_ac_count=`expr $lt_ac_count + 1` + if test "$lt_ac_count" -gt "$lt_ac_max"; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine what file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/m4/lock.m4 b/m4/lock.m4 new file mode 100644 index 00000000..9da8465e --- /dev/null +++ b/m4/lock.m4 @@ -0,0 +1,37 @@ +# lock.m4 serial 10 (gettext-0.18) +dnl Copyright (C) 2005-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gl_LOCK], +[ + AC_REQUIRE([gl_THREADLIB]) + if test "$gl_threads_api" = posix; then + # OSF/1 4.0 and MacOS X 10.1 lack the pthread_rwlock_t type and the + # pthread_rwlock_* functions. + AC_CHECK_TYPE([pthread_rwlock_t], + [AC_DEFINE([HAVE_PTHREAD_RWLOCK], [1], + [Define if the POSIX multithreading library has read/write locks.])], + [], + [#include ]) + # glibc defines PTHREAD_MUTEX_RECURSIVE as enum, not as a macro. + AC_TRY_COMPILE([#include ], + [#if __FreeBSD__ == 4 +error "No, in FreeBSD 4.0 recursive mutexes actually don't work." +#else +int x = (int)PTHREAD_MUTEX_RECURSIVE; +return !x; +#endif], + [AC_DEFINE([HAVE_PTHREAD_MUTEX_RECURSIVE], [1], + [Define if the defines PTHREAD_MUTEX_RECURSIVE.])]) + fi + gl_PREREQ_LOCK +]) + +# Prerequisites of lib/lock.c. +AC_DEFUN([gl_PREREQ_LOCK], [ + AC_REQUIRE([AC_C_INLINE]) +]) diff --git a/m4/longlong.m4 b/m4/longlong.m4 new file mode 100644 index 00000000..cca3c1a9 --- /dev/null +++ b/m4/longlong.m4 @@ -0,0 +1,106 @@ +# longlong.m4 serial 14 +dnl Copyright (C) 1999-2007, 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_LONG_LONG_INT if 'long long int' works. +# This fixes a bug in Autoconf 2.61, but can be removed once we +# assume 2.62 everywhere. + +# Note: If the type 'long long int' exists but is only 32 bits large +# (as on some very old compilers), HAVE_LONG_LONG_INT will not be +# defined. In this case you can treat 'long long int' like 'long int'. + +AC_DEFUN([AC_TYPE_LONG_LONG_INT], +[ + AC_CACHE_CHECK([for long long int], [ac_cv_type_long_long_int], + [AC_LINK_IFELSE( + [_AC_TYPE_LONG_LONG_SNIPPET], + [dnl This catches a bug in Tandem NonStop Kernel (OSS) cc -O circa 2004. + dnl If cross compiling, assume the bug isn't important, since + dnl nobody cross compiles for this platform as far as we know. + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[@%:@include + @%:@ifndef LLONG_MAX + @%:@ define HALF \ + (1LL << (sizeof (long long int) * CHAR_BIT - 2)) + @%:@ define LLONG_MAX (HALF - 1 + HALF) + @%:@endif]], + [[long long int n = 1; + int i; + for (i = 0; ; i++) + { + long long int m = n << i; + if (m >> i != n) + return 1; + if (LLONG_MAX / 2 < m) + break; + } + return 0;]])], + [ac_cv_type_long_long_int=yes], + [ac_cv_type_long_long_int=no], + [ac_cv_type_long_long_int=yes])], + [ac_cv_type_long_long_int=no])]) + if test $ac_cv_type_long_long_int = yes; then + AC_DEFINE([HAVE_LONG_LONG_INT], [1], + [Define to 1 if the system has the type `long long int'.]) + fi +]) + +# Define HAVE_UNSIGNED_LONG_LONG_INT if 'unsigned long long int' works. +# This fixes a bug in Autoconf 2.61, but can be removed once we +# assume 2.62 everywhere. + +# Note: If the type 'unsigned long long int' exists but is only 32 bits +# large (as on some very old compilers), AC_TYPE_UNSIGNED_LONG_LONG_INT +# will not be defined. In this case you can treat 'unsigned long long int' +# like 'unsigned long int'. + +AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT], +[ + AC_CACHE_CHECK([for unsigned long long int], + [ac_cv_type_unsigned_long_long_int], + [AC_LINK_IFELSE( + [_AC_TYPE_LONG_LONG_SNIPPET], + [ac_cv_type_unsigned_long_long_int=yes], + [ac_cv_type_unsigned_long_long_int=no])]) + if test $ac_cv_type_unsigned_long_long_int = yes; then + AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], [1], + [Define to 1 if the system has the type `unsigned long long int'.]) + fi +]) + +# Expands to a C program that can be used to test for simultaneous support +# of 'long long' and 'unsigned long long'. We don't want to say that +# 'long long' is available if 'unsigned long long' is not, or vice versa, +# because too many programs rely on the symmetry between signed and unsigned +# integer types (excluding 'bool'). +AC_DEFUN([_AC_TYPE_LONG_LONG_SNIPPET], +[ + AC_LANG_PROGRAM( + [[/* For now, do not test the preprocessor; as of 2007 there are too many + implementations with broken preprocessors. Perhaps this can + be revisited in 2012. In the meantime, code should not expect + #if to work with literals wider than 32 bits. */ + /* Test literals. */ + long long int ll = 9223372036854775807ll; + long long int nll = -9223372036854775807LL; + unsigned long long int ull = 18446744073709551615ULL; + /* Test constant expressions. */ + typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + ? 1 : -1)]; + typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 + ? 1 : -1)]; + int i = 63;]], + [[/* Test availability of runtime routines for shift and division. */ + long long int llmax = 9223372036854775807ll; + unsigned long long int ullmax = 18446744073709551615ull; + return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) + | (llmax / ll) | (llmax % ll) + | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) + | (ullmax / ull) | (ullmax % ull));]]) +]) diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4 new file mode 100644 index 00000000..94b08297 --- /dev/null +++ b/m4/ltoptions.m4 @@ -0,0 +1,437 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 8 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option '$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' +# LT_INIT options. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [pic_mode=m4_default([$1], [default])]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/m4/ltsugar.m4 b/m4/ltsugar.m4 new file mode 100644 index 00000000..48bc9344 --- /dev/null +++ b/m4/ltsugar.m4 @@ -0,0 +1,124 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59, which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/m4/ltversion.m4 b/m4/ltversion.m4 new file mode 100644 index 00000000..fa04b52a --- /dev/null +++ b/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 4179 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.6' +macro_revision='2.4.6' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4 new file mode 100644 index 00000000..c6b26f88 --- /dev/null +++ b/m4/lt~obsolete.m4 @@ -0,0 +1,99 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/m4/nls.m4 b/m4/nls.m4 new file mode 100644 index 00000000..afdb9cac --- /dev/null +++ b/m4/nls.m4 @@ -0,0 +1,32 @@ +# nls.m4 serial 5 (gettext-0.18) +dnl Copyright (C) 1995-2003, 2005-2006, 2008-2014, 2016 Free Software +dnl Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ([2.50]) + +AC_DEFUN([AM_NLS], +[ + AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE([nls], + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT([$USE_NLS]) + AC_SUBST([USE_NLS]) +]) diff --git a/m4/po.m4 b/m4/po.m4 new file mode 100644 index 00000000..c5a2f6bf --- /dev/null +++ b/m4/po.m4 @@ -0,0 +1,453 @@ +# po.m4 serial 24 (gettext-0.19) +dnl Copyright (C) 1995-2014, 2016 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ([2.60]) + +dnl Checks for all prerequisites of the po subdirectory. +AC_DEFUN([AM_PO_SUBDIRS], +[ + AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AC_PROG_MKDIR_P])dnl + AC_REQUIRE([AC_PROG_SED])dnl + AC_REQUIRE([AM_NLS])dnl + + dnl Release version of the gettext macros. This is used to ensure that + dnl the gettext macros and po/Makefile.in.in are in sync. + AC_SUBST([GETTEXT_MACRO_VERSION], [0.19]) + + dnl Perform the following tests also if --disable-nls has been given, + dnl because they are needed for "make dist" to work. + + dnl Search for GNU msgfmt in the PATH. + dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions. + dnl The second test excludes FreeBSD msgfmt. + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + AC_PATH_PROG([GMSGFMT], [gmsgfmt], [$MSGFMT]) + + dnl Test whether it is GNU msgfmt >= 0.15. +changequote(,)dnl + case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; + *) MSGFMT_015=$MSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([MSGFMT_015]) +changequote(,)dnl + case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; + *) GMSGFMT_015=$GMSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([GMSGFMT_015]) + + dnl Search for GNU xgettext 0.12 or newer in the PATH. + dnl The first test excludes Solaris xgettext and early GNU xgettext versions. + dnl The second test excludes FreeBSD xgettext. + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + dnl Remove leftover from FreeBSD xgettext call. + rm -f messages.po + + dnl Test whether it is GNU xgettext >= 0.15. +changequote(,)dnl + case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; + *) XGETTEXT_015=$XGETTEXT ;; + esac +changequote([,])dnl + AC_SUBST([XGETTEXT_015]) + + dnl Search for GNU msgmerge 0.11 or newer in the PATH. + AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, + [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :) + + dnl Installation directories. + dnl Autoconf >= 2.60 defines localedir. For older versions of autoconf, we + dnl have to define it here, so that it can be used in po/Makefile. + test -n "$localedir" || localedir='${datadir}/locale' + AC_SUBST([localedir]) + + dnl Support for AM_XGETTEXT_OPTION. + test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= + AC_SUBST([XGETTEXT_EXTRA_OPTIONS]) + + AC_CONFIG_COMMANDS([po-directories], [[ + for ac_file in $CONFIG_FILES; do + # Support "outfile[:infile[:infile...]]" + case "$ac_file" in + *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + esac + # PO directories have a Makefile.in generated from Makefile.in.in. + case "$ac_file" in */Makefile.in) + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + # Treat a directory as a PO directory if and only if it has a + # POTFILES.in file. This allows packages to have multiple PO + # directories under different names or in different locations. + if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then + rm -f "$ac_dir/POTFILES" + test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" + gt_tab=`printf '\t'` + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ${gt_tab}]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + POMAKEFILEDEPS="POTFILES.in" + # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend + # on $ac_dir but don't depend on user-specified configuration + # parameters. + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' + fi + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + done + fi + test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" + sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" + for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do + if test -f "$f"; then + case "$f" in + *.orig | *.bak | *~) ;; + *) cat "$f" >> "$ac_dir/Makefile" ;; + esac + fi + done + fi + ;; + esac + done]], + [# Capture the value of obsolete ALL_LINGUAS because we need it to compute + # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it + # from automake < 1.5. + eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' + # Capture the value of LINGUAS because we need it to compute CATALOGS. + LINGUAS="${LINGUAS-%UNSET%}" + ]) +]) + +dnl Postprocesses a Makefile in a directory containing PO files. +AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE], +[ + # When this code is run, in config.status, two variables have already been + # set: + # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in, + # - LINGUAS is the value of the environment variable LINGUAS at configure + # time. + +changequote(,)dnl + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + # Find a way to echo strings without interpreting backslash. + if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='echo' + else + if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='printf %s\n' + else + echo_func () { + cat < "$ac_file.tmp" + tab=`printf '\t'` + if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + cat >> "$ac_file.tmp" < /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'` + cat >> "$ac_file.tmp" <> "$ac_file.tmp" < +#include +/* The string "%2$d %1$d", with dollar characters protected from the shell's + dollar expansion (possibly an autoconf bug). */ +static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' }; +static char buf[100]; +int main () +{ + sprintf (buf, format, 33, 55); + return (strcmp (buf, "55 33") != 0); +}], gt_cv_func_printf_posix=yes, gt_cv_func_printf_posix=no, + [ + AC_EGREP_CPP([notposix], [ +#if defined __NetBSD__ || defined __BEOS__ || defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ + notposix +#endif + ], + [gt_cv_func_printf_posix="guessing no"], + [gt_cv_func_printf_posix="guessing yes"]) + ]) + ]) + case $gt_cv_func_printf_posix in + *yes) + AC_DEFINE([HAVE_POSIX_PRINTF], [1], + [Define if your printf() function supports format strings with positions.]) + ;; + esac +]) diff --git a/m4/progtest.m4 b/m4/progtest.m4 new file mode 100644 index 00000000..9ace7c34 --- /dev/null +++ b/m4/progtest.m4 @@ -0,0 +1,91 @@ +# progtest.m4 serial 7 (gettext-0.18.2) +dnl Copyright (C) 1996-2003, 2005, 2008-2016 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1996. + +AC_PREREQ([2.50]) + +# Search path for a program which passes the given test. + +dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN([AM_PATH_PROG_WITH_TEST], +[ +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL([ac_cv_path_$1], +[case "[$]$1" in + [[\\/]]* | ?:[[\\/]]*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in ifelse([$5], , $PATH, [$5]); do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then + AC_MSG_RESULT([$][$1]) +else + AC_MSG_RESULT([no]) +fi +AC_SUBST([$1])dnl +]) diff --git a/m4/size_max.m4 b/m4/size_max.m4 new file mode 100644 index 00000000..ce992db1 --- /dev/null +++ b/m4/size_max.m4 @@ -0,0 +1,75 @@ +# size_max.m4 serial 9 +dnl Copyright (C) 2003, 2005-2006, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gl_SIZE_MAX], +[ + AC_CHECK_HEADERS([stdint.h]) + dnl First test whether the system already has SIZE_MAX. + AC_CACHE_CHECK([for SIZE_MAX], [gl_cv_size_max], [ + gl_cv_size_max= + AC_EGREP_CPP([Found it], [ +#include +#if HAVE_STDINT_H +#include +#endif +#ifdef SIZE_MAX +Found it +#endif +], [gl_cv_size_max=yes]) + if test -z "$gl_cv_size_max"; then + dnl Define it ourselves. Here we assume that the type 'size_t' is not wider + dnl than the type 'unsigned long'. Try hard to find a definition that can + dnl be used in a preprocessor #if, i.e. doesn't contain a cast. + AC_COMPUTE_INT([size_t_bits_minus_1], [sizeof (size_t) * CHAR_BIT - 1], + [#include +#include ], [size_t_bits_minus_1=]) + AC_COMPUTE_INT([fits_in_uint], [sizeof (size_t) <= sizeof (unsigned int)], + [#include ], [fits_in_uint=]) + if test -n "$size_t_bits_minus_1" && test -n "$fits_in_uint"; then + if test $fits_in_uint = 1; then + dnl Even though SIZE_MAX fits in an unsigned int, it must be of type + dnl 'unsigned long' if the type 'size_t' is the same as 'unsigned long'. + AC_TRY_COMPILE([#include + extern size_t foo; + extern unsigned long foo; + ], [], [fits_in_uint=0]) + fi + dnl We cannot use 'expr' to simplify this expression, because 'expr' + dnl works only with 'long' integers in the host environment, while we + dnl might be cross-compiling from a 32-bit platform to a 64-bit platform. + if test $fits_in_uint = 1; then + gl_cv_size_max="(((1U << $size_t_bits_minus_1) - 1) * 2 + 1)" + else + gl_cv_size_max="(((1UL << $size_t_bits_minus_1) - 1) * 2 + 1)" + fi + else + dnl Shouldn't happen, but who knows... + gl_cv_size_max='((size_t)~(size_t)0)' + fi + fi + ]) + if test "$gl_cv_size_max" != yes; then + AC_DEFINE_UNQUOTED([SIZE_MAX], [$gl_cv_size_max], + [Define as the maximum value of type 'size_t', if the system doesn't define it.]) + fi + dnl Don't redefine SIZE_MAX in config.h if config.h is re-included after + dnl . Remember that the #undef in AH_VERBATIM gets replaced with + dnl #define by AC_DEFINE_UNQUOTED. + AH_VERBATIM([SIZE_MAX], +[/* Define as the maximum value of type 'size_t', if the system doesn't define + it. */ +#ifndef SIZE_MAX +# undef SIZE_MAX +#endif]) +]) + +dnl Autoconf >= 2.61 has AC_COMPUTE_INT built-in. +dnl Remove this when we can assume autoconf >= 2.61. +m4_ifdef([AC_COMPUTE_INT], [], [ + AC_DEFUN([AC_COMPUTE_INT], [_AC_COMPUTE_INT([$2],[$1],[$3],[$4])]) +]) diff --git a/m4/stdint_h.m4 b/m4/stdint_h.m4 new file mode 100644 index 00000000..b8e3c6cc --- /dev/null +++ b/m4/stdint_h.m4 @@ -0,0 +1,26 @@ +# stdint_h.m4 serial 8 +dnl Copyright (C) 1997-2004, 2006, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_STDINT_H_WITH_UINTMAX if exists, +# doesn't clash with , and declares uintmax_t. + +AC_DEFUN([gl_AC_HEADER_STDINT_H], +[ + AC_CACHE_CHECK([for stdint.h], [gl_cv_header_stdint_h], + [AC_TRY_COMPILE( + [#include +#include ], + [uintmax_t i = (uintmax_t) -1; return !i;], + [gl_cv_header_stdint_h=yes], + [gl_cv_header_stdint_h=no])]) + if test $gl_cv_header_stdint_h = yes; then + AC_DEFINE_UNQUOTED([HAVE_STDINT_H_WITH_UINTMAX], [1], + [Define if exists, doesn't clash with , + and declares uintmax_t. ]) + fi +]) diff --git a/m4/threadlib.m4 b/m4/threadlib.m4 new file mode 100644 index 00000000..05cc4ffa --- /dev/null +++ b/m4/threadlib.m4 @@ -0,0 +1,347 @@ +# threadlib.m4 serial 5 (gettext-0.18) +dnl Copyright (C) 2005-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl gl_THREADLIB +dnl ------------ +dnl Tests for a multithreading library to be used. +dnl Defines at most one of the macros USE_POSIX_THREADS, USE_SOLARIS_THREADS, +dnl USE_PTH_THREADS, USE_WIN32_THREADS +dnl Sets the variables LIBTHREAD and LTLIBTHREAD to the linker options for use +dnl in a Makefile (LIBTHREAD for use without libtool, LTLIBTHREAD for use with +dnl libtool). +dnl Sets the variables LIBMULTITHREAD and LTLIBMULTITHREAD similarly, for +dnl programs that really need multithread functionality. The difference +dnl between LIBTHREAD and LIBMULTITHREAD is that on platforms supporting weak +dnl symbols, typically LIBTHREAD="" whereas LIBMULTITHREAD="-lpthread". +dnl Adds to CPPFLAGS the flag -D_REENTRANT or -D_THREAD_SAFE if needed for +dnl multithread-safe programs. + +AC_DEFUN([gl_THREADLIB_EARLY], +[ + AC_REQUIRE([gl_THREADLIB_EARLY_BODY]) +]) + +dnl The guts of gl_THREADLIB_EARLY. Needs to be expanded only once. + +AC_DEFUN([gl_THREADLIB_EARLY_BODY], +[ + dnl Ordering constraints: This macro modifies CPPFLAGS in a way that + dnl influences the result of the autoconf tests that test for *_unlocked + dnl declarations, on AIX 5 at least. Therefore it must come early. + AC_BEFORE([$0], [gl_FUNC_GLIBC_UNLOCKED_IO])dnl + AC_BEFORE([$0], [gl_ARGP])dnl + + AC_REQUIRE([AC_CANONICAL_HOST]) + dnl _GNU_SOURCE is needed for pthread_rwlock_t on glibc systems. + dnl AC_USE_SYSTEM_EXTENSIONS was introduced in autoconf 2.60 and obsoletes + dnl AC_GNU_SOURCE. + m4_ifdef([AC_USE_SYSTEM_EXTENSIONS], + [AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])], + [AC_REQUIRE([AC_GNU_SOURCE])]) + dnl Check for multithreading. + m4_divert_text([DEFAULTS], [gl_use_threads_default=]) + AC_ARG_ENABLE([threads], +AC_HELP_STRING([--enable-threads={posix|solaris|pth|win32}], [specify multithreading API]) +AC_HELP_STRING([--disable-threads], [build without multithread safety]), + [gl_use_threads=$enableval], + [if test -n "$gl_use_threads_default"; then + gl_use_threads="$gl_use_threads_default" + else +changequote(,)dnl + case "$host_os" in + dnl Disable multithreading by default on OSF/1, because it interferes + dnl with fork()/exec(): When msgexec is linked with -lpthread, its + dnl child process gets an endless segmentation fault inside execvp(). + dnl Disable multithreading by default on Cygwin 1.5.x, because it has + dnl bugs that lead to endless loops or crashes. See + dnl . + osf*) gl_use_threads=no ;; + cygwin*) + case `uname -r` in + 1.[0-5].*) gl_use_threads=no ;; + *) gl_use_threads=yes ;; + esac + ;; + *) gl_use_threads=yes ;; + esac +changequote([,])dnl + fi + ]) + if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then + # For using : + case "$host_os" in + osf*) + # On OSF/1, the compiler needs the flag -D_REENTRANT so that it + # groks . cc also understands the flag -pthread, but + # we don't use it because 1. gcc-2.95 doesn't understand -pthread, + # 2. putting a flag into CPPFLAGS that has an effect on the linker + # causes the AC_TRY_LINK test below to succeed unexpectedly, + # leading to wrong values of LIBTHREAD and LTLIBTHREAD. + CPPFLAGS="$CPPFLAGS -D_REENTRANT" + ;; + esac + # Some systems optimize for single-threaded programs by default, and + # need special flags to disable these optimizations. For example, the + # definition of 'errno' in . + case "$host_os" in + aix* | freebsd*) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" ;; + solaris*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;; + esac + fi +]) + +dnl The guts of gl_THREADLIB. Needs to be expanded only once. + +AC_DEFUN([gl_THREADLIB_BODY], +[ + AC_REQUIRE([gl_THREADLIB_EARLY_BODY]) + gl_threads_api=none + LIBTHREAD= + LTLIBTHREAD= + LIBMULTITHREAD= + LTLIBMULTITHREAD= + if test "$gl_use_threads" != no; then + dnl Check whether the compiler and linker support weak declarations. + AC_CACHE_CHECK([whether imported symbols can be declared weak], + [gl_cv_have_weak], + [gl_cv_have_weak=no + dnl First, test whether the compiler accepts it syntactically. + AC_TRY_LINK([extern void xyzzy (); +#pragma weak xyzzy], [xyzzy();], [gl_cv_have_weak=maybe]) + if test $gl_cv_have_weak = maybe; then + dnl Second, test whether it actually works. On Cygwin 1.7.2, with + dnl gcc 4.3, symbols declared weak always evaluate to the address 0. + AC_TRY_RUN([ +#include +#pragma weak fputs +int main () +{ + return (fputs == NULL); +}], [gl_cv_have_weak=yes], [gl_cv_have_weak=no], + [dnl When cross-compiling, assume that only ELF platforms support + dnl weak symbols. + AC_EGREP_CPP([Extensible Linking Format], + [#ifdef __ELF__ + Extensible Linking Format + #endif + ], + [gl_cv_have_weak="guessing yes"], + [gl_cv_have_weak="guessing no"]) + ]) + fi + ]) + if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then + # On OSF/1, the compiler needs the flag -pthread or -D_REENTRANT so that + # it groks . It's added above, in gl_THREADLIB_EARLY_BODY. + AC_CHECK_HEADER([pthread.h], + [gl_have_pthread_h=yes], [gl_have_pthread_h=no]) + if test "$gl_have_pthread_h" = yes; then + # Other possible tests: + # -lpthreads (FSU threads, PCthreads) + # -lgthreads + gl_have_pthread= + # Test whether both pthread_mutex_lock and pthread_mutexattr_init exist + # in libc. IRIX 6.5 has the first one in both libc and libpthread, but + # the second one only in libpthread, and lock.c needs it. + AC_TRY_LINK([#include ], + [pthread_mutex_lock((pthread_mutex_t*)0); + pthread_mutexattr_init((pthread_mutexattr_t*)0);], + [gl_have_pthread=yes]) + # Test for libpthread by looking for pthread_kill. (Not pthread_self, + # since it is defined as a macro on OSF/1.) + if test -n "$gl_have_pthread"; then + # The program links fine without libpthread. But it may actually + # need to link with libpthread in order to create multiple threads. + AC_CHECK_LIB([pthread], [pthread_kill], + [LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread + # On Solaris and HP-UX, most pthread functions exist also in libc. + # Therefore pthread_in_use() needs to actually try to create a + # thread: pthread_create from libc will fail, whereas + # pthread_create will actually create a thread. + case "$host_os" in + solaris* | hpux*) + AC_DEFINE([PTHREAD_IN_USE_DETECTION_HARD], [1], + [Define if the pthread_in_use() detection is hard.]) + esac + ]) + else + # Some library is needed. Try libpthread and libc_r. + AC_CHECK_LIB([pthread], [pthread_kill], + [gl_have_pthread=yes + LIBTHREAD=-lpthread LTLIBTHREAD=-lpthread + LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread]) + if test -z "$gl_have_pthread"; then + # For FreeBSD 4. + AC_CHECK_LIB([c_r], [pthread_kill], + [gl_have_pthread=yes + LIBTHREAD=-lc_r LTLIBTHREAD=-lc_r + LIBMULTITHREAD=-lc_r LTLIBMULTITHREAD=-lc_r]) + fi + fi + if test -n "$gl_have_pthread"; then + gl_threads_api=posix + AC_DEFINE([USE_POSIX_THREADS], [1], + [Define if the POSIX multithreading library can be used.]) + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then + AC_DEFINE([USE_POSIX_THREADS_WEAK], [1], + [Define if references to the POSIX multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + fi + fi + fi + if test -z "$gl_have_pthread"; then + if test "$gl_use_threads" = yes || test "$gl_use_threads" = solaris; then + gl_have_solaristhread= + gl_save_LIBS="$LIBS" + LIBS="$LIBS -lthread" + AC_TRY_LINK([#include +#include ], + [thr_self();], + [gl_have_solaristhread=yes]) + LIBS="$gl_save_LIBS" + if test -n "$gl_have_solaristhread"; then + gl_threads_api=solaris + LIBTHREAD=-lthread + LTLIBTHREAD=-lthread + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + AC_DEFINE([USE_SOLARIS_THREADS], [1], + [Define if the old Solaris multithreading library can be used.]) + if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then + AC_DEFINE([USE_SOLARIS_THREADS_WEAK], [1], + [Define if references to the old Solaris multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + fi + fi + if test "$gl_use_threads" = pth; then + gl_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_LINKFLAGS([pth]) + gl_have_pth= + gl_save_LIBS="$LIBS" + LIBS="$LIBS -lpth" + AC_TRY_LINK([#include ], [pth_self();], [gl_have_pth=yes]) + LIBS="$gl_save_LIBS" + if test -n "$gl_have_pth"; then + gl_threads_api=pth + LIBTHREAD="$LIBPTH" + LTLIBTHREAD="$LTLIBPTH" + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + AC_DEFINE([USE_PTH_THREADS], [1], + [Define if the GNU Pth multithreading library can be used.]) + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then + AC_DEFINE([USE_PTH_THREADS_WEAK], [1], + [Define if references to the GNU Pth multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + else + CPPFLAGS="$gl_save_CPPFLAGS" + fi + fi + if test -z "$gl_have_pthread"; then + if test "$gl_use_threads" = yes || test "$gl_use_threads" = win32; then + if { case "$host_os" in + mingw*) true;; + *) false;; + esac + }; then + gl_threads_api=win32 + AC_DEFINE([USE_WIN32_THREADS], [1], + [Define if the Win32 multithreading API can be used.]) + fi + fi + fi + fi + AC_MSG_CHECKING([for multithread API to use]) + AC_MSG_RESULT([$gl_threads_api]) + AC_SUBST([LIBTHREAD]) + AC_SUBST([LTLIBTHREAD]) + AC_SUBST([LIBMULTITHREAD]) + AC_SUBST([LTLIBMULTITHREAD]) +]) + +AC_DEFUN([gl_THREADLIB], +[ + AC_REQUIRE([gl_THREADLIB_EARLY]) + AC_REQUIRE([gl_THREADLIB_BODY]) +]) + + +dnl gl_DISABLE_THREADS +dnl ------------------ +dnl Sets the gl_THREADLIB default so that threads are not used by default. +dnl The user can still override it at installation time, by using the +dnl configure option '--enable-threads'. + +AC_DEFUN([gl_DISABLE_THREADS], [ + m4_divert_text([INIT_PREPARE], [gl_use_threads_default=no]) +]) + + +dnl Survey of platforms: +dnl +dnl Platform Available Compiler Supports test-lock +dnl flavours option weak result +dnl --------------- --------- --------- -------- --------- +dnl Linux 2.4/glibc posix -lpthread Y OK +dnl +dnl GNU Hurd/glibc posix +dnl +dnl FreeBSD 5.3 posix -lc_r Y +dnl posix -lkse ? Y +dnl posix -lpthread ? Y +dnl posix -lthr Y +dnl +dnl FreeBSD 5.2 posix -lc_r Y +dnl posix -lkse Y +dnl posix -lthr Y +dnl +dnl FreeBSD 4.0,4.10 posix -lc_r Y OK +dnl +dnl NetBSD 1.6 -- +dnl +dnl OpenBSD 3.4 posix -lpthread Y OK +dnl +dnl MacOS X 10.[123] posix -lpthread Y OK +dnl +dnl Solaris 7,8,9 posix -lpthread Y Sol 7,8: 0.0; Sol 9: OK +dnl solaris -lthread Y Sol 7,8: 0.0; Sol 9: OK +dnl +dnl HP-UX 11 posix -lpthread N (cc) OK +dnl Y (gcc) +dnl +dnl IRIX 6.5 posix -lpthread Y 0.5 +dnl +dnl AIX 4.3,5.1 posix -lpthread N AIX 4: 0.5; AIX 5: OK +dnl +dnl OSF/1 4.0,5.1 posix -pthread (cc) N OK +dnl -lpthread (gcc) Y +dnl +dnl Cygwin posix -lpthread Y OK +dnl +dnl Any of the above pth -lpth 0.0 +dnl +dnl Mingw win32 N OK +dnl +dnl BeOS 5 -- +dnl +dnl The test-lock result shows what happens if in test-lock.c EXPLICIT_YIELD is +dnl turned off: +dnl OK if all three tests terminate OK, +dnl 0.5 if the first test terminates OK but the second one loops endlessly, +dnl 0.0 if the first test already loops endlessly. diff --git a/m4/uintmax_t.m4 b/m4/uintmax_t.m4 new file mode 100644 index 00000000..03b51bcf --- /dev/null +++ b/m4/uintmax_t.m4 @@ -0,0 +1,30 @@ +# uintmax_t.m4 serial 12 +dnl Copyright (C) 1997-2004, 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +AC_PREREQ([2.13]) + +# Define uintmax_t to 'unsigned long' or 'unsigned long long' +# if it is not already defined in or . + +AC_DEFUN([gl_AC_TYPE_UINTMAX_T], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then + AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) + test $ac_cv_type_unsigned_long_long_int = yes \ + && ac_type='unsigned long long' \ + || ac_type='unsigned long' + AC_DEFINE_UNQUOTED([uintmax_t], [$ac_type], + [Define to unsigned long or unsigned long long + if and don't define.]) + else + AC_DEFINE([HAVE_UINTMAX_T], [1], + [Define if you have the 'uintmax_t' type in or .]) + fi +]) diff --git a/m4/visibility.m4 b/m4/visibility.m4 new file mode 100644 index 00000000..077c4765 --- /dev/null +++ b/m4/visibility.m4 @@ -0,0 +1,74 @@ +# visibility.m4 serial 3 (gettext-0.18) +dnl Copyright (C) 2005, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl Tests whether the compiler supports the command-line option +dnl -fvisibility=hidden and the function and variable attributes +dnl __attribute__((__visibility__("hidden"))) and +dnl __attribute__((__visibility__("default"))). +dnl Does *not* test for __visibility__("protected") - which has tricky +dnl semantics (see the 'vismain' test in glibc) and does not exist e.g. on +dnl MacOS X. +dnl Does *not* test for __visibility__("internal") - which has processor +dnl dependent semantics. +dnl Does *not* test for #pragma GCC visibility push(hidden) - which is +dnl "really only recommended for legacy code". +dnl Set the variable CFLAG_VISIBILITY. +dnl Defines and sets the variable HAVE_VISIBILITY. + +AC_DEFUN([gl_VISIBILITY], +[ + AC_REQUIRE([AC_PROG_CC]) + CFLAG_VISIBILITY= + HAVE_VISIBILITY=0 + if test -n "$GCC"; then + dnl First, check whether -Werror can be added to the command line, or + dnl whether it leads to an error because of some other option that the + dnl user has put into $CC $CFLAGS $CPPFLAGS. + AC_MSG_CHECKING([whether the -Werror option is usable]) + AC_CACHE_VAL([gl_cv_cc_vis_werror], [ + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Werror" + AC_TRY_COMPILE([], [], + [gl_cv_cc_vis_werror=yes], + [gl_cv_cc_vis_werror=no]) + CFLAGS="$gl_save_CFLAGS"]) + AC_MSG_RESULT([$gl_cv_cc_vis_werror]) + dnl Now check whether visibility declarations are supported. + AC_MSG_CHECKING([for simple visibility declarations]) + AC_CACHE_VAL([gl_cv_cc_visibility], [ + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fvisibility=hidden" + dnl We use the option -Werror and a function dummyfunc, because on some + dnl platforms (Cygwin 1.7) the use of -fvisibility triggers a warning + dnl "visibility attribute not supported in this configuration; ignored" + dnl at the first function definition in every compilation unit, and we + dnl don't want to use the option in this case. + if test $gl_cv_cc_vis_werror = yes; then + CFLAGS="$CFLAGS -Werror" + fi + AC_TRY_COMPILE( + [extern __attribute__((__visibility__("hidden"))) int hiddenvar; + extern __attribute__((__visibility__("default"))) int exportedvar; + extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void); + extern __attribute__((__visibility__("default"))) int exportedfunc (void); + void dummyfunc (void) {}], + [], + [gl_cv_cc_visibility=yes], + [gl_cv_cc_visibility=no]) + CFLAGS="$gl_save_CFLAGS"]) + AC_MSG_RESULT([$gl_cv_cc_visibility]) + if test $gl_cv_cc_visibility = yes; then + CFLAG_VISIBILITY="-fvisibility=hidden" + HAVE_VISIBILITY=1 + fi + fi + AC_SUBST([CFLAG_VISIBILITY]) + AC_SUBST([HAVE_VISIBILITY]) + AC_DEFINE_UNQUOTED([HAVE_VISIBILITY], [$HAVE_VISIBILITY], + [Define to 1 or 0, depending whether the compiler supports simple visibility declarations.]) +]) diff --git a/m4/wchar_t.m4 b/m4/wchar_t.m4 new file mode 100644 index 00000000..ed804e66 --- /dev/null +++ b/m4/wchar_t.m4 @@ -0,0 +1,20 @@ +# wchar_t.m4 serial 3 (gettext-0.18) +dnl Copyright (C) 2002-2003, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether has the 'wchar_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WCHAR_T], +[ + AC_CACHE_CHECK([for wchar_t], [gt_cv_c_wchar_t], + [AC_TRY_COMPILE([#include + wchar_t foo = (wchar_t)'\0';], , + [gt_cv_c_wchar_t=yes], [gt_cv_c_wchar_t=no])]) + if test $gt_cv_c_wchar_t = yes; then + AC_DEFINE([HAVE_WCHAR_T], [1], [Define if you have the 'wchar_t' type.]) + fi +]) diff --git a/m4/wint_t.m4 b/m4/wint_t.m4 new file mode 100644 index 00000000..a6c7d15c --- /dev/null +++ b/m4/wint_t.m4 @@ -0,0 +1,28 @@ +# wint_t.m4 serial 4 (gettext-0.18) +dnl Copyright (C) 2003, 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether has the 'wint_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WINT_T], +[ + AC_CACHE_CHECK([for wint_t], [gt_cv_c_wint_t], + [AC_TRY_COMPILE([ +/* Tru64 with Desktop Toolkit C has a bug: must be included before + . + BSD/OS 4.0.1 has a bug: , and must be included + before . */ +#include +#include +#include +#include + wint_t foo = (wchar_t)'\0';], , + [gt_cv_c_wint_t=yes], [gt_cv_c_wint_t=no])]) + if test $gt_cv_c_wint_t = yes; then + AC_DEFINE([HAVE_WINT_T], [1], [Define if you have the 'wint_t' type.]) + fi +]) diff --git a/m4/xsize.m4 b/m4/xsize.m4 new file mode 100644 index 00000000..b653693a --- /dev/null +++ b/m4/xsize.m4 @@ -0,0 +1,13 @@ +# xsize.m4 serial 4 +dnl Copyright (C) 2003-2004, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_XSIZE], +[ + dnl Prerequisites of lib/xsize.h. + AC_REQUIRE([gl_SIZE_MAX]) + AC_REQUIRE([AC_C_INLINE]) + AC_CHECK_HEADERS([stdint.h]) +]) From 6b83962612f5c2d52950049138f8b05f5e229373 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Thu, 8 Mar 2018 08:44:07 +0100 Subject: [PATCH 128/210] Distribute config.rpath and sources for some configuration files (fixes Mutabor distcheck). --- Makefile.am | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 5de9f221..e0735c77 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,7 @@ RTMIDITESTCXXFLAGS = $(EXTRA_RTMIDITESTCXXFLAGS) -I$(top_srcdir)/%D% RTMIDILIBRARYNAME = %D%/librtmidi@rtmidi_suffix@.la RTMIDITESTLDFLAGS = $(EXTRA_RTMIDITESTLDFLAGS) $(RTMIDILIBRARYNAME) +RTMIDICONFIGRPATH = config/config.rpath lib_LTLIBRARIES += %D%/librtmidi@rtmidi_suffix@.la %C%_librtmidi@rtmidi_suffix@_la_LDFLAGS = -no-undefined $(RTMIDI__TS_LIBS) %C%_librtmidi@rtmidi_suffix@_la_CXXFLAGS = $(CXXFLAGS) $(CPPFLAGS) $(RTMIDI_TS_API) -DRTMIDI_NO_WARN_DEPRECATED @@ -8,6 +9,10 @@ lib_LTLIBRARIES += %D%/librtmidi@rtmidi_suffix@.la %D%/RtMidi.cpp \ %D%/RtMidi.h -EXTRA_DIST += config/config.rpath m4/ChangeLog +EXTRA_DIST += \ + $(RTMIDICONFIGRPATH) \ + %D%/m4/ChangeLog \ + %D%/rtmidi-config.in \ + %D%/librtmidi.pc.in include %D%/tests/Makefile.am From 2a781d05244dd070f819e1a68a0dfd9384f2f7b6 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 Mar 2018 17:17:15 +0100 Subject: [PATCH 129/210] fix two errors with new api --- RtMidi.cpp | 192 +++++++++++++++++++++++++++-------------------------- 1 file changed, 97 insertions(+), 95 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 9183bc74..fa1f98f7 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1606,12 +1606,12 @@ void MidiInCore::midiInputCallback( const MIDIPacketList *list, else { time = packet->timeStamp; if ( time == 0 ) { // this happens when receiving asynchronous sysex messages - time = AudioGetCurrentHostTime(); + time = AudioGetCurrentHostTime(); } time -= apiData->lastTime; time = AudioConvertHostTimeToNanos( time ); 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 @@ -1623,109 +1623,111 @@ void MidiInCore::midiInputCallback( const MIDIPacketList *list, if ( continueSysex ) { // We have a continuing, segmented sysex message. if ( !( data->ignoreFlags & 0x01 ) ) { - // If we're not ignoring sysex messages, copy the entire packet. - for ( unsigned int j=0; jdata[j] ); + // If we're not ignoring sysex messages, copy the entire packet. + for ( unsigned int j=0; jdata[j] ); } continueSysex = packet->data[nBytes-1] != 0xF7; if ( !( data->ignoreFlags & 0x01 ) ) { - if ( !continueSysex ) { - // If not a continuing sysex message, invoke the user callback function or queue the message. - if ( data->userCallback ) { - data->userCallback->rtmidi_midi_in( message.timeStamp, &message.bytes); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else { - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + if ( !continueSysex ) { + // If not a continuing sysex message, invoke the user callback function or queue the message. + if ( data->userCallback ) { + data->userCallback->rtmidi_midi_in( message.timeStamp, + message.bytes); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else { + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother ALSA with an unhandled exception - } - } - } - message.bytes.clear(); - } + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } + } + } + message.bytes.clear(); + } } } else { while ( iByte < nBytes ) { - size = 0; - // We are expecting that the next byte in the packet is a status byte. - status = packet->data[iByte]; - if ( !(status & 0x80) ) break; - // Determine the number of bytes in the MIDI message. - if ( status < 0xC0 ) size = 3; - else if ( status < 0xE0 ) size = 2; - else if ( status < 0xF0 ) size = 3; - else if ( status == 0xF0 ) { - // A MIDI sysex - if ( data->ignoreFlags & 0x01 ) { - size = 0; - iByte = nBytes; - } - else size = nBytes - iByte; - continueSysex = packet->data[nBytes-1] != 0xF7; - } - else if ( status == 0xF1 ) { - // A MIDI time code message - if ( data->ignoreFlags & 0x02 ) { - size = 0; - iByte += 2; - } - else size = 2; - } - else if ( status == 0xF2 ) size = 3; - else if ( status == 0xF3 ) size = 2; - else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) { - // A MIDI timing tick message and we're ignoring it. - size = 0; - iByte += 1; - } - else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) { - // A MIDI active sensing message and we're ignoring it. - size = 0; - iByte += 1; - } - else size = 1; - - // Copy the MIDI data to our vector. - if ( size ) { - 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. - if ( data->userCallback ) { - data->userCallback->rtmidi_midi_in( message.timeStamp, &message.bytes); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else { - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + size = 0; + // We are expecting that the next byte in the packet is a status byte. + status = packet->data[iByte]; + if ( !(status & 0x80) ) break; + // Determine the number of bytes in the MIDI message. + if ( status < 0xC0 ) size = 3; + else if ( status < 0xE0 ) size = 2; + else if ( status < 0xF0 ) size = 3; + else if ( status == 0xF0 ) { + // A MIDI sysex + if ( data->ignoreFlags & 0x01 ) { + size = 0; + iByte = nBytes; + } + else size = nBytes - iByte; + continueSysex = packet->data[nBytes-1] != 0xF7; + } + else if ( status == 0xF1 ) { + // A MIDI time code message + if ( data->ignoreFlags & 0x02 ) { + size = 0; + iByte += 2; + } + else size = 2; + } + else if ( status == 0xF2 ) size = 3; + else if ( status == 0xF3 ) size = 2; + else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) { + // A MIDI timing tick message and we're ignoring it. + size = 0; + iByte += 1; + } + else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) { + // A MIDI active sensing message and we're ignoring it. + size = 0; + iByte += 1; + } + else size = 1; + + // Copy the MIDI data to our vector. + if ( size ) { + 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. + if ( data->userCallback ) { + data->userCallback->rtmidi_midi_in( message.timeStamp, + message.bytes); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else { + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother WinMM with an unhandled exception - } - } - } - message.bytes.clear(); - } - iByte += size; - } + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } + } + } + message.bytes.clear(); + } + iByte += size; + } } } packet = MIDIPacketNext(packet); From 962f50b1da64ebc9e9c6d03825b2132f938cc4c2 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 Mar 2018 17:21:40 +0100 Subject: [PATCH 130/210] implement trim according to C++11 --- RtMidi.cpp | 12 ++++++++---- RtMidi.h | 9 --------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index fa1f98f7..3b6350d4 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -584,21 +584,25 @@ MidiOutApi :: ~MidiOutApi( void ) // trim from start static inline std::string <rim(std::string &s) { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); + s.erase(s.begin(), + std::find_if(s.begin(), s.end(), [](int ch) { + return ! std::isspace(ch); + })); return s; } // trim from end static inline std::string &rtrim(std::string &s) { - s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); + s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { + return ! std::isspace(ch); + }).base(), s.end()); return s; } -#if 0 + // trim from both ends static inline std::string &trim(std::string &s) { return ltrim(rtrim(s)); } -#endif NAMESPACE_RTMIDI_END // *************************************************** // diff --git a/RtMidi.h b/RtMidi.h index e8bff778..6963570d 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -325,15 +325,6 @@ bool operator!=(const Pointer& lhs, const Pointer& rhs) { return (&(*lhs)) != (&(*rhs)); } -template -bool operator==(const Pointer& lhs, const Pointer& rhs) { - return (&(*lhs)) == (&(*rhs)); -} - -template -bool operator!=(const Pointer& lhs, const Pointer& rhs) { - return (&(*lhs)) != (&(*rhs)); -} #else template using Pointer = std::shared_ptr; From a45866e4a33a430b795de8d010803a2c3a517550 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 Mar 2018 17:22:06 +0100 Subject: [PATCH 131/210] Use old gettext to make travis happy --- configure.library | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.library b/configure.library index 81cf6fc2..1ebe8c14 100644 --- a/configure.library +++ b/configure.library @@ -299,7 +299,7 @@ return jack_port_uuid(NULL); esac AM_CONDITIONAL(HAVE_VIRTUAL_DEVICES,test "$have_virtual_devices" == yes) AM_GNU_GETTEXT([external]) -AM_GNU_GETTEXT_VERSION([0.19.8]) +AM_GNU_GETTEXT_VERSION([0.18.3]) if test "x$rtmidicopydlls" = "x" then From dc916a208a0b329639575e44080013f98736d748 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 Mar 2018 17:22:24 +0100 Subject: [PATCH 132/210] Add travis.yml --- .travis.yml | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..cbbe3a19 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,43 @@ +git: + depth: 3 +language: c++ +group: travis_latest +compiler: + - gcc + - clang +matrix: + include: + - os: osx + osx_image: xcode9.2 + env: + - MATRIX_EVAL="CC=clang && CXX=clang++ && EXTRA_BREW= " + + - os: osx + osx_image: xcode9.2 + env: + - MATRIX_EVAL="CC=gcc && CXX=g++ && EXTRA_BREW=gcc " + + +addons: + apt: + packages: + - autoconf + - libtool + - autopoint + - automake + - libasound-dev + - libjack-dev + - libcppunit-dev + - doxygen + + +before_install: + - eval "${MATRIX_EVAL}" + - if test "$TRAVIS_OS_NAME" = osx ; then brew update ; fi + - if test "$TRAVIS_OS_NAME" = osx ; then brew upgrade boost ; fi + - if test "$TRAVIS_OS_NAME" = osx ; then rm -rf /usr/local/include/c++ ; fi # fix broken gcc installation + - if test "$TRAVIS_OS_NAME" = osx ; then brew install $EXTRA_BREW gettext flex bison libtool autoconf jack ; fi + - if test "$TRAVIS_OS_NAME" = osx ; then brew link --force $EXTRA_BREW gettext flex bison libtool autoconf jack ; fi + +script: + autoreconf -i -f && ./configure && make -j4 && $TEST_RUNNER make check From ff3536adb04d2ac02ba3403ec9761e4d80c6d4d1 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 Mar 2018 17:30:38 +0100 Subject: [PATCH 133/210] add po to SUBDIRS Signed-off-by: Tobias Schlemmer --- Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.am b/Makefile.am index e0735c77..fd7dd628 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,4 @@ +SUBDIRS = po RTMIDITESTCXXFLAGS = $(EXTRA_RTMIDITESTCXXFLAGS) -I$(top_srcdir)/%D% RTMIDILIBRARYNAME = %D%/librtmidi@rtmidi_suffix@.la RTMIDITESTLDFLAGS = $(EXTRA_RTMIDITESTLDFLAGS) $(RTMIDILIBRARYNAME) From 6691109e8f1568f908f9daf34041b128366531ce Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 Mar 2018 17:30:52 +0100 Subject: [PATCH 134/210] check for ar --- configure.library | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.library b/configure.library index 1ebe8c14..0b51b3bb 100644 --- a/configure.library +++ b/configure.library @@ -13,7 +13,7 @@ AC_SUBST(RTMIDI_TS_SUFFIX,[ts]) # Checks for programs. AC_PROG_CXX -dnl AM_PROG_AR +AM_PROG_AR dnl AC_PATH_PROG(AR, ar, no) dnl if [[ $AR = "no" ]] ; then dnl AC_MSG_ERROR("Could not find ar - needed to create a library"); From a9035690e6f7a55fc95907637dcb6126d101b2b0 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 Mar 2018 17:47:22 +0100 Subject: [PATCH 135/210] Another fix for the po not in SUBDIRS problem. --- Makefile.am | 3 +++ configure.ac | 3 ++- configure.library | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index fd7dd628..f8428e42 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,7 @@ +if RTMIDI_STANDALONE +ACLOCAL_AMFLAGS = -I m4 SUBDIRS = po +endif RTMIDITESTCXXFLAGS = $(EXTRA_RTMIDITESTCXXFLAGS) -I$(top_srcdir)/%D% RTMIDILIBRARYNAME = %D%/librtmidi@rtmidi_suffix@.la RTMIDITESTLDFLAGS = $(EXTRA_RTMIDITESTLDFLAGS) $(RTMIDILIBRARYNAME) diff --git a/configure.ac b/configure.ac index 8b825ef3..6d006870 100644 --- a/configure.ac +++ b/configure.ac @@ -9,9 +9,10 @@ AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) AC_CONFIG_MACRO_DIR([m4]) rtmidi_suffix="-ts" +rtmidi_standalone="yes" +SUBDIRS="$SUBDIRS %D%/po" m4_include(configure.library) -SUBDIRS="$SUBDIRS %D%/po" AC_OUTPUT diff --git a/configure.library b/configure.library index 0b51b3bb..c79653b7 100644 --- a/configure.library +++ b/configure.library @@ -6,11 +6,11 @@ AC_SUBST(noinst_LIBRARIES) AC_SUBST(noinst_PROGRAMS) AC_SUBST(TESTS) -AC_SUBST(SUBDIRS) +dnl AC_SUBST(SUBDIRS) AC_SUBST(lib_LTLIBRARIES) AC_SUBST(EXTRA_DIST) AC_SUBST(RTMIDI_TS_SUFFIX,[ts]) - +AM_CONDITIONAL(RTMIDI_STANDALONE,test "$rtmidi_standalone" = "yes") # Checks for programs. AC_PROG_CXX AM_PROG_AR From 6866ce5e35b5c45bd99206cb185cbf031e87b808 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 Mar 2018 17:52:38 +0100 Subject: [PATCH 136/210] generate config/config.rpath by script --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cbbe3a19..2cfd4f75 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,6 +38,10 @@ before_install: - if test "$TRAVIS_OS_NAME" = osx ; then rm -rf /usr/local/include/c++ ; fi # fix broken gcc installation - if test "$TRAVIS_OS_NAME" = osx ; then brew install $EXTRA_BREW gettext flex bison libtool autoconf jack ; fi - if test "$TRAVIS_OS_NAME" = osx ; then brew link --force $EXTRA_BREW gettext flex bison libtool autoconf jack ; fi + - mkdir -p config + - touch config/config.rpath script: - autoreconf -i -f && ./configure && make -j4 && $TEST_RUNNER make check + - mkdir -p config + - touch config/config.rpath + - autoreconf -i -f && ./configure && make -j4 && $TEST_RUNNER make check From 2d12be9bca66c24d07347fc3c594572285ec595a Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 Mar 2018 17:58:10 +0100 Subject: [PATCH 137/210] neutralize fallthrough macro if it is not defined. --- RtMidi.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RtMidi.cpp b/RtMidi.cpp index 3b6350d4..58936673 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -42,6 +42,9 @@ #include #include #include +#ifndef FALLTHROUGH +#define FALLTHROUGH +#endif NAMESPACE_RTMIDI_START #ifdef RTMIDI_GETTEXT From ec1b13aeda4382719b0cbcfa14b54a345c5e1f5b Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 Mar 2018 18:03:23 +0100 Subject: [PATCH 138/210] Fix fallthrough --- RtMidi.cpp | 6 +++--- configure.library | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 58936673..8273897e 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -42,8 +42,8 @@ #include #include #include -#ifndef FALLTHROUGH -#define FALLTHROUGH +#ifdef RTMIDI_FALLTHROUGH +#define RTMIDI_FALLTHROUGH #endif NAMESPACE_RTMIDI_START @@ -2938,7 +2938,7 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() break; } } - FALLTHROUGH; + RTMIDI_FALLTHROUGH; default: doDecode = true; } diff --git a/configure.library b/configure.library index c79653b7..2af381ef 100644 --- a/configure.library +++ b/configure.library @@ -332,4 +332,4 @@ AC_COMPILE_IFELSE([ ]); ]); ]) -AC_DEFINE_UNQUOTED(mutfallthrough,[$ac_cv_cxx_fallthrough],[syntax for swtich case fallthrough attributes in C++]) +AC_DEFINE_UNQUOTED(FALLTHROUGH,[$ac_cv_cxx_fallthrough],[syntax for switch case fallthrough attributes in C++]) From 226f6461c46ad1dde2b4967b5c7300ccbca00b3c Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 Mar 2018 18:05:46 +0100 Subject: [PATCH 139/210] Forch C++11 --- configure.library | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure.library b/configure.library index 2af381ef..81fd8513 100644 --- a/configure.library +++ b/configure.library @@ -13,6 +13,7 @@ AC_SUBST(RTMIDI_TS_SUFFIX,[ts]) AM_CONDITIONAL(RTMIDI_STANDALONE,test "$rtmidi_standalone" = "yes") # Checks for programs. AC_PROG_CXX +AX_CXX_COMPILE_STDCXX(11) AM_PROG_AR dnl AC_PATH_PROG(AR, ar, no) dnl if [[ $AR = "no" ]] ; then @@ -332,4 +333,4 @@ AC_COMPILE_IFELSE([ ]); ]); ]) -AC_DEFINE_UNQUOTED(FALLTHROUGH,[$ac_cv_cxx_fallthrough],[syntax for switch case fallthrough attributes in C++]) +AC_DEFINE_UNQUOTED(RTMIDI_FALLTHROUGH,[$ac_cv_cxx_fallthrough],[syntax for switch case fallthrough attributes in C++]) From 661b830040dd9b3c596af1554a71e62cfdda8be4 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 Mar 2018 18:11:11 +0100 Subject: [PATCH 140/210] Add missing m4 files --- Makefile.am | 2 +- m4/ax_cxx_compile_stdcxx.m4 | 982 ++++++++++++++++++++++++++++++++++++ m4/ax_require_defined.m4 | 37 ++ 3 files changed, 1020 insertions(+), 1 deletion(-) create mode 100644 m4/ax_cxx_compile_stdcxx.m4 create mode 100644 m4/ax_require_defined.m4 diff --git a/Makefile.am b/Makefile.am index f8428e42..67066b58 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ if RTMIDI_STANDALONE -ACLOCAL_AMFLAGS = -I m4 +ACLOCAL_AMFLAGS = -I m4 --install SUBDIRS = po endif RTMIDITESTCXXFLAGS = $(EXTRA_RTMIDITESTCXXFLAGS) -I$(top_srcdir)/%D% diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4 new file mode 100644 index 00000000..5032bba8 --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx.m4 @@ -0,0 +1,982 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) +# or '14' (for the C++14 standard). +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016 Krzesimir Nowak +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 7 + +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). + +AX_REQUIRE_DEFINED([AC_MSG_WARN]) +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], + [$1], [14], [ax_cxx_compile_alternatives="14 1y"], + [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then + ac_success=yes + fi + + m4_if([$2], [noext], [], [dnl + if test x$ac_success = xno; then + for alternative in ${ax_cxx_compile_alternatives}; do + switch="-std=gnu++${alternative}" + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [], [dnl + if test x$ac_success = xno; then + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + for alternative in ${ax_cxx_compile_alternatives}; do + for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + if test x$ac_success = xyes; then + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + AC_SUBST(HAVE_CXX$1) + m4_if([$1], [17], [AC_MSG_WARN([C++17 is not yet standardized, so the checks may change in incompatible ways anytime])]) +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 +) + + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 +) + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 +) + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual void f() {} + }; + + struct Derived : public Base + { + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) + + +dnl Tests for new features in C++17 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ + +// If the compiler admits that it is not ready for C++17, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus <= 201402L + +#error "This is not a C++17 compiler" + +#else + +#if defined(__clang__) + #define REALLY_CLANG +#else + #if defined(__GNUC__) + #define REALLY_GCC + #endif +#endif + +#include +#include +#include + +namespace cxx17 +{ + +#if !defined(REALLY_CLANG) + namespace test_constexpr_lambdas + { + + // TODO: test it with clang++ from git + + constexpr int foo = [](){return 42;}(); + + } +#endif // !defined(REALLY_CLANG) + + namespace test::nested_namespace::definitions + { + + } + + namespace test_fold_expression + { + + template + int multiply(Args... args) + { + return (args * ... * 1); + } + + template + bool all(Args... args) + { + return (args && ...); + } + + } + + namespace test_extended_static_assert + { + + static_assert (true); + + } + + namespace test_auto_brace_init_list + { + + auto foo = {5}; + auto bar {5}; + + static_assert(std::is_same, decltype(foo)>::value); + static_assert(std::is_same::value); + } + + namespace test_typename_in_template_template_parameter + { + + template typename X> struct D; + + } + + namespace test_fallthrough_nodiscard_maybe_unused_attributes + { + + int f1() + { + return 42; + } + + [[nodiscard]] int f2() + { + [[maybe_unused]] auto unused = f1(); + + switch (f1()) + { + case 17: + f1(); + [[fallthrough]]; + case 42: + f1(); + } + return f1(); + } + + } + + namespace test_extended_aggregate_initialization + { + + struct base1 + { + int b1, b2 = 42; + }; + + struct base2 + { + base2() { + b3 = 42; + } + int b3; + }; + + struct derived : base1, base2 + { + int d; + }; + + derived d1 {{1, 2}, {}, 4}; // full initialization + derived d2 {{}, {}, 4}; // value-initialized bases + + } + + namespace test_general_range_based_for_loop + { + + struct iter + { + int i; + + int& operator* () + { + return i; + } + + const int& operator* () const + { + return i; + } + + iter& operator++() + { + ++i; + return *this; + } + }; + + struct sentinel + { + int i; + }; + + bool operator== (const iter& i, const sentinel& s) + { + return i.i == s.i; + } + + bool operator!= (const iter& i, const sentinel& s) + { + return !(i == s); + } + + struct range + { + iter begin() const + { + return {0}; + } + + sentinel end() const + { + return {5}; + } + }; + + void f() + { + range r {}; + + for (auto i : r) + { + [[maybe_unused]] auto v = i; + } + } + + } + + namespace test_lambda_capture_asterisk_this_by_value + { + + struct t + { + int i; + int foo() + { + return [*this]() + { + return i; + }(); + } + }; + + } + + namespace test_enum_class_construction + { + + enum class byte : unsigned char + {}; + + byte foo {42}; + + } + + namespace test_constexpr_if + { + + template + int f () + { + if constexpr(cond) + { + return 13; + } + else + { + return 42; + } + } + + } + + namespace test_selection_statement_with_initializer + { + + int f() + { + return 13; + } + + int f2() + { + if (auto i = f(); i > 0) + { + return 3; + } + + switch (auto i = f(); i + 4) + { + case 17: + return 2; + + default: + return 1; + } + } + + } + +#if !defined(REALLY_CLANG) + namespace test_template_argument_deduction_for_class_templates + { + + // TODO: test it with clang++ from git + + template + struct pair + { + pair (T1 p1, T2 p2) + : m1 {p1}, + m2 {p2} + {} + + T1 m1; + T2 m2; + }; + + void f() + { + [[maybe_unused]] auto p = pair{13, 42u}; + } + + } +#endif // !defined(REALLY_CLANG) + + namespace test_non_type_auto_template_parameters + { + + template + struct B + {}; + + B<5> b1; + B<'a'> b2; + + } + +#if !defined(REALLY_CLANG) + namespace test_structured_bindings + { + + // TODO: test it with clang++ from git + + int arr[2] = { 1, 2 }; + std::pair pr = { 1, 2 }; + + auto f1() -> int(&)[2] + { + return arr; + } + + auto f2() -> std::pair& + { + return pr; + } + + struct S + { + int x1 : 2; + volatile double y1; + }; + + S f3() + { + return {}; + } + + auto [ x1, y1 ] = f1(); + auto& [ xr1, yr1 ] = f1(); + auto [ x2, y2 ] = f2(); + auto& [ xr2, yr2 ] = f2(); + const auto [ x3, y3 ] = f3(); + + } +#endif // !defined(REALLY_CLANG) + +#if !defined(REALLY_CLANG) + namespace test_exception_spec_type_system + { + + // TODO: test it with clang++ from git + + struct Good {}; + struct Bad {}; + + void g1() noexcept; + void g2(); + + template + Bad + f(T*, T*); + + template + Good + f(T1*, T2*); + + static_assert (std::is_same_v); + + } +#endif // !defined(REALLY_CLANG) + + namespace test_inline_variables + { + + template void f(T) + {} + + template inline T g(T) + { + return T{}; + } + + template<> inline void f<>(int) + {} + + template<> int g<>(int) + { + return 5; + } + + } + +} // namespace cxx17 + +#endif // __cplusplus <= 201402L + +]]) diff --git a/m4/ax_require_defined.m4 b/m4/ax_require_defined.m4 new file mode 100644 index 00000000..17c3eab7 --- /dev/null +++ b/m4/ax_require_defined.m4 @@ -0,0 +1,37 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_require_defined.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_REQUIRE_DEFINED(MACRO) +# +# DESCRIPTION +# +# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have +# been defined and thus are available for use. This avoids random issues +# where a macro isn't expanded. Instead the configure script emits a +# non-fatal: +# +# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found +# +# It's like AC_REQUIRE except it doesn't expand the required macro. +# +# Here's an example: +# +# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) +# +# LICENSE +# +# Copyright (c) 2014 Mike Frysinger +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 2 + +AC_DEFUN([AX_REQUIRE_DEFINED], [dnl + m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) +])dnl AX_REQUIRE_DEFINED From 3bda3bc15a4bd96746e097307cb40c296a6b7580 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 17 Mar 2018 21:38:51 +0100 Subject: [PATCH 141/210] split Makefile --- Makefile.am | 17 +---------------- Makefile.library | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 16 deletions(-) create mode 100644 Makefile.library diff --git a/Makefile.am b/Makefile.am index 67066b58..11fa7834 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,21 +2,6 @@ if RTMIDI_STANDALONE ACLOCAL_AMFLAGS = -I m4 --install SUBDIRS = po endif -RTMIDITESTCXXFLAGS = $(EXTRA_RTMIDITESTCXXFLAGS) -I$(top_srcdir)/%D% -RTMIDILIBRARYNAME = %D%/librtmidi@rtmidi_suffix@.la -RTMIDITESTLDFLAGS = $(EXTRA_RTMIDITESTLDFLAGS) $(RTMIDILIBRARYNAME) RTMIDICONFIGRPATH = config/config.rpath -lib_LTLIBRARIES += %D%/librtmidi@rtmidi_suffix@.la -%C%_librtmidi@rtmidi_suffix@_la_LDFLAGS = -no-undefined $(RTMIDI__TS_LIBS) -%C%_librtmidi@rtmidi_suffix@_la_CXXFLAGS = $(CXXFLAGS) $(CPPFLAGS) $(RTMIDI_TS_API) -DRTMIDI_NO_WARN_DEPRECATED -%C%_librtmidi@rtmidi_suffix@_la_SOURCES = \ - %D%/RtMidi.cpp \ - %D%/RtMidi.h -EXTRA_DIST += \ - $(RTMIDICONFIGRPATH) \ - %D%/m4/ChangeLog \ - %D%/rtmidi-config.in \ - %D%/librtmidi.pc.in - -include %D%/tests/Makefile.am +include %D%/Makefile.library diff --git a/Makefile.library b/Makefile.library new file mode 100644 index 00000000..b22b06c8 --- /dev/null +++ b/Makefile.library @@ -0,0 +1,17 @@ +RTMIDITESTCXXFLAGS = $(EXTRA_RTMIDITESTCXXFLAGS) -I$(top_srcdir)/%D% +RTMIDILIBRARYNAME = %D%/librtmidi@rtmidi_suffix@.la +RTMIDITESTLDFLAGS = $(EXTRA_RTMIDITESTLDFLAGS) $(RTMIDILIBRARYNAME) +lib_LTLIBRARIES += %D%/librtmidi@rtmidi_suffix@.la +%C%_librtmidi@rtmidi_suffix@_la_LDFLAGS = -no-undefined $(RTMIDI__TS_LIBS) +%C%_librtmidi@rtmidi_suffix@_la_CXXFLAGS = $(CXXFLAGS) $(CPPFLAGS) $(RTMIDI_TS_API) -DRTMIDI_NO_WARN_DEPRECATED +%C%_librtmidi@rtmidi_suffix@_la_SOURCES = \ + %D%/RtMidi.cpp \ + %D%/RtMidi.h + +EXTRA_DIST += \ + $(RTMIDICONFIGRPATH) \ + %D%/m4/ChangeLog \ + %D%/rtmidi-config.in \ + %D%/librtmidi.pc.in + +include %D%/tests/Makefile.am From 4ee5c802be4b5adb0ee8f8fce67acecec1328172 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 Mar 2018 18:37:29 +0100 Subject: [PATCH 142/210] Update README to match current state. --- readme => README.md | 50 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) rename readme => README.md (55%) diff --git a/readme b/README.md similarity index 55% rename from readme rename to README.md index e6b966b5..388bc122 100644 --- a/readme +++ b/README.md @@ -1,6 +1,40 @@ +[![Build Status](https://travis-ci.org/keinstein/rtmidi.svg?branch=master-ts)](https://travis-ci.org/keinstein/rtmidi) + +Extended RtMidi fork for Mutabor, GUI based Software, and saving MIDI connections +================================================================================= + RtMidi - a set of C++ classes that provide a common API for realtime MIDI input/output across Linux (ALSA & JACK), Macintosh OS X (CoreMidi & JACK) and Windows (Multimedia). By Gary P. Scavone, 2003-2014. +Forked by Tobias Schlemmer, 2014-2018. + +This fork has been started because the original RtMidi did not work +for Mutabor and ALSA. Mutabor has a two-step activation scheme. The +MIDI configuration is set up while no connections are active. After +compiling the tuning logic all MIDI interfaces are activated at +once. Each MIDI connection that RtMidi makes is reported as MIDI +device again by RtMidi. This leads to a renumbering of all MIDI +endpoints which have a higher ALSA device ID than the current RtMidi +instance. The result is unexpected behaviour. + +As a side effect this library uses a different namespace and is more +C++-ish than the original RtMidi. + +Incompatible changes against upstream +------------------------------------- + +- The old API has been deprecated as there is no way to rely on + consecutive port numbers. It is always the responsibility of the + end user not to change the MIDI configuration between certain points + in the execution path of the library. Obviously they usually lack the + necessary information for that Currently, it is still available, but a + compiler warning is generated if applicable + +- `__MACOSX_CORE__` has been renamed to `__MACOSX_CORE__` + + +Compilation +----------- This distribution of RtMidi contains the following: @@ -11,9 +45,10 @@ On unix systems, type "./configure" in the top level directory, then "make" in t If you checked out the code from git, please run "autoreconf" before "./configure". -OVERVIEW: +Overview +-------- -RtMidi is a set of C++ classes (RtMidiIn, RtMidiOut, and API specific classes) that provide a common API (Application Programming Interface) for realtime MIDI input/output across Linux (ALSA, JACK), Macintosh OS X (CoreMIDI, JACK), and Windows (Multimedia Library) operating systems. RtMidi significantly simplifies the process of interacting with computer MIDI hardware and software. It was designed with the following goals: +RtMidi is a set of C++ classes (rtmidi::MidiIn, rtmidi::MidiOut, and API specific classes) that provide a common API (Application Programming Interface) for realtime MIDI input/output across Linux (ALSA, JACK), Macintosh OS X (CoreMIDI, JACK), and Windows (Multimedia Library) operating systems. RtMidi significantly simplifies the process of interacting with computer MIDI hardware and software. It was designed with the following goals: - object oriented C++ design - simple, common API across all supported platforms @@ -22,14 +57,17 @@ RtMidi is a set of C++ classes (RtMidiIn, RtMidiOut, and API specific classes) t MIDI input and output functionality are separated into two classes, RtMidiIn and RtMidiOut. Each class instance supports only a single MIDI connection. RtMidi does not provide timing functionality (i.e., output messages are sent immediately). Input messages are timestamped with delta times in seconds (via a double floating point type). MIDI data is passed to the user as raw bytes using an std::vector. -FURTHER READING: +Further reading +--------------- -For complete documentation on RtMidi, see the doc directory of the distribution or surf to http://music.mcgill.ca/~gary/rtmidi/. +For complete documentation on the original RtMidi, see the doc directory of the distribution or surf to http://music.mcgill.ca/~gary/rtmidi/. -LEGAL AND ETHICAL: +Legal and ethical +----------------- -The RtMidi license is similar to the the MIT License, with the added "feature" that modifications be sent to the developer. +The RtMidi license is similar to the the MIT License, with the added +"feature" that modifications be sent to the developer. RtMidi: realtime MIDI i/o C++ classes Copyright (c) 2003-2014 Gary P. Scavone From 69711ceaeeb275c4367175fa8b858bb6ba076c0f Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 Mar 2018 18:39:08 +0100 Subject: [PATCH 143/210] rename COREMIDI defined macro --- RtMidi.cpp | 316 +++++++++++++++++++-------------------- RtMidi.h | 34 ++--- doc/doxygen/Doxyfile | 2 +- doc/doxygen/tutorial.txt | 4 +- 4 files changed, 178 insertions(+), 178 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 8273897e..cbc6b793 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -133,7 +133,7 @@ void Midi :: getCompiledApi( std::vector &apis, bool preferSystem ) thr } // check OS provided backends -#if defined(__MACOSX_CORE__) +#if defined(__MACOSX_COREMIDI__) apis.push_back( rtmidi::MACOSX_CORE ); #endif #if defined(__LINUX_ALSA__) @@ -214,7 +214,7 @@ void MidiIn :: openMidiApi( ApiType api ) #endif break; case rtmidi::MACOSX_CORE: -#if defined(__MACOSX_CORE__) +#if defined(__MACOSX_COREMIDI__) rtapi_ = new MidiInCore( clientName, queueSizeLimit ); #endif break; @@ -253,14 +253,14 @@ MidiIn :: MidiIn( ApiType api, getCompiledApi( apis ); for ( unsigned int i=0; itimeStamp; if ( time == 0 ) { // this happens when receiving asynchronous sysex messages - time = AudioGetCurrentHostTime(); + time = AudioGetCurrentHostTime(); } time -= apiData->lastTime; time = AudioConvertHostTimeToNanos( time ); 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 @@ -1630,111 +1630,111 @@ void MidiInCore::midiInputCallback( const MIDIPacketList *list, if ( continueSysex ) { // We have a continuing, segmented sysex message. if ( !( data->ignoreFlags & 0x01 ) ) { - // If we're not ignoring sysex messages, copy the entire packet. - for ( unsigned int j=0; jdata[j] ); + // If we're not ignoring sysex messages, copy the entire packet. + for ( unsigned int j=0; jdata[j] ); } continueSysex = packet->data[nBytes-1] != 0xF7; if ( !( data->ignoreFlags & 0x01 ) ) { - if ( !continueSysex ) { - // If not a continuing sysex message, invoke the user callback function or queue the message. - if ( data->userCallback ) { - data->userCallback->rtmidi_midi_in( message.timeStamp, + if ( !continueSysex ) { + // If not a continuing sysex message, invoke the user callback function or queue the message. + if ( data->userCallback ) { + data->userCallback->rtmidi_midi_in( message.timeStamp, message.bytes); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else { - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else { + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother ALSA with an unhandled exception - } - } - } - message.bytes.clear(); - } + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } + } + } + message.bytes.clear(); + } } } else { while ( iByte < nBytes ) { - size = 0; - // We are expecting that the next byte in the packet is a status byte. - status = packet->data[iByte]; - if ( !(status & 0x80) ) break; - // Determine the number of bytes in the MIDI message. - if ( status < 0xC0 ) size = 3; - else if ( status < 0xE0 ) size = 2; - else if ( status < 0xF0 ) size = 3; - else if ( status == 0xF0 ) { - // A MIDI sysex - if ( data->ignoreFlags & 0x01 ) { - size = 0; - iByte = nBytes; - } - else size = nBytes - iByte; - continueSysex = packet->data[nBytes-1] != 0xF7; - } - else if ( status == 0xF1 ) { - // A MIDI time code message - if ( data->ignoreFlags & 0x02 ) { - size = 0; - iByte += 2; - } - else size = 2; - } - else if ( status == 0xF2 ) size = 3; - else if ( status == 0xF3 ) size = 2; - else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) { - // A MIDI timing tick message and we're ignoring it. - size = 0; - iByte += 1; - } - else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) { - // A MIDI active sensing message and we're ignoring it. - size = 0; - iByte += 1; - } - else size = 1; - - // Copy the MIDI data to our vector. - if ( size ) { - 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. - if ( data->userCallback ) { - data->userCallback->rtmidi_midi_in( message.timeStamp, + size = 0; + // We are expecting that the next byte in the packet is a status byte. + status = packet->data[iByte]; + if ( !(status & 0x80) ) break; + // Determine the number of bytes in the MIDI message. + if ( status < 0xC0 ) size = 3; + else if ( status < 0xE0 ) size = 2; + else if ( status < 0xF0 ) size = 3; + else if ( status == 0xF0 ) { + // A MIDI sysex + if ( data->ignoreFlags & 0x01 ) { + size = 0; + iByte = nBytes; + } + else size = nBytes - iByte; + continueSysex = packet->data[nBytes-1] != 0xF7; + } + else if ( status == 0xF1 ) { + // A MIDI time code message + if ( data->ignoreFlags & 0x02 ) { + size = 0; + iByte += 2; + } + else size = 2; + } + else if ( status == 0xF2 ) size = 3; + else if ( status == 0xF3 ) size = 2; + else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) { + // A MIDI timing tick message and we're ignoring it. + size = 0; + iByte += 1; + } + else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) { + // A MIDI active sensing message and we're ignoring it. + size = 0; + iByte += 1; + } + else size = 1; + + // Copy the MIDI data to our vector. + if ( size ) { + 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. + if ( data->userCallback ) { + data->userCallback->rtmidi_midi_in( message.timeStamp, message.bytes); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else { - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else { + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother WinMM with an unhandled exception - } - } - } - message.bytes.clear(); - } - iByte += size; - } + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } + } + } + message.bytes.clear(); + } + iByte += size; + } } } packet = MIDIPacketNext(packet); @@ -2924,19 +2924,19 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() case SND_SEQ_EVENT_SYSEX: if ( (data->ignoreFlags & 0x01) ) break; if ( ev->data.ext.len > apiData->bufferSize ) { - apiData->bufferSize = ev->data.ext.len; - free( buffer ); - buffer = (unsigned char *) malloc( apiData->bufferSize ); - if ( buffer == NULL ) { - data->doInput = false; - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error resizing buffer memory."), + apiData->bufferSize = ev->data.ext.len; + free( buffer ); + buffer = (unsigned char *) malloc( apiData->bufferSize ); + if ( buffer == NULL ) { + data->doInput = false; + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error resizing buffer memory."), Error::WARNING)); - } catch (Error e) { - // don't bother ALSA with an unhandled exception - } - break; - } + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } + break; + } } RTMIDI_FALLTHROUGH; default: @@ -2947,38 +2947,38 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() nBytes = snd_midi_event_decode( apiData->coder, buffer, apiData->bufferSize, ev ); if ( nBytes > 0 ) { - // The ALSA sequencer has a maximum buffer size for MIDI sysex - // events of 256 bytes. If a device sends sysex messages larger - // than this, they are segmented into 256 byte chunks. So, - // we'll watch for this and concatenate sysex chunks into a - // single sysex message if necessary. - if ( !continueSysex ) - message.bytes.assign( buffer, &buffer[nBytes] ); - else - message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] ); - - continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) ); - if ( !continueSysex ) { - - // Calculate the time stamp: - message.timeStamp = 0.0; - - // Method 1: Use the system time. - //(void)gettimeofday(&tv, (struct timezone *)NULL); - //time = (tv.tv_sec * 1000000) + tv.tv_usec; - - // Method 2: Use the ALSA sequencer event time data. - // (thanks to Pedro Lopez-Cabanillas!). - time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 ); - lastTime = time; - time -= apiData->lastTime; - apiData->lastTime = lastTime; - if ( data->firstMessage == true ) - data->firstMessage = false; - else - message.timeStamp = time * 0.000001; - } - else { + // The ALSA sequencer has a maximum buffer size for MIDI sysex + // events of 256 bytes. If a device sends sysex messages larger + // than this, they are segmented into 256 byte chunks. So, + // we'll watch for this and concatenate sysex chunks into a + // single sysex message if necessary. + if ( !continueSysex ) + message.bytes.assign( buffer, &buffer[nBytes] ); + else + message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] ); + + continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) ); + if ( !continueSysex ) { + + // Calculate the time stamp: + message.timeStamp = 0.0; + + // Method 1: Use the system time. + //(void)gettimeofday(&tv, (struct timezone *)NULL); + //time = (tv.tv_sec * 1000000) + tv.tv_usec; + + // Method 2: Use the ALSA sequencer event time data. + // (thanks to Pedro Lopez-Cabanillas!). + time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 ); + lastTime = time; + time -= apiData->lastTime; + apiData->lastTime = lastTime; + if ( data->firstMessage == true ) + data->firstMessage = false; + else + message.timeStamp = time * 0.000001; + } + else { #if defined(__RTMIDI_DEBUG__) try { data->error(RTMIDI_ERROR(rtmidi_gettext("Event parsing error or not a MIDI event."), diff --git a/RtMidi.h b/RtMidi.h index 6963570d..85c7a65d 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -194,11 +194,11 @@ class Error : public std::exception //! The constructor. Error( const char * message, - Type type, - const char * class_name, - const char * function_name, - const char * file_name, - int line_number, ...) throw(); + Type type, + const char * class_name, + const char * function_name, + const char * file_name, + int line_number, ...) throw(); //! The destructor. virtual ~Error( void ) throw() {} @@ -303,8 +303,8 @@ class Pointer { Pointer & operator = (const Pointer & other) { if (ptr) { if (!(--ptr->count)) { - delete ptr->descriptor; - delete ptr; + delete ptr->descriptor; + delete ptr; } } if ((ptr = other.ptr)) @@ -838,10 +838,10 @@ class Midi { if (list && !list->empty()) { PortList retval; for (MidiApiList::iterator i = list->begin(); - i != list->end(); - ++i) { - PortList tmp = (*i)->getPortList(capabilities); - retval.splice(retval.end(), tmp); + i != list->end(); + ++i) { + PortList tmp = (*i)->getPortList(capabilities); + retval.splice(retval.end(), tmp); } return retval; } @@ -1135,8 +1135,8 @@ class MidiIn : public Midi std::vector< ApiType > apis; getCompiledApi( apis ); for (size_t i = 0 ; i < apis.size() ; i++) { - openMidiApi( apis[0] ); - if (rtapi_ && rtapi_->hasVirtualPorts()) break; + openMidiApi( apis[0] ); + if (rtapi_ && rtapi_->hasVirtualPorts()) break; } } @@ -1390,8 +1390,8 @@ class MidiOut : public Midi std::vector< ApiType > apis; getCompiledApi( apis ); for (size_t i = 0 ; i < apis.size() ; i++) { - openMidiApi( apis[0] ); - if (rtapi_ && rtapi_->hasVirtualPorts()) break; + openMidiApi( apis[0] ); + if (rtapi_ && rtapi_->hasVirtualPorts()) break; } } @@ -1475,11 +1475,11 @@ class MidiOut : public Midi // **************************************************************** // -#if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__) +#if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_COREMIDI__) && !defined(__WINDOWS_MM__) #define __RTMIDI_DUMMY__ #endif -#if defined(__MACOSX_CORE__) +#if defined(__MACOSX_COREMIDI__) NAMESPACE_RTMIDI_END struct MIDIPacketList; NAMESPACE_RTMIDI_START diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index 4f8489c5..430dcd6b 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -1580,7 +1580,7 @@ INCLUDE_FILE_PATTERNS = # undefined via #undef or recursively expanded use the := operator # instead of the = operator. -PREDEFINED = __MACOSX_CORE__ \ +PREDEFINED = __MACOSX_COREMIDI__ \ __WINDOWS_MM__ \ __UNIX_JACK__ \ __LINUX_ALSA__ \ diff --git a/doc/doxygen/tutorial.txt b/doc/doxygen/tutorial.txt index 3ba6f9e0..8ca80e08 100644 --- a/doc/doxygen/tutorial.txt +++ b/doc/doxygen/tutorial.txt @@ -433,9 +433,9 @@ In order to compile RtMidi for a specific OS and API, it is necessary to supply Macintosh OS X CoreMIDI - __MACOSX_CORE__ + __MACOSX_COREMIDI__ CoreMIDI, CoreAudio, CoreFoundation - g++ -Wall -D__MACOSX_CORE__ -o midiprobe midiprobe2.cpp RtMidi.cpp -framework CoreMIDI -framework CoreAudio -framework CoreFoundation + g++ -Wall -D__MACOSX_COREMIDI__ -o midiprobe midiprobe2.cpp RtMidi.cpp -framework CoreMIDI -framework CoreAudio -framework CoreFoundation Windows From 1c9bb4d81c0fd8275c88f5961473f6e35af80b95 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 Mar 2018 18:47:41 +0100 Subject: [PATCH 144/210] Reorganize build system. - remove duplicate checks for backend libraries - move backend checks into separate files - properly use pkg-config - fix DLL installation --- Makefile.am | 2 + Makefile.library | 16 +- configure.library | 425 ++++++++++++++++++++------------------ m4/alsa.m4 | 143 +++++++++++++ m4/pkg.m4 | 275 ++++++++++++++++++++++++ m4/rtmidi_lib_alsa.m4 | 44 ++++ m4/rtmidi_lib_coremidi.m4 | 46 +++++ m4/rtmidi_lib_jack.m4 | 66 ++++++ m4/rtmidi_lib_winks.m4 | 47 +++++ m4/rtmidi_lib_winmm.m4 | 47 +++++ tests/Makefile.am | 68 +++--- 11 files changed, 945 insertions(+), 234 deletions(-) create mode 100644 m4/alsa.m4 create mode 100644 m4/pkg.m4 create mode 100644 m4/rtmidi_lib_alsa.m4 create mode 100644 m4/rtmidi_lib_coremidi.m4 create mode 100644 m4/rtmidi_lib_jack.m4 create mode 100644 m4/rtmidi_lib_winks.m4 create mode 100644 m4/rtmidi_lib_winmm.m4 diff --git a/Makefile.am b/Makefile.am index 11fa7834..1c265562 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,5 +3,7 @@ ACLOCAL_AMFLAGS = -I m4 --install SUBDIRS = po endif RTMIDICONFIGRPATH = config/config.rpath +DLLPROGRAMS = $(check_PROGRAMS) +check_PROGRAMS = include %D%/Makefile.library diff --git a/Makefile.library b/Makefile.library index b22b06c8..e5c68ce7 100644 --- a/Makefile.library +++ b/Makefile.library @@ -1,9 +1,21 @@ +# -*- makefile-automake -*- RTMIDITESTCXXFLAGS = $(EXTRA_RTMIDITESTCXXFLAGS) -I$(top_srcdir)/%D% RTMIDILIBRARYNAME = %D%/librtmidi@rtmidi_suffix@.la RTMIDITESTLDFLAGS = $(EXTRA_RTMIDITESTLDFLAGS) $(RTMIDILIBRARYNAME) lib_LTLIBRARIES += %D%/librtmidi@rtmidi_suffix@.la -%C%_librtmidi@rtmidi_suffix@_la_LDFLAGS = -no-undefined $(RTMIDI__TS_LIBS) -%C%_librtmidi@rtmidi_suffix@_la_CXXFLAGS = $(CXXFLAGS) $(CPPFLAGS) $(RTMIDI_TS_API) -DRTMIDI_NO_WARN_DEPRECATED +DLLPROGRAMS += %D%/librtmidi@rtmidi_suffix@.* +DLLPROGRAMS += %D%/.libs/librtmidi@rtmidi_suffix@.* +%C%_librtmidi@rtmidi_suffix@_la_LDFLAGS = \ + $(RTMIDI_LIBS) \ + $(LDADD) \ + -version-info 3:0:0 \ + -no-undefined \ + -v +%C%_librtmidi@rtmidi_suffix@_la_CXXFLAGS = \ + $(CXXFLAGS) \ + $(CPPFLAGS) \ + $(RTMIDI_API) \ + -DRTMIDI_NO_WARN_DEPRECATED %C%_librtmidi@rtmidi_suffix@_la_SOURCES = \ %D%/RtMidi.cpp \ %D%/RtMidi.h diff --git a/configure.library b/configure.library index 81fd8513..c37f1a62 100644 --- a/configure.library +++ b/configure.library @@ -29,21 +29,21 @@ AC_HEADER_STDC AC_ARG_ENABLE(suffix, AS_HELP_STRING([--with-suffix],[add a suffix to the library. Default is $rtmidi_suffix]), [AS_IF(test "x$enableval" = "xno", - [ rtmidi_suffix=""], - [ rtmidi_suffix="$enableval"])]) + [ rtmidi_suffix=""], + [ rtmidi_suffix="$enableval"])]) AC_SUBST(rtmidi_suffix) # Check for debug AC_MSG_CHECKING(whether to compile debug version) AC_ARG_ENABLE(debug, - [ --enable-debug = enable various debug output], - [ - AC_SUBST( RTMIDI_CPPFLAGS, [-D__RTMIDI_DEBUG__] ) - AC_SUBST( RTMIDI_CXXFLAGS, [-g] ) - AC_MSG_RESULT(yes)], - [AC_SUBST( RTMIDI_CPPFLAGS, [] ) - AC_SUBST( RTMIDI_CXXFLAGS, [-O3] ) - AC_MSG_RESULT(no)]) + [ --enable-debug = enable various debug output], + [ + AC_SUBST( RTMIDI_CPPFLAGS, [-D__RTMIDI_DEBUG__] ) + AC_SUBST( RTMIDI_CXXFLAGS, [-g] ) + AC_MSG_RESULT(yes)], + [AC_SUBST( RTMIDI_CPPFLAGS, [] ) + AC_SUBST( RTMIDI_CXXFLAGS, [-O3] ) + AC_MSG_RESULT(no)]) dnl # Set paths if prefix is defined dnl if test "x$prefix" != "x" && test "x$prefix" != "xNONE"; then @@ -57,99 +57,99 @@ do tmpcxxflags="$CXXFLAGS" CXXFLAGS="$CXXFLAGS $flag" AC_MSG_CHECKING([whether $CXX supports $flag]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], - [AC_MSG_RESULT([yes])], - [CXXFLAGS="$tmpcxxflags" - AC_MSG_RESULT([no])]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CXXFLAGS="$tmpcxxflags" + AC_MSG_RESULT([no])]) AC_LANG_PUSH(C) tmpcflags="$CFLAGS" CFLAGS="$CFLAGS $flag" AC_MSG_CHECKING([whether $CC supports $flag]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], - [AC_MSG_RESULT([yes])], - [CFLAGS="$tmpcflags" - AC_MSG_RESULT([no])]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CFLAGS="$tmpcflags" + AC_MSG_RESULT([no])]) AC_LANG_POP(C) done dnl mudflap is not possible with g++ 4.7.1 and wxWidgets 2.8 -dnl tmpcxxflags="$CXXFLAGS" -dnl tmplibs="$LIBS" -dnl CXXFLAGS="$CXXFLAGS -fmudflapth" -dnl LIBS="-lmudflapth" -dnl AC_MSG_CHECKING([whether $CXX supports -fmudflapth -lmudflapth]) -dnl AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], -dnl [AC_MSG_RESULT([yes])], +dnl tmpcxxflags="$CXXFLAGS" +dnl tmplibs="$LIBS" +dnl CXXFLAGS="$CXXFLAGS -fmudflapth" +dnl LIBS="-lmudflapth" +dnl AC_MSG_CHECKING([whether $CXX supports -fmudflapth -lmudflapth]) +dnl AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], +dnl [AC_MSG_RESULT([yes])], dnl [CXXFLAGS="$tmpcxxflags" dnl LIBS="$tmplibs"] -dnl [AC_MSG_RESULT([no])]) +dnl [AC_MSG_RESULT([no])]) dnl AC_ARG_ENABLE(address-sanitizer, AS_HELP_STRING([--enable-address-sanitizer],[Enable gcc/clang address santizer]), [AS_IF(test "$enableval" = yes, - AC_LANG_PUSH(C++) - for flag in -fsanitize=address -fno-omit-frame-pointer -fno-common - do - tmpcxxflags="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $flag" - AC_MSG_CHECKING([whether $CXX supports $flag]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], - [AC_MSG_RESULT([yes])], - [CXXFLAGS="$tmpcxxflags" - AC_MSG_RESULT([no])]) + AC_LANG_PUSH(C++) + for flag in -fsanitize=address -fno-omit-frame-pointer -fno-common + do + tmpcxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $flag" + AC_MSG_CHECKING([whether $CXX supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CXXFLAGS="$tmpcxxflags" + AC_MSG_RESULT([no])]) AC_LANG_PUSH(C) tmpcflags="$CFLAGS" CFLAGS="$CFLAGS $flag" AC_MSG_CHECKING([whether $CC supports $flag]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], - [AC_MSG_RESULT([yes])], - [CFLAGS="$tmpcflags" - AC_MSG_RESULT([no])]) + [AC_MSG_RESULT([yes])], + [CFLAGS="$tmpcflags" + AC_MSG_RESULT([no])]) AC_LANG_POP(C) - done - AC_LANG_POP(C++) - ) + done + AC_LANG_POP(C++) + ) ] ) AC_ARG_ENABLE(thread-sanitizer, AS_HELP_STRING([--enable-thread-sanitizer],[Enable gcc/clang thread santizer]), [AS_IF(test "$enableval" = yes, - AC_LANG_PUSH(C++) - for flag in -fsanitize=thread -fno-omit-frame-pointer -fno-common -fPIC - do - tmpcxxflags="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $flag" - AC_MSG_CHECKING([whether $CXX supports $flag]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], - [AC_MSG_RESULT([yes])], - [CXXFLAGS="$tmpcxxflags" - AC_MSG_RESULT([no])]) - AC_LANG_PUSH(C) - tmpcflags="$CFLAGS" - CFLAGS="$CFLAGS $flag" - AC_MSG_CHECKING([whether $CC supports $flag]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], - [AC_MSG_RESULT([yes])], - [CFLAGS="$tmpcflags" - AC_MSG_RESULT([no])]) - AC_LANG_POP(C) - done - for flag in -pie - do - tmpldflags="$LDFLAGS" - LDFLAGS="$LDFLAGS $flag" - AC_MSG_CHECKING([whether $LD supports $flag]) - AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])], - [AC_MSG_RESULT([yes])], - [LDFLAGS="$tmpldflags" - AC_MSG_RESULT([no])]) - done - AC_LANG_POP(C++) - ) + AC_LANG_PUSH(C++) + for flag in -fsanitize=thread -fno-omit-frame-pointer -fno-common -fPIC + do + tmpcxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $flag" + AC_MSG_CHECKING([whether $CXX supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CXXFLAGS="$tmpcxxflags" + AC_MSG_RESULT([no])]) + AC_LANG_PUSH(C) + tmpcflags="$CFLAGS" + CFLAGS="$CFLAGS $flag" + AC_MSG_CHECKING([whether $CC supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CFLAGS="$tmpcflags" + AC_MSG_RESULT([no])]) + AC_LANG_POP(C) + done + for flag in -pie + do + tmpldflags="$LDFLAGS" + LDFLAGS="$LDFLAGS $flag" + AC_MSG_CHECKING([whether $LD supports $flag]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [LDFLAGS="$tmpldflags" + AC_MSG_RESULT([no])]) + done + AC_LANG_POP(C++) + ) ] ) @@ -163,142 +163,155 @@ dnl AC_SUBST( sharedname, ["librtmidi.\$(RELEASE).dylib"] ) dnl AC_SUBST( libflags, ["-dynamiclib -o librtmidi.\$(RELEASE).dylib"] ) dnl esac -AC_SUBST( RTMIDI_TS_API, [""] ) -AC_SUBST( req, [""] ) + + + +AC_SUBST( RTMIDI_API, [""] ) +AC_SUBST( RTMIDI_LIBS, [""] ) AC_MSG_CHECKING(for MIDI API) -have_virtual_devices=no +RTMIDI_HAVE_VIRTUAL_DEVICES=no +rtmidi_check_jack=auto case $host in - *-*-linux*) - AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (mac and linux only)], [ - have_virtual_devices=yes - RTMIDI_TS_API="$RTMIDI_TS_API -D__UNIX_JACK__" - AC_MSG_RESULT(using JACK) - AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], ) - AC_LANG_PUSH(C++) - AC_TRY_COMPILE([ -#include - ],[ -return jack_port_uuid(NULL); - ],RTMIDI_TS_API="$RTMIDI_TS_API -D__UNIX_JACK_HAS_UUID__") - AC_LANG_POP(C++) - - # Look for ALSA flag - AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA sequencer API support (linux only)], [ - have_virtual_devices=yes - RTMIDI_TS_API="$RTMIDI_TS_API -D__LINUX_ALSA__" - req="$req alsa" - AC_MSG_RESULT(using ALSA) - AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(ALSA support requires the asound library!))], ) - - if [test "$RTMIDI_TS_API" == "";] then - AC_MSG_RESULT(using ALSA) - AC_SUBST( RTMIDI_TS_API, [-D__LINUX_ALSA__] ) - req="$req alsa" - have_virtual_devices=yes - AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(ALSA sequencer support requires the asound library!)) - fi - - # Checks for pthread library. - AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtMidi requires the pthread library!)) - ;; - - *-apple*) - AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (mac and linux only)], [ - have_virtual_devices=yes - RTMIDI_TS_API="$RTMIDI_TS_API -D__UNIX_JACK__" - AC_MSG_RESULT(using JACK) - AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], ) - AC_LANG_PUSH(C++) - AC_TRY_COMPILE([ -#include - ],[ -return jack_port_uuid(NULL); - ],RTMIDI_TS_API="$RTMIDI_TS_API -D__UNIX_JACK_HAS_UUID__") - AC_LANG_POP(C++) - - # Look for Core flag - AC_ARG_WITH(core, [ --with-core = choose CoreMidi API support (mac only)], [ - have_virtual_devices=yes - RTMIDI_TS_API="$RTMIDI_TS_API -D__MACOSX_CORE__" - AC_MSG_RESULT(using CoreMidi) - AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, [], [AC_MSG_ERROR(CoreMIDI header files not found!)] ) - RTMIDI_TS_LIBS="$RTMIDI_TS_LIBS -framework CoreMIDI -framework CoreFoundation -framework CoreAudio" ], ) - - # If no api flags specified, use CoreMidi - if [test "$RTMIDI_TS_API" == ""; ] then - have_virtual_devices=yes - AC_SUBST( RTMIDI_TS_API, [-D__MACOSX_CORE__] ) - AC_MSG_RESULT(using CoreMidi) - AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, - [], - [AC_MSG_ERROR(CoreMIDI header files not found!)] ) - AC_SUBST( RTMIDI_TS_LIBS, ["-framework CoreMIDI -framework CoreFoundation -framework CoreAudio"] ) - fi - ;; - - *-mingw32*) - - # Look for WinMM flag - AC_ARG_WITH(winmm, [ --with-winmm = choose Windows MultiMedia (MM) API support (windoze only)], [ - RTMIDI_TS_API="$RTMIDI_TS_API -D__WINDOWS_MM__" - AC_MSG_RESULT(using WinMM) - AC_SUBST( RTMIDI_TS_LIBS, [-lwinmm] )], ) - - AC_ARG_WITH(winks, [ --with-winks = choose kernel streaming support (windoze only)], [ - api="$RTMIDI_TS_API -D__WINDOWS_KS__" - AC_SUBST( RTMIDI_TS_LIBS, ["-lsetupapi -lksuser"] ) - AC_MSG_RESULT(using kernel streaming) ], ) - - # I can't get the following check to work so just manually add the library +*linux*) + PLATFORM=linux +dnl with_winmm=no +dnl with_winks=no +dnl with_coremidi=no + + # Checks for pthread library. + ;; + +darwin*|*apple*) + PLATFORM=macosx + # Check for CoreAudio framework + with_winmm=no + with_winks=no + with_alsa=no + + ;; + +*winnt*|*interix*|cygwin*|*mingw*|uwin*) + PLATFORM=windows + with_alsa=no + with_coremidi=no + + # I can't get the following check to work so just manually add the library # or could try the following? AC_LIB_WINMM([midiOutGetNumDevs]) - # AC_CHECK_LIB(winmm, midiInGetNumDevs, , AC_MSG_ERROR(Windows MIDI support requires the winmm library!) )],) - - # If no RTMIDI_TS_API flags specified, use WinMM - if [test "$RTMIDI_TS_API" == "";] then - AC_SUBST( RTMIDI_TS_API, [-D__WINDOWS_MM__] ) - AC_MSG_RESULT(using WinMM) - AC_SUBST( RTMIDI_TS_LIBS, [-lwinmm] ) - fi - - AC_CACHE_CHECK([where to find support dlls], [ac_cv_rtmidi_ts_mingw_dll_dirs], - [ - gccsearchdirs=`$CXX $CXXFLAGS -print-search-dirs|\ - sed -e '/^libraries:/ { s/^libraries: *=\?//;s/:/ /g; p } ; d'` - SEARCHDIRS="$DLLSEARCHPATH" - for d in \ - $gccsearchdirs \ - /usr/share/doc/mingw32-runtime \ - /usr/$host/bin \ - /usr/$host/lib \ - /usr/bin/$host/ \ - /usr/lib/$host/ \ - /usr/lib/$host/lib \ - /usr/lib/$host/bin \ - /usr/bin/$host/lib \ - /usr/bin/$host/bin \ - /mingw/lib \ - /mingw/bin \ - /usr/lib \ - /lib \ - /usr/bin \ - /bin - do - AS_IF(test -d $d, - [ SEARCHDIRS="$SEARCHDIRS $d" ]) - done - ac_cv_rtmidi_ts_mingw_dll_dirs="$SEARCHDIRS" - ]) - - AC_SUBST(DLLSEARCHPATH,"$ac_cv_rtmidi_ts_mingw_dll_dirs") - - ;; - - *) - # Default case for unknown realtime systems. - AC_MSG_ERROR(Unknown system type for MIDI support!) - ;; + # AC_CHECK_LIB(winmm, midiInGetNumDevs, , AC_MSG_ERROR(Windows MIDI support requires the winmm library!) )],) + AC_CACHE_CHECK([where to find support dlls], [ac_cv_rtmidi_ts_mingw_dll_dirs], + [ + gccsearchdirs=`$CXX $CXXFLAGS -print-search-dirs|\ + sed -e '/^libraries:/ { s/^libraries: *=\?//; p } ; d'` + gccsearchdirs="$WINEDLLPATH:$gccsearchdirs:\ +/usr/share/doc/mingw32-runtime:\ +/usr/$host/bin:\ +/usr/$host/lib:\ +/usr/bin/$host/:\ +/usr/lib/$host/:\ +/usr/lib/$host/lib:\ +/usr/lib/$host/bin:\ +/usr/bin/$host/lib:\ +/usr/bin/$host/bin:\ +/mingw/lib:\ +/mingw/bin:\ +/usr/lib:\ +/lib:\ +/usr/bin:\ +/bin" + SEARCHDIRS="$PWD:$PWD/.libs" + old_FS="$IFS" + IFS=: + for d in $gccsearchdirs ; + do + echo "testing $d" + AS_IF(test -d $d, + [ SEARCHDIRS="$SEARCHDIRS:$d" ]) + done + IFS="$old_FS" + ac_cv_rtmidi_ts_mingw_dll_dirs="$SEARCHDIRS" + ]) + + AC_SUBST(DLLSEARCHPATH,"$ac_cv_rtmidi_ts_mingw_dll_dirs") + rtmidicopydlls=true + echo + echo "DLL path= $DLLSEARCHPATH" + + ;; + +*) + # Default case for unknown realtime systems. + AC_MSG_WARN([ + Your target system could not be recognized. $PACKAGE depends on + a working MIDI configuration for your System. We are trying all + supported APIs. The result may be varying. + + Please contact the development team at + + $PACKAGE_BUGREPORT + + and provide the following information: + + * The output of configure + * The description of your System. + + ]) + ;; esac -AM_CONDITIONAL(HAVE_VIRTUAL_DEVICES,test "$have_virtual_devices" == yes) +echo "with-jack: $with_jack" +echo "nochmal withjack" +AC_ARG_WITH(jack, + [ --with-jack = choose JACK server support (needs libjack to be installed)],[ + echo running jack: + AS_IF([test "x$with_jack" = "no"],,[RTMIDI_LIB_JACK ]) + ],[ echo runnning jack 2 ; RTMIDI_LIB_JACK(,[true]) ]) + +echo +echo "RTMIDI_API = $RTMIDI_API" +echo "RTMIDI_LIBS = $RTMIDI_LIBS" +echo "virtual devices: $RTMIDI_HAVE_VIRTUAL_DEVICES" +echo +echo "with_alsa: $with_alsa" +echo +AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA sequencer API support],[ + AS_IF([test "x$with_alsa" = "no"],,[ RTMIDI_LIB_ALSA ]) + ],[ RTMIDI_LIB_ALSA(,[true]) ]) + +echo +echo "RTMIDI_API = $RTMIDI_API" +echo "RTMIDI_LIBS = $RTMIDI_LIBS" +echo "virtual devices: $RTMIDI_HAVE_VIRTUAL_DEVICES" +echo +AC_ARG_WITH(winmm, [ --with-winmm = choose native Windows Multimedia API support],[ + AS_IF([test "x$with_winmm" = "no"],,[RTMIDI_LIB_WINMM ]) + ],[ RTMIDI_LIB_WINMM(,[true]) ]) +echo +echo "RTMIDI_API = $RTMIDI_API" +echo "RTMIDI_LIBS = $RTMIDI_LIBS" +echo "virtual devices: $RTMIDI_HAVE_VIRTUAL_DEVICES" +echo +AC_ARG_WITH(winks, [ --with-winks = choose native Windows kernel streaming API support],[ + AS_IF([test "x$with_winks" = "no"],,[ RTMIDI_LIB_WINKS ]) + ],[ RTMIDI_LIB_WINKS(,[true]) ]) + +echo +echo "RTMIDI_API = $RTMIDI_API" +echo "RTMIDI_LIBS = $RTMIDI_LIBS" +echo "virtual devices: $RTMIDI_HAVE_VIRTUAL_DEVICES" +echo +AC_ARG_WITH(coremidi, [--with-coremidi = choose native CoreAudio API support],[ + AS_IF([test "x$with_core" = "no"],,[RTMIDI_LIB_CORE ]) + ],[ RTMIDI_LIB_COREMIDI(,[true]) ]) +echo +echo "RTMIDI_API = $RTMIDI_API" +echo "RTMIDI_LIBS = $RTMIDI_LIBS" +echo "virtual devices: $RTMIDI_HAVE_VIRTUAL_DEVICES" +echo +AS_IF([test "x$RTMIDI_API" = "x"],[ + AC_MSG_WARN("No suitable MIDI interface found. Using dummy driver") + RTMIDI_API="-D__RTMIDI_DUMMY__" +]) + +AM_CONDITIONAL(RTMIDI_HAVE_VIRTUAL_DEVICES,test "$RTMIDI_HAVE_VIRTUAL_DEVICES" == yes) AM_GNU_GETTEXT([external]) AM_GNU_GETTEXT_VERSION([0.18.3]) diff --git a/m4/alsa.m4 b/m4/alsa.m4 new file mode 100644 index 00000000..e12310df --- /dev/null +++ b/m4/alsa.m4 @@ -0,0 +1,143 @@ +dnl Configure Paths for Alsa +dnl Some modifications by Richard Boulton +dnl Christopher Lansdown +dnl Jaroslav Kysela +dnl Last modification: $Id: alsa.m4,v 1.24 2004/09/15 18:48:07 tiwai Exp $ +dnl AM_PATH_ALSA([MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for libasound, and define ALSA_CFLAGS and ALSA_LIBS as appropriate. +dnl enables arguments --with-alsa-prefix= +dnl --with-alsa-enc-prefix= +dnl --disable-alsatest +dnl +dnl For backwards compatibility, if ACTION_IF_NOT_FOUND is not specified, +dnl and the alsa libraries are not found, a fatal AC_MSG_ERROR() will result. +dnl +AC_DEFUN([AM_PATH_ALSA], +[dnl Save the original CFLAGS, LDFLAGS, and LIBS +alsa_save_CFLAGS="$CFLAGS" +alsa_save_LDFLAGS="$LDFLAGS" +alsa_save_LIBS="$LIBS" +alsa_found=yes + +dnl +dnl Get the cflags and libraries for alsa +dnl +AC_ARG_WITH(alsa-prefix, +[ --with-alsa-prefix=PFX Prefix where Alsa library is installed(optional)], +[alsa_prefix="$withval"], [alsa_prefix=""]) + +AC_ARG_WITH(alsa-inc-prefix, +[ --with-alsa-inc-prefix=PFX Prefix where include libraries are (optional)], +[alsa_inc_prefix="$withval"], [alsa_inc_prefix=""]) + +dnl FIXME: this is not yet implemented +AC_ARG_ENABLE(alsatest, +[ --disable-alsatest Do not try to compile and run a test Alsa program], +[enable_alsatest="$enableval"], +[enable_alsatest=yes]) + +dnl Add any special include directories +AC_MSG_CHECKING(for ALSA CFLAGS) +if test "$alsa_inc_prefix" != "" ; then + ALSA_CFLAGS="$ALSA_CFLAGS -I$alsa_inc_prefix" + CFLAGS="$CFLAGS -I$alsa_inc_prefix" +fi +AC_MSG_RESULT($ALSA_CFLAGS) + +dnl add any special lib dirs +AC_MSG_CHECKING(for ALSA LDFLAGS) +if test "$alsa_prefix" != "" ; then + ALSA_LIBS="$ALSA_LIBS -L$alsa_prefix" + LDFLAGS="$LDFLAGS $ALSA_LIBS" +fi + +dnl add the alsa library +ALSA_LIBS="$ALSA_LIBS -lasound -lm -ldl -lpthread" +LIBS="$ALSA_LIBS $LIBS" +AC_MSG_RESULT($ALSA_LIBS) + +dnl Check for a working version of libasound that is of the right version. +if test "x$enable_alsatest" = "xyes"; then +min_alsa_version=ifelse([$1], ,0.1.1,$1) +AC_MSG_CHECKING(for libasound headers version >= $min_alsa_version) +no_alsa="" + alsa_min_major_version=`echo $min_alsa_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + alsa_min_minor_version=`echo $min_alsa_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + alsa_min_micro_version=`echo $min_alsa_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + +AC_LANG_SAVE +AC_LANG_C +AC_TRY_COMPILE([ +#include +], [ +/* ensure backward compatibility */ +#if !defined(SND_LIB_MAJOR) && defined(SOUNDLIB_VERSION_MAJOR) +#define SND_LIB_MAJOR SOUNDLIB_VERSION_MAJOR +#endif +#if !defined(SND_LIB_MINOR) && defined(SOUNDLIB_VERSION_MINOR) +#define SND_LIB_MINOR SOUNDLIB_VERSION_MINOR +#endif +#if !defined(SND_LIB_SUBMINOR) && defined(SOUNDLIB_VERSION_SUBMINOR) +#define SND_LIB_SUBMINOR SOUNDLIB_VERSION_SUBMINOR +#endif + +# if(SND_LIB_MAJOR > $alsa_min_major_version) + exit(0); +# else +# if(SND_LIB_MAJOR < $alsa_min_major_version) +# error not present +# endif + +# if(SND_LIB_MINOR > $alsa_min_minor_version) + exit(0); +# else +# if(SND_LIB_MINOR < $alsa_min_minor_version) +# error not present +# endif + +# if(SND_LIB_SUBMINOR < $alsa_min_micro_version) +# error not present +# endif +# endif +# endif +exit(0); +], + [AC_MSG_RESULT(found.)], + [AC_MSG_RESULT(not present.) + ifelse([$3], , [AC_MSG_ERROR(Sufficiently new version of libasound not found.)]) + alsa_found=no] +) +AC_LANG_RESTORE +fi + +dnl Now that we know that we have the right version, let's see if we have the library and not just the headers. +if test "x$enable_alsatest" = "xyes"; then +AC_CHECK_LIB([asound], [snd_ctl_open],, + [ifelse([$3], , [AC_MSG_ERROR(No linkable libasound was found.)]) + alsa_found=no] +) +fi + +if test "x$alsa_found" = "xyes" ; then + ifelse([$2], , :, [$2]) + LIBS=`echo $LIBS | sed 's/-lasound//g'` + LIBS=`echo $LIBS | sed 's/ //'` + LIBS="-lasound $LIBS" +fi +if test "x$alsa_found" = "xno" ; then + ifelse([$3], , :, [$3]) + CFLAGS="$alsa_save_CFLAGS" + LDFLAGS="$alsa_save_LDFLAGS" + LIBS="$alsa_save_LIBS" + ALSA_CFLAGS="" + ALSA_LIBS="" +fi + +dnl That should be it. Now just export out symbols: +AC_SUBST(ALSA_CFLAGS) +AC_SUBST(ALSA_LIBS) +]) + diff --git a/m4/pkg.m4 b/m4/pkg.m4 new file mode 100644 index 00000000..4688002e --- /dev/null +++ b/m4/pkg.m4 @@ -0,0 +1,275 @@ +dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +dnl serial 11 (pkg-config-0.29) +dnl +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR diff --git a/m4/rtmidi_lib_alsa.m4 b/m4/rtmidi_lib_alsa.m4 new file mode 100644 index 00000000..083539fa --- /dev/null +++ b/m4/rtmidi_lib_alsa.m4 @@ -0,0 +1,44 @@ +# AC_LIB_ALSA(FUNCTION, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [OTHER-LIBRARIES]) +# ------------------------------------------------------ +# +# Use a cache variable name containing both the library and function name, +# because the test really is for library $1 defining function $2, not +# just for library $1. Separate tests with the same $1 and different $2s +# may have different results. +# +# Note that using directly AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$2]) +# is asking for troubles, since AC_CHECK_LIB($lib, fun) would give +# ac_cv_lib_$lib_fun, which is definitely not what was meant. Hence +# the AS_LITERAL_IF indirection. +# +# FIXME: This macro is extremely suspicious. It DEFINEs unconditionally, +# whatever the FUNCTION, in addition to not being a *S macro. Note +# that the cache does depend upon the function we are looking for. +# +# It is on purpose we used `ac_check_lib_save_LIBS' and not just +# `ac_save_LIBS': there are many macros which don't want to see `LIBS' +# changed but still want to use AC_CHECK_LIB, so they save `LIBS'. +# And ``ac_save_LIBS' is too tempting a name, so let's leave them some +# freedom. +AC_DEFUN([RTMIDI_LIB_ALSA],[ + AC_LANG_PUSH(C++) + rtmidi_have_alsa=no + AM_PATH_ALSA(1.0.27,[rtmidi_have_alsa=yes],[rtmidi_have_alsa=no]) + AS_IF(test "x$rtmidi_have_alsa" = "xyes",,[ + AC_CHECK_LIB(pthread, pthread_create,[ + AC_MSG_WARN([RtMidi requires the pthread library! Disabling Alsa!]) + rtmidi_have_alsa=no + ]) + ]) + AS_IF(test "x$rtmidi_have_alsa" = "xyes",[ + RTMIDI_API="$RTMIDI_API -D__LINUX_ALSA__ $ALSA_CFLAGS" + RTMIDI_LIBS="$RTMIDI_LIBS $ALSA_LIBS" + RTMIDI_HAVE_VIRTUAL_DEVICES=yes + $1 + ],[ + m4_default([$2],[AC_MSG_WARN(ALSA support requires the asound and pthread libraries!)]) + ]) + AC_LANG_POP(C++) +])dnl RTMIDI_LIB_ALSA diff --git a/m4/rtmidi_lib_coremidi.m4 b/m4/rtmidi_lib_coremidi.m4 new file mode 100644 index 00000000..d4eb29e5 --- /dev/null +++ b/m4/rtmidi_lib_coremidi.m4 @@ -0,0 +1,46 @@ +# AC_LIB_COREMIDI(FUNCTION, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [OTHER-LIBRARIES]) +# ------------------------------------------------------ +# +# Use a cache variable name containing both the library and function name, +# because the test really is for library $1 defining function $2, not +# just for library $1. Separate tests with the same $1 and different $2s +# may have different results. +# +# Note that using directly AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$2]) +# is asking for troubles, since AC_CHECK_LIB($lib, fun) would give +# ac_cv_lib_$lib_fun, which is definitely not what was meant. Hence +# the AS_LITERAL_IF indirection. +# +# FIXME: This macro is extremely suspicious. It DEFINEs unconditionally, +# whatever the FUNCTION, in addition to not being a *S macro. Note +# that the cache does depend upon the function we are looking for. +# +# It is on purpose we used `ac_check_lib_save_LIBS' and not just +# `ac_save_LIBS': there are many macros which don't want to see `LIBS' +# changed but still want to use AC_CHECK_LIB, so they save `LIBS'. +# And ``ac_save_LIBS' is too tempting a name, so let's leave them some +# freedom. +AC_DEFUN([RTMIDI_LIB_COREMIDI],[ + AC_LANG_PUSH(C++) + ac_cv_rtmidi_lib_coremidi="$LIBS" + LIBS="$LIBS -framework CoreMIDI -framework CoreFoundation -framework CoreAudio" + rtmidi_have_coremidi=no + AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, [rtmidi_have_coremidi=yes]) + AS_IF(test "x$rtmidi_have_coremidi" = "xyes",[ + AC_CHECK_LIB(pthread, pthread_create, ,[ + rtmidi_have_coremidi=no + AC_MSG_WARN([RtMidi requires the pthread library!]) + ]) + ]) + AS_IF(test "x$rtmidi_have_coremidi" = "xyes",[ + RTMIDI_API="$RTMIDI_API -D__MACOSX_COREMIDI__" + RTMIDI_LIBS="$RTMIDI_LIBS -framework CoreMIDI -framework CoreFoundation -framework CoreAudio" + $1 + ], [ + m4_default([$2],[AC_MSG_ERROR(CoreMIDI header files not found!)] ) + ]) + LIBS="$ac_cv_rtmidi_lib_coremidi" + AC_LANG_POP(C++) +])dnl RTMIDI_LIB_COREMIDI diff --git a/m4/rtmidi_lib_jack.m4 b/m4/rtmidi_lib_jack.m4 new file mode 100644 index 00000000..5ab5658a --- /dev/null +++ b/m4/rtmidi_lib_jack.m4 @@ -0,0 +1,66 @@ +# AC_LIB_JACK(FUNCTION, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [OTHER-LIBRARIES]) +# ------------------------------------------------------ +# +# Use a cache variable name containing both the library and function name, +# because the test really is for library $1 defining function $2, not +# just for library $1. Separate tests with the same $1 and different $2s +# may have different results. +# +# Note that using directly AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$2]) +# is asking for troubles, since AC_CHECK_LIB($lib, fun) would give +# ac_cv_lib_$lib_fun, which is definitely not what was meant. Hence +# the AS_LITERAL_IF indirection. +# +# FIXME: This macro is extremely suspicious. It DEFINEs unconditionally, +# whatever the FUNCTION, in addition to not being a *S macro. Note +# that the cache does depend upon the function we are looking for. +# +# It is on purpose we used `ac_check_lib_save_LIBS' and not just +# `ac_save_LIBS': there are many macros which don't want to see `LIBS' +# changed but still want to use AC_CHECK_LIB, so they save `LIBS'. +# And ``ac_save_LIBS' is too tempting a name, so let's leave them some +# freedom. +AC_DEFUN([RTMIDI_LIB_JACK],[ + AC_REQUIRE([PKG_PROG_PKG_CONFIG]) + AC_LANG_PUSH(C++) + rtmidi_have_jack=no + PKG_CHECK_MODULES(JACK,[jack],[rtmidi_have_jack=yes],[rtmidi_have_jack=no]) + AS_IF(test "x$rtmidi_have_jack" = "xyes",[ + rtmidi_save_libs="$LIBS" + LIBS="$LIBS $JACK_LIBS" + AC_TRY_LINK([ +#include + ],[ +return jack_client_close(NULL); + ],,[ + rtmidi_have_jack=no + AC_MSG_WARN([JACK is not usable. Disabling JACK.]) + ]) + LIBS="$rtmidi_save_libs" + ]) + AS_IF(test "x$rtmidi_have_jack" = "xyes",[ + AC_CHECK_LIB(pthread, pthread_create, ,[ + rtmidi_have_jack=no + AC_MSG_WARN([RtMidi requires the pthread library disabling JACK!]) + ]) + ]) + AS_IF(test "x$rtmidi_have_jack" = "xyes",[ + rtmidi_save_libs="$LIBS" + LIBS="$LIBS $JACK_LIBS" + AC_TRY_LINK([ +#include + ],[ +return jack_port_uuid(NULL); + ],[RTMIDI_API="$RTMIDI_API -D__UNIX_JACK_HAS_UUID__"]) + LIBS="$rtmidi_save_libs" + RTMIDI_API="$RTMIDI_API -D__UNIX_JACK__ $JACK_CFLAGS" + RTMIDI_LIBS="$RTMIDI_LIBS $JACK_LIBS" + RTMIDI_HAVE_VIRTUAL_DEVICES=yes + $1 + ],[ + m4_default([$2],[AC_MSG_ERROR(JACK support requires the jack library!)]) + ]) + AC_LANG_POP(C++) +])dnl RTMIDI_LIB_JACK diff --git a/m4/rtmidi_lib_winks.m4 b/m4/rtmidi_lib_winks.m4 new file mode 100644 index 00000000..3b904499 --- /dev/null +++ b/m4/rtmidi_lib_winks.m4 @@ -0,0 +1,47 @@ +# AC_LIB_WINKS(FUNCTION, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [OTHER-LIBRARIES]) +# ------------------------------------------------------ +# +# Use a cache variable name containing both the library and function name, +# because the test really is for library $1 defining function $2, not +# just for library $1. Separate tests with the same $1 and different $2s +# may have different results. +# +# Note that using directly AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$2]) +# is asking for troubles, since AC_CHECK_LIB($lib, fun) would give +# ac_cv_lib_$lib_fun, which is definitely not what was meant. Hence +# the AS_LITERAL_IF indirection. +# +# FIXME: This macro is extremely suspicious. It DEFINEs unconditionally, +# whatever the FUNCTION, in addition to not being a *S macro. Note +# that the cache does depend upon the function we are looking for. +# +# It is on purpose we used `ac_check_lib_save_LIBS' and not just +# `ac_save_LIBS': there are many macros which don't want to see `LIBS' +# changed but still want to use AC_CHECK_LIB, so they save `LIBS'. +# And ``ac_save_LIBS' is too tempting a name, so let's leave them some +# freedom. +AC_DEFUN([RTMIDI_LIB_WINKS],[ + AC_LANG_PUSH(C++) + AC_CACHE_CHECK([for midiOutGetNumDevs in -lwinks], [ac_cv_lib_winks],[ + ac_check_lib_save_LIBS="$LIBS" + LIBS="-lsetupapi -lksuser $LIBS" + AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#include "windows.h" +#include "mmsystem.h" + ],[[void * x= &midiOutGetNumDevs;]])], + [ac_cv_lib_winks=yes], + [ac_cv_lib_winks=no]) + LIBS=$ac_check_lib_save_LIBS]) + AS_IF([test "${ac_cv_lib_winks}" = yes], + [ + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBWINKS)) + RTMIDI_LIBS="$RTMIDI_LIBS -lsetupapi -lksuser" + RTMIDI_API="$RTMIDI_API -D__WINDOWS_KS__" + $1 + ],[ + m4_default([$2],[AC_MSG_ERROR(Windows mulitmedia library not found!)] ) + ]) + AC_LANG_POP(C++) +])dnl RTMIDI_LIB_WINKS diff --git a/m4/rtmidi_lib_winmm.m4 b/m4/rtmidi_lib_winmm.m4 new file mode 100644 index 00000000..9be4513d --- /dev/null +++ b/m4/rtmidi_lib_winmm.m4 @@ -0,0 +1,47 @@ +# AC_LIB_WINMM(FUNCTION, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [OTHER-LIBRARIES]) +# ------------------------------------------------------ +# +# Use a cache variable name containing both the library and function name, +# because the test really is for library $1 defining function $2, not +# just for library $1. Separate tests with the same $1 and different $2s +# may have different results. +# +# Note that using directly AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$2]) +# is asking for troubles, since AC_CHECK_LIB($lib, fun) would give +# ac_cv_lib_$lib_fun, which is definitely not what was meant. Hence +# the AS_LITERAL_IF indirection. +# +# FIXME: This macro is extremely suspicious. It DEFINEs unconditionally, +# whatever the FUNCTION, in addition to not being a *S macro. Note +# that the cache does depend upon the function we are looking for. +# +# It is on purpose we used `ac_check_lib_save_LIBS' and not just +# `ac_save_LIBS': there are many macros which don't want to see `LIBS' +# changed but still want to use AC_CHECK_LIB, so they save `LIBS'. +# And ``ac_save_LIBS' is too tempting a name, so let's leave them some +# freedom. +AC_DEFUN([RTMIDI_LIB_WINMM],[ + AC_LANG_PUSH(C++) + AC_CACHE_CHECK([for midiOutGetNumDevs in -lwinmm], [ac_cv_lib_winmm],[ + ac_check_lib_save_LIBS="$LIBS" + LIBS="-lwinmm $LIBS" + AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#include "windows.h" +#include "mmsystem.h" + ],[[int x= midiOutGetNumDevs();]])], + [ac_cv_lib_winmm=yes], + [ac_cv_lib_winmm=no]) + LIBS=$ac_check_lib_save_LIBS]) + AS_IF([test "${ac_cv_lib_winmm}" = yes], + [ + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBWINMM)) + RTMIDI_LIBS="$RTMIDI_LIBS -lwinmm" + RTMIDI_API="$RTMIDI_API -D__WINDOWS_MM__" + $1 + ],[ + m4_default([$2],[AC_MSG_ERROR(Windows mulitmedia library not found!)] ) + ]) + AC_LANG_POP(C++) +])dnl RTMIDI_LIB_WINMM diff --git a/tests/Makefile.am b/tests/Makefile.am index 476d6fc1..1adb4798 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -2,7 +2,7 @@ #RTMIDITESTCXXFLAGS += -I$(top_srcdir)/%D% #RTMIDITESTLDFLAGS += -L$(top_builddir)/%D% -lrtmidi@rtmidi_suffix@ @LIBS@ -noinst_PROGRAMS += \ +check_PROGRAMS += \ %D%/midiprobe \ %D%/midiout \ %D%/qmidiin \ @@ -22,8 +22,10 @@ TESTS += \ %D%/midiprobe-all \ %D%/errors -if HAVE_VIRTUAL_DEVICES + +if RTMIDI_HAVE_VIRTUAL_DEVICES TESTS += %D%/loopback +DLLPROGRAMS += %D%/loopback endif @@ -91,27 +93,39 @@ if RTMIDICOPYDLLS #------------------------------------------------------------------------------------- + rtmidi_installdll: @echo 'solving references for $(DLLLINKFILE)... ' DLLSEARCHPATH="$(DLLSEARCHPATH)" ; \ - for d in `LANG=C $(OBJDUMP) -p $(DLLEXEDIR)/$(DLLLINKFILE) |sed '/^\s*DLL Name:.*\(lib\|thread\|wx\|mingw\|gcc\|stdc++\)/ { s/^\s*DLL Name:\s*//; p } ; d '` ; \ + for f in `LANG=C $(OBJDUMP) -p $(DLLEXEDIR)/$(DLLLINKFILE) |sed '/^\s*DLL Name:.*\(lib\|thread\|wx\|mingw\|gcc\|stdc++\)/ { s/^\s*DLL Name:\s*//; p } ; d '` ; \ do \ - echo -n checking "$$d ... " ; \ - if [ ! -f $(DLLEXEDIR)/$$d ] ; then \ + echo -n checking "$$f ... " ; \ + if [ ! -f $(DLLEXEDIR)/$$f ] ; then \ echo -n "searching... " ; \ - f=`( find $$DLLSEARCHPATH -name "$$d" || \ - find $$DLLSEARCHPATH -name "$$d.*")|head -n 1` ; \ - if test -f "$$f" ; \ - then \ - echo "installing $$f " ; \ - $(INSTALL_PROGRAM_ENV) $(INSTALL_DATA) "$$f" "`pwd`/$(DLLEXEDIR)" ; \ - case "$$f" in \ - *.gz) GZIP=$(GZIP_ENV) gzip -dc $(DLLEXEDIR)/`basename "$$f"` >$(DLLEXEDIR)/"$$d" ;; \ - esac ; \ - $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$d" DLLEXEDIR="$(DLLEXEDIR)" rtmidi_installdll ; \ - else \ - echo "not found." ; \ - fi ; \ + IFS=: ; \ + for d in $$DLLSEARCHPATH ; do \ + echo "looking in $$d" ; \ + echo -n "found " ; \ + (test -f "$$d/$$f" && \ + echo "$$d/$$f" || \ + ls -1 "$$d/$$f.*" 2>/dev/null) ; \ + echo ; \ + IFS= ; \ + fullname=`(test -f "$$d/$$f" && \ + echo "$$d/$$f" || \ + ls -1 "$$d/$$f.*" 2>/dev/null) | \ + head -n1` ; \ + echo "testing $$fullname" ; \ + if test -f "$$fullname" ; \ + then \ + echo "installing $$fullname " ; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_DATA) "$$fullname" "`pwd`/$(DLLEXEDIR)" ; \ + case "$$f" in \ + *.gz) GZIP=$(GZIP_ENV) gzip -dc $(DLLEXEDIR)/`basename "$$fullname"` >$(DLLEXEDIR)/"$$f" ;; \ + esac ; \ + $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$f" DLLEXEDIR="$(DLLEXEDIR)" rtmidi_installdll ; \ + fi ; \ + done ; \ fi ; \ echo "done." ;\ done ; @@ -122,18 +136,20 @@ rtmidi_installdll: -check-am: check-dll +check-am: check-dll-rtmidi -check-dll: all-am +check-dll-rtmidi: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) - $(MAKE) $(AM_MAKEFLAGS) linkchecks + $(MAKE) $(AM_MAKEFLAGS) linkchecks-rtmidi -linkchecks: - for d in `echo $(TESTS)| tr ' ' '\n' | grep -i -e '$(EXEEXT)$$'` ; \ +linkchecks-rtmidi: + for d in `echo $(DLLPROGRAMS)| tr ' ' '\n' | grep -i -e '$(EXEEXT)$$\|.dll$$'` ; \ do \ ls -l "$$d" ; \ - $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$d" DLLEXEDIR="." rtmidi_installdll ; \ - test -f ".libs/$$d" && \ - $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE=".libs/$$d" DLLEXEDIR="." rtmidi_installdll ; \ + file=`basename "$$d"` ; \ + dir=`dirname "$$d"` ; \ + $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$file" DLLEXEDIR="$$dir" rtmidi_installdll ; \ + test -f "$$dir/.libs/$$file" && \ + $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$file" DLLEXEDIR="$$dir/.libs" rtmidi_installdll ; \ done endif From 4ffae07e33fa1d3faa3371bfe1d7a9ca24691446 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 Mar 2018 18:56:16 +0100 Subject: [PATCH 145/210] Fix some minor build system errors --- Makefile.am | 3 +-- configure.ac | 2 +- tests/Makefile.am | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 1c265562..fe5ca427 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,9 +1,8 @@ -if RTMIDI_STANDALONE ACLOCAL_AMFLAGS = -I m4 --install SUBDIRS = po -endif RTMIDICONFIGRPATH = config/config.rpath DLLPROGRAMS = $(check_PROGRAMS) check_PROGRAMS = +TESTS = include %D%/Makefile.library diff --git a/configure.ac b/configure.ac index 6d006870..63f16e08 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_INIT(RtMidi-ts, 3.0, keinstein_junior@gmx.net, rtmidi-ts) AC_CONFIG_AUX_DIR(config) AC_CONFIG_SRCDIR(RtMidi.cpp) -AC_CONFIG_FILES([rtmidi-config librtmidi.pc Makefile tests/Makefile po/Makefile.in]) +AC_CONFIG_FILES([rtmidi-config librtmidi.pc Makefile po/Makefile.in]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/tests/Makefile.am b/tests/Makefile.am index 1adb4798..4a4a9525 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -25,7 +25,6 @@ TESTS += \ if RTMIDI_HAVE_VIRTUAL_DEVICES TESTS += %D%/loopback -DLLPROGRAMS += %D%/loopback endif From d9ff42375eadb1d1c08c62ee816f52a0f35a0858 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 Mar 2018 19:00:14 +0100 Subject: [PATCH 146/210] output test-suite.log in case of check errors --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2cfd4f75..90eef72b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,4 +44,4 @@ before_install: script: - mkdir -p config - touch config/config.rpath - - autoreconf -i -f && ./configure && make -j4 && $TEST_RUNNER make check + - autoreconf -i -f && ./configure && make -j4 && $TEST_RUNNER make check || cat test-suite.log From 6d4618482fe62aaece3d30dac0da959ee8b533c7 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 Mar 2018 19:15:48 +0100 Subject: [PATCH 147/210] Fix check for preventing backend tests. --- configure.library | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.library b/configure.library index c37f1a62..03b9b047 100644 --- a/configure.library +++ b/configure.library @@ -262,7 +262,7 @@ echo "nochmal withjack" AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (needs libjack to be installed)],[ echo running jack: - AS_IF([test "x$with_jack" = "no"],,[RTMIDI_LIB_JACK ]) + AS_IF([test "x$with_jack" = "xno"],,[RTMIDI_LIB_JACK ]) ],[ echo runnning jack 2 ; RTMIDI_LIB_JACK(,[true]) ]) echo @@ -273,7 +273,7 @@ echo echo "with_alsa: $with_alsa" echo AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA sequencer API support],[ - AS_IF([test "x$with_alsa" = "no"],,[ RTMIDI_LIB_ALSA ]) + AS_IF([test "x$with_alsa" = "xno"],,[ RTMIDI_LIB_ALSA ]) ],[ RTMIDI_LIB_ALSA(,[true]) ]) echo @@ -282,7 +282,7 @@ echo "RTMIDI_LIBS = $RTMIDI_LIBS" echo "virtual devices: $RTMIDI_HAVE_VIRTUAL_DEVICES" echo AC_ARG_WITH(winmm, [ --with-winmm = choose native Windows Multimedia API support],[ - AS_IF([test "x$with_winmm" = "no"],,[RTMIDI_LIB_WINMM ]) + AS_IF([test "x$with_winmm" = "xno"],,[RTMIDI_LIB_WINMM ]) ],[ RTMIDI_LIB_WINMM(,[true]) ]) echo echo "RTMIDI_API = $RTMIDI_API" @@ -290,7 +290,7 @@ echo "RTMIDI_LIBS = $RTMIDI_LIBS" echo "virtual devices: $RTMIDI_HAVE_VIRTUAL_DEVICES" echo AC_ARG_WITH(winks, [ --with-winks = choose native Windows kernel streaming API support],[ - AS_IF([test "x$with_winks" = "no"],,[ RTMIDI_LIB_WINKS ]) + AS_IF([test "x$with_winks" = "xno"],,[ RTMIDI_LIB_WINKS ]) ],[ RTMIDI_LIB_WINKS(,[true]) ]) echo @@ -299,7 +299,7 @@ echo "RTMIDI_LIBS = $RTMIDI_LIBS" echo "virtual devices: $RTMIDI_HAVE_VIRTUAL_DEVICES" echo AC_ARG_WITH(coremidi, [--with-coremidi = choose native CoreAudio API support],[ - AS_IF([test "x$with_core" = "no"],,[RTMIDI_LIB_CORE ]) + AS_IF([test "x$with_core" = "xno"],,[RTMIDI_LIB_CORE ]) ],[ RTMIDI_LIB_COREMIDI(,[true]) ]) echo echo "RTMIDI_API = $RTMIDI_API" From b711ce8c6b85485eed37b7588520c250b4ecdde7 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 Mar 2018 19:16:17 +0100 Subject: [PATCH 148/210] Some further diagnostics for errors.cpp --- RtMidi.cpp | 1 - tests/errors.cpp | 14 ++++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index cbc6b793..ccf55465 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -5595,7 +5595,6 @@ void MidiOutJack :: initialize( const std::string& clientName ) void MidiOutJack :: connect() { - abort(); #if 0 JackMidiData *data = static_cast (apiData_); if ( *(data->seq) ) diff --git a/tests/errors.cpp b/tests/errors.cpp index 31281486..9a91943f 100644 --- a/tests/errors.cpp +++ b/tests/errors.cpp @@ -23,6 +23,10 @@ #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) #endif +#define rtmidi_abort \ + std::cerr << __FILE__ << ":" << __LINE__ << ": rtmidi_aborting" << std::endl; \ + abort + using namespace rtmidi; bool ok = false; @@ -44,8 +48,9 @@ int main( int /* argc */, char * /*argv*/[] ) } catch (Error e) { std::string msg = e.getMessage(); e.printMessage(); - if (e.getType() != Error::INVALID_DEVICE) - abort(); + if (e.getType() != Error::INVALID_DEVICE) { + rtmidi_abort(); + } } } } catch (Error e) { @@ -53,8 +58,9 @@ int main( int /* argc */, char * /*argv*/[] ) e.printMessage(); if (msg != rtmidi_gettext("")) { if (e.getType() != Error::WARNING && - e.getType() != Error::NO_DEVICES_FOUND) - abort(); + e.getType() != Error::NO_DEVICES_FOUND) { + rtmidi_abort(); + } } } } From 4dee467c368fede150f503926d39f25f9ad1b9d9 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 Mar 2018 19:16:44 +0100 Subject: [PATCH 149/210] return error after output of test-suite.log --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 90eef72b..b1ff3b52 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,4 +44,4 @@ before_install: script: - mkdir -p config - touch config/config.rpath - - autoreconf -i -f && ./configure && make -j4 && $TEST_RUNNER make check || cat test-suite.log + - autoreconf -i -f && ./configure && make -j4 && $TEST_RUNNER make check || (cat test-suite.log ; false) From 923c13b7d09df30d546ffe7875dbf3742cb631ae Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 Mar 2018 22:26:12 +0100 Subject: [PATCH 150/210] Fix interface errors from CoreMidi --- RtMidi.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index ccf55465..65b7164b 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1741,7 +1741,7 @@ void MidiInCore::midiInputCallback( const MIDIPacketList *list, } } -MidiInCore :: MidiInCore( const std::string clientName, +MidiInCore :: MidiInCore( const std::string & clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { @@ -1836,7 +1836,7 @@ void MidiInCore :: openPort( unsigned int portNumber, connected_ = true; } -void MidiInCore :: openVirtualPort( const std::string portName ) +void MidiInCore :: openVirtualPort( const std::string & portName ) { CoreMidiData *data = static_cast (apiData_); @@ -1971,7 +1971,7 @@ std::string MidiInCore :: getPortName( unsigned int portNumber ) //*********************************************************************// #define RTMIDI_CLASSNAME "MidiOutCore" -MidiOutCore :: MidiOutCore( const std::string clientName ) : MidiOutApi() +MidiOutCore :: MidiOutCore( const std::string & clientName ) : MidiOutApi() { initialize( clientName ); } @@ -2081,7 +2081,7 @@ void MidiOutCore :: closePort( void ) } } -void MidiOutCore :: openVirtualPort( std::string portName ) +void MidiOutCore :: openVirtualPort( const std::string & portName ) { CoreMidiData *data = static_cast (apiData_); @@ -2200,7 +2200,7 @@ void MidiOutCore :: sendMessage( std::vector &message ) CoreMidiData *data = static_cast (apiData_); OSStatus result; - if ( message->at(0) != 0xF0 && nBytes > 3 ) { + if ( message.at(0) != 0xF0 && nBytes > 3 ) { error(RTMIDI_ERROR(gettext_noopt("message format problem ... not sysex but > 3 bytes?"), Error::WARNING )); return; @@ -2214,7 +2214,7 @@ void MidiOutCore :: sendMessage( std::vector &message ) ByteCount remainingBytes = nBytes; while (remainingBytes && packet) { ByteCount bytesForPacket = remainingBytes > 65535 ? 65535 : remainingBytes; // 65535 = maximum size of a MIDIPacket - const Byte* dataStartPtr = (const Byte *) &message->at( nBytes - remainingBytes ); + const Byte* dataStartPtr = (const Byte *) &message.at( nBytes - remainingBytes ); packet = MIDIPacketListAdd( packetList, listSize, packet, timeStamp, bytesForPacket, dataStartPtr); remainingBytes -= bytesForPacket; } From 5048c71ee344932b3dd2c5d9586298dce135a6c0 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 Mar 2018 22:29:01 +0100 Subject: [PATCH 151/210] Report ALSA error in case AlsaSequencer cannot be initialized. --- RtMidi.cpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 65b7164b..e0dba3d4 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -2354,42 +2354,42 @@ class AlsaSequencer { switch (naming) { case PortDescriptor::SESSION_PATH: if (flags & PortDescriptor::INCLUDE_API) - os << "ALSA:"; + os << "ALSA:"; os << client << ":" << port; break; case PortDescriptor::STORAGE_PATH: if (flags & PortDescriptor::INCLUDE_API) - os << "ALSA:"; + os << "ALSA:"; os << snd_seq_client_info_get_name(cinfo); os << ":"; os << snd_seq_port_info_get_name(pinfo); if (flags & PortDescriptor::UNIQUE_PORT_NAME) - os << ";" << client << ":" << port; + os << ";" << client << ":" << port; break; case PortDescriptor::LONG_NAME: os << snd_seq_client_info_get_name( cinfo ); if (flags & PortDescriptor::UNIQUE_PORT_NAME) { - os << " " << client; + os << " " << client; } os << ":"; if (flags & PortDescriptor::UNIQUE_PORT_NAME) { - os << port; + os << port; } os << " " << snd_seq_port_info_get_name(pinfo); if (flags & PortDescriptor::INCLUDE_API) - os << " (ALSA)"; + os << " (ALSA)"; break; case PortDescriptor::SHORT_NAME: default: os << snd_seq_client_info_get_name( cinfo ); if (flags & PortDescriptor::UNIQUE_PORT_NAME) { - os << " "; - os << client; + os << " "; + os << client; } os << ":" << port; if (flags & PortDescriptor::INCLUDE_API) - os << " (ALSA)"; + os << " (ALSA)"; break; } @@ -2455,11 +2455,11 @@ class AlsaSequencer { { scoped_lock lock (mutex); if ( snd_seq_subscribe_port(seq, subscription) ) { - snd_seq_port_subscribe_free( subscription ); - subscription = 0; - throw RTMIDI_ERROR(gettext_noopt("Error making ALSA port connection."), + snd_seq_port_subscribe_free( subscription ); + subscription = 0; + throw RTMIDI_ERROR(gettext_noopt("Error making ALSA port connection."), Error::DRIVER_ERROR); - return 0; + return 0; } } return subscription; @@ -2494,12 +2494,12 @@ class AlsaSequencer { scoped_lock(pthread_mutex_t & m): mutex(&m) { if (locking) - pthread_mutex_lock(mutex); + pthread_mutex_lock(mutex); } ~scoped_lock() { if (locking) - pthread_mutex_unlock(mutex); + pthread_mutex_unlock(mutex); } }; pthread_mutex_t mutex; @@ -2527,9 +2527,9 @@ class AlsaSequencer { scoped_lock lock(mutex); int result = snd_seq_open(&s, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); if ( result < 0 ) { - throw RTMIDI_ERROR(gettext_noopt("Error creating ALSA sequencer client object."), + throw RTMIDI_ERROR(snd_strerror(result), Error::DRIVER_ERROR ); - return; + return; } snd_seq_set_client_name( seq, name.c_str() ); } From ac78ba4ac9ebdbfe7bb38937eba2a75914276c48 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 Mar 2018 22:45:53 +0100 Subject: [PATCH 152/210] Report NO_DEVICES_FOUND if ALSA does not find /dev/snd/seq. --- RtMidi.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index e0dba3d4..34824395 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -2527,9 +2527,16 @@ class AlsaSequencer { scoped_lock lock(mutex); int result = snd_seq_open(&s, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); if ( result < 0 ) { - throw RTMIDI_ERROR(snd_strerror(result), - Error::DRIVER_ERROR ); - return; + switch (result) { + case ENOENT: // /dev/snd/seq does not exist + throw RTMIDI_ERROR(snd_strerror(result), + Error::NO_DEVICES_FOUND); + return; + default: + throw RTMIDI_ERROR(snd_strerror(result), + Error::DRIVER_ERROR ); + return; + } } snd_seq_set_client_name( seq, name.c_str() ); } From 96062769dbee253d5ca4c549aa6ea1cdc5e8eb64 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 Mar 2018 22:54:26 +0100 Subject: [PATCH 153/210] Report Error number if AlsaSequencer cannot be intitialized. --- RtMidi.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RtMidi.cpp b/RtMidi.cpp index 34824395..5be9b6c5 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -2529,6 +2529,8 @@ class AlsaSequencer { if ( result < 0 ) { switch (result) { case ENOENT: // /dev/snd/seq does not exist + std::cerr << __FILE__ << ":" << __LINE__ + << "Got error number " << result << std::endl; throw RTMIDI_ERROR(snd_strerror(result), Error::NO_DEVICES_FOUND); return; From 46b5f68b0ba1a8fd43f5a577cb3fa674535394f7 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 Mar 2018 22:58:35 +0100 Subject: [PATCH 154/210] Correct last patch: show error code in default branch. --- RtMidi.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 5be9b6c5..ae821b9a 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -2529,12 +2529,12 @@ class AlsaSequencer { if ( result < 0 ) { switch (result) { case ENOENT: // /dev/snd/seq does not exist - std::cerr << __FILE__ << ":" << __LINE__ - << "Got error number " << result << std::endl; throw RTMIDI_ERROR(snd_strerror(result), Error::NO_DEVICES_FOUND); return; default: + std::cerr << __FILE__ << ":" << __LINE__ + << "Got unhandled error number " << result << std::endl; throw RTMIDI_ERROR(snd_strerror(result), Error::DRIVER_ERROR ); return; From 558201e4e54da9155290c793405aea856b585f6b Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 Mar 2018 23:05:35 +0100 Subject: [PATCH 155/210] Error numbers are negative and error constants positive... --- RtMidi.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index ae821b9a..f21c567c 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -2528,7 +2528,9 @@ class AlsaSequencer { int result = snd_seq_open(&s, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); if ( result < 0 ) { switch (result) { - case ENOENT: // /dev/snd/seq does not exist + case -ENOENT: // /dev/snd/seq does not exist + // Error numbers are defined to be positive + case ENOENT: // just in case ... throw RTMIDI_ERROR(snd_strerror(result), Error::NO_DEVICES_FOUND); return; From dd0a2da4eff53ca3ffcdc08c9f07970e020d03ce Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 Mar 2018 23:16:49 +0100 Subject: [PATCH 156/210] trying with sudo: false --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index b1ff3b52..6b9a528f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ git: depth: 3 +sudo: false language: c++ group: travis_latest compiler: From 01b9ace9a4ac0cc310ebbbcf40a9cd23bc61c069 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 18 Mar 2018 23:22:10 +0100 Subject: [PATCH 157/210] always show errors.log so that we know how ALSA performs --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 6b9a528f..457cea55 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,3 +46,4 @@ script: - mkdir -p config - touch config/config.rpath - autoreconf -i -f && ./configure && make -j4 && $TEST_RUNNER make check || (cat test-suite.log ; false) + - cat tests/errors.log \ No newline at end of file From 530a086a5966f151b50de6fe89dbde2b7b1de1d0 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Mon, 19 Mar 2018 20:31:47 +0100 Subject: [PATCH 158/210] Define HAVE_LIBWINKS to 1 This seems to be necessary under certain circumstances. As the old version is deprecated, this fix is helpful anyways. --- m4/rtmidi_lib_winks.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/m4/rtmidi_lib_winks.m4 b/m4/rtmidi_lib_winks.m4 index 3b904499..5abb1156 100644 --- a/m4/rtmidi_lib_winks.m4 +++ b/m4/rtmidi_lib_winks.m4 @@ -36,7 +36,7 @@ AC_DEFUN([RTMIDI_LIB_WINKS],[ LIBS=$ac_check_lib_save_LIBS]) AS_IF([test "${ac_cv_lib_winks}" = yes], [ - AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBWINKS)) + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBWINKS),1,[Define this to 1 if windows kernel streaming libraries are present]) RTMIDI_LIBS="$RTMIDI_LIBS -lsetupapi -lksuser" RTMIDI_API="$RTMIDI_API -D__WINDOWS_KS__" $1 From 2491c8dbf11e0613cc42d3dbdca391753638be55 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 21 Mar 2018 09:07:26 +0100 Subject: [PATCH 159/210] Move rtmidi-private m4 files into separate subdirectory --- Makefile.am | 2 +- {m4 => rtmidi-m4}/rtmidi_lib_alsa.m4 | 0 {m4 => rtmidi-m4}/rtmidi_lib_coremidi.m4 | 0 {m4 => rtmidi-m4}/rtmidi_lib_jack.m4 | 0 {m4 => rtmidi-m4}/rtmidi_lib_winks.m4 | 0 {m4 => rtmidi-m4}/rtmidi_lib_winmm.m4 | 0 6 files changed, 1 insertion(+), 1 deletion(-) rename {m4 => rtmidi-m4}/rtmidi_lib_alsa.m4 (100%) rename {m4 => rtmidi-m4}/rtmidi_lib_coremidi.m4 (100%) rename {m4 => rtmidi-m4}/rtmidi_lib_jack.m4 (100%) rename {m4 => rtmidi-m4}/rtmidi_lib_winks.m4 (100%) rename {m4 => rtmidi-m4}/rtmidi_lib_winmm.m4 (100%) diff --git a/Makefile.am b/Makefile.am index fe5ca427..bfee0f14 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -ACLOCAL_AMFLAGS = -I m4 --install +ACLOCAL_AMFLAGS = -I m4 -I rtmidi-m4 --install SUBDIRS = po RTMIDICONFIGRPATH = config/config.rpath DLLPROGRAMS = $(check_PROGRAMS) diff --git a/m4/rtmidi_lib_alsa.m4 b/rtmidi-m4/rtmidi_lib_alsa.m4 similarity index 100% rename from m4/rtmidi_lib_alsa.m4 rename to rtmidi-m4/rtmidi_lib_alsa.m4 diff --git a/m4/rtmidi_lib_coremidi.m4 b/rtmidi-m4/rtmidi_lib_coremidi.m4 similarity index 100% rename from m4/rtmidi_lib_coremidi.m4 rename to rtmidi-m4/rtmidi_lib_coremidi.m4 diff --git a/m4/rtmidi_lib_jack.m4 b/rtmidi-m4/rtmidi_lib_jack.m4 similarity index 100% rename from m4/rtmidi_lib_jack.m4 rename to rtmidi-m4/rtmidi_lib_jack.m4 diff --git a/m4/rtmidi_lib_winks.m4 b/rtmidi-m4/rtmidi_lib_winks.m4 similarity index 100% rename from m4/rtmidi_lib_winks.m4 rename to rtmidi-m4/rtmidi_lib_winks.m4 diff --git a/m4/rtmidi_lib_winmm.m4 b/rtmidi-m4/rtmidi_lib_winmm.m4 similarity index 100% rename from m4/rtmidi_lib_winmm.m4 rename to rtmidi-m4/rtmidi_lib_winmm.m4 From f2787d11c8c9776850c062502bc4dd9bcedf3e7d Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 21 Mar 2018 16:28:19 +0100 Subject: [PATCH 160/210] New FALLTHROUGH check and added ac_lib_winmm.m4 --- configure.library | 29 ++------ m4/ax_check_compile_flag.m4 | 74 +++++++++++++++++++ rtmidi-m4/ac_lib_winmm.m4 | 43 +++++++++++ rtmidi-m4/ax_check_fallthrough_syntax.m4 | 90 ++++++++++++++++++++++++ 4 files changed, 212 insertions(+), 24 deletions(-) create mode 100644 m4/ax_check_compile_flag.m4 create mode 100644 rtmidi-m4/ac_lib_winmm.m4 create mode 100644 rtmidi-m4/ax_check_fallthrough_syntax.m4 diff --git a/configure.library b/configure.library index 03b9b047..440b00d7 100644 --- a/configure.library +++ b/configure.library @@ -13,7 +13,6 @@ AC_SUBST(RTMIDI_TS_SUFFIX,[ts]) AM_CONDITIONAL(RTMIDI_STANDALONE,test "$rtmidi_standalone" = "yes") # Checks for programs. AC_PROG_CXX -AX_CXX_COMPILE_STDCXX(11) AM_PROG_AR dnl AC_PATH_PROG(AR, ar, no) dnl if [[ $AR = "no" ]] ; then @@ -22,6 +21,9 @@ dnl fi LT_INIT([win32-dll]) +AC_LANG_PUSH(C++) +AX_CXX_COMPILE_STDCXX(11) + # Checks for header files. AC_HEADER_STDC #AC_CHECK_HEADERS(sys/ioctl.h unistd.h) @@ -323,27 +325,6 @@ fi AM_CONDITIONAL(RTMIDICOPYDLLS,$rtmidicopydlls && test -n "$DLLSEARCHPATH") -AC_LANG(C++) -AC_CACHE_CHECK([fallthrough syntax in the C++ language], ac_cv_cxx_fallthrough, -[ -AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([ - int j; - void test(int i) { switch (i) { case 1: j = 3; [[[fallthrough]]] ; case 2: j++; }} - ],[])],[ac_cv_cxx_fallthrough="[[[fallthrough]]]"],[ - AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([ - int j; - void test(int i) { switch (i) { case 1: j = 3; [[[gnu::fallthrough]]] ; case 2: j++; }} - ],[])],[ac_cv_cxx_fallthrough="[[[gnu::fallthrough]]]"],[ - AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([ - int j; - void test(int i) { switch (i) { case 1: j = 3; __attribute__((fallthrough)) ; case 2: j++; }} - ],[])],[ac_cv_cxx_fallthrough="__attribute__((fallthrough))"],[ - ac_cv_cxx_fallthrough="" - ]); - ]); -]); -]) +AX_CHECK_FALLTHROUGH_SYNTAX AC_DEFINE_UNQUOTED(RTMIDI_FALLTHROUGH,[$ac_cv_cxx_fallthrough],[syntax for switch case fallthrough attributes in C++]) +AC_LANG_POP(C++) diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4 new file mode 100644 index 00000000..dcabb92a --- /dev/null +++ b/m4/ax_check_compile_flag.m4 @@ -0,0 +1,74 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's compiler +# or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 5 + +AC_DEFUN([AX_CHECK_COMPILE_FLAG], +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ + ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" + AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) +AS_VAR_IF(CACHEVAR,yes, + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_COMPILE_FLAGS diff --git a/rtmidi-m4/ac_lib_winmm.m4 b/rtmidi-m4/ac_lib_winmm.m4 new file mode 100644 index 00000000..8d7089a1 --- /dev/null +++ b/rtmidi-m4/ac_lib_winmm.m4 @@ -0,0 +1,43 @@ +# AC_LIB_WINMM(FUNCTION, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [OTHER-LIBRARIES]) +# ------------------------------------------------------ +# +# Use a cache variable name containing both the library and function name, +# because the test really is for library $1 defining function $2, not +# just for library $1. Separate tests with the same $1 and different $2s +# may have different results. +# +# Note that using directly AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$2]) +# is asking for troubles, since AC_CHECK_LIB($lib, fun) would give +# ac_cv_lib_$lib_fun, which is definitely not what was meant. Hence +# the AS_LITERAL_IF indirection. +# +# FIXME: This macro is extremely suspicious. It DEFINEs unconditionally, +# whatever the FUNCTION, in addition to not being a *S macro. Note +# that the cache does depend upon the function we are looking for. +# +# It is on purpose we used `ac_check_lib_save_LIBS' and not just +# `ac_save_LIBS': there are many macros which don't want to see `LIBS' +# changed but still want to use AC_CHECK_LIB, so they save `LIBS'. +# And ``ac_save_LIBS' is too tempting a name, so let's leave them some +# freedom. +AC_DEFUN([AC_LIB_WINMM],[ + m4_ifval([$2], , [AH_CHECK_LIB([winmm])])dnl + AC_CACHE_CHECK([for $1 in -lwinmm], [ac_cv_lib_winmm_$1],[ + ac_check_lib_save_LIBS="$LIBS" + LIBS="-lwinmm $4 $LIBS" + AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#include "windows.h" +#include "mmsystem.h" + ],[[void * x= &$1;]])], + [ac_cv_lib_winmm_$1=yes], + [ac_cv_lib_winmm_$1=no]) + LIBS=$ac_check_lib_save_LIBS]) + AS_IF([test "${ac_cv_lib_winmm_$1}" = yes], + [m4_default([$2], + [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBWINMM)) + LIBS="-lwinmm $LIBS" + ])],[$3] + )dnl +])# AC_CHECK_LIB diff --git a/rtmidi-m4/ax_check_fallthrough_syntax.m4 b/rtmidi-m4/ax_check_fallthrough_syntax.m4 new file mode 100644 index 00000000..f9c0cd16 --- /dev/null +++ b/rtmidi-m4/ax_check_fallthrough_syntax.m4 @@ -0,0 +1,90 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_check_fallthrough_syntax.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_FALLTHROUGH_SYNTAX([ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's compiler +# or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 1 +AC_DEFUN([_AX_CHECK_FALLTHROUGH_SYNTAX_COMPILE], +[ + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([ +int j; +void test(int i) { + switch (i) { + case 1: j = 3; + $1 ; + case 2: j++; + } +} + ],[])],$2,$3) +]) + +AC_DEFUN([AX_CHECK_FALLTHROUGH_SYNTAX], +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]_fallthrough_syntax_$1])dnl +AC_CACHE_CHECK([syntax of _AC_LANG fallthrough attribute ], CACHEVAR, [ + ax_check_save_flags_fallthrough="$[]_AC_LANG_PREFIX[]FLAGS" + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $1" + AS_UNSET([ax_cv_check_[]_AC_LANG_ABBREV[]flags___Werror]) + AX_CHECK_COMPILE_FLAG([-Werror],[_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS -Werror"]) + AS_VAR_SET(CACHEVAR,[]) + for flag in "[[fallthrough]]" "[[gnu::fallthrough]]" "__attribute__((fallthrough))" + do + _AX_CHECK_FALLTHROUGH_SYNTAX_COMPILE([$flag],[ + AS_VAR_SET(CACHEVAR,[[[fallthrough]]]) + break; + ],[:]) + done + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags_fallthrough + ]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_FALLTHROUGH_SYNTAX From 33319a4487bd777ebf03fd96dd7a9204b0a73894 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 21 Mar 2018 18:34:40 +0100 Subject: [PATCH 161/210] Add missing variables to Makevars --- po/Makevars | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/po/Makevars b/po/Makevars index c8a877e3..57406079 100644 --- a/po/Makevars +++ b/po/Makevars @@ -18,7 +18,14 @@ XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ --keyword=gettext_noopt --keyword=rt # or entity, or to disclaim their copyright. The empty string stands for # the public domain; in this case the translators are expected to disclaim # their copyright. -COPYRIGHT_HOLDER = Gary P. Scavone +COPYRIGHT_HOLDER = Gary P. Scavone, Tobias Schlemmer + +# This tells whether or not to prepend "GNU " prefix to the package +# name that gets inserted into the header of the $(DOMAIN).pot file. +# Possible values are "yes", "no", or empty. If it is empty, try to +# detect it automatically by scanning the files in $(top_srcdir) for +# "GNU packagename" string. +PACKAGE_GNU = no # This is the email address or URL to which the translators shall report # bugs in the untranslated strings: @@ -34,7 +41,7 @@ COPYRIGHT_HOLDER = Gary P. Scavone # It can be your email address, or a mailing list address where translators # can write to without being subscribed, or the URL of a web page through # which the translators can contact you. -MSGID_BUGS_ADDRESS = https://github.com/thestk/rtmidi +MSGID_BUGS_ADDRESS = https://github.com/keinstein/rtmidi # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. @@ -52,6 +59,27 @@ USE_MSGCTXT = no # --quiet to reduce the verbosity. MSGMERGE_OPTIONS = +# These options get passed to msginit. +# If you want to disable line wrapping when writing PO files, add +# --no-wrap to MSGMERGE_OPTIONS, XGETTEXT_OPTIONS, and +# MSGINIT_OPTIONS. +MSGINIT_OPTIONS = + +# This tells whether or not to regenerate a PO file when $(DOMAIN).pot +# has changed. Possible values are "yes" and "no". Set this to no if +# the POT file is checked in the repository and the version control +# program ignores timestamps. +PO_DEPENDS_ON_POT = yes + +# This tells whether or not to forcibly update $(DOMAIN).pot and +# regenerate PO files on "make dist". Possible values are "yes" and +# "no". Set this to no if the POT file and PO files are maintained +# externally. +DIST_DEPENDS_ON_UPDATE_PO = yes + + +# Extra rules + all: tags: From 520ffbb08b4c774338b998281aa680a7ce147e18 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 21 Mar 2018 18:34:58 +0100 Subject: [PATCH 162/210] Travis-ci: make distcheck --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 457cea55..f25cfbff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,4 +46,5 @@ script: - mkdir -p config - touch config/config.rpath - autoreconf -i -f && ./configure && make -j4 && $TEST_RUNNER make check || (cat test-suite.log ; false) - - cat tests/errors.log \ No newline at end of file + - make distcheck + - cat tests/errors.log From e1bc3a37e54f872b3869930e73fa304e8c1aee0b Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 12:09:31 +0200 Subject: [PATCH 163/210] fix check for fallthrough syntax --- rtmidi-m4/ax_check_fallthrough_syntax.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rtmidi-m4/ax_check_fallthrough_syntax.m4 b/rtmidi-m4/ax_check_fallthrough_syntax.m4 index f9c0cd16..583ad827 100644 --- a/rtmidi-m4/ax_check_fallthrough_syntax.m4 +++ b/rtmidi-m4/ax_check_fallthrough_syntax.m4 @@ -77,10 +77,10 @@ AC_CACHE_CHECK([syntax of _AC_LANG fallthrough attribute ], CACHEVAR, [ AS_UNSET([ax_cv_check_[]_AC_LANG_ABBREV[]flags___Werror]) AX_CHECK_COMPILE_FLAG([-Werror],[_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS -Werror"]) AS_VAR_SET(CACHEVAR,[]) - for flag in "[[fallthrough]]" "[[gnu::fallthrough]]" "__attribute__((fallthrough))" + for flag in "[[[fallthrough]]]" "[[[gnu::fallthrough]]]" "__attribute__((fallthrough))" do _AX_CHECK_FALLTHROUGH_SYNTAX_COMPILE([$flag],[ - AS_VAR_SET(CACHEVAR,[[[fallthrough]]]) + AS_VAR_SET(CACHEVAR,[$flag]) break; ],[:]) done From 2de93a5f5e0f2ee47f05c0d0c7c16ce15e5fb9f0 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 13:10:21 +0200 Subject: [PATCH 164/210] full matrix including windows --- .travis.yml | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index f25cfbff..aae50cb5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,23 +1,28 @@ git: - depth: 3 + depth: 1 sudo: false language: c++ group: travis_latest +os + - osx + - linux + - windows compiler: - gcc - clang -matrix: - include: - - os: osx - osx_image: xcode9.2 - env: - - MATRIX_EVAL="CC=clang && CXX=clang++ && EXTRA_BREW= " - - - os: osx - osx_image: xcode9.2 - env: - - MATRIX_EVAL="CC=gcc && CXX=g++ && EXTRA_BREW=gcc " - +osx_image: + - xcode9.2 +# matrix: +# include: +# - os: osx +# env: +# - MATRIX_EVAL="CC=clang && CXX=clang++ && EXTRA_BREW= " +# +# - os: osx +# osx_image: xcode9.2 +# env: +# - MATRIX_EVAL="CC=gcc && CXX=g++ && EXTRA_BREW=gcc " +# addons: apt: From 7ca9ebe99a190d29d73c68f73c4487097d897035 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 13:33:47 +0200 Subject: [PATCH 165/210] move osx_image into os:osx --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index aae50cb5..a24d14df 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,13 +5,13 @@ language: c++ group: travis_latest os - osx + osx_image: + - xcode9.2 - linux - windows compiler: - gcc - clang -osx_image: - - xcode9.2 # matrix: # include: # - os: osx From fed5162bfb8a2cd733df9eccec00c86e95208b6d Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 13:35:42 +0200 Subject: [PATCH 166/210] remove osx_image and windows --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index a24d14df..9fba2449 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,7 @@ language: c++ group: travis_latest os - osx - osx_image: - - xcode9.2 - linux - - windows compiler: - gcc - clang From 05f362204798b05d1a6828857cb9de164ddf0444 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 13:38:56 +0200 Subject: [PATCH 167/210] add colon after os --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9fba2449..ec0232f4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,12 @@ git: sudo: false language: c++ group: travis_latest -os +os: - osx + osx_image: + - xcode9.2 - linux + - windows compiler: - gcc - clang From 8c1403cbda7c21fbcd7de603f02bf5d1918f323f Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 13:40:14 +0200 Subject: [PATCH 168/210] remove everything --- .travis.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index ec0232f4..31ff7c22 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,24 +5,10 @@ language: c++ group: travis_latest os: - osx - osx_image: - - xcode9.2 - linux - - windows compiler: - gcc - clang -# matrix: -# include: -# - os: osx -# env: -# - MATRIX_EVAL="CC=clang && CXX=clang++ && EXTRA_BREW= " -# -# - os: osx -# osx_image: xcode9.2 -# env: -# - MATRIX_EVAL="CC=gcc && CXX=g++ && EXTRA_BREW=gcc " -# addons: apt: From 6ee538371020e028b330c82ca161474bbe4db1fe Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 13:41:18 +0200 Subject: [PATCH 169/210] readd xcode image --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 31ff7c22..25cf82da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,8 @@ language: c++ group: travis_latest os: - osx + osx_image: + - xcode9.2 - linux compiler: - gcc From 728c35d9a6ef96f2c3d9b47c42a29d52f58f35f0 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 13:42:42 +0200 Subject: [PATCH 170/210] move osx_image to top level --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 25cf82da..d493c7ea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,13 +5,14 @@ language: c++ group: travis_latest os: - osx - osx_image: - - xcode9.2 - linux compiler: - gcc - clang +osx_image: + - xcode9.2 + addons: apt: packages: From fa5e6f8bbca4b3affa52bc0f1c9a8b8b71ff105f Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 13:43:39 +0200 Subject: [PATCH 171/210] readd windows --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index d493c7ea..f1fad30e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,8 @@ group: travis_latest os: - osx - linux + - windows + compiler: - gcc - clang From 63c932b4d2263298f4ad99a661757ec012fe8158 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 14:22:20 +0200 Subject: [PATCH 172/210] remove windows --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f1fad30e..b389f059 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,6 @@ group: travis_latest os: - osx - linux - - windows compiler: - gcc From 642006c8c4c2bfd0fd2a2c60402c459872de46ea Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 14:43:35 +0200 Subject: [PATCH 173/210] trying appveyor --- appveyor.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..b5e02614 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,11 @@ +environment: + matrix: + ### + - TOOLCHAIN: "default" + CONFIG: Release + + - TOOLCHAIN: "default" + CONFIG: Debug + +build_script: +- cmd: ./configure && make && make check && make distcheck From 23ef177482b4181c36e99b2dd27e2774ce104172 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 15:39:40 +0200 Subject: [PATCH 174/210] add appveyor badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 388bc122..f9eb99bd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://travis-ci.org/keinstein/rtmidi.svg?branch=master-ts)](https://travis-ci.org/keinstein/rtmidi) +[![Build Status](https://travis-ci.org/keinstein/rtmidi.svg?branch=master-ts)](https://travis-ci.org/keinstein/rtmidi)[![Build status](https://ci.appveyor.com/api/projects/status/ac98q210qscfjayk/branch/master-ts?svg=true)](https://ci.appveyor.com/project/keinstein/rtmidi/branch/travis-tests) Extended RtMidi fork for Mutabor, GUI based Software, and saving MIDI connections ================================================================================= From 47804e5d8931b80d837cd2d96b0e4d5b72bff976 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 15:40:08 +0200 Subject: [PATCH 175/210] try to activate gcc --- appveyor.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index b5e02614..9909b66a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,4 +8,8 @@ environment: CONFIG: Debug build_script: -- cmd: ./configure && make && make check && make distcheck + - SET PATH=C:\MinGW\bin;%PATH% + - configure + - make + - make check + - make distcheck From 29b4feaec77eb188a46973d58cf35e241d4df28e Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 15:44:16 +0200 Subject: [PATCH 176/210] show topdir and use bash to run compilation --- appveyor.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 9909b66a..6d874f99 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,8 +8,9 @@ environment: CONFIG: Debug build_script: + - dir C:\ - SET PATH=C:\MinGW\bin;%PATH% - - configure - - make - - make check - - make distcheck + - bash -c configure + - bash -c make + - bash -c "make check" + - bash -c "make distcheck" From b47700a3cca36011922d0f27289ab2df38a3d368 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 16:37:26 +0200 Subject: [PATCH 177/210] Disable deprecated warnings for test suite --- tests/Makefile.am | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 4a4a9525..5f6e4e11 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -48,12 +48,12 @@ endif %C%_qmidiin_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED %C%_cmidiin_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED %C%_sysextest_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED -%C%_midiprobe2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -%C%_midiprobe_all_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -%C%_cmidiin2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -%C%_qmidiin2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -%C%_midiout2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -%C%_loopback_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) +%C%_midiprobe2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_midiprobe_all_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_cmidiin2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_qmidiin2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_midiout2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_loopback_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED %C%_errors_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED # From 19e8cb2646f71fb67cdf7c937de46680f2942854 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 16:48:20 +0200 Subject: [PATCH 178/210] trying xcode only in osx --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b389f059..d401bebb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,14 +5,13 @@ language: c++ group: travis_latest os: - osx + osx_image: xcode9.2 - linux compiler: - gcc - clang -osx_image: - - xcode9.2 addons: apt: From eecd8cfc593988fd22e07e8ae941c7bd07628771 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 18:39:47 +0200 Subject: [PATCH 179/210] exclude appveyor test branches from travis builds --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index d401bebb..fe2608bd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,8 @@ git: depth: 1 +branches: + except: + /(?i:appveyor)/ sudo: false language: c++ group: travis_latest From fd60e273dac15e1bae418b45e8611132975a1ee3 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 18:45:25 +0200 Subject: [PATCH 180/210] remove appveyor.yml --- appveyor.yml | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 6d874f99..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,16 +0,0 @@ -environment: - matrix: - ### - - TOOLCHAIN: "default" - CONFIG: Release - - - TOOLCHAIN: "default" - CONFIG: Debug - -build_script: - - dir C:\ - - SET PATH=C:\MinGW\bin;%PATH% - - bash -c configure - - bash -c make - - bash -c "make check" - - bash -c "make distcheck" From e864662866f3c4a03e2fb5d9cc93df32d8dca36e Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Mon, 26 Mar 2018 08:35:10 +0200 Subject: [PATCH 181/210] add dash to branch exception patten --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fe2608bd..57dcc5dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ git: depth: 1 branches: except: - /(?i:appveyor)/ + - /(?i:appveyor)/ sudo: false language: c++ group: travis_latest From fbea08a6bf98073eb39a57c48c120b40eb4b7593 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Mon, 26 Mar 2018 08:49:21 +0200 Subject: [PATCH 182/210] fix error in .travis.yml --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 57dcc5dd..18d1f58d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,9 +8,10 @@ language: c++ group: travis_latest os: - osx - osx_image: xcode9.2 - linux +osx_image: xcode9.2 + compiler: - gcc - clang From cfc87ae1a4b2061f67f637d750f60bdad42fb491 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 25 Mar 2018 14:43:35 +0200 Subject: [PATCH 183/210] Use appveyor --- appveyor.yml | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..35505301 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,65 @@ +environment: + matrix: + ### + - TOOLCHAIN: "default" + CONFIG: Release + _CC: MINGW + + - TOOLCHAIN: "default" + CONFIG: Debug + _CC: MINGW + +# example see: https://github.com/wang-bin/avbuild/blob/master/appveyor.yml +init: + - echo NUMBER_OF_PROCESSORS=%NUMBER_OF_PROCESSORS% + - echo PROCESSOR_IDENTIFIER=%PROCESSOR_IDENTIFIER% + - set MSYS2_PATH_TYPE=inherit + - set MSYS2_DIR=C:\msys64 + +install: +# can not starts with % +# - git submodule update --init + - if /i %_CC%==MinGW ( + C:\msys64\usr\bin\pacman -Syyuu --noconfirm && + C:\msys64\usr\bin\pacman -Suu --noconfirm && + C:\msys64\usr\bin\pacman -S --noconfirm --needed mingw-w64-i686-gcc mingw-w64-x86_64-gcc && + C:\msys64\usr\bin\pacman -Sc --noconfirm + ) + - C:\msys64\usr\bin\pacman -Ss --noconfirm boost + - C:\msys64\usr\bin\pacman -Ss --noconfirm autoconf + - C:\msys64\usr\bin\pacman -Ss --noconfirm automake + - C:\msys64\usr\bin\pacman -Ss --noconfirm libtool + - C:\msys64\usr\bin\pacman -Ss --noconfirm gettext + - C:\msys64\usr\bin\pacman -S --noconfirm --needed + mingw-w64-x86_64-boost autoconf mingw-w64-x86_64-libtool automake1.15 mingw-w64-x86_64-gettext + +build_script: + - dir C:\ + - dir C:\msys64 + - dir C:\msys64\usr\bin + - dir C:\msys64\opt + - dir C:\msys64\mingw64 + - dir c:\msys64\mingw64\bin + - dir C:\msys64\mingw64\x86_64-w64-mingw32 + - dir C:\msys64\mingw64\x86_64-w64-mingw32\bin + - dir C:\mingw-w64 + - dir C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin + - dir C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\opt\bin + - SET PATH=C:\mingw-w64\bin;C:\msys64\mingw64\bin;C:\msys64\usr\bin;%PATH% + - echo "%PATH%" + - path + - bash -c "env" + - bash -c pwd + - bash -c ls + - bash -c "#aclocal -I m4 --install" + - bash -c "#automake --add-missing -f" + - bash -c "#autopoint -f" + - bash -c "#libtoolize -i -f" + - bash -c "#autoconf --add-missing" + - bash -c "mkdir -p config" + - bash -c "touch config/config.rpath" + - bash -c "autoreconf -i -f" + - bash -c "./configure" + - bash -c make + - bash -c "make check" + - bash -c "make distcheck" From 8629e054463368404d4c1424e92e327d5da77806 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Thu, 7 Jun 2018 20:24:29 +0200 Subject: [PATCH 184/210] fix FALLTHROUGH definition --- RtMidi.cpp | 2 +- configure.library | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index f21c567c..bb81ebb3 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -42,7 +42,7 @@ #include #include #include -#ifdef RTMIDI_FALLTHROUGH +#ifndef RTMIDI_FALLTHROUGH #define RTMIDI_FALLTHROUGH #endif diff --git a/configure.library b/configure.library index 440b00d7..21b873e3 100644 --- a/configure.library +++ b/configure.library @@ -326,5 +326,7 @@ AM_CONDITIONAL(RTMIDICOPYDLLS,$rtmidicopydlls && test -n "$DLLSEARCHPATH") AX_CHECK_FALLTHROUGH_SYNTAX -AC_DEFINE_UNQUOTED(RTMIDI_FALLTHROUGH,[$ac_cv_cxx_fallthrough],[syntax for switch case fallthrough attributes in C++]) +AC_DEFINE_UNQUOTED(RTMIDI_FALLTHROUGH, + [$ax_cv_check_cxx_fallthrough_syntax_], + [syntax for switch case fallthrough attributes in C++]) AC_LANG_POP(C++) From 7489c952312286d38fd5f4837c139786521ad012 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Thu, 7 Jun 2018 20:25:19 +0200 Subject: [PATCH 185/210] Silence some warnings. --- RtMidi.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index 85c7a65d..8f0f1a4d 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -1778,7 +1778,7 @@ typedef rtmidi::Midi RTMIDI_DEPRECATED(RtMidi,"RtMidi has been replaced by rtmid class RtMidiIn: public rtmidi::MidiIn { public: - RTMIDI_DEPRECATED(RtMidiIn( RtMidi::Api api = RtMidi::UNSPECIFIED, + RTMIDI_DEPRECATED(RtMidiIn( RtMidi::Api api = (Api_t)rtmidi::UNSPECIFIED, const std::string & clientName = std::string( "RtMidi Input Client")), "Class RtMidiIn has been replaced by rtmidi::MidiIn"): MidiIn((rtmidi::ApiType)api, @@ -1786,7 +1786,7 @@ class RtMidiIn: public rtmidi::MidiIn { }; class RtMidiOut: public rtmidi::MidiOut { public: - RTMIDI_DEPRECATED(RtMidiOut( RtMidi::Api api = RtMidi::UNSPECIFIED, + RTMIDI_DEPRECATED(RtMidiOut( RtMidi::Api api = (Api_t)rtmidi::UNSPECIFIED, const std::string & clientName = std::string( "RtMidi Output Client")), "Class RtMidiOut has been replaced by rtmidi::MidiOut"): MidiOut((rtmidi::ApiType)api, From 8caf657697f0dd381afb735950f3de4850723963 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Thu, 7 Jun 2018 20:26:16 +0200 Subject: [PATCH 186/210] reactivate RTMIDITESTLDFLAGS --- tests/Makefile.am | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 5f6e4e11..7a3830d4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -22,6 +22,10 @@ TESTS += \ %D%/midiprobe-all \ %D%/errors +CLEANFILES += \ + %D%/*.class + + if RTMIDI_HAVE_VIRTUAL_DEVICES TESTS += %D%/loopback @@ -56,20 +60,20 @@ endif %C%_loopback_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED %C%_errors_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED -# -#%C%_midiprobe_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -#%C%_midiout_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -#%C%_qmidiin_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -#%C%_cmidiin_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -#%C%_sysextest_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -#%C%_midiprobe2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -#%C%_midiprobe_all_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -#%C%_cmidiin2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -#%C%_qmidiin2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -#%C%_midiout2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -#%C%_loopback_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -#%C%_errors_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) -# + +%C%_midiprobe_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_midiout_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_qmidiin_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_cmidiin_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_sysextest_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_midiprobe2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_midiprobe_all_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_cmidiin2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_qmidiin2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_midiout2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_loopback_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_errors_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) + %C%_midiprobe_LDADD = $(RTMIDILIBRARYNAME) %C%_midiout_LDADD = $(RTMIDILIBRARYNAME) From 817439e0fbf553d62091cb5049551af183831cdb Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Thu, 7 Jun 2018 20:33:04 +0200 Subject: [PATCH 187/210] create CLEANFILES variable --- Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.am b/Makefile.am index bfee0f14..0ba2c5b5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,5 +4,6 @@ RTMIDICONFIGRPATH = config/config.rpath DLLPROGRAMS = $(check_PROGRAMS) check_PROGRAMS = TESTS = +CLEANFILES = include %D%/Makefile.library From 94fa1a0dcac6a4679f5965ed250bdd99e6a1273b Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 20 Jul 2018 08:49:38 +0200 Subject: [PATCH 188/210] Fix windows paths for DLL dirs. --- configure.library | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.library b/configure.library index 21b873e3..c2753e76 100644 --- a/configure.library +++ b/configure.library @@ -203,7 +203,7 @@ darwin*|*apple*) AC_CACHE_CHECK([where to find support dlls], [ac_cv_rtmidi_ts_mingw_dll_dirs], [ gccsearchdirs=`$CXX $CXXFLAGS -print-search-dirs|\ - sed -e '/^libraries:/ { s/^libraries: *=\?//; p } ; d'` + sed -e '/^libraries:/ { s/^libraries: *=\?//;/;\([0-9a-zA-Z]\):/ { s,;\([0-9a-zA-Z]\):,:/\1/,g;s,^\([0-9a-zA-Z]\):,/\1/,g; s,\\,/,g } ; p } ; d'` gccsearchdirs="$WINEDLLPATH:$gccsearchdirs:\ /usr/share/doc/mingw32-runtime:\ /usr/$host/bin:\ From e6d1714c288f28b4548b955cb621c5e10c355dfb Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sun, 29 Jul 2018 21:49:22 +0200 Subject: [PATCH 189/210] fix dll search path --- configure.library | 9 ++------- tests/Makefile.am | 4 ++-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/configure.library b/configure.library index c2753e76..d8265cad 100644 --- a/configure.library +++ b/configure.library @@ -203,7 +203,7 @@ darwin*|*apple*) AC_CACHE_CHECK([where to find support dlls], [ac_cv_rtmidi_ts_mingw_dll_dirs], [ gccsearchdirs=`$CXX $CXXFLAGS -print-search-dirs|\ - sed -e '/^libraries:/ { s/^libraries: *=\?//;/;\([0-9a-zA-Z]\):/ { s,;\([0-9a-zA-Z]\):,:/\1/,g;s,^\([0-9a-zA-Z]\):,/\1/,g; s,\\,/,g } ; p } ; d'` + sed -e '/^libraries:/ { s/^libraries: *=\?//; /;\([0-9a-zA-Z]\):/ { s,;\([0-9a-zA-Z]\):,:/\1/,g;s,^\([0-9a-zA-Z]\):,/\1/,g; s,\\\\,/,g } ; p } ; d'` ; \ gccsearchdirs="$WINEDLLPATH:$gccsearchdirs:\ /usr/share/doc/mingw32-runtime:\ /usr/$host/bin:\ @@ -225,9 +225,7 @@ darwin*|*apple*) IFS=: for d in $gccsearchdirs ; do - echo "testing $d" - AS_IF(test -d $d, - [ SEARCHDIRS="$SEARCHDIRS:$d" ]) + AS_IF(test -d "$d",[ SEARCHDIRS="$SEARCHDIRS:$d" ]) done IFS="$old_FS" ac_cv_rtmidi_ts_mingw_dll_dirs="$SEARCHDIRS" @@ -235,9 +233,6 @@ darwin*|*apple*) AC_SUBST(DLLSEARCHPATH,"$ac_cv_rtmidi_ts_mingw_dll_dirs") rtmidicopydlls=true - echo - echo "DLL path= $DLLSEARCHPATH" - ;; *) diff --git a/tests/Makefile.am b/tests/Makefile.am index 7a3830d4..e6757b76 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -99,8 +99,8 @@ if RTMIDICOPYDLLS rtmidi_installdll: @echo 'solving references for $(DLLLINKFILE)... ' - DLLSEARCHPATH="$(DLLSEARCHPATH)" ; \ - for f in `LANG=C $(OBJDUMP) -p $(DLLEXEDIR)/$(DLLLINKFILE) |sed '/^\s*DLL Name:.*\(lib\|thread\|wx\|mingw\|gcc\|stdc++\)/ { s/^\s*DLL Name:\s*//; p } ; d '` ; \ + DLLSEARCHPATH="$(DLLSEARCHPATH)$(LOCALDLLSEARCHPATH)" ; \ + for f in `LANG=C $(OBJDUMP) -p $(DLLEXEDIR)/$(DLLLINKFILE) |sed '/^\s*DLL Name:.*\(lib\|thread\|wx\|mingw\|gcc\|stdc++\)/ { s/^\s*DLL Name:\s*//; p } ; d '`; \ do \ echo -n checking "$$f ... " ; \ if [ ! -f $(DLLEXEDIR)/$$f ] ; then \ From b156317b6dae68e1f7f6d4df950fa13827570882 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Thu, 2 Aug 2018 21:55:21 +0200 Subject: [PATCH 190/210] Additional debug output --- tests/Makefile.am | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index e6757b76..d69d299b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -99,6 +99,7 @@ if RTMIDICOPYDLLS rtmidi_installdll: @echo 'solving references for $(DLLLINKFILE)... ' + set -e -x; \ DLLSEARCHPATH="$(DLLSEARCHPATH)$(LOCALDLLSEARCHPATH)" ; \ for f in `LANG=C $(OBJDUMP) -p $(DLLEXEDIR)/$(DLLLINKFILE) |sed '/^\s*DLL Name:.*\(lib\|thread\|wx\|mingw\|gcc\|stdc++\)/ { s/^\s*DLL Name:\s*//; p } ; d '`; \ do \ @@ -108,24 +109,29 @@ rtmidi_installdll: IFS=: ; \ for d in $$DLLSEARCHPATH ; do \ echo "looking in $$d" ; \ - echo -n "found " ; \ - (test -f "$$d/$$f" && \ - echo "$$d/$$f" || \ - ls -1 "$$d/$$f.*" 2>/dev/null) ; \ - echo ; \ IFS= ; \ - fullname=`(test -f "$$d/$$f" && \ - echo "$$d/$$f" || \ - ls -1 "$$d/$$f.*" 2>/dev/null) | \ - head -n1` ; \ + fullname="$$d/$$f" ; \ echo "testing $$fullname" ; \ if test -f "$$fullname" ; \ then \ - echo "installing $$fullname " ; \ - $(INSTALL_PROGRAM_ENV) $(INSTALL_DATA) "$$fullname" "`pwd`/$(DLLEXEDIR)" ; \ - case "$$f" in \ - *.gz) GZIP=$(GZIP_ENV) gzip -dc $(DLLEXEDIR)/`basename "$$fullname"` >$(DLLEXEDIR)/"$$f" ;; \ - esac ; \ + if cmp "$$fullname" "`pwd`/$(DLLEXEDIR)/$$f"; \ + then \ + echo "ok." ;\ + else \ + echo "installing $$fullname " ; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_DATA) "$$fullname" "`pwd`/$(DLLEXEDIR)" ; \ + fi ; \ + $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$f" DLLEXEDIR="$(DLLEXEDIR)" rtmidi_installdll ; \ + elif test -f "$${fullname}.gz" ; \ + then \ + if cmp "$${fullname}.gz" "`pwd`/$(DLLEXEDIR)/$${f}.gz"; \ + then \ + echo "ok." ;\ + else \ + echo "installing $$fullname " ; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_DATA) "$${fullname}.gz" "`pwd`/$(DLLEXEDIR)" ; \ + fi; \ + GZIP=$(GZIP_ENV) gzip -dc $(DLLEXEDIR)/`basename "$${fullname}.gz"` >$(DLLEXEDIR)/"$$f" ; \ $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$f" DLLEXEDIR="$(DLLEXEDIR)" rtmidi_installdll ; \ fi ; \ done ; \ @@ -146,6 +152,7 @@ check-dll-rtmidi: all-am $(MAKE) $(AM_MAKEFLAGS) linkchecks-rtmidi linkchecks-rtmidi: + set -e -x ; \ for d in `echo $(DLLPROGRAMS)| tr ' ' '\n' | grep -i -e '$(EXEEXT)$$\|.dll$$'` ; \ do \ ls -l "$$d" ; \ From 244e310b363c74091b08c8f0cc53e1e93258e68b Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 3 Aug 2018 09:34:44 +0200 Subject: [PATCH 191/210] Fix DLL target dir --- tests/Makefile.am | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index d69d299b..71a5d6f4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -119,7 +119,7 @@ rtmidi_installdll: echo "ok." ;\ else \ echo "installing $$fullname " ; \ - $(INSTALL_PROGRAM_ENV) $(INSTALL_DATA) "$$fullname" "`pwd`/$(DLLEXEDIR)" ; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_DATA) "$$fullname" "$(DLLEXEDIR)" ; \ fi ; \ $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$f" DLLEXEDIR="$(DLLEXEDIR)" rtmidi_installdll ; \ elif test -f "$${fullname}.gz" ; \ @@ -129,7 +129,7 @@ rtmidi_installdll: echo "ok." ;\ else \ echo "installing $$fullname " ; \ - $(INSTALL_PROGRAM_ENV) $(INSTALL_DATA) "$${fullname}.gz" "`pwd`/$(DLLEXEDIR)" ; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_DATA) "$${fullname}.gz" "$(DLLEXEDIR)" ; \ fi; \ GZIP=$(GZIP_ENV) gzip -dc $(DLLEXEDIR)/`basename "$${fullname}.gz"` >$(DLLEXEDIR)/"$$f" ; \ $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$f" DLLEXEDIR="$(DLLEXEDIR)" rtmidi_installdll ; \ @@ -159,7 +159,9 @@ linkchecks-rtmidi: file=`basename "$$d"` ; \ dir=`dirname "$$d"` ; \ $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$file" DLLEXEDIR="$$dir" rtmidi_installdll ; \ - test -f "$$dir/.libs/$$file" && \ + if test -f "$$dir/.libs/$$file"; \ + then \ $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$file" DLLEXEDIR="$$dir/.libs" rtmidi_installdll ; \ + fi ; \ done endif From f74c64463f5f1e61092d2a04026945243a8bd0da Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 4 Aug 2018 14:55:06 +0200 Subject: [PATCH 192/210] Ignore namespace in indentation Hopefully this provides better patches. --- RtMidi.cpp | 950 +++++++++++++++++++++++++++-------------------------- RtMidi.h | 49 ++- 2 files changed, 500 insertions(+), 499 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index c3c18d9b..50187926 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -46,7 +46,9 @@ #define RTMIDI_FALLTHROUGH #endif -NAMESPACE_RTMIDI_START + +RTMIDI_NAMESPACE_START + #ifdef RTMIDI_GETTEXT const char * rtmidi_gettext (const char * s) { init_rtmidi_gettext(); @@ -99,7 +101,7 @@ Error::Error( const char * message, message_.resize(length); } else { const char * msg - = gettext_noopt("Error: could not format the error message"); + = gettext_noopt("Error: could not format the error message"); #ifdef RTMIDI_GETTEXT msg = rtmidi_gettext(msg); #endif @@ -253,14 +255,14 @@ MidiIn :: MidiIn( ApiType api, getCompiledApi( apis ); for ( unsigned int i=0; i #include - -NAMESPACE_RTMIDI_START +RTMIDI_NAMESPACE_START /*! An abstraction layer for the CORE sequencer layer. It provides the following functionality: - dynamic allocation of the sequencer @@ -688,8 +689,8 @@ CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal ) return str; } else { if ( CFStringGetLength( str ) == 0 ) { - CFRelease( str ); - return result; + CFRelease( str ); + return result; } // does the entity name already start with the device name? // (some drivers do this though they shouldn't) @@ -697,10 +698,10 @@ CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal ) if ( CFStringCompareWithOptions( result, /* endpoint name */ str /* device name */, CFRangeMake(0, CFStringGetLength( str ) ), 0 ) != kCFCompareEqualTo ) { - // prepend the device name to the entity name - if ( CFStringGetLength( result ) > 0 ) - CFStringInsert( result, 0, CFSTR(" ") ); - CFStringInsert( result, 0, str ); + // prepend the device name to the entity name + if ( CFStringGetLength( result ) > 0 ) + CFStringInsert( result, 0, CFSTR(" ") ); + CFStringInsert( result, 0, str ); } CFRelease( str ); } @@ -731,28 +732,28 @@ static CFStringRef ConnectedEndpointName( MIDIEndpointRef endpoint ) if ( nConnected ) { const SInt32 *pid = (const SInt32 *)(CFDataGetBytePtr(connections)); for ( i=0; i(CFDataGetBytePtr(connections)); - for (int i = 0; i < nConnected; ++i, ++pid) { - MIDIUniqueID id = EndianS32_BtoN(*pid); - MIDIObjectRef connObject; - MIDIObjectType connObjectType; - err = MIDIObjectFindByUniqueID(id, &connObject, &connObjectType); - if (err == noErr) { - if (connObjectType == kMIDIObjectType_ExternalSource || - connObjectType == kMIDIObjectType_ExternalDestination) { - // Connected to an external device's endpoint (10.3 and later). - str = EndpointName(static_cast(connObject), true); - } else { - // Connected to an external device (10.2) (or something else, catch-all) - str = NULL; - MIDIObjectGetStringProperty(connObject, kMIDIPropertyName, &str); - } - - if (str != NULL) { - if (anyStrings) - CFStringAppend(result, CFSTR(", ")); - else anyStrings = true; - CFStringAppend(result, str); - CFRelease(str); - } - } - } + const SInt32 *pid = reinterpret_cast(CFDataGetBytePtr(connections)); + for (int i = 0; i < nConnected; ++i, ++pid) { + MIDIUniqueID id = EndianS32_BtoN(*pid); + MIDIObjectRef connObject; + MIDIObjectType connObjectType; + err = MIDIObjectFindByUniqueID(id, &connObject, &connObjectType); + if (err == noErr) { + if (connObjectType == kMIDIObjectType_ExternalSource || + connObjectType == kMIDIObjectType_ExternalDestination) { + // Connected to an external device's endpoint (10.3 and later). + str = EndpointName(static_cast(connObject), true); + } else { + // Connected to an external device (10.2) (or something else, catch-all) + str = NULL; + MIDIObjectGetStringProperty(connObject, kMIDIPropertyName, &str); + } + + if (str != NULL) { + if (anyStrings) + CFStringAppend(result, CFSTR(", ")); + else anyStrings = true; + CFStringAppend(result, str); + CFRelease(str); + } + } + } } CFRelease(connections); } @@ -928,8 +929,8 @@ class CoreSequencer { str = NULL; MIDIObjectGetStringProperty(entity, kMIDIPropertyName, &str); if (str != NULL) { - CFStringAppend(result, str); - CFRelease(str); + CFStringAppend(result, str); + CFRelease(str); } } @@ -946,25 +947,25 @@ class CoreSequencer { // if an external device has only one entity, throw away // the endpoint name and just use the device name if (isExternal && MIDIDeviceGetNumberOfEntities(device) < 2) { - CFRelease(result); - return str; + CFRelease(result); + return str; } else { - // does the entity name already start with the device name? - // (some drivers do this though they shouldn't) - // if so, do not prepend + // does the entity name already start with the device name? + // (some drivers do this though they shouldn't) + // if so, do not prepend - if (CFStringCompareWithOptions(str /* device name */, + if (CFStringCompareWithOptions(str /* device name */, result /* endpoint name */, CFRangeMake(0, CFStringGetLength(str)), 0) - != kCFCompareEqualTo) { - // prepend the device name to the entity name - if (CFStringGetLength(result) > 0) - CFStringInsert(result, 0, CFSTR(" ")); - CFStringInsert(result, 0, str); - } - CFRelease(str); + != kCFCompareEqualTo) { + // prepend the device name to the entity name + if (CFStringGetLength(result) > 0) + CFStringInsert(result, 0, CFSTR(" ")); + CFStringInsert(result, 0, str); + } + CFRelease(str); } } @@ -1002,29 +1003,29 @@ class CoreSequencer { MIDIObjectType connObjectType; err = MIDIObjectFindByUniqueID(id, &connObject, &connObjectType); if (err != noErr) - continue; + continue; if (connObjectType == kMIDIObjectType_ExternalSource || - connObjectType == kMIDIObjectType_ExternalDestination) { - // Connected to an external - // device's endpoint - // (10.3 and later). - strRef = EndpointName(static_cast(connObject), + connObjectType == kMIDIObjectType_ExternalDestination) { + // Connected to an external + // device's endpoint + // (10.3 and later). + strRef = EndpointName(static_cast(connObject), true); } else { - // Connected to an external device - // (10.2) (or something else, catch-all) - strRef = NULL; - MIDIObjectGetStringProperty(connObject, + // Connected to an external device + // (10.2) (or something else, catch-all) + strRef = NULL; + MIDIObjectGetStringProperty(connObject, kMIDIPropertyName, &strRef); } if (strRef != NULL) { - if (anyStrings) - result << ", "; - else anyStrings = true; - result << str(strRef); - CFRelease(strRef); + if (anyStrings) + result << ", "; + else anyStrings = true; + result << str(strRef); + CFRelease(strRef); } } CFRelease(connections); @@ -1062,33 +1063,33 @@ class CoreSequencer { nameRef = NULL; MIDIObjectGetStringProperty(entity, kMIDIPropertyName, &nameRef); if (nameRef != NULL) { - entityname = str(nameRef); - CFRelease(nameRef); + entityname = str(nameRef); + CFRelease(nameRef); } hasManyEndpoints = - MIDIEntityGetNumberOfSources(entity) >= 2 || - MIDIEntityGetNumberOfDestinations(entity) - >= 2; + MIDIEntityGetNumberOfSources(entity) >= 2 || + MIDIEntityGetNumberOfDestinations(entity) + >= 2; // now consider the device's name MIDIDeviceRef device = 0; MIDIEntityGetDevice(entity, &device); if (device != 0) { - hasManyEntities = MIDIDeviceGetNumberOfEntities(device) >= 2; - MIDIObjectGetStringProperty(device, + hasManyEntities = MIDIDeviceGetNumberOfEntities(device) >= 2; + MIDIObjectGetStringProperty(device, kMIDIPropertyName, &nameRef); - devicename = str(nameRef); - CFRelease(nameRef); + devicename = str(nameRef); + CFRelease(nameRef); } // does the entity name already start with the device name? // (some drivers do this though they shouldn't) if (entityname.substr(0,devicename.length()) - == devicename) { - int start = devicename.length(); - while (isspace(entityname[start])) - start++; - entityname = entityname.substr(start); + == devicename) { + int start = devicename.length(); + while (isspace(entityname[start])) + start++; + entityname = entityname.substr(start); } } @@ -1099,12 +1100,12 @@ class CoreSequencer { switch (naming) { case PortDescriptor::SESSION_PATH: if (flags & PortDescriptor::INCLUDE_API) - os << "CORE:"; + os << "CORE:"; os << port; break; case PortDescriptor::STORAGE_PATH: if (flags & PortDescriptor::INCLUDE_API) - os << "CORE:"; + os << "CORE:"; // os << clientname; os << devicename; os << ":" << portname; @@ -1113,54 +1114,54 @@ class CoreSequencer { os << ":" << connections; // os << ":" << recommendedname; if (flags & PortDescriptor::UNIQUE_PORT_NAME) - os << ";" << port; + os << ";" << port; break; case PortDescriptor::LONG_NAME: needcolon = !devicename.empty(); os << devicename; if (hasManyEndpoints || - hasManyEntities || - devicename.empty()) { - if (!entityname.empty()) { - if (needcolon) - os << ": "; - os << entityname; - needcolon = true; - } - if ((hasManyEndpoints - || entityname.empty()) + hasManyEntities || + devicename.empty()) { + if (!entityname.empty()) { + if (needcolon) + os << ": "; + os << entityname; + needcolon = true; + } + if ((hasManyEndpoints + || entityname.empty()) && !portname.empty()) { - if (needcolon) - os << ": "; - os << portname; - } + if (needcolon) + os << ": "; + os << portname; + } } if (!connections.empty()) { - os << " ⇒ "; - os << connections; + os << " ⇒ "; + os << connections; } if (flags & - (PortDescriptor::INCLUDE_API - | PortDescriptor::UNIQUE_PORT_NAME)) { - os << " ("; - if (flags & - PortDescriptor::INCLUDE_API) { - os << "CORE"; - if (flags & PortDescriptor::UNIQUE_PORT_NAME) - os << ":"; - } - if (flags & PortDescriptor::UNIQUE_PORT_NAME) { - os << port; - } - os << ")"; + (PortDescriptor::INCLUDE_API + | PortDescriptor::UNIQUE_PORT_NAME)) { + os << " ("; + if (flags & + PortDescriptor::INCLUDE_API) { + os << "CORE"; + if (flags & PortDescriptor::UNIQUE_PORT_NAME) + os << ":"; + } + if (flags & PortDescriptor::UNIQUE_PORT_NAME) { + os << port; + } + os << ")"; } break; case PortDescriptor::SHORT_NAME: default: if (!recommendedname.empty()) { - os << recommendedname; + os << recommendedname; } else - if (!connections.empty()) { + if (!connections.empty()) { os << connections; } else { os << devicename; @@ -1178,19 +1179,19 @@ class CoreSequencer { } } if (flags & - (PortDescriptor::INCLUDE_API - | PortDescriptor::UNIQUE_PORT_NAME)) { - os << " ("; - if (flags & - PortDescriptor::INCLUDE_API) { - os << "CORE"; - if (flags & PortDescriptor::UNIQUE_PORT_NAME) - os << ":"; - } - if (flags & PortDescriptor::UNIQUE_PORT_NAME) { - os << port; - } - os << ")"; + (PortDescriptor::INCLUDE_API + | PortDescriptor::UNIQUE_PORT_NAME)) { + os << " ("; + if (flags & + PortDescriptor::INCLUDE_API) { + os << "CORE"; + if (flags & PortDescriptor::UNIQUE_PORT_NAME) + os << ":"; + } + if (flags & PortDescriptor::UNIQUE_PORT_NAME) { + os << port; + } + os << ")"; } break; } @@ -1209,9 +1210,9 @@ class CoreSequencer { kMIDIPropertyUniqueID, &uid); if (stat != noErr) { - throw RTMIDI_ERROR(gettext_noopt("Could not get the unique identifier of a midi endpoint."), + throw RTMIDI_ERROR(gettext_noopt("Could not get the unique identifier of a midi endpoint."), Error::WARNING); - return 0; + return 0; } MIDIObjectRef obj; MIDIObjectType type; @@ -1219,18 +1220,18 @@ class CoreSequencer { &obj, &type); if (stat != noErr || obj != port) { - throw RTMIDI_ERROR(gettext_noopt("Could not get the endpoint back from the unique identifier of a midi endpoint."), + throw RTMIDI_ERROR(gettext_noopt("Could not get the endpoint back from the unique identifier of a midi endpoint."), Error::WARNING); - return 0; + return 0; } if (type == kMIDIObjectType_Source - || type == kMIDIObjectType_ExternalSource) - return PortDescriptor::INPUT; + || type == kMIDIObjectType_ExternalSource) + return PortDescriptor::INPUT; else if (type == kMIDIObjectType_Destination || type == kMIDIObjectType_ExternalDestination) - return PortDescriptor::OUTPUT; + return PortDescriptor::OUTPUT; else { - return 0; + return 0; } } else if (stat != noErr) { @@ -1249,21 +1250,21 @@ class CoreSequencer { MIDIEntityGetNumberOfDestinations(entity); for (ItemCount i = 0; i < count ; i++) { MIDIEndpointRef dest= - MIDIEntityGetDestination(entity,i); + MIDIEntityGetDestination(entity,i); if (dest == port) { - retval |= - PortDescriptor::OUTPUT; - break; + retval |= + PortDescriptor::OUTPUT; + break; } } count = MIDIEntityGetNumberOfSources(entity); for (ItemCount i = 0; i < count ; i++) { MIDIEndpointRef src= - MIDIEntityGetSource(entity,i); + MIDIEntityGetSource(entity,i); if (src == port) { - retval |= - PortDescriptor::INPUT; + retval |= + PortDescriptor::INPUT; } } return retval; @@ -1291,7 +1292,7 @@ class CoreSequencer { break; case PortDescriptor::OUTPUT: result - = MIDIOutputPortCreate(seq, + = MIDIOutputPortCreate(seq, CFStringCreateWithCString( NULL, portName.c_str(), @@ -1320,7 +1321,7 @@ class CoreSequencer { switch (flags) { case PortDescriptor::INPUT: result - = MIDIDestinationCreate(seq, + = MIDIDestinationCreate(seq, CFStringCreateWithCString( NULL, portName.c_str(), @@ -1331,7 +1332,7 @@ class CoreSequencer { break; case PortDescriptor::OUTPUT: result - = MIDISourceCreate(seq, + = MIDISourceCreate(seq, CFStringCreateWithCString( NULL, portName.c_str(), @@ -1366,12 +1367,12 @@ class CoreSequencer { scoped_lock(pthread_mutex_t & m): mutex(&m) { if (locking) - pthread_mutex_lock(mutex); + pthread_mutex_lock(mutex); } ~scoped_lock() { if (locking) - pthread_mutex_unlock(mutex); + pthread_mutex_unlock(mutex); } }; pthread_mutex_t mutex; @@ -1396,9 +1397,9 @@ class CoreSequencer { OSStatus result = MIDIClientCreate(cfname, NULL, NULL, &client ); CFRelease(cfname); if ( result != noErr ) { - throw RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI client object."), + throw RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI client object."), Error::DRIVER_ERROR); - return; + return; } } } @@ -1495,17 +1496,17 @@ PortList CorePortDescriptor :: getPortList(int capabilities, const std::string & MIDIGetNumberOfDestinations(); for (ItemCount i = 0 ; i < count; i++) { MIDIEndpointRef destination = - MIDIGetDestination(i); + MIDIGetDestination(i); try { - if ((seq.getPortCapabilities(destination) - & caps) == caps) - list.push_back(Pointer( + if ((seq.getPortCapabilities(destination) + & caps) == caps) + list.push_back(Pointer( new CorePortDescriptor(destination, clientName))); } catch (Error e) { - if (e.getType() == Error::WARNING || - e.getType() == Error::DEBUG_WARNING) - e.printMessage(); - else throw; + if (e.getType() == Error::WARNING || + e.getType() == Error::DEBUG_WARNING) + e.printMessage(); + else throw; } } // Combined sources and destinations @@ -1516,17 +1517,17 @@ PortList CorePortDescriptor :: getPortList(int capabilities, const std::string & MIDIGetNumberOfSources(); for (ItemCount i = 0 ; i < count; i++) { MIDIEndpointRef src = - MIDIGetSource(i); + MIDIGetSource(i); try { - if ((seq.getPortCapabilities(src) - & caps) == caps) - list.push_back(Pointer( + if ((seq.getPortCapabilities(src) + & caps) == caps) + list.push_back(Pointer( new CorePortDescriptor(src, clientName))); } catch (Error e) { - if (e.getType() == Error::WARNING || - e.getType() == Error::DEBUG_WARNING) - e.printMessage(); - else throw; + if (e.getType() == Error::WARNING || + e.getType() == Error::DEBUG_WARNING) + e.printMessage(); + else throw; } } } @@ -1613,12 +1614,12 @@ void MidiInCore::midiInputCallback( const MIDIPacketList *list, else { time = packet->timeStamp; if ( time == 0 ) { // this happens when receiving asynchronous sysex messages - time = AudioGetCurrentHostTime(); + time = AudioGetCurrentHostTime(); } time -= apiData->lastTime; time = AudioConvertHostTimeToNanos( time ); 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 @@ -1630,111 +1631,111 @@ void MidiInCore::midiInputCallback( const MIDIPacketList *list, if ( continueSysex ) { // We have a continuing, segmented sysex message. if ( !( data->ignoreFlags & 0x01 ) ) { - // If we're not ignoring sysex messages, copy the entire packet. - for ( unsigned int j=0; jdata[j] ); + // If we're not ignoring sysex messages, copy the entire packet. + for ( unsigned int j=0; jdata[j] ); } continueSysex = packet->data[nBytes-1] != 0xF7; if ( !( data->ignoreFlags & 0x01 ) ) { - if ( !continueSysex ) { - // If not a continuing sysex message, invoke the user callback function or queue the message. - if ( data->userCallback ) { - data->userCallback->rtmidi_midi_in( message.timeStamp, + if ( !continueSysex ) { + // If not a continuing sysex message, invoke the user callback function or queue the message. + if ( data->userCallback ) { + data->userCallback->rtmidi_midi_in( message.timeStamp, message.bytes); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else { - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else { + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother ALSA with an unhandled exception - } - } - } - message.bytes.clear(); - } + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } + } + } + message.bytes.clear(); + } } } else { while ( iByte < nBytes ) { - size = 0; - // We are expecting that the next byte in the packet is a status byte. - status = packet->data[iByte]; - if ( !(status & 0x80) ) break; - // Determine the number of bytes in the MIDI message. - if ( status < 0xC0 ) size = 3; - else if ( status < 0xE0 ) size = 2; - else if ( status < 0xF0 ) size = 3; - else if ( status == 0xF0 ) { - // A MIDI sysex - if ( data->ignoreFlags & 0x01 ) { - size = 0; - iByte = nBytes; - } - else size = nBytes - iByte; - continueSysex = packet->data[nBytes-1] != 0xF7; - } - else if ( status == 0xF1 ) { - // A MIDI time code message - if ( data->ignoreFlags & 0x02 ) { - size = 0; - iByte += 2; - } - else size = 2; - } - else if ( status == 0xF2 ) size = 3; - else if ( status == 0xF3 ) size = 2; - else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) { - // A MIDI timing tick message and we're ignoring it. - size = 0; - iByte += 1; - } - else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) { - // A MIDI active sensing message and we're ignoring it. - size = 0; - iByte += 1; - } - else size = 1; - - // Copy the MIDI data to our vector. - if ( size ) { - 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. - if ( data->userCallback ) { - data->userCallback->rtmidi_midi_in( message.timeStamp, + size = 0; + // We are expecting that the next byte in the packet is a status byte. + status = packet->data[iByte]; + if ( !(status & 0x80) ) break; + // Determine the number of bytes in the MIDI message. + if ( status < 0xC0 ) size = 3; + else if ( status < 0xE0 ) size = 2; + else if ( status < 0xF0 ) size = 3; + else if ( status == 0xF0 ) { + // A MIDI sysex + if ( data->ignoreFlags & 0x01 ) { + size = 0; + iByte = nBytes; + } + else size = nBytes - iByte; + continueSysex = packet->data[nBytes-1] != 0xF7; + } + else if ( status == 0xF1 ) { + // A MIDI time code message + if ( data->ignoreFlags & 0x02 ) { + size = 0; + iByte += 2; + } + else size = 2; + } + else if ( status == 0xF2 ) size = 3; + else if ( status == 0xF3 ) size = 2; + else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) { + // A MIDI timing tick message and we're ignoring it. + size = 0; + iByte += 1; + } + else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) { + // A MIDI active sensing message and we're ignoring it. + size = 0; + iByte += 1; + } + else size = 1; + + // Copy the MIDI data to our vector. + if ( size ) { + 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. + if ( data->userCallback ) { + data->userCallback->rtmidi_midi_in( message.timeStamp, message.bytes); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else { - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + } + else { + // As long as we haven't reached our queue size limit, push the message. + if ( data->queue.size < data->queue.ringSize ) { + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; + } + else { + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother WinMM with an unhandled exception - } - } - } - message.bytes.clear(); - } - iByte += size; - } + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } + } + } + message.bytes.clear(); + } + iByte += size; + } } } packet = MIDIPacketNext(packet); @@ -1942,6 +1943,7 @@ void MidiInCore :: closePort( void ) connected_ = false; } + unsigned int MidiInCore :: getPortCount() { CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); @@ -2163,12 +2165,12 @@ Pointer MidiOutCore :: getDescriptor(bool local) try { if (local) { if (data && data->localEndpoint) { - return Pointer( + return Pointer( new CorePortDescriptor(data->localEndpoint, data->getClientName())); } } else { if (data->getEndpoint()) { - return Pointer( + return Pointer( new CorePortDescriptor(*data)); } } @@ -2259,7 +2261,7 @@ void MidiOutCore :: sendMessage( std::vector &message ) } } #undef RTMIDI_CLASSNAME -NAMESPACE_RTMIDI_END +RTMIDI_NAMESPACE_END #endif // __MACOSX_COREMIDI__ @@ -2288,7 +2290,7 @@ NAMESPACE_RTMIDI_END // ALSA header file. #include -NAMESPACE_RTMIDI_START +RTMIDI_NAMESPACE_START struct AlsaMidiData; /*! An abstraction layer for the ALSA sequencer layer. It provides @@ -2641,21 +2643,21 @@ PortList AlsaPortDescriptor :: getPortList(int capabilities, const std::string & unsigned int atyp = snd_seq_port_info_get_type( pinfo ); // otherwise we get ports without any if ( !(capabilities & UNLIMITED) && - !( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) && - !( atyp & SND_SEQ_PORT_TYPE_SYNTH ) - ) continue; + !( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) && + !( atyp & SND_SEQ_PORT_TYPE_SYNTH ) + ) continue; unsigned int caps = snd_seq_port_info_get_capability( pinfo ); if (capabilities & INPUT) { - /* we need both READ and SUBS_READ */ - if ((caps & (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) - != (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) - continue; + /* we need both READ and SUBS_READ */ + if ((caps & (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) + != (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) + continue; } if (capabilities & OUTPUT) { - /* we need both WRITE and SUBS_WRITE */ - if ((caps & (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) - != (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) - continue; + /* we need both WRITE and SUBS_WRITE */ + if ((caps & (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) + != (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) + continue; } list.push_back(Pointer( new AlsaPortDescriptor(client,snd_seq_port_info_get_port(pinfo),clientName))); @@ -2865,11 +2867,11 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() if ( snd_seq_event_input_pending( apiData->seq, 1 ) == 0 ) { // No data pending if ( poll( poll_fds, poll_fd_count, -1) >= 0 ) { - if ( poll_fds[0].revents & POLLIN ) { - bool dummy; - int res = read( poll_fds[0].fd, &dummy, sizeof(dummy) ); - (void) res; - } + if ( poll_fds[0].revents & POLLIN ) { + bool dummy; + int res = read( poll_fds[0].fd, &dummy, sizeof(dummy) ); + (void) res; + } } continue; } @@ -2878,31 +2880,31 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() result = snd_seq_event_input( apiData->seq, &ev ); if ( result == -ENOSPC ) { try { - data->error(RTMIDI_ERROR(rtmidi_gettext("MIDI input buffer overrun."), + data->error(RTMIDI_ERROR(rtmidi_gettext("MIDI input buffer overrun."), Error::WARNING)); } catch (Error e) { - // don't bother ALSA with an unhandled exception + // don't bother ALSA with an unhandled exception } continue; } else if ( result == -EAGAIN ) { try { - data->error(RTMIDI_ERROR(rtmidi_gettext("ALSA returned without providing a MIDI event."), + data->error(RTMIDI_ERROR(rtmidi_gettext("ALSA returned without providing a MIDI event."), Error::WARNING)); } catch (Error e) { - // don't bother ALSA with an unhandled exception + // don't bother ALSA with an unhandled exception } continue; } else if ( result <= 0 ) { try { - data->error(RTMIDI_ERROR1(rtmidi_gettext("Unknown MIDI input error.\nThe system reports:\n%s"), + data->error(RTMIDI_ERROR1(rtmidi_gettext("Unknown MIDI input error.\nThe system reports:\n%s"), Error::WARNING, strerror(-result))); } catch (Error e) { - // don't bother ALSA with an unhandled exception + // don't bother ALSA with an unhandled exception } continue; } @@ -2950,19 +2952,19 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() case SND_SEQ_EVENT_SYSEX: if ( (data->ignoreFlags & 0x01) ) break; if ( ev->data.ext.len > apiData->bufferSize ) { - apiData->bufferSize = ev->data.ext.len; - free( buffer ); - buffer = (unsigned char *) malloc( apiData->bufferSize ); - if ( buffer == NULL ) { - data->doInput = false; - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error resizing buffer memory."), + apiData->bufferSize = ev->data.ext.len; + free( buffer ); + buffer = (unsigned char *) malloc( apiData->bufferSize ); + if ( buffer == NULL ) { + data->doInput = false; + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error resizing buffer memory."), Error::WARNING)); - } catch (Error e) { - // don't bother ALSA with an unhandled exception - } - break; - } + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } + break; + } } RTMIDI_FALLTHROUGH; default: @@ -2973,47 +2975,47 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() nBytes = snd_midi_event_decode( apiData->coder, buffer, apiData->bufferSize, ev ); if ( nBytes > 0 ) { - // The ALSA sequencer has a maximum buffer size for MIDI sysex - // events of 256 bytes. If a device sends sysex messages larger - // than this, they are segmented into 256 byte chunks. So, - // we'll watch for this and concatenate sysex chunks into a - // single sysex message if necessary. - if ( !continueSysex ) - message.bytes.assign( buffer, &buffer[nBytes] ); - else - message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] ); - - continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) ); - if ( !continueSysex ) { - - // Calculate the time stamp: - message.timeStamp = 0.0; - - // Method 1: Use the system time. - //(void)gettimeofday(&tv, (struct timezone *)NULL); - //time = (tv.tv_sec * 1000000) + tv.tv_usec; - - // Method 2: Use the ALSA sequencer event time data. - // (thanks to Pedro Lopez-Cabanillas!). - time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 ); - lastTime = time; - time -= apiData->lastTime; - apiData->lastTime = lastTime; - if ( data->firstMessage == true ) - data->firstMessage = false; - else - message.timeStamp = time * 0.000001; - } - else { + // The ALSA sequencer has a maximum buffer size for MIDI sysex + // events of 256 bytes. If a device sends sysex messages larger + // than this, they are segmented into 256 byte chunks. So, + // we'll watch for this and concatenate sysex chunks into a + // single sysex message if necessary. + if ( !continueSysex ) + message.bytes.assign( buffer, &buffer[nBytes] ); + else + message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] ); + + continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) ); + if ( !continueSysex ) { + + // Calculate the time stamp: + message.timeStamp = 0.0; + + // Method 1: Use the system time. + //(void)gettimeofday(&tv, (struct timezone *)NULL); + //time = (tv.tv_sec * 1000000) + tv.tv_usec; + + // Method 2: Use the ALSA sequencer event time data. + // (thanks to Pedro Lopez-Cabanillas!). + time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 ); + lastTime = time; + time -= apiData->lastTime; + apiData->lastTime = lastTime; + if ( data->firstMessage == true ) + data->firstMessage = false; + else + message.timeStamp = time * 0.000001; + } + else { #if defined(__RTMIDI_DEBUG__) - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Event parsing error or not a MIDI event."), + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Event parsing error or not a MIDI event."), Error::WARNING)); - } catch (Error e) { - // don't bother ALSA with an unhandled exception - } + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } #endif - } + } } } @@ -3026,18 +3028,18 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() else { // As long as we haven't reached our queue size limit, push the message. if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; + data->queue.ring[data->queue.back++] = message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; } else { - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother ALSA with an unhandled exception - } + } catch (Error e) { + // don't bother ALSA with an unhandled exception + } } } } @@ -3321,7 +3323,7 @@ void MidiInAlsa :: openPort( const PortDescriptor & port, if ( doInput == false ) { doInput - = data->startQueue(this); + = data->startQueue(this); } connected_ = true; @@ -3336,12 +3338,12 @@ Pointer MidiInAlsa :: getDescriptor(bool local) try { if (local) { if (data && data->local.client) { - return Pointer( + return Pointer( new AlsaPortDescriptor(data->local,data->getClientName())); } } else { if (data && data->client) { - return Pointer( + return Pointer( new AlsaPortDescriptor(*data,data->getClientName())); } } @@ -3416,9 +3418,9 @@ void MidiInAlsa :: openVirtualPort(const std::string & portName ) pthread_attr_destroy(&attr); if ( err ) { if ( data->subscription ) { - snd_seq_unsubscribe_port( data->seq, data->subscription ); - snd_seq_port_subscribe_free( data->subscription ); - data->subscription = 0; + snd_seq_unsubscribe_port( data->seq, data->subscription ); + snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; } doInput = false; error( RTMIDI_ERROR(gettext_noopt("Error starting MIDI input thread!"), @@ -3742,12 +3744,12 @@ Pointer MidiOutAlsa :: getDescriptor(bool local) try { if (local) { if (data && data->local.client) { - return Pointer( + return Pointer( new AlsaPortDescriptor(data->local, data->getClientName())); } } else { if (data && data->client) { - return Pointer( + return Pointer( new AlsaPortDescriptor(*data, data->getClientName())); } } @@ -3766,7 +3768,7 @@ PortList MidiOutAlsa :: getPortList(int capabilities) return PortList(); } } -NAMESPACE_RTMIDI_END +RTMIDI_NAMESPACE_END #undef RTMIDI_CLASSNAME #endif // __LINUX_ALSA__ @@ -3792,7 +3794,7 @@ NAMESPACE_RTMIDI_END #define RT_SYSEX_BUFFER_SIZE 1024 #define RT_SYSEX_BUFFER_COUNT 4 -NAMESPACE_RTMIDI_START +RTMIDI_NAMESPACE_START /* some header defines UNIQUE_PORT_NAME as a macro */ #ifdef UNIQUE_PORT_NAME @@ -3912,26 +3914,26 @@ class WinMMSequencer { switch (naming) { case PortDescriptor::SESSION_PATH: if (flags & PortDescriptor::INCLUDE_API) - os << "WinMM:"; + os << "WinMM:"; os << port << ":" << name.c_str(); break; case PortDescriptor::STORAGE_PATH: if (flags & PortDescriptor::INCLUDE_API) - os << "WinMM:"; + os << "WinMM:"; os << name.c_str(); if (flags & PortDescriptor::UNIQUE_PORT_NAME) - os << ";" << port; + os << ";" << port; break; case PortDescriptor::LONG_NAME: case PortDescriptor::SHORT_NAME: default: os << name.c_str(); if (flags & PortDescriptor::UNIQUE_PORT_NAME) { - os << " "; - os << port; + os << " "; + os << port; } if (flags & PortDescriptor::INCLUDE_API) - os << " (WinMM)"; + os << " (WinMM)"; break; } @@ -3945,14 +3947,14 @@ class WinMMSequencer { { #if 0 if (locking) - pthread_mutex_lock(mutex); + pthread_mutex_lock(mutex); #endif } ~scoped_lock() { #if 0 if (locking) - pthread_mutex_unlock(mutex); + pthread_mutex_unlock(mutex); #endif } }; @@ -4016,11 +4018,11 @@ struct WinMMPortDescriptor:public PortDescriptor bool is_valid() const { if (is_input) { if (midiInGetNumDevs() <= port) { - return false; + return false; } } else { if (midiOutGetNumDevs() <= port) { - return false; + return false; } } return seq.getPortName(port,is_input,PortDescriptor::STORAGE_PATH) @@ -4145,18 +4147,18 @@ struct WinMMCallbacks { else if ( status < 0xE0 ) nBytes = 2; else if ( status < 0xF0 ) nBytes = 3; else if ( status == 0xF1 ) { - if ( data->ignoreFlags & 0x02 ) return; - else nBytes = 2; + if ( data->ignoreFlags & 0x02 ) return; + else nBytes = 2; } else if ( status == 0xF2 ) nBytes = 3; else if ( status == 0xF3 ) nBytes = 2; else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) { - // A MIDI timing tick message and we're ignoring it. - return; + // A MIDI timing tick message and we're ignoring it. + return; } else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { - // A MIDI active sensing message and we're ignoring it. - return; + // A MIDI active sensing message and we're ignoring it. + return; } // Copy bytes to our MIDI message. @@ -4166,9 +4168,9 @@ struct WinMMCallbacks { else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) MIDIHDR *sysex = ( MIDIHDR *) midiMessage; if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { - // Sysex message and we're not ignoring it - for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) - apiData->message.bytes.push_back( sysex->lpData[i] ); + // Sysex message and we're not ignoring it + for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) + apiData->message.bytes.push_back( sysex->lpData[i] ); } // The WinMM API requires that the sysex buffer be requeued after @@ -4180,20 +4182,20 @@ struct WinMMCallbacks { // avoid requeueing it, else the computer suddenly reboots after // one or two minutes. if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { - //if ( sysex->dwBytesRecorded > 0 ) { - EnterCriticalSection( &(apiData->_mutex) ); - MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); - LeaveCriticalSection( &(apiData->_mutex) ); - if ( result != MMSYSERR_NOERROR ){ - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error sending sysex to Midi device."), + //if ( sysex->dwBytesRecorded > 0 ) { + EnterCriticalSection( &(apiData->_mutex) ); + MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); + LeaveCriticalSection( &(apiData->_mutex) ); + if ( result != MMSYSERR_NOERROR ){ + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error sending sysex to Midi device."), Error::WARNING)); - } catch (Error e) { - // don't bother WinMM with an unhandled exception - } - } + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } + } - if ( data->ignoreFlags & 0x01 ) return; + if ( data->ignoreFlags & 0x01 ) return; } else return; } @@ -4204,18 +4206,18 @@ struct WinMMCallbacks { else { // As long as we haven't reached our queue size limit, push the message. if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = apiData->message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; + data->queue.ring[data->queue.back++] = apiData->message; + if ( data->queue.back == data->queue.ringSize ) + data->queue.back = 0; + data->queue.size++; } else { - try { - data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother WinMM with an unhandled exception - } + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } } } @@ -4440,10 +4442,10 @@ void MidiInWinMM :: closePort( void ) delete [] data->sysexBuffer[i]->lpData; delete [] data->sysexBuffer[i]; if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - error(RTMIDI_ERROR(gettext_noopt("Error closing Windows MM MIDI input port."), + midiInClose( data->inHandle ); + error(RTMIDI_ERROR(gettext_noopt("Error closing Windows MM MIDI input port."), Error::DRIVER_ERROR) ); - return; + return; } } @@ -4772,7 +4774,7 @@ void MidiOutWinMM :: sendMessage( std::vector &message ) } } #undef RTMIDI_CLASSNAME -NAMESPACE_RTMIDI_END +RTMIDI_NAMESPACE_END #endif // __WINDOWS_MM__ @@ -4793,7 +4795,7 @@ NAMESPACE_RTMIDI_END #define JACK_RINGBUFFER_SIZE 16384 // Default size for ringbuffer -NAMESPACE_RTMIDI_START +RTMIDI_NAMESPACE_START struct JackMidiData; struct JackBackendCallbacks { @@ -4831,10 +4833,10 @@ class JackSequencer { { scoped_lock lock (mutex); if (client) { - jack_deactivate (client); - // the latter doesn't flush the queue - jack_client_close (client); - client = 0; + jack_deactivate (client); + // the latter doesn't flush the queue + jack_client_close (client); + client = 0; } } if (locking) { @@ -4874,7 +4876,7 @@ class JackSequencer { switch (naming) { case PortDescriptor::SESSION_PATH: if (flags & PortDescriptor::INCLUDE_API) - os << "JACK:"; + os << "JACK:"; #if __UNIX_JACK_HAS_UUID__ os << "UUID:" << std::hex << jack_port_uuid(port); #else @@ -4883,19 +4885,19 @@ class JackSequencer { break; case PortDescriptor::STORAGE_PATH: if (flags & PortDescriptor::INCLUDE_API) - os << "JACK:"; + os << "JACK:"; os << jack_port_name(port); break; case PortDescriptor::LONG_NAME: os << jack_port_name(port); if (flags & PortDescriptor::INCLUDE_API) - os << " (JACK)"; + os << " (JACK)"; break; case PortDescriptor::SHORT_NAME: default: os << jack_port_short_name(port); if (flags & PortDescriptor::INCLUDE_API) - os << " (JACK)"; + os << " (JACK)"; break; } return os.str(); @@ -4969,12 +4971,12 @@ class JackSequencer { scoped_lock(pthread_mutex_t & m): mutex(&m) { if (locking) - pthread_mutex_lock(mutex); + pthread_mutex_lock(mutex); } ~scoped_lock() { if (locking) - pthread_mutex_unlock(mutex); + pthread_mutex_unlock(mutex); } }; pthread_mutex_t mutex; @@ -4996,16 +4998,16 @@ class JackSequencer { if (( c = jack_client_open( name.c_str(), JackNoStartServer, NULL )) == 0) { - c = NULL; - throw RTMIDI_ERROR(gettext_noopt("Could not connect to JACK server. Is it runnig?"), + c = NULL; + throw RTMIDI_ERROR(gettext_noopt("Could not connect to JACK server. Is it runnig?"), Error::NO_DEVICES_FOUND); - return; + return; } if (isoutput && data) { - jack_set_process_callback( c, JackBackendCallbacks::jackProcessOut, data ); + jack_set_process_callback( c, JackBackendCallbacks::jackProcessOut, data ); } else if (data) - jack_set_process_callback( c, JackBackendCallbacks::jackProcessIn, data ); + jack_set_process_callback( c, JackBackendCallbacks::jackProcessIn, data ); jack_activate( c ); } } @@ -5274,24 +5276,24 @@ int JackBackendCallbacks::jackProcessIn( jack_nframes_t nframes, void *arg ) if ( !rtData->continueSysex ) { if ( rtData->userCallback ) { - rtData->userCallback->rtmidi_midi_in( message.timeStamp, message.bytes); + rtData->userCallback->rtmidi_midi_in( message.timeStamp, message.bytes); } else { - // As long as we haven't reached our queue size limit, push the message. - if ( rtData->queue.size < rtData->queue.ringSize ) { - rtData->queue.ring[rtData->queue.back++] = message; - if ( rtData->queue.back == rtData->queue.ringSize ) - rtData->queue.back = 0; - rtData->queue.size++; - } - else { - try { - rtData->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + // As long as we haven't reached our queue size limit, push the message. + if ( rtData->queue.size < rtData->queue.ringSize ) { + rtData->queue.ring[rtData->queue.back++] = message; + if ( rtData->queue.back == rtData->queue.ringSize ) + rtData->queue.back = 0; + rtData->queue.size++; + } + else { + try { + rtData->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { - // don't bother WinMM with an unhandled exception - } - } + } catch (Error e) { + // don't bother WinMM with an unhandled exception + } + } } } } @@ -5505,12 +5507,12 @@ Pointer MidiInJack :: getDescriptor(bool local) try { if (local) { if (data && data->local) { - return Pointer( + return Pointer( new JackPortDescriptor(data->local,data->getClientName())); } } else { if (data && *data) { - return Pointer( + return Pointer( new JackPortDescriptor(*data,data->getClientName())); } } @@ -5727,12 +5729,12 @@ Pointer MidiOutJack :: getDescriptor(bool local) try { if (local) { if (data && data->local) { - return Pointer( + return Pointer( new JackPortDescriptor(data->local,data->getClientName())); } } else { if (data && *data) { - return Pointer( + return Pointer( new JackPortDescriptor(*data,data->getClientName())); } } @@ -5824,6 +5826,6 @@ void MidiOutJack :: sendMessage( std::vector &message ) jack_ringbuffer_write( data->buffSize, ( char * ) &nBytes, sizeof( nBytes ) ); } #undef RTMIDI_CLASSNAME -NAMESPACE_RTMIDI_END +RTMIDI_NAMESPACE_END #endif // __UNIX_JACK__ diff --git a/RtMidi.h b/RtMidi.h index 8f0f1a4d..0bedad8c 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -87,11 +87,10 @@ #endif #define gettext_noopt(str) (str) -#define NAMESPACE_RTMIDI_START namespace rtmidi { -#define NAMESPACE_RTMIDI_END } - -NAMESPACE_RTMIDI_START +#define RTMIDI_NAMESPACE_START namespace rtmidi { +#define RTMIDI_NAMESPACE_END } +RTMIDI_NAMESPACE_START #ifdef RTMIDI_GETTEXT const char * rtmidi_gettext(const char * s); @@ -108,8 +107,8 @@ enum ApiType { UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ - DUMMY, /*!< A compilable but non-functional API. */ - ALL_API /*!< Use all available APIs for port selection. */ + DUMMY, /*!< A compilable but non-functional API. */ + ALL_API /*!< Use all available APIs for port selection. */ }; //! Return the name on a MIDI API @@ -179,7 +178,7 @@ class Error : public std::exception public: //! Defined Error types. enum Type { - WARNING, /*!< A non-critical error. */ + WARNING, /*!< A non-critical error. */ DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ UNSPECIFIED, /*!< The default, unspecified error type. */ NO_DEVICES_FOUND, /*!< No devices found on system. */ @@ -194,11 +193,11 @@ class Error : public std::exception //! The constructor. Error( const char * message, - Type type, - const char * class_name, - const char * function_name, - const char * file_name, - int line_number, ...) throw(); + Type type, + const char * class_name, + const char * function_name, + const char * file_name, + int line_number, ...) throw(); //! The destructor. virtual ~Error( void ) throw() {} @@ -303,8 +302,8 @@ class Pointer { Pointer & operator = (const Pointer & other) { if (ptr) { if (!(--ptr->count)) { - delete ptr->descriptor; - delete ptr; + delete ptr->descriptor; + delete ptr; } } if ((ptr = other.ptr)) @@ -838,10 +837,10 @@ class Midi { if (list && !list->empty()) { PortList retval; for (MidiApiList::iterator i = list->begin(); - i != list->end(); - ++i) { - PortList tmp = (*i)->getPortList(capabilities); - retval.splice(retval.end(), tmp); + i != list->end(); + ++i) { + PortList tmp = (*i)->getPortList(capabilities); + retval.splice(retval.end(), tmp); } return retval; } @@ -1135,8 +1134,8 @@ class MidiIn : public Midi std::vector< ApiType > apis; getCompiledApi( apis ); for (size_t i = 0 ; i < apis.size() ; i++) { - openMidiApi( apis[0] ); - if (rtapi_ && rtapi_->hasVirtualPorts()) break; + openMidiApi( apis[0] ); + if (rtapi_ && rtapi_->hasVirtualPorts()) break; } } @@ -1390,8 +1389,8 @@ class MidiOut : public Midi std::vector< ApiType > apis; getCompiledApi( apis ); for (size_t i = 0 ; i < apis.size() ; i++) { - openMidiApi( apis[0] ); - if (rtapi_ && rtapi_->hasVirtualPorts()) break; + openMidiApi( apis[0] ); + if (rtapi_ && rtapi_->hasVirtualPorts()) break; } } @@ -1480,9 +1479,9 @@ class MidiOut : public Midi #endif #if defined(__MACOSX_COREMIDI__) -NAMESPACE_RTMIDI_END +RTMIDI_NAMESPACE_END struct MIDIPacketList; -NAMESPACE_RTMIDI_START +RTMIDI_NAMESPACE_START class MidiInCore: public MidiInApi { @@ -1772,7 +1771,7 @@ struct CompatibilityErrorInterface: ErrorInterface { -NAMESPACE_RTMIDI_END +RTMIDI_NAMESPACE_END typedef rtmidi::Midi RTMIDI_DEPRECATED(RtMidi,"RtMidi has been replaced by rtmidi::Midi"); From 61caaf690e99367e10160fc24dc44533f13de4a8 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 4 Aug 2018 15:13:08 +0200 Subject: [PATCH 193/210] Catch exceptions without unnecessary copies. --- RtMidi.cpp | 79 ++++++++++++++++++++++++------------------------ tests/errors.cpp | 4 +-- 2 files changed, 41 insertions(+), 42 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 50187926..62f4b394 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -46,7 +46,6 @@ #define RTMIDI_FALLTHROUGH #endif - RTMIDI_NAMESPACE_START #ifdef RTMIDI_GETTEXT @@ -1502,7 +1501,7 @@ PortList CorePortDescriptor :: getPortList(int capabilities, const std::string & & caps) == caps) list.push_back(Pointer( new CorePortDescriptor(destination, clientName))); - } catch (Error e) { + } catch (Error & e) { if (e.getType() == Error::WARNING || e.getType() == Error::DEBUG_WARNING) e.printMessage(); @@ -1523,7 +1522,7 @@ PortList CorePortDescriptor :: getPortList(int capabilities, const std::string & & caps) == caps) list.push_back(Pointer( new CorePortDescriptor(src, clientName))); - } catch (Error e) { + } catch (Error & e) { if (e.getType() == Error::WARNING || e.getType() == Error::DEBUG_WARNING) e.printMessage(); @@ -1656,7 +1655,7 @@ void MidiInCore::midiInputCallback( const MIDIPacketList *list, try { data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { + } catch (Error & e) { // don't bother ALSA with an unhandled exception } } @@ -1727,7 +1726,7 @@ void MidiInCore::midiInputCallback( const MIDIPacketList *list, try { data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { + } catch (Error & e) { // don't bother WinMM with an unhandled exception } } @@ -1757,7 +1756,7 @@ MidiInCore :: ~MidiInCore( void ) // Close a connection if it exists. closePort(); - } catch (Error e) { + } catch (Error & e) { delete data; throw; } @@ -1920,7 +1919,7 @@ PortList MidiInCore :: getPortList(int capabilities) try { return CorePortDescriptor::getPortList(capabilities | PortDescriptor::INPUT, data->getClientName()); - } catch (Error e) { + } catch (Error & e) { error(e); return PortList(); } @@ -2150,7 +2149,7 @@ void MidiOutCore :: openPort( const PortDescriptor & port, PortDescriptor::OUTPUT); data->setRemote(*remote); connected_ = true; - } catch (Error e) { + } catch (Error & e) { error(e); } } @@ -2174,7 +2173,7 @@ Pointer MidiOutCore :: getDescriptor(bool local) new CorePortDescriptor(*data)); } } - } catch (Error e) { + } catch (Error & e) { error(e); } return NULL; @@ -2186,7 +2185,7 @@ PortList MidiOutCore :: getPortList(int capabilities) try { return CorePortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT, data->getClientName()); - } catch (Error e) { + } catch (Error & e) { error(e); return PortList(); } @@ -2835,7 +2834,7 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() try { data->error(RTMIDI_ERROR(rtmidi_gettext("Error initializing MIDI event parser."), Error::WARNING)); - } catch (Error e) { + } catch (Error & e) { // don't bother ALSA with an unhandled exception } return 0; @@ -2848,7 +2847,7 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() try { data->error(RTMIDI_ERROR(rtmidi_gettext("Error initializing buffer memory."), Error::WARNING)); - } catch (Error e) { + } catch (Error & e) { // don't bother ALSA with an unhandled exception } return 0; @@ -2882,7 +2881,7 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() try { data->error(RTMIDI_ERROR(rtmidi_gettext("MIDI input buffer overrun."), Error::WARNING)); - } catch (Error e) { + } catch (Error & e) { // don't bother ALSA with an unhandled exception } @@ -2892,7 +2891,7 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() try { data->error(RTMIDI_ERROR(rtmidi_gettext("ALSA returned without providing a MIDI event."), Error::WARNING)); - } catch (Error e) { + } catch (Error & e) { // don't bother ALSA with an unhandled exception } @@ -2903,7 +2902,7 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() data->error(RTMIDI_ERROR1(rtmidi_gettext("Unknown MIDI input error.\nThe system reports:\n%s"), Error::WARNING, strerror(-result))); - } catch (Error e) { + } catch (Error & e) { // don't bother ALSA with an unhandled exception } continue; @@ -2960,7 +2959,7 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() try { data->error(RTMIDI_ERROR(rtmidi_gettext("Error resizing buffer memory."), Error::WARNING)); - } catch (Error e) { + } catch (Error & e) { // don't bother ALSA with an unhandled exception } break; @@ -3011,7 +3010,7 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() try { data->error(RTMIDI_ERROR(rtmidi_gettext("Event parsing error or not a MIDI event."), Error::WARNING)); - } catch (Error e) { + } catch (Error & e) { // don't bother ALSA with an unhandled exception } #endif @@ -3037,7 +3036,7 @@ void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() try { data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { + } catch (Error & e) { // don't bother ALSA with an unhandled exception } } @@ -3161,7 +3160,7 @@ std::string MidiInAlsa :: getPortName( unsigned int portNumber ) snd_seq_get_any_client_info( data->seq, cnum, cinfo ); std::ostringstream os; os << snd_seq_client_info_get_name( cinfo ); - os << " "; // These lines added to make sure devices are listed + os << " "; // These lines added to make sure devices are listed os << snd_seq_port_info_get_client( pinfo ); // with full portnames added to ensure individual device names os << ":"; os << snd_seq_port_info_get_port( pinfo ); @@ -3327,7 +3326,7 @@ void MidiInAlsa :: openPort( const PortDescriptor & port, } connected_ = true; - } catch (Error e) { + } catch (Error & e) { error(e); } } @@ -3347,7 +3346,7 @@ Pointer MidiInAlsa :: getDescriptor(bool local) new AlsaPortDescriptor(*data,data->getClientName())); } } - } catch (Error e) { + } catch (Error & e) { error (e); } return NULL; @@ -3358,7 +3357,7 @@ PortList MidiInAlsa :: getPortList(int capabilities) try { return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::INPUT, data->getClientName()); - } catch (Error e) { + } catch (Error & e) { error (e); return PortList(); } @@ -3545,7 +3544,7 @@ std::string MidiOutAlsa :: getPortName( unsigned int portNumber ) snd_seq_get_any_client_info( data->seq, cnum, cinfo ); std::ostringstream os; os << snd_seq_client_info_get_name(cinfo); - os << " "; // These lines added to make sure devices are listed + os << " "; // These lines added to make sure devices are listed os << snd_seq_port_info_get_client( pinfo ); // with full portnames added to ensure individual device names os << ":"; os << snd_seq_port_info_get_port(pinfo); @@ -3734,7 +3733,7 @@ void MidiOutAlsa :: openPort( const PortDescriptor & port, data->connectPorts(data->local,*remote,true); connected_ = true; - } catch (Error e) { + } catch (Error & e) { error (e); } } @@ -3753,7 +3752,7 @@ Pointer MidiOutAlsa :: getDescriptor(bool local) new AlsaPortDescriptor(*data, data->getClientName())); } } - } catch (Error e) { + } catch (Error & e) { error(e); } return NULL; @@ -3764,7 +3763,7 @@ PortList MidiOutAlsa :: getPortList(int capabilities) try { return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT, data->getClientName()); - } catch (Error e) { + } catch (Error & e) { return PortList(); } } @@ -4190,7 +4189,7 @@ struct WinMMCallbacks { try { data->error(RTMIDI_ERROR(rtmidi_gettext("Error sending sysex to Midi device."), Error::WARNING)); - } catch (Error e) { + } catch (Error & e) { // don't bother WinMM with an unhandled exception } } @@ -4215,7 +4214,7 @@ struct WinMMCallbacks { try { data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { + } catch (Error & e) { // don't bother WinMM with an unhandled exception } } @@ -4369,7 +4368,7 @@ void MidiInWinMM :: openPort(const PortDescriptor & p, const std::string & portN // reordering of ports so we must check whether we opened the right port. try { openPort(port->getPortNumber(),portName); - } catch (Error e) { + } catch (Error & e) { error(e); } if (!port->is_valid()) { @@ -4404,7 +4403,7 @@ Pointer MidiInWinMM :: getDescriptor(bool local) WinMMPortDescriptor * retval = NULL; try { retval = new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); - } catch (Error e) { + } catch (Error & e) { try { error(e); } catch (...) { @@ -4422,7 +4421,7 @@ PortList MidiInWinMM :: getPortList(int capabilities) if (!data || capabilities != PortDescriptor::INPUT) return PortList(); try { return WinMMPortDescriptor::getPortList(PortDescriptor::INPUT,data->getClientName()); - } catch (Error e) { + } catch (Error & e) { error(e); return PortList(); } @@ -4646,7 +4645,7 @@ void MidiOutWinMM :: openPort(const PortDescriptor & p, const std::string & port // reordering of ports so we must check whether we opened the right port. try { openPort(port->getPortNumber(),portName); - } catch (Error e) { + } catch (Error & e) { error(e); } if (!port->is_valid()) { @@ -4689,7 +4688,7 @@ PortList MidiOutWinMM :: getPortList(int capabilities) if (!data || capabilities != PortDescriptor::OUTPUT) return PortList(); try { return WinMMPortDescriptor::getPortList(PortDescriptor::OUTPUT,data->getClientName()); - } catch (Error e) { + } catch (Error & e) { error(e); return PortList(); } @@ -5290,7 +5289,7 @@ int JackBackendCallbacks::jackProcessIn( jack_nframes_t nframes, void *arg ) try { rtData->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), Error::WARNING)); - } catch (Error e) { + } catch (Error & e) { // don't bother WinMM with an unhandled exception } } @@ -5411,7 +5410,7 @@ MidiInJack :: ~MidiInJack() JackMidiData *data = static_cast (apiData_); try { closePort(); - } catch (Error e) { + } catch (Error & e) { try { delete data; } catch (...) { @@ -5495,7 +5494,7 @@ void MidiInJack :: openPort( const PortDescriptor & p, portName); data->setRemote(*port); data->connectPorts(*port,data->local); - } catch (Error e) { + } catch (Error & e) { error (e); } @@ -5516,7 +5515,7 @@ Pointer MidiInJack :: getDescriptor(bool local) new JackPortDescriptor(*data,data->getClientName())); } } - } catch (Error e) { + } catch (Error & e) { error(e); } return NULL; @@ -5528,7 +5527,7 @@ PortList MidiInJack :: getPortList(int capabilities) try { return JackPortDescriptor::getPortList(capabilities | PortDescriptor::INPUT, data->getClientName()); - } catch (Error e) { + } catch (Error & e) { error(e); } return PortList(); @@ -5718,7 +5717,7 @@ void MidiOutJack :: openPort( const PortDescriptor & p, portName); data->setRemote(*port); data->connectPorts(data->local,*port); - } catch (Error e) { + } catch (Error & e) { error(e); } } @@ -5738,7 +5737,7 @@ Pointer MidiOutJack :: getDescriptor(bool local) new JackPortDescriptor(*data,data->getClientName())); } } - } catch (Error e) { + } catch (Error & e) { error(e); } return NULL; diff --git a/tests/errors.cpp b/tests/errors.cpp index 9a91943f..f6b1ecf0 100644 --- a/tests/errors.cpp +++ b/tests/errors.cpp @@ -45,7 +45,7 @@ int main( int /* argc */, char * /*argv*/[] ) MidiIn in2 (types[i?0:1]); try { in2.openPort(ports.front()); - } catch (Error e) { + } catch (Error & e) { std::string msg = e.getMessage(); e.printMessage(); if (e.getType() != Error::INVALID_DEVICE) { @@ -53,7 +53,7 @@ int main( int /* argc */, char * /*argv*/[] ) } } } - } catch (Error e) { + } catch (Error & e) { std::string msg = e.getMessage(); e.printMessage(); if (msg != rtmidi_gettext("")) { From bbaf9b6f6f14bf1ee51bcb221087c8167bc07356 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 4 Aug 2018 17:56:41 +0200 Subject: [PATCH 194/210] Silence unnecessary debug output --- configure.library | 34 +++++----------------------------- 1 file changed, 5 insertions(+), 29 deletions(-) diff --git a/configure.library b/configure.library index a841ed42..785d73d1 100644 --- a/configure.library +++ b/configure.library @@ -35,6 +35,8 @@ AS_HELP_STRING([--with-suffix],[add a suffix to the library. Default is $rtmidi_ [ rtmidi_suffix="$enableval"])]) AC_SUBST(rtmidi_suffix) + + # Check for debug AC_MSG_CHECKING(whether to compile debug version) AC_ARG_ENABLE(debug, @@ -282,55 +284,29 @@ darwin*|*apple*) ]) ;; esac -echo "with-jack: $with_jack" -echo "nochmal withjack" + AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (needs libjack to be installed)],[ echo running jack: AS_IF([test "x$with_jack" = "xno"],,[RTMIDI_LIB_JACK ]) ],[ echo runnning jack 2 ; RTMIDI_LIB_JACK(,[true]) ]) -echo -echo "RTMIDI_API = $RTMIDI_API" -echo "RTMIDI_LIBS = $RTMIDI_LIBS" -echo "virtual devices: $RTMIDI_HAVE_VIRTUAL_DEVICES" -echo -echo "with_alsa: $with_alsa" -echo AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA sequencer API support],[ AS_IF([test "x$with_alsa" = "xno"],,[ RTMIDI_LIB_ALSA ]) ],[ RTMIDI_LIB_ALSA(,[true]) ]) -echo -echo "RTMIDI_API = $RTMIDI_API" -echo "RTMIDI_LIBS = $RTMIDI_LIBS" -echo "virtual devices: $RTMIDI_HAVE_VIRTUAL_DEVICES" -echo AC_ARG_WITH(winmm, [ --with-winmm = choose native Windows Multimedia API support],[ AS_IF([test "x$with_winmm" = "xno"],,[RTMIDI_LIB_WINMM ]) ],[ RTMIDI_LIB_WINMM(,[true]) ]) -echo -echo "RTMIDI_API = $RTMIDI_API" -echo "RTMIDI_LIBS = $RTMIDI_LIBS" -echo "virtual devices: $RTMIDI_HAVE_VIRTUAL_DEVICES" -echo + AC_ARG_WITH(winks, [ --with-winks = choose native Windows kernel streaming API support],[ AS_IF([test "x$with_winks" = "xno"],,[ RTMIDI_LIB_WINKS ]) ],[ RTMIDI_LIB_WINKS(,[true]) ]) -echo -echo "RTMIDI_API = $RTMIDI_API" -echo "RTMIDI_LIBS = $RTMIDI_LIBS" -echo "virtual devices: $RTMIDI_HAVE_VIRTUAL_DEVICES" -echo AC_ARG_WITH(coremidi, [--with-coremidi = choose native CoreAudio API support],[ AS_IF([test "x$with_core" = "xno"],,[RTMIDI_LIB_CORE ]) ],[ RTMIDI_LIB_COREMIDI(,[true]) ]) -echo -echo "RTMIDI_API = $RTMIDI_API" -echo "RTMIDI_LIBS = $RTMIDI_LIBS" -echo "virtual devices: $RTMIDI_HAVE_VIRTUAL_DEVICES" -echo + AS_IF([test "x$RTMIDI_API" = "x"],[ AC_MSG_WARN("No suitable MIDI interface found. Using dummy driver") RTMIDI_API="-D__RTMIDI_DUMMY__" From de02b24ae561eadea82c33940877b540da46d40a Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 4 Aug 2018 17:56:57 +0200 Subject: [PATCH 195/210] Fix C interface --- rtmidi_c.cpp | 38 ++++++++++++++++++++------------------ rtmidi_c.h | 23 +++++++++++++++++++---- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index b259e625..18ee64f6 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -3,6 +3,8 @@ #include "rtmidi_c.h" #include "RtMidi.h" +#define RTMIDI_CLASSNAME "C interface" + /* misc */ int rtmidi_sizeof_rtmidi_api () { @@ -36,10 +38,10 @@ int rtmidi_get_compiled_api (enum RtMidiApi **apis) // return length for NULL ar } } -void rtmidi_error (MidiApi *api, enum RtMidiErrorType type, const char* errorString) +void rtmidi_error (rtmidi::MidiApi *api, enum RtMidiErrorType type, const char* errorString) { - std::string msg = errorString; - api->error ((RtMidiError::Type) type, msg); + // std::string msg = errorString; + api->error (RTMIDI_ERROR(errorString,(rtmidi::Error::Type)type)); /* (RtMidiError::Type) type, msg); */ } void rtmidi_open_port (RtMidiPtr device, unsigned int portNumber, const char *portName) @@ -61,7 +63,7 @@ void rtmidi_close_port (RtMidiPtr device) unsigned int rtmidi_get_port_count (RtMidiPtr device) { - return ((RtMidi*) device)->getPortCount (); + return device->getPortCount (); } const char* rtmidi_get_port_name (RtMidiPtr device, unsigned int portNumber) @@ -70,26 +72,26 @@ const char* rtmidi_get_port_name (RtMidiPtr device, unsigned int portNumber) return strdup (name.c_str ()); } -/* RtMidiIn API */ +/* MidiIn API */ RtMidiInPtr rtmidi_in_create_default () { - return new RtMidiIn (); + return new rtmidi::MidiIn (); } RtMidiInPtr rtmidi_in_create (enum RtMidiApi api, const char *clientName, unsigned int queueSizeLimit) { std::string name = clientName; - return new RtMidiIn ((RtMidi::Api) api, name, queueSizeLimit); + return new rtmidi::MidiIn ((rtmidi::ApiType) api, name, queueSizeLimit); } void rtmidi_in_free (RtMidiInPtr device) { - delete (RtMidiIn*) device; + delete device; } enum RtMidiApi rtmidi_in_get_current_api (RtMidiPtr device) { - return (RtMidiApi) ((RtMidiIn*) device)->getCurrentApi (); + return (RtMidiApi) ((rtmidi::MidiIn*) device)->getCurrentApi (); } class CallbackProxyUserData @@ -112,17 +114,17 @@ void callback_proxy (double timeStamp, std::vector *message, void void rtmidi_in_set_callback (RtMidiInPtr device, RtMidiCCallback callback, void *userData) { void *data = (void *) new CallbackProxyUserData (callback, userData); - ((RtMidiIn*) device)->setCallback (callback_proxy, data); + device->setCallback (callback_proxy, data); } void rtmidi_in_cancel_callback (RtMidiInPtr device) { - ((RtMidiIn*) device)->cancelCallback (); + device->cancelCallback (); } void rtmidi_in_ignore_types (RtMidiInPtr device, bool midiSysex, bool midiTime, bool midiSense) { - ((RtMidiIn*) device)->ignoreTypes (midiSysex, midiTime, midiSense); + device->ignoreTypes (midiSysex, midiTime, midiSense); } double rtmidi_in_get_message (RtMidiInPtr device, unsigned char **message) @@ -130,7 +132,7 @@ double rtmidi_in_get_message (RtMidiInPtr device, unsigned char **message) try { // FIXME: use allocator to achieve efficient buffering std::vector *v = new std::vector (); - double ret = ((RtMidiIn*) device)->getMessage (v); + double ret = device->getMessage (v); *message = (unsigned char *) malloc ((int) ret); memcpy (*message, v->data (), (int) ret); delete v; @@ -143,23 +145,23 @@ double rtmidi_in_get_message (RtMidiInPtr device, unsigned char **message) /* RtMidiOut API */ RtMidiOutPtr rtmidi_out_create_default () { - return new RtMidiOut (); + return new rtmidi::MidiOut (); } RtMidiOutPtr rtmidi_out_create (enum RtMidiApi api, const char *clientName) { std::string name = clientName; - return new RtMidiOut ((RtMidi::Api) api, name); + return new rtmidi::MidiOut ((rtmidi::ApiType) api, name); } void rtmidi_out_free (RtMidiOutPtr device) { - delete (RtMidiOut*) device; + delete device; } enum RtMidiApi rtmidi_out_get_current_api (RtMidiPtr device) { - return (RtMidiApi) ((RtMidiOut*) device)->getCurrentApi (); + return (RtMidiApi) device->getCurrentApi (); } int rtmidi_out_send_message (RtMidiOutPtr device, const unsigned char *message, int length) @@ -168,7 +170,7 @@ int rtmidi_out_send_message (RtMidiOutPtr device, const unsigned char *message, // FIXME: use allocator to achieve efficient buffering std::vector *v = new std::vector (length); memcpy (v->data (), message, length); - ((RtMidiOut*) device)->sendMessage (v); + device->sendMessage (v); delete v; return 0; } catch (...) { diff --git a/rtmidi_c.h b/rtmidi_c.h index c37b655c..765ebb94 100644 --- a/rtmidi_c.h +++ b/rtmidi_c.h @@ -11,12 +11,26 @@ #endif #ifdef __cplusplus +namespace rtmidi { + class Midi; + class MidiIn; + class MidiOut; +} +typedef rtmidi::Midi CRtMidi; +typedef rtmidi::MidiIn CRtMidiIn; +typedef rtmidi::MidiOut CRtMidiOut; extern "C" { + +#else +struct CRtMidi; +struct CRtMidiIn; +struct CRtMidiOut; #endif -typedef void* RtMidiPtr; -typedef void* RtMidiInPtr; -typedef void* RtMidiOutPtr; + +typedef CRtMidi* RtMidiPtr; +typedef CRtMidiIn* RtMidiInPtr; +typedef CRtMidiOut* RtMidiOutPtr; enum RtMidiApi { RT_MIDI_API_UNSPECIFIED, /*!< Search for a working compiled API. */ @@ -25,7 +39,8 @@ typedef void* RtMidiOutPtr; RT_MIDI_API_UNIX_JACK, /*!< The Jack Low-Latency MIDI Server API. */ RT_MIDI_API_WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ RT_MIDI_API_WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ - RT_MIDI_API_RTMIDI_DUMMY /*!< A compilable but non-functional API. */ + RT_MIDI_API_RTMIDI_DUMMY, /*!< A compilable but non-functional API. */ + RT_MIDI_API_ALL_API /*!< Use all available APIs for port selection. */ }; enum RtMidiErrorType { From ced1f049d55c7ce81142243f370c8f102d301613 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 4 Aug 2018 18:11:35 +0200 Subject: [PATCH 196/210] Fix distclean --- Makefile.am | 1 + Makefile.library | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 47fc7579..e08af61f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,5 +8,6 @@ DLLPROGRAMS = $(check_PROGRAMS) check_PROGRAMS = TESTS = CLEANFILES = +DISTCLEANFILES = include %D%/Makefile.library diff --git a/Makefile.library b/Makefile.library index 9c2dcb27..1fe1a2bd 100644 --- a/Makefile.library +++ b/Makefile.library @@ -5,6 +5,11 @@ RTMIDITESTLDFLAGS = $(EXTRA_RTMIDITESTLDFLAGS) $(RTMIDILIBRARYNAME) lib_LTLIBRARIES += %D%/librtmidi@rtmidi_suffix@.la DLLPROGRAMS += %D%/librtmidi@rtmidi_suffix@.* DLLPROGRAMS += %D%/.libs/librtmidi@rtmidi_suffix@.* + +DISTCLEANFILES += \ + %D%/rtmidi@rtmidi_suffix@.pc \ + %D%/rtmidi@rtmidi_suffix@-config + %C%_librtmidi@rtmidi_suffix@_la_LDFLAGS = \ $(RTMIDI_LIBS) \ $(LDADD) \ @@ -34,7 +39,7 @@ EXTRA_DIST += \ %D%/rtmidi-config.in \ %D%/rtmidi.pc.in \ %D%/autogen.sh \ - %D%/readme \ + %D%/README.md \ %D%/msw pkgconfigdatadir = $(libdir)/pkgconfig From 172af4b82c0491a0fec6e0b03e1a7540619f61fb Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 4 Aug 2018 18:24:53 +0200 Subject: [PATCH 197/210] Fix distcheck when doxygen is not available --- doc/Makefile.am | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/Makefile.am b/doc/Makefile.am index b670116b..5cf2c0d0 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -15,10 +15,16 @@ DOC_DIR=$(HTML_DIR) all-local: doxygen-build.stamp +if MAKE_DOC doxygen-build.stamp: doxygen/$(DOX) $(top_srcdir)/RtMidi.h $(top_srcdir)/rtmidi_c.h @echo '*** Running doxygen ***' cd doxygen; $(DOXYGEN) $(DOX) touch doxygen-build.stamp +else +doxygen-build.stamp: + touch "$@" + mkdir html +endif clean-local: rm -f *~ *.bak $(DOC_STAMPS) || true From b0c3451965c2cbaaad5a4e159703245ba23e4769 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 10 Aug 2018 10:40:12 +0200 Subject: [PATCH 198/210] Upgrade boost only if necessary --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c8b8c8b6..7d4ef037 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,7 @@ addons: before_install: - eval "${MATRIX_EVAL}" - if test "$TRAVIS_OS_NAME" = osx ; then brew update ; fi - - if test "$TRAVIS_OS_NAME" = osx ; then brew upgrade boost ; fi + - if test "$TRAVIS_OS_NAME" = osx ; then if brew upgrade boost ; then echo "upgraded" ; else echo "nothing to be done"; fi ; fi - if test "$TRAVIS_OS_NAME" = osx ; then rm -rf /usr/local/include/c++ ; fi # fix broken gcc installation - if test "$TRAVIS_OS_NAME" = osx ; then brew install $EXTRA_BREW gettext flex bison libtool autoconf jack doxygen ; fi - if test "$TRAVIS_OS_NAME" = osx ; then brew link --force $EXTRA_BREW gettext flex bison libtool autoconf jack ; fi From 6b36a0dcf909230a163d1aa10e97dc62fbac35f6 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 10 Aug 2018 11:43:06 +0200 Subject: [PATCH 199/210] Use temporary objects for CFStringRef on MacOS Using temporary objects to store CFStringRef has some advantages: * Use less arguments * Avoid unnecessary copies * Automatic deallocation --- RtMidi.cpp | 77 +++++++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 1a0549c6..09a435fc 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -688,6 +688,30 @@ RTMIDI_NAMESPACE_START the parameter \ref locking. */ +/* A wrapper for temporary CFString objects */ +class CFStringWrapper { +public: + CFStringWrapper(const std::string & s): + cfname(CFStringCreateWithCStringNoCopy( NULL, + s.c_str(), + kCFStringEncodingUTF8, + kCFAllocatorNull)) + {} + CFStringWrapper(const char * s): + cfname(CFStringCreateWithCStringNoCopy( NULL, + s, + kCFStringEncodingUTF8, + kCFAllocatorNull)) + {} + ~CFStringWrapper() { + CFRelease(cfname); + } + + operator CFStringRef&() { return cfname; } +protected: + CFStringRef cfname; +}; + // This function was submitted by Douglas Casey Tucker and apparently // derived largely from PortMidi. // or copied from the Apple developer Q&A website @@ -1333,26 +1357,19 @@ class CoreSequencer { OSStatus result; switch (flags) { case PortDescriptor::INPUT: { - CFStringRef portNameRef = CFStringCreateWithCString(NULL, - portName.c_str(), - kCFStringEncodingUTF8 ); result = MIDIInputPortCreate(seq, - portNameRef, + CFStringWrapper(portName), MidiInCore::midiInputCallback, (void *)data, &port); - CFRelease(portNameRef); } break; - case PortDescriptor::OUTPUT: - CFStringRef portNameRef = CFStringCreateWithCString(NULL, - portName.c_str(), - kCFStringEncodingUTF8 ); + case PortDescriptor::OUTPUT: { result = MIDIOutputPortCreate(seq, - , + CFStringWrapper(portName), &port); - CFRelease(portNameRef); + } break; default: throw RTMIDI_ERROR(gettext_noopt("Error creating OS X MIDI port because of invalid port flags."), @@ -1374,25 +1391,21 @@ class CoreSequencer { MIDIEndpointRef port = 0; OSStatus result; switch (flags) { - case PortDescriptor::INPUT: + case PortDescriptor::INPUT: { result = MIDIDestinationCreate(seq, - CFStringCreateWithCString( - NULL, - portName.c_str(), - kCFStringEncodingUTF8 ), + CFStringWrapper(portName), MidiInCore::midiInputCallback, (void *)data, &port); + } break; - case PortDescriptor::OUTPUT: + case PortDescriptor::OUTPUT: { result = MIDISourceCreate(seq, - CFStringCreateWithCString( - NULL, - portName.c_str(), - kCFStringEncodingUTF8 ), + CFStringWrapper(portName), &port); + } break; default: throw RTMIDI_ERROR(gettext_noopt("Error creating OS X MIDI port because of invalid port flags."), @@ -1446,15 +1459,11 @@ class CoreSequencer { { scoped_lock lock(mutex); - CFStringRef cfname = CFStringCreateWithCString( NULL, - name.c_str(), - kCFStringEncodingUTF8); - OSStatus result = MIDIClientCreate(cfname, NULL, NULL, &client ); - CFRelease(cfname); + OSStatus result = MIDIClientCreate(CFStringWrapper(name), NULL, NULL, &client ); if ( result != noErr ) { - throw RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI client object (Error no: %d."), - Error::DRIVER_ERROR, - result); + throw RTMIDI_ERROR1(gettext_noopt("Error creating OS-X MIDI client object (Error no: %d)."), + Error::DRIVER_ERROR, + result); return; } } @@ -1845,7 +1854,7 @@ void MidiInCore :: openPort( unsigned int portNumber, MIDIPortRef port; CoreMidiData *data = static_cast (apiData_); OSStatus result = MIDIInputPortCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingUTF8 ), + CFStringWrapper(portName), midiInputCallback, (void *)this, &port ); if ( result != noErr ) { MIDIClientDispose( data->client ); @@ -1888,7 +1897,7 @@ void MidiInCore :: openVirtualPort( const std::string & portName ) // Create a virtual MIDI input destination. MIDIEndpointRef endpoint; OSStatus result = MIDIDestinationCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingUTF8 ), + CFStringWrapper(portName), midiInputCallback, (void *)this, &endpoint ); if ( result != noErr ) { error(RTMIDI_ERROR(gettext_noopt("Error creating virtual OS-X MIDI destination."), @@ -2099,11 +2108,9 @@ void MidiOutCore :: openPort( unsigned int portNumber, MIDIPortRef port; CoreMidiData *data = static_cast (apiData_); - CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingUTF8 ); OSStatus result = MIDIOutputPortCreate( data->client, - portNameRef, + CFStringWrapper( portName ), &port ); - CFRelease( portNameRef ); if ( result != noErr ) { MIDIClientDispose( data->client ); error(RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI output port."), @@ -2157,7 +2164,7 @@ 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(), kCFStringEncodingUTF8 ), + CFStringWrapper( portName ), &endpoint ); if ( result != noErr ) { error(RTMIDI_ERROR(gettext_noopt("Error creating OS-X virtual MIDI source."), From 8fd1c7fd0cb1f4199182f4a324d189921a6d2676 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Fri, 10 Aug 2018 14:14:57 +0200 Subject: [PATCH 200/210] Fix coremidi renaming --- configure.library | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/configure.library b/configure.library index aff59bf9..29ca75cc 100644 --- a/configure.library +++ b/configure.library @@ -224,16 +224,16 @@ dnl with_coremidi=no darwin*|*apple*) PLATFORM=macosx # Check for CoreAudio framework - with_winmm=no - with_winks=no - with_alsa=no +dnl with_winmm=no +dnl with_winks=no +dnl with_alsa=no ;; *winnt*|*interix*|cygwin*|*mingw*|uwin*) PLATFORM=windows - with_alsa=no - with_coremidi=no +dnl with_alsa=no +dnl with_coremidi=no # I can't get the following check to work so just manually add the library # or could try the following? AC_LIB_WINMM([midiOutGetNumDevs]) @@ -312,7 +312,7 @@ AC_ARG_WITH(winks, [ --with-winks = choose native Windows kernel streaming API ],[ RTMIDI_LIB_WINKS(,[true]) ]) AC_ARG_WITH(coremidi, [--with-coremidi = choose native CoreAudio API support],[ - AS_IF([test "x$with_core" = "xno"],,[RTMIDI_LIB_CORE ]) + AS_IF([test "x$with_coremidi" = "xno"],,[RTMIDI_LIB_COREMIDI ]) ],[ RTMIDI_LIB_COREMIDI(,[true]) ]) AS_IF([test "x$RTMIDI_API" = "x"],[ From fa87b8f60102d1a524407faa8c52b4a0c4f917b3 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 11 Aug 2018 11:54:28 +0200 Subject: [PATCH 201/210] Move *Api classes below the public API 1st step towards better comparability to upstream --- RtMidi.h | 1386 +++++++++++++++++++++++++++--------------------------- 1 file changed, 693 insertions(+), 693 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index 31672979..bf727137 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -333,6 +333,8 @@ using Pointer = std::shared_ptr; class MidiApi; class MidiInApi; class MidiOutApi; +typedef Pointer MidiApiPtr; +typedef std::list MidiApiList; class PortDescriptor { public: @@ -476,104 +478,183 @@ typedef void (*MidiCallback_t)( double timeStamp, std::vector *me RTMIDI_DEPRECATED(typedef MidiCallback_t MidiCallback,"RtMidi now provides a class MidiInterface for MIDI callbacks"); #define MidiCallback MidiCallback_t -// **************************************************************** // -// -// MidiInApi / MidiOutApi class declarations. -// -// Subclasses of MidiInApi and MidiOutApi contain all API- and -// OS-specific code necessary to fully implement the RtMidi API. -// -// Note that MidiInApi and MidiOutApi are abstract base classes and -// cannot be explicitly instantiated. MidiIn and MidiOut will -// create instances of a MidiInApi or MidiOutApi subclass. -// -// **************************************************************** // -#define RTMIDI_CLASSNAME "MidiApi" -class MidiApi -{ -public: +/*! \class Midi + \brief A global class that implements basic backend API handling. - MidiApi(); - virtual ~MidiApi(); + This class enhances \ref MidiApi by some functionality to handle + backend API objects. It serves as base class for the public RtMidi + API. - //! Return whether the API supports virtual ports + by Gary P. Scavone, 2003-2014. +*/ +/**********************************************************************/ +#define RTMIDI_CLASSNAME "Midi" +class Midi { +public: + //! A static function to determine the current RtMidi version. + static std::string getVersion( void ) throw(); + + //! A static function to determine the available compiled MIDI APIs. /*! - \retval true The funcion returns true if the API supports virtual ports. - \retval false The funcion returns false if the API doesn't support virtual ports. - \sa openVirtualPort + The values returned in the std::vector can be compared against + the enumerated list values. Note that there can be more than one + API compiled for certain operating systems. + + \param apis A vector apis must be provided for the + return value. All data in this vector will be + deleted prior to filling in the API data. + + \param preferSystem An opitonal boolean parameter + may be provided that tells wheter system or software + APIs shall be prefered. Passing \c true will prefer OS provided APIs */ - virtual bool hasVirtualPorts() const = 0; + static void getCompiledApi( std::vector &apis, bool preferSystem = true ) throw(); - //! Pure virtal function to create a virtual port, with optional name. + //! A static function to determine the available compiled MIDI APIs. /*! - This function creates a virtual MIDI port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, any JACK, - and Linux ALSA APIs (the function returns an error for the other APIs). + The values returned in the std::vector can be compared against + the enumerated list values. Note that there can be more than one + API compiled for certain operating systems. + */ + static std::vector getCompiledApi( ) throw() { + std::vector apis; + getCompiledApi(apis); + return apis; + } - \param portName An optional name for the applicaction port that is - used to connect to portId can be specified. + //! Returns the MIDI API specifier for the current instance of RtMidiIn. + ApiType getCurrentApi( void ) throw() + { + if (rtapi_) return rtapi_->getCurrentApi(); + else return rtmidi::UNSPECIFIED; + } - \sa hasVirtualPorts - */ - virtual void openVirtualPort( const std::string &portName = std::string( "RtMidi virtual port" ) ) = 0; - //! Pure virtual function to open a MIDI connection given by enumeration number. - /*! \param portNumber An optional port number greater than 0 - can be specified. Otherwise, the default or first port - found is opened. + //! Pure virtual function to return a port descirptor if the port is open + Pointer getDescriptor(bool local=false) + { + if (rtapi_) return rtapi_->getDescriptor(local); + return 0; + } - \param portName An optional name for the applicaction port - that will be generated to connect to portId can be - specified. + //! Return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that + describes which capabilities the returned devices + must support. The returned devices may have + additional capabilities to those which have been + requested, but not less. + + \return This function returns a list of port descriptors. + + \note Each API will request additonal + capabilites. An output API will set always add \ref + PortDescriptor::OUTPUT to the mask while an input + device will always add \ref PortDescriptor::OUTPUT. + + \note An input API may but need not necessarily + report output devices which cannot be used as input + if \ref PortDescriptor::OUTPUT is passed as \ref + capabilities parameter. */ - virtual void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi" ) ) = 0; + PortList getPortList(int capabilities = 0) + { + if (rtapi_) return rtapi_->getPortList(capabilities); + if (list && !list->empty()) { + PortList retval; + for (MidiApiList::iterator i = list->begin(); + i != list->end(); + ++i) { + PortList tmp = (*i)->getPortList(capabilities); + retval.splice(retval.end(), tmp); + } + return retval; + } + return PortList(); + } - //! Pure virtual function to open a MIDI connection given by a port descriptor. + //! Close an open MIDI connection (if one exists). + void closePort( void ) + { + if (rtapi_) rtapi_->closePort(); + } + + //! Returns true if a port is open and false if not. /*! - \param port A port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + Note that this only applies to connections made with the openPort() + function, not to virtual ports. + + \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). */ - virtual void openPort( const PortDescriptor & port, const std::string &portName = std::string( "RtMidi" ) ) = 0; + bool isPortOpen( void ) const + { + if (rtapi_) return rtapi_->isPortOpen(); + return false; + } - //! Open a MIDI connection given by a port descriptor pointer. + //! Pure virtual function to set an error callback function to be invoked when an error has occured. /*! - \param port A pointer to a port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - \sa openPort(const PortDescriptor &,const std::string &); + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. */ - void openPort( Pointer p, const std::string &portName = std::string( "RtMidi" ) ) { - if (!p) { - error(RTMIDI_ERROR( gettext_noopt("Passed NULL pointer."), - Error::INVALID_PARAMETER)); - return; + void setErrorCallback( ErrorInterface * callback) + { + if (rtapi_) rtapi_->setErrorCallback(callback); + } + + //! A basic error reporting function for RtMidi classes. + void error( Error e ); + + enum Api_t { + UNSPECIFIED = rtmidi::UNSPECIFIED, + MACOSX_CORE = rtmidi::MACOSX_CORE, + LINUX_ALSA = rtmidi::LINUX_ALSA, + UNIX_JACK = rtmidi::UNIX_JACK, + WINDOWS_MM = rtmidi::WINDOWS_MM, + RTMIDI_DUMMY = rtmidi::DUMMY + }; + + /* old functions */ + RTMIDI_DEPRECATED(typedef Api_t Api, + "enum RtMidi::Api has been replaced by enum rtmidi::ApiType"); +#define Api Api_t + RTMIDI_DEPRECATED(static void getCompiledApi( std::vector &apis, bool + preferSystem + = true ) throw(), "enum RtMidi::Api has been replaced by enum rtmidi::ApiType" ) { + std::vector api2; + Midi::getCompiledApi(api2,preferSystem); + apis.reserve(api2.size()); + size_t s = api2.size(); + for (size_t i = 0; i < s; i++) { + apis.push_back((Api)api2[i]); } - openPort(*p, portName); } - //! Pure virtual function to return a port descriptor if the port is open - /*! This function returns a port descriptor that can be used to open another port - either to the connected port or – if the backend supports it – the connecting port. - \param local The parameter local defines whether the function returns a descriptor to - the virtual port (true) or the remote port (false). The function returns 0 if the - port cannot be determined (e.g. if the port is not connected or the backend dosen't support it). - */ - virtual Pointer getDescriptor(bool local=false) = 0; + //! Compatibilty function for older code + virtual + RTMIDI_DEPRECATED(void openVirtualPort( const std::string &portName + = std::string( "RtMidi virtual port" ) ), + "For better usability you should call this function from a derived class") = 0; - //! Pure virtual function to return a list of all available ports of the current API. - /*! - \param capabilities an optional parameter that describes which - capabilities the device typu + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. - \return This function returns a list of port descriptors. + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. - \note An input API may but need not necessarily report - output devices which cannot be used as input if - \ref 0 is passed as \ref capabilities parameter. - \sa PortDescriptor::PortCapabilitiers + \deprecated */ - virtual PortList getPortList(int capabilities = 0) = 0; + RTMIDI_DEPRECATED(void openPort( unsigned int portNumber = 0, + const std::string &portName = std::string( "RtMidi" ) + ),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)") + { + if (rtapi_) rtapi_->openPort(portNumber,portName); + } //! Pure virtual to return the number of available MIDI ports of the current API. /*! @@ -585,8 +666,13 @@ class MidiApi and vice versa. \sa getPortName + \deprecated */ - virtual unsigned int getPortCount() = 0; + RTMIDI_DEPRECATED(unsigned int getPortCount(),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)") + { + if (rtapi_) return rtapi_->getPortCount(); + return 0; + } //! Pure virtual function to return a string identifier for the specified MIDI port number. /*! @@ -599,387 +685,15 @@ class MidiApi and vice versa. \sa getPortCount() + \deprecated */ - virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; - - //! Pure virtual function to close an open MIDI connection (if one exists). - virtual void closePort( void ) = 0; - - // ! A basic error reporting function for RtMidi classes. - // static void error( Error::Type type, std::string &errorString ); - - //! Pure virtual function to return whether a port is open or not. - /*! \retval true if a port is open and - \retval false if the port is not open (e.g. not opend or closed). - */ - bool isPortOpen() const { return connected_; } - + RTMIDI_DEPRECATED(std::string getPortName( unsigned int portNumber = 0 ),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)") + { + if (rtapi_) return rtapi_->getPortName(portNumber); + return ""; + } - //! Virtual function to set the error callback object - /*! - Everytime an error is detected or a warning is issued the function - \r ErrorInterface::rtmidi_error of the callback object is called with an error object - that describes the situation. - - \param callback An objact that provides an ErrorInterface. - */ - virtual void setErrorCallback(ErrorInterface * callback); - - - //! Returns the MIDI API specifier for the current instance of RtMidiIn. - virtual ApiType getCurrentApi( void ) throw() = 0; - - //! A basic error reporting function for RtMidi classes. - /*! This function hanles errors end warnings that - occur during runtime of RtMidi. If an error callback - has been set the function calls the callback and - returns quietly assuming the callback handled the - case correctly. - - Otherwise it depends on the type of the error. If it - is a warning, a message is displayed to - std::cerr. If it is an error the object is thrown as - an exception. - - \param e Error/Warning object describing the current - situation. - - \throw Error - */ - void error( Error e ); - - - //! Virtual function to set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. - */ - RTMIDI_DEPRECATED(virtual void setErrorCallback( ErrorCallback errorCallback = NULL, void * userData = 0 ), "RtMidi now provides a typesafe ErrorInterface class"); - -protected: - virtual void initialize( const std::string &clientName ) = 0; - - void *apiData_; - bool connected_; - bool firstErrorOccurred_; - std::string errorString_; - ErrorInterface * errorCallback_; -}; -#undef RTMIDI_CLASSNAME - -#define RTMIDI_CLASSNAME "MidiInApi" -class MidiInApi : public MidiApi -{ -public: - - MidiInApi( unsigned int queueSizeLimit ); - virtual ~MidiInApi( void ); - void setCallback( MidiInterface * callback); - void cancelCallback( void ); - virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); - double getMessage( std::vector &message ); - - // A MIDI structure used internally by the class to store incoming - // messages. Each message represents one and only one MIDI message. - struct MidiMessage { - std::vector bytes; - //! Time in seconds elapsed since the previous message - double timeStamp; - - // Default constructor. - MidiMessage() - :bytes(0), timeStamp(0.0) {} - }; - - struct MidiQueue { - unsigned int front; - unsigned int back; - unsigned int ringSize; - MidiMessage *ring; - - // Default constructor. - MidiQueue() - :front(0), back(0), ringSize(0), ring(0) {} - bool push(const MidiMessage&); - bool pop(std::vector& message, double& timestamp); - unsigned int size(unsigned int *back=0, - unsigned int *front=0); - }; - - - - RTMIDI_DEPRECATED(void setCallback( MidiCallback callback, void *userData = 0 ), - "RtMidi now provides a type-safe MidiInterface class."); - RTMIDI_DEPRECATED(double getMessage( std::vector *message ), - "Please, use a C++ style reference to pass the message vector.") - { - if (!message) { - error( RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), - Error::WARNING )); - } - return getMessage(*message); - } - -protected: - // The RtMidiInData structure is used to pass private class data to - // the MIDI input handling function or thread. - MidiQueue queue; - MidiMessage message; - unsigned char ignoreFlags; - bool doInput; - bool firstMessage; - MidiInterface * userCallback; - bool continueSysex; - friend struct JackBackendCallbacks; -}; -#undef RTMIDI_CLASSNAME - -#define RTMIDI_CLASSNAME "MidiOutApi" -class MidiOutApi : public MidiApi -{ -public: - - MidiOutApi( void ); - virtual ~MidiOutApi( void ); - virtual void sendMessage( const unsigned char *message, size_t size ) = 0; - void sendMessage( const std::vector &message ) - { - if (message.empty()) { - error( RTMIDI_ERROR(gettext_noopt("No data in message argument."), - Error::WARNING)); - } - sendMessage(message.data(),message.size()); - } - RTMIDI_DEPRECATED(void sendMessage( const std::vector *message ), - "Please, use a C++ style reference to pass the message vector.") - { - if (!message) { - error( RTMIDI_ERROR(gettext_noopt("No data in message argument."), - Error::WARNING)); - } - sendMessage(*message); - } -}; -#undef RTMIDI_CLASSNAME - -typedef Pointer MidiApiPtr; -typedef std::list MidiApiList; - -/*! \class Midi - \brief A global class that implements basic backend API handling. - - This class enhances \ref MidiApi by some functionality to handle - backend API objects. It serves as base class for the public RtMidi - API. - - by Gary P. Scavone, 2003-2014. -*/ -/**********************************************************************/ -#define RTMIDI_CLASSNAME "Midi" -class Midi { -public: - //! A static function to determine the current RtMidi version. - static std::string getVersion( void ) throw(); - - //! A static function to determine the available compiled MIDI APIs. - /*! - The values returned in the std::vector can be compared against - the enumerated list values. Note that there can be more than one - API compiled for certain operating systems. - - \param apis A vector apis must be provided for the - return value. All data in this vector will be - deleted prior to filling in the API data. - - \param preferSystem An opitonal boolean parameter - may be provided that tells wheter system or software - APIs shall be prefered. Passing \c true will prefer OS provided APIs - */ - static void getCompiledApi( std::vector &apis, bool preferSystem = true ) throw(); - - //! A static function to determine the available compiled MIDI APIs. - /*! - The values returned in the std::vector can be compared against - the enumerated list values. Note that there can be more than one - API compiled for certain operating systems. - */ - static std::vector getCompiledApi( ) throw() { - std::vector apis; - getCompiledApi(apis); - return apis; - } - - //! Returns the MIDI API specifier for the current instance of RtMidiIn. - ApiType getCurrentApi( void ) throw() - { - if (rtapi_) return rtapi_->getCurrentApi(); - else return rtmidi::UNSPECIFIED; - } - - - //! Pure virtual function to return a port descirptor if the port is open - Pointer getDescriptor(bool local=false) - { - if (rtapi_) return rtapi_->getDescriptor(local); - return 0; - } - - //! Return a list of all available ports of the current API. - /*! - \param capabilities an optional parameter that - describes which capabilities the returned devices - must support. The returned devices may have - additional capabilities to those which have been - requested, but not less. - - \return This function returns a list of port descriptors. - - \note Each API will request additonal - capabilites. An output API will set always add \ref - PortDescriptor::OUTPUT to the mask while an input - device will always add \ref PortDescriptor::OUTPUT. - - \note An input API may but need not necessarily - report output devices which cannot be used as input - if \ref PortDescriptor::OUTPUT is passed as \ref - capabilities parameter. - */ - PortList getPortList(int capabilities = 0) - { - if (rtapi_) return rtapi_->getPortList(capabilities); - if (list && !list->empty()) { - PortList retval; - for (MidiApiList::iterator i = list->begin(); - i != list->end(); - ++i) { - PortList tmp = (*i)->getPortList(capabilities); - retval.splice(retval.end(), tmp); - } - return retval; - } - return PortList(); - } - - //! Close an open MIDI connection (if one exists). - void closePort( void ) - { - if (rtapi_) rtapi_->closePort(); - } - - //! Returns true if a port is open and false if not. - /*! - Note that this only applies to connections made with the openPort() - function, not to virtual ports. - - \retval true if a port is open and - \retval false if the port is not open (e.g. not opend or closed). - */ - bool isPortOpen( void ) const - { - if (rtapi_) return rtapi_->isPortOpen(); - return false; - } - - //! Pure virtual function to set an error callback function to be invoked when an error has occured. - /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. - */ - void setErrorCallback( ErrorInterface * callback) - { - if (rtapi_) rtapi_->setErrorCallback(callback); - } - - //! A basic error reporting function for RtMidi classes. - void error( Error e ); - - enum Api_t { - UNSPECIFIED = rtmidi::UNSPECIFIED, - MACOSX_CORE = rtmidi::MACOSX_CORE, - LINUX_ALSA = rtmidi::LINUX_ALSA, - UNIX_JACK = rtmidi::UNIX_JACK, - WINDOWS_MM = rtmidi::WINDOWS_MM, - RTMIDI_DUMMY = rtmidi::DUMMY - }; - - /* old functions */ - RTMIDI_DEPRECATED(typedef Api_t Api, - "enum RtMidi::Api has been replaced by enum rtmidi::ApiType"); -#define Api Api_t - RTMIDI_DEPRECATED(static void getCompiledApi( std::vector &apis, bool - preferSystem - = true ) throw(), "enum RtMidi::Api has been replaced by enum rtmidi::ApiType" ) { - std::vector api2; - Midi::getCompiledApi(api2,preferSystem); - apis.reserve(api2.size()); - size_t s = api2.size(); - for (size_t i = 0; i < s; i++) { - apis.push_back((Api)api2[i]); - } - } - - //! Compatibilty function for older code - virtual - RTMIDI_DEPRECATED(void openVirtualPort( const std::string &portName - = std::string( "RtMidi virtual port" ) ), - "For better usability you should call this function from a derived class") = 0; - - //! Pure virtual function to open a MIDI connection given by enumeration number. - /*! \param portNumber An optional port number greater than 0 - can be specified. Otherwise, the default or first port - found is opened. - - \param portName An optional name for the applicaction port - that will be generated to connect to portId can be - specified. - - \deprecated - */ - RTMIDI_DEPRECATED(void openPort( unsigned int portNumber = 0, - const std::string &portName = std::string( "RtMidi" ) - ),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)") - { - if (rtapi_) rtapi_->openPort(portNumber,portName); - } - - //! Pure virtual to return the number of available MIDI ports of the current API. - /*! - \return This function returns the number of MIDI ports of - the selected API. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortName - \deprecated - */ - RTMIDI_DEPRECATED(unsigned int getPortCount(),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)") - { - if (rtapi_) return rtapi_->getPortCount(); - return 0; - } - - //! Pure virtual function to return a string identifier for the specified MIDI port number. - /*! - \param portNumber Number of the device to be referred to. - \return The name of the port with the given Id is returned. - \retval An empty string is returned if an invalid port specifier is provided. - - \note Only ports are counted that can be used with the - current API so an input API does ignore all output devices - and vice versa. - - \sa getPortCount() - \deprecated - */ - RTMIDI_DEPRECATED(std::string getPortName( unsigned int portNumber = 0 ),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)") - { - if (rtapi_) return rtapi_->getPortName(portNumber); - return ""; - } - - //! Pure virtual function to set an error callback function to be invoked when an error has occured. + //! Pure virtual function to set an error callback function to be invoked when an error has occured. /*! The callback function will be called whenever an error has occured. It is best to set the error callback function before opening a port. @@ -1138,7 +852,262 @@ class MidiIn : public Midi \param portName An optional name for the application port that is used to connect to portId can be specified. */ - void openVirtualPort( const std::string &portName = std::string( "RtMidi virtual input port" ) ) + void openVirtualPort( const std::string &portName = std::string( "RtMidi virtual input port" ) ) + { + if (!rtapi_ && list && !list->empty()) { + Pointer api = list->front(); + + std::vector< ApiType > apis; + getCompiledApi( apis ); + for (size_t i = 0 ; i < apis.size() ; i++) { + openMidiApi( apis[0] ); + if (rtapi_ && rtapi_->hasVirtualPorts()) break; + } + } + + if (rtapi_) rtapi_->openVirtualPort(portName); + else { + error(RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), + Error::INVALID_DEVICE)); + } + } + + //! Return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that + describes which capabilities the returned devices + must support. The returned devices may have + additional capabilities to those which have been + requested, but not less. + + \return This function returns a list of port descriptors. + + \note Each API will request additonal + capabilites. An output API will set always add \ref + PortDescriptor::OUTPUT to the mask while an input + device will always add \ref PortDescriptor::OUTPUT. + + \note An input API may but need not necessarily + report output devices which cannot be used as input + if \ref PortDescriptor::OUTPUT is passed as \ref + capabilities parameter. + */ + PortList getPortList(int capabilities = PortDescriptor::INPUT) { + return Midi::getPortList(capabilities); + } + + + + //! Set a callback function to be invoked for incoming MIDI messages. + /*! + The callback function will be called whenever an incoming MIDI + message is received. While not absolutely necessary, it is best + to set the callback function before opening a MIDI port to avoid + leaving some messages in the queue. + + \param callback A callback function must be given. + \param userData Opitionally, a pointer to additional data can be + passed to the callback function whenever it is called. + */ + void setCallback( MidiInterface * callback ) + { + if (rtapi_) + static_cast(rtapi_)->setCallback(callback); + } + + //! Cancel use of the current callback function (if one exists). + /*! + Subsequent incoming MIDI messages will be written to the queue + and can be retrieved with the \e getMessage function. + */ + void cancelCallback() + { + if (rtapi_) + static_cast(rtapi_)->cancelCallback(); + } + + //! Specify whether certain MIDI message types should be queued or ignored during input. + /*! + By default, MIDI timing and active sensing messages are ignored + during message input because of their relative high data rates. + MIDI sysex messages are ignored by default as well. Variable + values of "true" imply that the respective message type will be + ignored. + */ + void ignoreTypes( bool midiSysex = true, + bool midiTime = true, + bool midiSense = true ) + { + if (rtapi_) + static_cast(rtapi_)->ignoreTypes(midiSysex, midiTime, midiSense); + } + + //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. + /*! + This function returns immediately whether a new message is + available or not. A valid message is indicated by a non-zero + vector size. An exception is thrown if an error occurs during + message retrieval or an input connection was not previously + established. + */ + double getMessage( std::vector &message ) + { + if (rtapi_) + return static_cast(rtapi_)->getMessage(message); + error( RTMIDI_ERROR(gettext_noopt("Could not find any valid MIDI system."), + Error::WARNING)); + return 0.0; + } + + + //! Set a callback function to be invoked for incoming MIDI messages. + /*! + The callback function will be called whenever an incoming MIDI + message is received. While not absolutely necessary, it is best + to set the callback function before opening a MIDI port to avoid + leaving some messages in the queue. + + \param callback A callback function must be given. + \param userData Opitionally, a pointer to additional data can be + passed to the callback function whenever it is called. + */ + RTMIDI_DEPRECATED(void setCallback( MidiCallback callback, void *userData = 0 ), + "RtMidi now provides a type-safe MidiInterface class.") + { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + if (rtapi_) + static_cast(rtapi_)->setCallback(callback,userData); +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + } + //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. + /*! + This function returns immediately whether a new message is + available or not. A valid message is indicated by a non-zero + vector size. An exception is thrown if an error occurs during + message retrieval or an input connection was not previously + established. + + \deprecated + */ + RTMIDI_DEPRECATED(double getMessage( std::vector *message ), + "Please, use a C++ style reference to pass the message vector.") + { + if (!message) { + error( RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), + Error::WARNING)); + } + if (rtapi_) + return static_cast(rtapi_)->getMessage(*message); + error( RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been found."), + Error::WARNING)); + return 0.0; + } +protected: + static MidiApiList queryApis; + int queueSizeLimit; + void openMidiApi( ApiType api ); + +}; +#undef RTMIDI_CLASSNAME + +/**********************************************************************/ +/*! \class MidiOut + \brief A realtime MIDI output class. + + This class provides a common, platform-independent API for MIDI + output. It allows one to probe available MIDI output ports, to + connect to one such port, and to send MIDI bytes immediately over + the connection. Create multiple instances of this class to + 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-2017. +*/ +/**********************************************************************/ + +#define RTMIDI_CLASSNAME "MidiOut" +class MidiOut : public Midi +{ +public: + + //! Default constructor that allows an optional client name. + /*! + An exception will be thrown if a MIDI system initialization error occurs. + + If no API argument is specified and multiple API support has been + compiled, the default order of use is JACK, ALSA (Linux) and CORE, + JACK (OS-X). + + \param api An optional API id can be specified. + \param clientName An optional Client name can be specified. This + will be used to group the ports that are created + by the application. + \param queueSizeLimit An optional size of the MIDI input queue can be specified. + + \param pfsystem An optional boolean parameter can be + provided to indicate the API preferences of the user + code. If RtMidi is requested to autoselect a backend + this parameter tells which backend should be tried + first. If it is \c true the backend will prefer OS + provieded APIs (WinMM, ALSA, Core MIDI) over other + APIs (JACK). If \c false, the order will be vice + versa. + */ + MidiOut( ApiType api=rtmidi::UNSPECIFIED, + const std::string &clientName = std::string( "RtMidi Output Client"), + bool pfsystem = true); + + //! The destructor closes any open MIDI connections. + ~MidiOut( void ) throw(); + + using Midi::openPort; + + //! Open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + void openPort( const PortDescriptor & port, + const std::string &portName = std::string( "RtMidi" ) ) + { + if (!rtapi_) rtapi_ = port.getOutputApi(); + if (rtapi_) rtapi_->openPort(port,portName); + } + + //! Open a MIDI connection given by a port descriptor pointer. + /*! + \param port A pointer to a port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + \sa openPort(const PortDescriptor &,const std::string &); + */ + void openPort( Pointer p, + const std::string &portName = std::string( "RtMidi" ) ) { + if (!p) { + error(RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), + Error::INVALID_PARAMETER)); + return; + } + openPort(*p, portName); + } + + + //! Function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + */ + void openVirtualPort( const std::string &portName = std::string( "RtMidi virtual output port" ) ) { if (!rtapi_ && list && !list->empty()) { Pointer api = list->front(); @@ -1178,312 +1147,343 @@ class MidiIn : public Midi if \ref PortDescriptor::OUTPUT is passed as \ref capabilities parameter. */ - PortList getPortList(int capabilities = PortDescriptor::INPUT) { + PortList getPortList(int capabilities = PortDescriptor::OUTPUT) { return Midi::getPortList(capabilities); } - - - //! Set a callback function to be invoked for incoming MIDI messages. + //! Immediately send a single message out an open MIDI output port. /*! - The callback function will be called whenever an incoming MIDI - message is received. While not absolutely necessary, it is best - to set the callback function before opening a MIDI port to avoid - leaving some messages in the queue. + An exception is thrown if an error occurs during output or an + output connection was not previously established. - \param callback A callback function must be given. - \param userData Opitionally, a pointer to additional data can be - passed to the callback function whenever it is called. + \deprecated */ - void setCallback( MidiInterface * callback ) + RTMIDI_DEPRECATED(void sendMessage( const std::vector *message ), + "Please, use a C++ style reference to pass the message vector.") { - if (rtapi_) - static_cast(rtapi_)->setCallback(callback); + sendMessage(*message); } - //! Cancel use of the current callback function (if one exists). + + //! Immediately send a single message out an open MIDI output port. /*! - Subsequent incoming MIDI messages will be written to the queue - and can be retrieved with the \e getMessage function. + An exception is thrown if an error occurs during output or an + output connection was not previously established. */ - void cancelCallback() - { - if (rtapi_) - static_cast(rtapi_)->cancelCallback(); - } - //! Specify whether certain MIDI message types should be queued or ignored during input. + void sendMessage(const std::vector &message ) { + sendMessage(message.data(), message.size()); + } + //! Immediately send a single message out an open MIDI output port. /*! - By default, MIDI timing and active sensing messages are ignored - during message input because of their relative high data rates. - MIDI sysex messages are ignored by default as well. Variable - values of "true" imply that the respective message type will be - ignored. + An exception is thrown if an error occurs during output or an + output connection was not previously established. + + \param message A pointer to the MIDI message as raw bytes + \param size Length of the MIDI message in bytes */ - void ignoreTypes( bool midiSysex = true, - bool midiTime = true, - bool midiSense = true ) - { + void sendMessage( const unsigned char *message, size_t size ) { + if (!message) { + error( RTMIDI_ERROR(gettext_noopt("No data in MIDI message."), + Error::WARNING)); + } if (rtapi_) - static_cast(rtapi_)->ignoreTypes(midiSysex, midiTime, midiSense); + static_cast(rtapi_)->sendMessage(message,size); + else + error( RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), + Error::WARNING)); } - //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. +protected: + static MidiApiList queryApis; + void openMidiApi( ApiType api ); + bool firstErrorOccurred_; +}; +#undef RTMIDI_CLASSNAME + +// **************************************************************** // +// +// MidiInApi / MidiOutApi class declarations. +// +// Subclasses of MidiInApi and MidiOutApi contain all API- and +// OS-specific code necessary to fully implement the RtMidi API. +// +// Note that MidiInApi and MidiOutApi are abstract base classes and +// cannot be explicitly instantiated. MidiIn and MidiOut will +// create instances of a MidiInApi or MidiOutApi subclass. +// +// **************************************************************** // + +#define RTMIDI_CLASSNAME "MidiApi" +class MidiApi +{ +public: + + MidiApi(); + virtual ~MidiApi(); + + //! Return whether the API supports virtual ports /*! - This function returns immediately whether a new message is - available or not. A valid message is indicated by a non-zero - vector size. An exception is thrown if an error occurs during - message retrieval or an input connection was not previously - established. + \retval true The funcion returns true if the API supports virtual ports. + \retval false The funcion returns false if the API doesn't support virtual ports. + \sa openVirtualPort */ - double getMessage( std::vector &message ) - { - if (rtapi_) - return static_cast(rtapi_)->getMessage(message); - error( RTMIDI_ERROR(gettext_noopt("Could not find any valid MIDI system."), - Error::WARNING)); - return 0.0; - } - + virtual bool hasVirtualPorts() const = 0; - //! Set a callback function to be invoked for incoming MIDI messages. + //! Pure virtal function to create a virtual port, with optional name. /*! - The callback function will be called whenever an incoming MIDI - message is received. While not absolutely necessary, it is best - to set the callback function before opening a MIDI port to avoid - leaving some messages in the queue. + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). - \param callback A callback function must be given. - \param userData Opitionally, a pointer to additional data can be - passed to the callback function whenever it is called. + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + + \sa hasVirtualPorts */ - RTMIDI_DEPRECATED(void setCallback( MidiCallback callback, void *userData = 0 ), - "RtMidi now provides a type-safe MidiInterface class.") - { -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - if (rtapi_) - static_cast(rtapi_)->setCallback(callback,userData); -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - } - //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. + virtual void openVirtualPort( const std::string &portName = std::string( "RtMidi virtual port" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. + + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. + */ + virtual void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by a port descriptor. /*! - This function returns immediately whether a new message is - available or not. A valid message is indicated by a non-zero - vector size. An exception is thrown if an error occurs during - message retrieval or an input connection was not previously - established. + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + virtual void openPort( const PortDescriptor & port, const std::string &portName = std::string( "RtMidi" ) ) = 0; - \deprecated + //! Open a MIDI connection given by a port descriptor pointer. + /*! + \param port A pointer to a port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + \sa openPort(const PortDescriptor &,const std::string &); */ - RTMIDI_DEPRECATED(double getMessage( std::vector *message ), - "Please, use a C++ style reference to pass the message vector.") - { - if (!message) { - error( RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), - Error::WARNING)); + void openPort( Pointer p, const std::string &portName = std::string( "RtMidi" ) ) { + if (!p) { + error(RTMIDI_ERROR( gettext_noopt("Passed NULL pointer."), + Error::INVALID_PARAMETER)); + return; } - if (rtapi_) - return static_cast(rtapi_)->getMessage(*message); - error( RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been found."), - Error::WARNING)); - return 0.0; + openPort(*p, portName); } -protected: - static MidiApiList queryApis; - int queueSizeLimit; - void openMidiApi( ApiType api ); -}; -#undef RTMIDI_CLASSNAME + //! Pure virtual function to return a port descriptor if the port is open + /*! This function returns a port descriptor that can be used to open another port + either to the connected port or – if the backend supports it – the connecting port. + \param local The parameter local defines whether the function returns a descriptor to + the virtual port (true) or the remote port (false). The function returns 0 if the + port cannot be determined (e.g. if the port is not connected or the backend dosen't support it). + */ + virtual Pointer getDescriptor(bool local=false) = 0; -/**********************************************************************/ -/*! \class MidiOut - \brief A realtime MIDI output class. + //! Pure virtual function to return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that describes which + capabilities the device typu - This class provides a common, platform-independent API for MIDI - output. It allows one to probe available MIDI output ports, to - connect to one such port, and to send MIDI bytes immediately over - the connection. Create multiple instances of this class to - 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. + \return This function returns a list of port descriptors. + + \note An input API may but need not necessarily report + output devices which cannot be used as input if + \ref 0 is passed as \ref capabilities parameter. + \sa PortDescriptor::PortCapabilitiers + */ + virtual PortList getPortList(int capabilities = 0) = 0; + + //! Pure virtual to return the number of available MIDI ports of the current API. + /*! + \return This function returns the number of MIDI ports of + the selected API. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortName + */ + virtual unsigned int getPortCount() = 0; + + //! Pure virtual function to return a string identifier for the specified MIDI port number. + /*! + \param portNumber Number of the device to be referred to. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortCount() + */ + virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; + + //! Pure virtual function to close an open MIDI connection (if one exists). + virtual void closePort( void ) = 0; - by Gary P. Scavone, 2003-2017. -*/ -/**********************************************************************/ + // ! A basic error reporting function for RtMidi classes. + // static void error( Error::Type type, std::string &errorString ); -#define RTMIDI_CLASSNAME "MidiOut" -class MidiOut : public Midi -{ -public: + //! Pure virtual function to return whether a port is open or not. + /*! \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). + */ + bool isPortOpen() const { return connected_; } - //! Default constructor that allows an optional client name. + + //! Virtual function to set the error callback object /*! - An exception will be thrown if a MIDI system initialization error occurs. + Everytime an error is detected or a warning is issued the function + \r ErrorInterface::rtmidi_error of the callback object is called with an error object + that describes the situation. - If no API argument is specified and multiple API support has been - compiled, the default order of use is JACK, ALSA (Linux) and CORE, - JACK (OS-X). + \param callback An objact that provides an ErrorInterface. + */ + virtual void setErrorCallback(ErrorInterface * callback); - \param api An optional API id can be specified. - \param clientName An optional Client name can be specified. This - will be used to group the ports that are created - by the application. - \param queueSizeLimit An optional size of the MIDI input queue can be specified. - \param pfsystem An optional boolean parameter can be - provided to indicate the API preferences of the user - code. If RtMidi is requested to autoselect a backend - this parameter tells which backend should be tried - first. If it is \c true the backend will prefer OS - provieded APIs (WinMM, ALSA, Core MIDI) over other - APIs (JACK). If \c false, the order will be vice - versa. - */ - MidiOut( ApiType api=rtmidi::UNSPECIFIED, - const std::string &clientName = std::string( "RtMidi Output Client"), - bool pfsystem = true); + //! Returns the MIDI API specifier for the current instance of RtMidiIn. + virtual ApiType getCurrentApi( void ) throw() = 0; - //! The destructor closes any open MIDI connections. - ~MidiOut( void ) throw(); + //! A basic error reporting function for RtMidi classes. + /*! This function hanles errors end warnings that + occur during runtime of RtMidi. If an error callback + has been set the function calls the callback and + returns quietly assuming the callback handled the + case correctly. - using Midi::openPort; + Otherwise it depends on the type of the error. If it + is a warning, a message is displayed to + std::cerr. If it is an error the object is thrown as + an exception. - //! Open a MIDI connection given by a port descriptor. - /*! - \param port A port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + \param e Error/Warning object describing the current + situation. + + \throw Error */ - void openPort( const PortDescriptor & port, - const std::string &portName = std::string( "RtMidi" ) ) - { - if (!rtapi_) rtapi_ = port.getOutputApi(); - if (rtapi_) rtapi_->openPort(port,portName); - } + void error( Error e ); - //! Open a MIDI connection given by a port descriptor pointer. + + //! Virtual function to set an error callback function to be invoked when an error has occured. /*! - \param port A pointer to a port descriptor of the port must be specified. - \param portName An optional name for the applicaction port that is used to connect to portId can be specified. - \sa openPort(const PortDescriptor &,const std::string &); + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. */ - void openPort( Pointer p, - const std::string &portName = std::string( "RtMidi" ) ) { - if (!p) { - error(RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), - Error::INVALID_PARAMETER)); - return; - } - openPort(*p, portName); - } + RTMIDI_DEPRECATED(virtual void setErrorCallback( ErrorCallback errorCallback = NULL, void * userData = 0 ), "RtMidi now provides a typesafe ErrorInterface class"); +protected: + virtual void initialize( const std::string &clientName ) = 0; - //! Function to create a virtual port, with optional name. - /*! - This function creates a virtual MIDI port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, any JACK, - and Linux ALSA APIs (the function returns an error for the other APIs). + void *apiData_; + bool connected_; + bool firstErrorOccurred_; + std::string errorString_; + ErrorInterface * errorCallback_; +}; +#undef RTMIDI_CLASSNAME - \param portName An optional name for the applicaction port that is - used to connect to portId can be specified. - */ - void openVirtualPort( const std::string &portName = std::string( "RtMidi virtual output port" ) ) - { - if (!rtapi_ && list && !list->empty()) { - Pointer api = list->front(); +#define RTMIDI_CLASSNAME "MidiInApi" +class MidiInApi : public MidiApi +{ +public: - std::vector< ApiType > apis; - getCompiledApi( apis ); - for (size_t i = 0 ; i < apis.size() ; i++) { - openMidiApi( apis[0] ); - if (rtapi_ && rtapi_->hasVirtualPorts()) break; - } - } + MidiInApi( unsigned int queueSizeLimit ); + virtual ~MidiInApi( void ); + void setCallback( MidiInterface * callback); + void cancelCallback( void ); + virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); + double getMessage( std::vector &message ); - if (rtapi_) rtapi_->openVirtualPort(portName); - else { - error(RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), - Error::INVALID_DEVICE)); - } - } + // A MIDI structure used internally by the class to store incoming + // messages. Each message represents one and only one MIDI message. + struct MidiMessage { + std::vector bytes; + //! Time in seconds elapsed since the previous message + double timeStamp; - //! Return a list of all available ports of the current API. - /*! - \param capabilities an optional parameter that - describes which capabilities the returned devices - must support. The returned devices may have - additional capabilities to those which have been - requested, but not less. + // Default constructor. + MidiMessage() + :bytes(0), timeStamp(0.0) {} + }; - \return This function returns a list of port descriptors. + struct MidiQueue { + unsigned int front; + unsigned int back; + unsigned int ringSize; + MidiMessage *ring; - \note Each API will request additonal - capabilites. An output API will set always add \ref - PortDescriptor::OUTPUT to the mask while an input - device will always add \ref PortDescriptor::OUTPUT. + // Default constructor. + MidiQueue() + :front(0), back(0), ringSize(0), ring(0) {} + bool push(const MidiMessage&); + bool pop(std::vector& message, double& timestamp); + unsigned int size(unsigned int *back=0, + unsigned int *front=0); + }; - \note An input API may but need not necessarily - report output devices which cannot be used as input - if \ref PortDescriptor::OUTPUT is passed as \ref - capabilities parameter. - */ - PortList getPortList(int capabilities = PortDescriptor::OUTPUT) { - return Midi::getPortList(capabilities); - } - //! Immediately send a single message out an open MIDI output port. - /*! - An exception is thrown if an error occurs during output or an - output connection was not previously established. - \deprecated - */ - RTMIDI_DEPRECATED(void sendMessage( const std::vector *message ), + RTMIDI_DEPRECATED(void setCallback( MidiCallback callback, void *userData = 0 ), + "RtMidi now provides a type-safe MidiInterface class."); + RTMIDI_DEPRECATED(double getMessage( std::vector *message ), "Please, use a C++ style reference to pass the message vector.") { - sendMessage(*message); + if (!message) { + error( RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), + Error::WARNING )); + } + return getMessage(*message); } +protected: + // The RtMidiInData structure is used to pass private class data to + // the MIDI input handling function or thread. + MidiQueue queue; + MidiMessage message; + unsigned char ignoreFlags; + bool doInput; + bool firstMessage; + MidiInterface * userCallback; + bool continueSysex; + friend struct JackBackendCallbacks; +}; +#undef RTMIDI_CLASSNAME - //! Immediately send a single message out an open MIDI output port. - /*! - An exception is thrown if an error occurs during output or an - output connection was not previously established. - */ +#define RTMIDI_CLASSNAME "MidiOutApi" +class MidiOutApi : public MidiApi +{ +public: - void sendMessage(const std::vector &message ) { - sendMessage(message.data(), message.size()); + MidiOutApi( void ); + virtual ~MidiOutApi( void ); + virtual void sendMessage( const unsigned char *message, size_t size ) = 0; + void sendMessage( const std::vector &message ) + { + if (message.empty()) { + error( RTMIDI_ERROR(gettext_noopt("No data in message argument."), + Error::WARNING)); + } + sendMessage(message.data(),message.size()); } - //! Immediately send a single message out an open MIDI output port. - /*! - An exception is thrown if an error occurs during output or an - output connection was not previously established. - - \param message A pointer to the MIDI message as raw bytes - \param size Length of the MIDI message in bytes - */ - void sendMessage( const unsigned char *message, size_t size ) { + RTMIDI_DEPRECATED(void sendMessage( const std::vector *message ), + "Please, use a C++ style reference to pass the message vector.") + { if (!message) { - error( RTMIDI_ERROR(gettext_noopt("No data in MIDI message."), + error( RTMIDI_ERROR(gettext_noopt("No data in message argument."), Error::WARNING)); } - if (rtapi_) - static_cast(rtapi_)->sendMessage(message,size); - else - error( RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), - Error::WARNING)); + sendMessage(*message); } - -protected: - static MidiApiList queryApis; - void openMidiApi( ApiType api ); - bool firstErrorOccurred_; }; #undef RTMIDI_CLASSNAME From 9b13e2a69cc497f10f34404b95b9c444aed654ba Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 11 Aug 2018 11:56:03 +0200 Subject: [PATCH 202/210] Move inline implementations of the public API classes after *Api This matches the layout of upstream RtMidi.h. --- RtMidi.h | 457 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 245 insertions(+), 212 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index bf727137..6298a0c8 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -517,26 +517,14 @@ class Midi { the enumerated list values. Note that there can be more than one API compiled for certain operating systems. */ - static std::vector getCompiledApi( ) throw() { - std::vector apis; - getCompiledApi(apis); - return apis; - } + static std::vector getCompiledApi( ) throw(); - //! Returns the MIDI API specifier for the current instance of RtMidiIn. - ApiType getCurrentApi( void ) throw() - { - if (rtapi_) return rtapi_->getCurrentApi(); - else return rtmidi::UNSPECIFIED; - } + //! Returns the MIDI API specifier for the current instance of rtmidi::MidiIn. + ApiType getCurrentApi( void ) throw(); //! Pure virtual function to return a port descirptor if the port is open - Pointer getDescriptor(bool local=false) - { - if (rtapi_) return rtapi_->getDescriptor(local); - return 0; - } + Pointer getDescriptor(bool local=false); //! Return a list of all available ports of the current API. /*! @@ -558,27 +546,10 @@ class Midi { if \ref PortDescriptor::OUTPUT is passed as \ref capabilities parameter. */ - PortList getPortList(int capabilities = 0) - { - if (rtapi_) return rtapi_->getPortList(capabilities); - if (list && !list->empty()) { - PortList retval; - for (MidiApiList::iterator i = list->begin(); - i != list->end(); - ++i) { - PortList tmp = (*i)->getPortList(capabilities); - retval.splice(retval.end(), tmp); - } - return retval; - } - return PortList(); - } + PortList getPortList(int capabilities = 0); //! Close an open MIDI connection (if one exists). - void closePort( void ) - { - if (rtapi_) rtapi_->closePort(); - } + void closePort( void ); //! Returns true if a port is open and false if not. /*! @@ -588,21 +559,14 @@ class Midi { \retval true if a port is open and \retval false if the port is not open (e.g. not opend or closed). */ - bool isPortOpen( void ) const - { - if (rtapi_) return rtapi_->isPortOpen(); - return false; - } + bool isPortOpen( void ) const; //! Pure virtual function to set an error callback function to be invoked when an error has occured. /*! The callback function will be called whenever an error has occured. It is best to set the error callback function before opening a port. */ - void setErrorCallback( ErrorInterface * callback) - { - if (rtapi_) rtapi_->setErrorCallback(callback); - } + void setErrorCallback( ErrorInterface * callback); //! A basic error reporting function for RtMidi classes. void error( Error e ); @@ -622,16 +586,7 @@ class Midi { #define Api Api_t RTMIDI_DEPRECATED(static void getCompiledApi( std::vector &apis, bool preferSystem - = true ) throw(), "enum RtMidi::Api has been replaced by enum rtmidi::ApiType" ) { - std::vector api2; - Midi::getCompiledApi(api2,preferSystem); - apis.reserve(api2.size()); - size_t s = api2.size(); - for (size_t i = 0; i < s; i++) { - apis.push_back((Api)api2[i]); - } - } - + = true ) throw(), "enum RtMidi::Api has been replaced by enum rtmidi::ApiType" ); //! Compatibilty function for older code virtual RTMIDI_DEPRECATED(void openVirtualPort( const std::string &portName @@ -651,10 +606,7 @@ class Midi { */ RTMIDI_DEPRECATED(void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi" ) - ),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)") - { - if (rtapi_) rtapi_->openPort(portNumber,portName); - } + ),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)"); //! Pure virtual to return the number of available MIDI ports of the current API. /*! @@ -668,11 +620,7 @@ class Midi { \sa getPortName \deprecated */ - RTMIDI_DEPRECATED(unsigned int getPortCount(),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)") - { - if (rtapi_) return rtapi_->getPortCount(); - return 0; - } + RTMIDI_DEPRECATED(unsigned int getPortCount(),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)"); //! Pure virtual function to return a string identifier for the specified MIDI port number. /*! @@ -687,28 +635,14 @@ class Midi { \sa getPortCount() \deprecated */ - RTMIDI_DEPRECATED(std::string getPortName( unsigned int portNumber = 0 ),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)") - { - if (rtapi_) return rtapi_->getPortName(portNumber); - return ""; - } + RTMIDI_DEPRECATED(std::string getPortName( unsigned int portNumber = 0 ),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)"); //! Pure virtual function to set an error callback function to be invoked when an error has occured. /*! The callback function will be called whenever an error has occured. It is best to set the error callback function before opening a port. */ - RTMIDI_DEPRECATED(void setErrorCallback( ErrorCallback errorCallback = NULL, void * userData = 0 ), "setErrorCallback now expects an object of type ErrorInterface") - { -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - if (rtapi_) rtapi_->setErrorCallback(errorCallback, userData); -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - } + RTMIDI_DEPRECATED(void setErrorCallback( ErrorCallback errorCallback = NULL, void * userData = 0 ), "setErrorCallback now expects an object of type ErrorInterface"); protected: @@ -719,15 +653,9 @@ class Midi { Midi(MidiApiList * l, bool pfsystem, - const std::string &name):rtapi_(0), - list(l), - preferSystem(pfsystem), - clientName(name) {} - virtual ~Midi() - { - delete rtapi_; - rtapi_ = 0; - } + const std::string &name); + + virtual ~Midi(); }; inline RTMIDI_DEPRECATED(std::string getApiName(Midi::Api type),"Use rtmidi::ApiType instead of RtMidi::Api"); @@ -819,11 +747,7 @@ class MidiIn : public Midi \param portName An optional name for the applicaction port that is used to connect to portId can be specified. */ void openPort( const PortDescriptor & port, - const std::string &portName = std::string( "RtMidi" ) ) - { - if (!rtapi_) rtapi_ = port.getInputApi(); - if (rtapi_) rtapi_->openPort(port,portName); - } + const std::string &portName = std::string( "RtMidi" ) ); //! Open a MIDI connection given by a port descriptor pointer. @@ -833,14 +757,7 @@ class MidiIn : public Midi \sa openPort(const PortDescriptor &,const std::string &); */ void openPort( Pointer p, - const std::string &portName = std::string( "RtMidi" ) ) { - if (!p) { - error(RTMIDI_ERROR(gettext_noopt("A NULL pointer has been passed as port descriptor"), - Error::INVALID_PARAMETER)); - return; - } - openPort(*p, portName); - } + const std::string &portName = std::string( "RtMidi" ) ); //! Function to create a virtual port, with optional name. /*! @@ -852,25 +769,7 @@ class MidiIn : public Midi \param portName An optional name for the application port that is used to connect to portId can be specified. */ - void openVirtualPort( const std::string &portName = std::string( "RtMidi virtual input port" ) ) - { - if (!rtapi_ && list && !list->empty()) { - Pointer api = list->front(); - - std::vector< ApiType > apis; - getCompiledApi( apis ); - for (size_t i = 0 ; i < apis.size() ; i++) { - openMidiApi( apis[0] ); - if (rtapi_ && rtapi_->hasVirtualPorts()) break; - } - } - - if (rtapi_) rtapi_->openVirtualPort(portName); - else { - error(RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), - Error::INVALID_DEVICE)); - } - } + void openVirtualPort( const std::string &portName = std::string( "RtMidi virtual input port" ) ); //! Return a list of all available ports of the current API. /*! @@ -909,22 +808,14 @@ class MidiIn : public Midi \param userData Opitionally, a pointer to additional data can be passed to the callback function whenever it is called. */ - void setCallback( MidiInterface * callback ) - { - if (rtapi_) - static_cast(rtapi_)->setCallback(callback); - } + void setCallback( MidiInterface * callback ); //! Cancel use of the current callback function (if one exists). /*! Subsequent incoming MIDI messages will be written to the queue and can be retrieved with the \e getMessage function. */ - void cancelCallback() - { - if (rtapi_) - static_cast(rtapi_)->cancelCallback(); - } + void cancelCallback(); //! Specify whether certain MIDI message types should be queued or ignored during input. /*! @@ -936,11 +827,7 @@ class MidiIn : public Midi */ void ignoreTypes( bool midiSysex = true, bool midiTime = true, - bool midiSense = true ) - { - if (rtapi_) - static_cast(rtapi_)->ignoreTypes(midiSysex, midiTime, midiSense); - } + bool midiSense = true ); //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. /*! @@ -950,14 +837,7 @@ class MidiIn : public Midi message retrieval or an input connection was not previously established. */ - double getMessage( std::vector &message ) - { - if (rtapi_) - return static_cast(rtapi_)->getMessage(message); - error( RTMIDI_ERROR(gettext_noopt("Could not find any valid MIDI system."), - Error::WARNING)); - return 0.0; - } + double getMessage( std::vector &message ); //! Set a callback function to be invoked for incoming MIDI messages. @@ -972,18 +852,8 @@ class MidiIn : public Midi passed to the callback function whenever it is called. */ RTMIDI_DEPRECATED(void setCallback( MidiCallback callback, void *userData = 0 ), - "RtMidi now provides a type-safe MidiInterface class.") - { -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - if (rtapi_) - static_cast(rtapi_)->setCallback(callback,userData); -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - } + "RtMidi now provides a type-safe MidiInterface class."); + //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. /*! This function returns immediately whether a new message is @@ -995,18 +865,7 @@ class MidiIn : public Midi \deprecated */ RTMIDI_DEPRECATED(double getMessage( std::vector *message ), - "Please, use a C++ style reference to pass the message vector.") - { - if (!message) { - error( RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), - Error::WARNING)); - } - if (rtapi_) - return static_cast(rtapi_)->getMessage(*message); - error( RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been found."), - Error::WARNING)); - return 0.0; - } + "Please, use a C++ style reference to pass the message vector."); protected: static MidiApiList queryApis; int queueSizeLimit; @@ -1074,12 +933,7 @@ class MidiOut : public Midi \param portName An optional name for the applicaction port that is used to connect to portId can be specified. */ void openPort( const PortDescriptor & port, - const std::string &portName = std::string( "RtMidi" ) ) - { - if (!rtapi_) rtapi_ = port.getOutputApi(); - if (rtapi_) rtapi_->openPort(port,portName); - } - + const std::string &portName = std::string( "RtMidi" ) ); //! Open a MIDI connection given by a port descriptor pointer. /*! \param port A pointer to a port descriptor of the port must be specified. @@ -1087,15 +941,7 @@ class MidiOut : public Midi \sa openPort(const PortDescriptor &,const std::string &); */ void openPort( Pointer p, - const std::string &portName = std::string( "RtMidi" ) ) { - if (!p) { - error(RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), - Error::INVALID_PARAMETER)); - return; - } - openPort(*p, portName); - } - + const std::string &portName = std::string( "RtMidi" ) ); //! Function to create a virtual port, with optional name. /*! @@ -1107,25 +953,7 @@ class MidiOut : public Midi \param portName An optional name for the applicaction port that is used to connect to portId can be specified. */ - void openVirtualPort( const std::string &portName = std::string( "RtMidi virtual output port" ) ) - { - if (!rtapi_ && list && !list->empty()) { - Pointer api = list->front(); - - std::vector< ApiType > apis; - getCompiledApi( apis ); - for (size_t i = 0 ; i < apis.size() ; i++) { - openMidiApi( apis[0] ); - if (rtapi_ && rtapi_->hasVirtualPorts()) break; - } - } - - if (rtapi_) rtapi_->openVirtualPort(portName); - else { - error(RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), - Error::INVALID_DEVICE)); - } - } + void openVirtualPort( const std::string &portName = std::string( "RtMidi virtual output port" ) ); //! Return a list of all available ports of the current API. /*! @@ -1182,17 +1010,7 @@ class MidiOut : public Midi \param message A pointer to the MIDI message as raw bytes \param size Length of the MIDI message in bytes */ - void sendMessage( const unsigned char *message, size_t size ) { - if (!message) { - error( RTMIDI_ERROR(gettext_noopt("No data in MIDI message."), - Error::WARNING)); - } - if (rtapi_) - static_cast(rtapi_)->sendMessage(message,size); - else - error( RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), - Error::WARNING)); - } + void sendMessage( const unsigned char *message, size_t size ); protected: static MidiApiList queryApis; @@ -1201,6 +1019,7 @@ class MidiOut : public Midi }; #undef RTMIDI_CLASSNAME + // **************************************************************** // // // MidiInApi / MidiOutApi class declarations. @@ -1488,6 +1307,220 @@ class MidiOutApi : public MidiApi #undef RTMIDI_CLASSNAME +// **************************************************************** // +// +// Inline rtmidi::Midi, rtmidi::MidiIn and rtmidid:MidiOut definitions. +// +// **************************************************************** // +// rtmidi::Midi +#define RTMIDI_CLASSNAME "Midi" +inline std::vector Midi :: getCompiledApi( ) throw() { + std::vector apis; + getCompiledApi(apis); + return apis; +} +inline ApiType Midi :: getCurrentApi( void ) throw() { + if (rtapi_) return rtapi_->getCurrentApi(); + else return rtmidi::UNSPECIFIED; +} +inline Pointer Midi :: getDescriptor( bool local ) { + if (rtapi_) return rtapi_->getDescriptor(local); + return 0; +} +inline PortList Midi :: getPortList(int capabilities ) { + if (rtapi_) return rtapi_->getPortList(capabilities); + if (list && !list->empty()) { + PortList retval; + for (MidiApiList::iterator i = list->begin(); + i != list->end(); + ++i) { + PortList tmp = (*i)->getPortList(capabilities); + retval.splice(retval.end(), tmp); + } + return retval; + } + return PortList(); +} +inline void Midi :: closePort( void ) { + if (rtapi_) rtapi_->closePort(); +} +inline bool Midi :: isPortOpen( void ) const { + if (rtapi_) return rtapi_->isPortOpen(); + return false; +} +inline void Midi :: setErrorCallback( ErrorInterface * callback) { + if (rtapi_) rtapi_->setErrorCallback(callback); +} +inline void Midi :: getCompiledApi( std::vector &apis, bool + preferSystem ) throw() { + std::vector api2; + Midi::getCompiledApi(api2,preferSystem); + apis.reserve(api2.size()); + size_t s = api2.size(); + for (size_t i = 0; i < s; i++) { + apis.push_back((Api)api2[i]); + } +} +inline void Midi :: openPort( unsigned int portNumber, + const std::string &portName) { + if (rtapi_) rtapi_->openPort(portNumber,portName); +} +inline unsigned int Midi :: getPortCount() { + if (rtapi_) return rtapi_->getPortCount(); + return 0; +} +inline std::string Midi :: getPortName( unsigned int portNumber ) { + if (rtapi_) return rtapi_->getPortName(portNumber); + return ""; +} +inline void Midi :: setErrorCallback( ErrorCallback errorCallback , void * userData ) { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + if (rtapi_) rtapi_->setErrorCallback(errorCallback, userData); +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif +} +inline Midi :: Midi(MidiApiList * l, + bool pfsystem, + const std::string &name):rtapi_(0), + list(l), + preferSystem(pfsystem), + clientName(name) { } +inline Midi :: ~Midi() { + delete rtapi_; + rtapi_ = 0; +} +#undef RTMIDI_CLASSNAME + +#define RTMIDI_CLASSNAME "MidiIn" +// rtmidi::MidiIn +inline void MidiIn :: openPort( const PortDescriptor & port, + const std::string &portName ) { + if (!rtapi_) rtapi_ = port.getInputApi(); + if (rtapi_) rtapi_->openPort(port,portName); +} +inline void MidiIn :: openPort( Pointer p, + const std::string &portName ) { + if (!p) { + error(RTMIDI_ERROR(gettext_noopt("A NULL pointer has been passed as port descriptor"), + Error::INVALID_PARAMETER)); + return; + } + openPort(*p, portName); +} +inline void MidiIn :: openVirtualPort( const std::string &portName ) { + if (!rtapi_ && list && !list->empty()) { + Pointer api = list->front(); + + std::vector< ApiType > apis; + getCompiledApi( apis ); + for (size_t i = 0 ; i < apis.size() ; i++) { + openMidiApi( apis[0] ); + if (rtapi_ && rtapi_->hasVirtualPorts()) break; + } + } + + if (rtapi_) rtapi_->openVirtualPort(portName); + else { + error(RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), + Error::INVALID_DEVICE)); + } +} +inline void MidiIn :: setCallback( MidiInterface * callback ) { + if (rtapi_) + static_cast(rtapi_)->setCallback(callback); +} +inline void MidiIn :: cancelCallback() { + if (rtapi_) + static_cast(rtapi_)->cancelCallback(); +} +inline void MidiIn :: ignoreTypes( bool midiSysex = true, + bool midiTime = true, + bool midiSense = true ) { + if (rtapi_) + static_cast(rtapi_)->ignoreTypes(midiSysex, midiTime, midiSense); +} +inline double MidiIn :: getMessage( std::vector &message ) { + if (rtapi_) + return static_cast(rtapi_)->getMessage(message); + error( RTMIDI_ERROR(gettext_noopt("Could not find any valid MIDI system."), + Error::WARNING)); + return 0.0; +} +inline void MidiIn :: setCallback( MidiCallback callback, void *userData) { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + if (rtapi_) + static_cast(rtapi_)->setCallback(callback,userData); +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif +} +inline double MidiIn :: getMessage( std::vector *message ) { + if (!message) { + error( RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), + Error::WARNING)); + } + if (rtapi_) + return static_cast(rtapi_)->getMessage(*message); + error( RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been found."), + Error::WARNING)); + return 0.0; +} +#undef RTMIDI_CLASSNAME + +// rtmidi::MidiOut +#define RTMIDI_CLASSNAME "MidiOut" +inline void MidiOut :: openPort( const PortDescriptor & port, + const std::string &portName ) { + if (!rtapi_) rtapi_ = port.getOutputApi(); + if (rtapi_) rtapi_->openPort(port,portName); +} +inline void MidiOut :: openPort( Pointer p, + const std::string &portName ) { + if (!p) { + error(RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), + Error::INVALID_PARAMETER)); + return; + } + openPort(*p, portName); +} +inline void MidiOut :: openVirtualPort( const std::string &portName ) { + if (!rtapi_ && list && !list->empty()) { + Pointer api = list->front(); + + std::vector< ApiType > apis; + getCompiledApi( apis ); + for (size_t i = 0 ; i < apis.size() ; i++) { + openMidiApi( apis[0] ); + if (rtapi_ && rtapi_->hasVirtualPorts()) break; + } + } + + if (rtapi_) rtapi_->openVirtualPort(portName); + else { + error(RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), + Error::INVALID_DEVICE)); + } +} +inline void MidiOut :: sendMessage( const unsigned char *message, size_t size ) { + if (!message) { + error( RTMIDI_ERROR(gettext_noopt("No data in MIDI message."), + Error::WARNING)); + } + if (rtapi_) + static_cast(rtapi_)->sendMessage(message,size); + else + error( RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), + Error::WARNING)); +} +#undef RTMIDI_CLASSNAME + // **************************************************************** // // // MidiInApi and MidiOutApi subclass prototypes. From 532b20cdf1ca7dd0c7f04212a53e6270885eba42 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 11 Aug 2018 15:05:11 +0200 Subject: [PATCH 203/210] remove libtool generated files --- m4/libtool.m4 | 8387 --------------------------------------------- m4/ltoptions.m4 | 437 --- m4/ltsugar.m4 | 124 - m4/ltversion.m4 | 23 - m4/lt~obsolete.m4 | 99 - 5 files changed, 9070 deletions(-) delete mode 100644 m4/libtool.m4 delete mode 100644 m4/ltoptions.m4 delete mode 100644 m4/ltsugar.m4 delete mode 100644 m4/ltversion.m4 delete mode 100644 m4/lt~obsolete.m4 diff --git a/m4/libtool.m4 b/m4/libtool.m4 deleted file mode 100644 index ee80844b..00000000 --- a/m4/libtool.m4 +++ /dev/null @@ -1,8387 +0,0 @@ -# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- -# -# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. -# Written by Gordon Matzigkeit, 1996 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -m4_define([_LT_COPYING], [dnl -# Copyright (C) 2014 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# GNU Libtool is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of of the License, or -# (at your option) any later version. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program or library that is built -# using GNU Libtool, you may include this file under the same -# distribution terms that you use for the rest of that program. -# -# GNU Libtool is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -]) - -# serial 58 LT_INIT - - -# LT_PREREQ(VERSION) -# ------------------ -# Complain and exit if this libtool version is less that VERSION. -m4_defun([LT_PREREQ], -[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, - [m4_default([$3], - [m4_fatal([Libtool version $1 or higher is required], - 63)])], - [$2])]) - - -# _LT_CHECK_BUILDDIR -# ------------------ -# Complain if the absolute build directory name contains unusual characters -m4_defun([_LT_CHECK_BUILDDIR], -[case `pwd` in - *\ * | *\ *) - AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; -esac -]) - - -# LT_INIT([OPTIONS]) -# ------------------ -AC_DEFUN([LT_INIT], -[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK -AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl -AC_BEFORE([$0], [LT_LANG])dnl -AC_BEFORE([$0], [LT_OUTPUT])dnl -AC_BEFORE([$0], [LTDL_INIT])dnl -m4_require([_LT_CHECK_BUILDDIR])dnl - -dnl Autoconf doesn't catch unexpanded LT_ macros by default: -m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl -m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl -dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 -dnl unless we require an AC_DEFUNed macro: -AC_REQUIRE([LTOPTIONS_VERSION])dnl -AC_REQUIRE([LTSUGAR_VERSION])dnl -AC_REQUIRE([LTVERSION_VERSION])dnl -AC_REQUIRE([LTOBSOLETE_VERSION])dnl -m4_require([_LT_PROG_LTMAIN])dnl - -_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) - -dnl Parse OPTIONS -_LT_SET_OPTIONS([$0], [$1]) - -# This can be used to rebuild libtool when needed -LIBTOOL_DEPS=$ltmain - -# Always use our own libtool. -LIBTOOL='$(SHELL) $(top_builddir)/libtool' -AC_SUBST(LIBTOOL)dnl - -_LT_SETUP - -# Only expand once: -m4_define([LT_INIT]) -])# LT_INIT - -# Old names: -AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) -AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_PROG_LIBTOOL], []) -dnl AC_DEFUN([AM_PROG_LIBTOOL], []) - - -# _LT_PREPARE_CC_BASENAME -# ----------------------- -m4_defun([_LT_PREPARE_CC_BASENAME], [ -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. -func_cc_basename () -{ - for cc_temp in @S|@*""; do - case $cc_temp in - compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; - distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; - \-*) ;; - *) break;; - esac - done - func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` -} -])# _LT_PREPARE_CC_BASENAME - - -# _LT_CC_BASENAME(CC) -# ------------------- -# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, -# but that macro is also expanded into generated libtool script, which -# arranges for $SED and $ECHO to be set by different means. -m4_defun([_LT_CC_BASENAME], -[m4_require([_LT_PREPARE_CC_BASENAME])dnl -AC_REQUIRE([_LT_DECL_SED])dnl -AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl -func_cc_basename $1 -cc_basename=$func_cc_basename_result -]) - - -# _LT_FILEUTILS_DEFAULTS -# ---------------------- -# It is okay to use these file commands and assume they have been set -# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. -m4_defun([_LT_FILEUTILS_DEFAULTS], -[: ${CP="cp -f"} -: ${MV="mv -f"} -: ${RM="rm -f"} -])# _LT_FILEUTILS_DEFAULTS - - -# _LT_SETUP -# --------- -m4_defun([_LT_SETUP], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl -AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl - -_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl -dnl -_LT_DECL([], [host_alias], [0], [The host system])dnl -_LT_DECL([], [host], [0])dnl -_LT_DECL([], [host_os], [0])dnl -dnl -_LT_DECL([], [build_alias], [0], [The build system])dnl -_LT_DECL([], [build], [0])dnl -_LT_DECL([], [build_os], [0])dnl -dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([LT_PATH_LD])dnl -AC_REQUIRE([LT_PATH_NM])dnl -dnl -AC_REQUIRE([AC_PROG_LN_S])dnl -test -z "$LN_S" && LN_S="ln -s" -_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl -dnl -AC_REQUIRE([LT_CMD_MAX_LEN])dnl -_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl -_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl -dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_CHECK_SHELL_FEATURES])dnl -m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl -m4_require([_LT_CMD_RELOAD])dnl -m4_require([_LT_CHECK_MAGIC_METHOD])dnl -m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl -m4_require([_LT_CMD_OLD_ARCHIVE])dnl -m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl -m4_require([_LT_WITH_SYSROOT])dnl -m4_require([_LT_CMD_TRUNCATE])dnl - -_LT_CONFIG_LIBTOOL_INIT([ -# See if we are running on zsh, and set the options that allow our -# commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}"; then - setopt NO_GLOB_SUBST -fi -]) -if test -n "${ZSH_VERSION+set}"; then - setopt NO_GLOB_SUBST -fi - -_LT_CHECK_OBJDIR - -m4_require([_LT_TAG_COMPILER])dnl - -case $host_os in -aix3*) - # AIX sometimes has problems with the GCC collect2 program. For some - # reason, if we set the COLLECT_NAMES environment variable, the problems - # vanish in a puff of smoke. - if test set != "${COLLECT_NAMES+set}"; then - COLLECT_NAMES= - export COLLECT_NAMES - fi - ;; -esac - -# Global variables: -ofile=libtool -can_build_shared=yes - -# All known linkers require a '.a' archive for static linking (except MSVC, -# which needs '.lib'). -libext=a - -with_gnu_ld=$lt_cv_prog_gnu_ld - -old_CC=$CC -old_CFLAGS=$CFLAGS - -# Set sane defaults for various variables -test -z "$CC" && CC=cc -test -z "$LTCC" && LTCC=$CC -test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS -test -z "$LD" && LD=ld -test -z "$ac_objext" && ac_objext=o - -_LT_CC_BASENAME([$compiler]) - -# Only perform the check for file, if the check method requires it -test -z "$MAGIC_CMD" && MAGIC_CMD=file -case $deplibs_check_method in -file_magic*) - if test "$file_magic_cmd" = '$MAGIC_CMD'; then - _LT_PATH_MAGIC - fi - ;; -esac - -# Use C for the default configuration in the libtool script -LT_SUPPORTED_TAG([CC]) -_LT_LANG_C_CONFIG -_LT_LANG_DEFAULT_CONFIG -_LT_CONFIG_COMMANDS -])# _LT_SETUP - - -# _LT_PREPARE_SED_QUOTE_VARS -# -------------------------- -# Define a few sed substitution that help us do robust quoting. -m4_defun([_LT_PREPARE_SED_QUOTE_VARS], -[# Backslashify metacharacters that are still active within -# double-quoted strings. -sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\([["`\\]]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to delay expansion of an escaped single quote. -delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' -]) - -# _LT_PROG_LTMAIN -# --------------- -# Note that this code is called both from 'configure', and 'config.status' -# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, -# 'config.status' has no value for ac_aux_dir unless we are using Automake, -# so we pass a copy along to make sure it has a sensible value anyway. -m4_defun([_LT_PROG_LTMAIN], -[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl -_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) -ltmain=$ac_aux_dir/ltmain.sh -])# _LT_PROG_LTMAIN - - -## ------------------------------------- ## -## Accumulate code for creating libtool. ## -## ------------------------------------- ## - -# So that we can recreate a full libtool script including additional -# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS -# in macros and then make a single call at the end using the 'libtool' -# label. - - -# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) -# ---------------------------------------- -# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. -m4_define([_LT_CONFIG_LIBTOOL_INIT], -[m4_ifval([$1], - [m4_append([_LT_OUTPUT_LIBTOOL_INIT], - [$1 -])])]) - -# Initialize. -m4_define([_LT_OUTPUT_LIBTOOL_INIT]) - - -# _LT_CONFIG_LIBTOOL([COMMANDS]) -# ------------------------------ -# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. -m4_define([_LT_CONFIG_LIBTOOL], -[m4_ifval([$1], - [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], - [$1 -])])]) - -# Initialize. -m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) - - -# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) -# ----------------------------------------------------- -m4_defun([_LT_CONFIG_SAVE_COMMANDS], -[_LT_CONFIG_LIBTOOL([$1]) -_LT_CONFIG_LIBTOOL_INIT([$2]) -]) - - -# _LT_FORMAT_COMMENT([COMMENT]) -# ----------------------------- -# Add leading comment marks to the start of each line, and a trailing -# full-stop to the whole comment if one is not present already. -m4_define([_LT_FORMAT_COMMENT], -[m4_ifval([$1], [ -m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], - [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) -)]) - - - -## ------------------------ ## -## FIXME: Eliminate VARNAME ## -## ------------------------ ## - - -# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) -# ------------------------------------------------------------------- -# CONFIGNAME is the name given to the value in the libtool script. -# VARNAME is the (base) name used in the configure script. -# VALUE may be 0, 1 or 2 for a computed quote escaped value based on -# VARNAME. Any other value will be used directly. -m4_define([_LT_DECL], -[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], - [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], - [m4_ifval([$1], [$1], [$2])]) - lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) - m4_ifval([$4], - [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) - lt_dict_add_subkey([lt_decl_dict], [$2], - [tagged?], [m4_ifval([$5], [yes], [no])])]) -]) - - -# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) -# -------------------------------------------------------- -m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) - - -# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) -# ------------------------------------------------ -m4_define([lt_decl_tag_varnames], -[_lt_decl_filter([tagged?], [yes], $@)]) - - -# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) -# --------------------------------------------------------- -m4_define([_lt_decl_filter], -[m4_case([$#], - [0], [m4_fatal([$0: too few arguments: $#])], - [1], [m4_fatal([$0: too few arguments: $#: $1])], - [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], - [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], - [lt_dict_filter([lt_decl_dict], $@)])[]dnl -]) - - -# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) -# -------------------------------------------------- -m4_define([lt_decl_quote_varnames], -[_lt_decl_filter([value], [1], $@)]) - - -# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) -# --------------------------------------------------- -m4_define([lt_decl_dquote_varnames], -[_lt_decl_filter([value], [2], $@)]) - - -# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) -# --------------------------------------------------- -m4_define([lt_decl_varnames_tagged], -[m4_assert([$# <= 2])dnl -_$0(m4_quote(m4_default([$1], [[, ]])), - m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), - m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) -m4_define([_lt_decl_varnames_tagged], -[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) - - -# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) -# ------------------------------------------------ -m4_define([lt_decl_all_varnames], -[_$0(m4_quote(m4_default([$1], [[, ]])), - m4_if([$2], [], - m4_quote(lt_decl_varnames), - m4_quote(m4_shift($@))))[]dnl -]) -m4_define([_lt_decl_all_varnames], -[lt_join($@, lt_decl_varnames_tagged([$1], - lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl -]) - - -# _LT_CONFIG_STATUS_DECLARE([VARNAME]) -# ------------------------------------ -# Quote a variable value, and forward it to 'config.status' so that its -# declaration there will have the same value as in 'configure'. VARNAME -# must have a single quote delimited value for this to work. -m4_define([_LT_CONFIG_STATUS_DECLARE], -[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) - - -# _LT_CONFIG_STATUS_DECLARATIONS -# ------------------------------ -# We delimit libtool config variables with single quotes, so when -# we write them to config.status, we have to be sure to quote all -# embedded single quotes properly. In configure, this macro expands -# each variable declared with _LT_DECL (and _LT_TAGDECL) into: -# -# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' -m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], -[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), - [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) - - -# _LT_LIBTOOL_TAGS -# ---------------- -# Output comment and list of tags supported by the script -m4_defun([_LT_LIBTOOL_TAGS], -[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl -available_tags='_LT_TAGS'dnl -]) - - -# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) -# ----------------------------------- -# Extract the dictionary values for VARNAME (optionally with TAG) and -# expand to a commented shell variable setting: -# -# # Some comment about what VAR is for. -# visible_name=$lt_internal_name -m4_define([_LT_LIBTOOL_DECLARE], -[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], - [description])))[]dnl -m4_pushdef([_libtool_name], - m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl -m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), - [0], [_libtool_name=[$]$1], - [1], [_libtool_name=$lt_[]$1], - [2], [_libtool_name=$lt_[]$1], - [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl -m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl -]) - - -# _LT_LIBTOOL_CONFIG_VARS -# ----------------------- -# Produce commented declarations of non-tagged libtool config variables -# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' -# script. Tagged libtool config variables (even for the LIBTOOL CONFIG -# section) are produced by _LT_LIBTOOL_TAG_VARS. -m4_defun([_LT_LIBTOOL_CONFIG_VARS], -[m4_foreach([_lt_var], - m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), - [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) - - -# _LT_LIBTOOL_TAG_VARS(TAG) -# ------------------------- -m4_define([_LT_LIBTOOL_TAG_VARS], -[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), - [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) - - -# _LT_TAGVAR(VARNAME, [TAGNAME]) -# ------------------------------ -m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) - - -# _LT_CONFIG_COMMANDS -# ------------------- -# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of -# variables for single and double quote escaping we saved from calls -# to _LT_DECL, we can put quote escaped variables declarations -# into 'config.status', and then the shell code to quote escape them in -# for loops in 'config.status'. Finally, any additional code accumulated -# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. -m4_defun([_LT_CONFIG_COMMANDS], -[AC_PROVIDE_IFELSE([LT_OUTPUT], - dnl If the libtool generation code has been placed in $CONFIG_LT, - dnl instead of duplicating it all over again into config.status, - dnl then we will have config.status run $CONFIG_LT later, so it - dnl needs to know what name is stored there: - [AC_CONFIG_COMMANDS([libtool], - [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], - dnl If the libtool generation code is destined for config.status, - dnl expand the accumulated commands and init code now: - [AC_CONFIG_COMMANDS([libtool], - [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) -])#_LT_CONFIG_COMMANDS - - -# Initialize. -m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], -[ - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -sed_quote_subst='$sed_quote_subst' -double_quote_subst='$double_quote_subst' -delay_variable_subst='$delay_variable_subst' -_LT_CONFIG_STATUS_DECLARATIONS -LTCC='$LTCC' -LTCFLAGS='$LTCFLAGS' -compiler='$compiler_DEFAULT' - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -\$[]1 -_LTECHO_EOF' -} - -# Quote evaled strings. -for var in lt_decl_all_varnames([[ \ -]], lt_decl_quote_varnames); do - case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in - *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes - ;; - *) - eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" - ;; - esac -done - -# Double-quote double-evaled strings. -for var in lt_decl_all_varnames([[ \ -]], lt_decl_dquote_varnames); do - case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in - *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes - ;; - *) - eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" - ;; - esac -done - -_LT_OUTPUT_LIBTOOL_INIT -]) - -# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) -# ------------------------------------ -# Generate a child script FILE with all initialization necessary to -# reuse the environment learned by the parent script, and make the -# file executable. If COMMENT is supplied, it is inserted after the -# '#!' sequence but before initialization text begins. After this -# macro, additional text can be appended to FILE to form the body of -# the child script. The macro ends with non-zero status if the -# file could not be fully written (such as if the disk is full). -m4_ifdef([AS_INIT_GENERATED], -[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], -[m4_defun([_LT_GENERATED_FILE_INIT], -[m4_require([AS_PREPARE])]dnl -[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl -[lt_write_fail=0 -cat >$1 <<_ASEOF || lt_write_fail=1 -#! $SHELL -# Generated by $as_me. -$2 -SHELL=\${CONFIG_SHELL-$SHELL} -export SHELL -_ASEOF -cat >>$1 <<\_ASEOF || lt_write_fail=1 -AS_SHELL_SANITIZE -_AS_PREPARE -exec AS_MESSAGE_FD>&1 -_ASEOF -test 0 = "$lt_write_fail" && chmod +x $1[]dnl -m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT - -# LT_OUTPUT -# --------- -# This macro allows early generation of the libtool script (before -# AC_OUTPUT is called), incase it is used in configure for compilation -# tests. -AC_DEFUN([LT_OUTPUT], -[: ${CONFIG_LT=./config.lt} -AC_MSG_NOTICE([creating $CONFIG_LT]) -_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], -[# Run this file to recreate a libtool stub with the current configuration.]) - -cat >>"$CONFIG_LT" <<\_LTEOF -lt_cl_silent=false -exec AS_MESSAGE_LOG_FD>>config.log -{ - echo - AS_BOX([Running $as_me.]) -} >&AS_MESSAGE_LOG_FD - -lt_cl_help="\ -'$as_me' creates a local libtool stub from the current configuration, -for use in further configure time tests before the real libtool is -generated. - -Usage: $[0] [[OPTIONS]] - - -h, --help print this help, then exit - -V, --version print version number, then exit - -q, --quiet do not print progress messages - -d, --debug don't remove temporary files - -Report bugs to ." - -lt_cl_version="\ -m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl -m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) -configured by $[0], generated by m4_PACKAGE_STRING. - -Copyright (C) 2011 Free Software Foundation, Inc. -This config.lt script is free software; the Free Software Foundation -gives unlimited permision to copy, distribute and modify it." - -while test 0 != $[#] -do - case $[1] in - --version | --v* | -V ) - echo "$lt_cl_version"; exit 0 ;; - --help | --h* | -h ) - echo "$lt_cl_help"; exit 0 ;; - --debug | --d* | -d ) - debug=: ;; - --quiet | --q* | --silent | --s* | -q ) - lt_cl_silent=: ;; - - -*) AC_MSG_ERROR([unrecognized option: $[1] -Try '$[0] --help' for more information.]) ;; - - *) AC_MSG_ERROR([unrecognized argument: $[1] -Try '$[0] --help' for more information.]) ;; - esac - shift -done - -if $lt_cl_silent; then - exec AS_MESSAGE_FD>/dev/null -fi -_LTEOF - -cat >>"$CONFIG_LT" <<_LTEOF -_LT_OUTPUT_LIBTOOL_COMMANDS_INIT -_LTEOF - -cat >>"$CONFIG_LT" <<\_LTEOF -AC_MSG_NOTICE([creating $ofile]) -_LT_OUTPUT_LIBTOOL_COMMANDS -AS_EXIT(0) -_LTEOF -chmod +x "$CONFIG_LT" - -# configure is writing to config.log, but config.lt does its own redirection, -# appending to config.log, which fails on DOS, as config.log is still kept -# open by configure. Here we exec the FD to /dev/null, effectively closing -# config.log, so it can be properly (re)opened and appended to by config.lt. -lt_cl_success=: -test yes = "$silent" && - lt_config_lt_args="$lt_config_lt_args --quiet" -exec AS_MESSAGE_LOG_FD>/dev/null -$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false -exec AS_MESSAGE_LOG_FD>>config.log -$lt_cl_success || AS_EXIT(1) -])# LT_OUTPUT - - -# _LT_CONFIG(TAG) -# --------------- -# If TAG is the built-in tag, create an initial libtool script with a -# default configuration from the untagged config vars. Otherwise add code -# to config.status for appending the configuration named by TAG from the -# matching tagged config vars. -m4_defun([_LT_CONFIG], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -_LT_CONFIG_SAVE_COMMANDS([ - m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl - m4_if(_LT_TAG, [C], [ - # See if we are running on zsh, and set the options that allow our - # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}"; then - setopt NO_GLOB_SUBST - fi - - cfgfile=${ofile}T - trap "$RM \"$cfgfile\"; exit 1" 1 2 15 - $RM "$cfgfile" - - cat <<_LT_EOF >> "$cfgfile" -#! $SHELL -# Generated automatically by $as_me ($PACKAGE) $VERSION -# NOTE: Changes made to this file will be lost: look at ltmain.sh. - -# Provide generalized library-building support services. -# Written by Gordon Matzigkeit, 1996 - -_LT_COPYING -_LT_LIBTOOL_TAGS - -# Configured defaults for sys_lib_dlsearch_path munging. -: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} - -# ### BEGIN LIBTOOL CONFIG -_LT_LIBTOOL_CONFIG_VARS -_LT_LIBTOOL_TAG_VARS -# ### END LIBTOOL CONFIG - -_LT_EOF - - cat <<'_LT_EOF' >> "$cfgfile" - -# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE - -_LT_PREPARE_MUNGE_PATH_LIST -_LT_PREPARE_CC_BASENAME - -# ### END FUNCTIONS SHARED WITH CONFIGURE - -_LT_EOF - - case $host_os in - aix3*) - cat <<\_LT_EOF >> "$cfgfile" -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test set != "${COLLECT_NAMES+set}"; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -_LT_EOF - ;; - esac - - _LT_PROG_LTMAIN - - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - sed '$q' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) - - mv -f "$cfgfile" "$ofile" || - (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") - chmod +x "$ofile" -], -[cat <<_LT_EOF >> "$ofile" - -dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded -dnl in a comment (ie after a #). -# ### BEGIN LIBTOOL TAG CONFIG: $1 -_LT_LIBTOOL_TAG_VARS(_LT_TAG) -# ### END LIBTOOL TAG CONFIG: $1 -_LT_EOF -])dnl /m4_if -], -[m4_if([$1], [], [ - PACKAGE='$PACKAGE' - VERSION='$VERSION' - RM='$RM' - ofile='$ofile'], []) -])dnl /_LT_CONFIG_SAVE_COMMANDS -])# _LT_CONFIG - - -# LT_SUPPORTED_TAG(TAG) -# --------------------- -# Trace this macro to discover what tags are supported by the libtool -# --tag option, using: -# autoconf --trace 'LT_SUPPORTED_TAG:$1' -AC_DEFUN([LT_SUPPORTED_TAG], []) - - -# C support is built-in for now -m4_define([_LT_LANG_C_enabled], []) -m4_define([_LT_TAGS], []) - - -# LT_LANG(LANG) -# ------------- -# Enable libtool support for the given language if not already enabled. -AC_DEFUN([LT_LANG], -[AC_BEFORE([$0], [LT_OUTPUT])dnl -m4_case([$1], - [C], [_LT_LANG(C)], - [C++], [_LT_LANG(CXX)], - [Go], [_LT_LANG(GO)], - [Java], [_LT_LANG(GCJ)], - [Fortran 77], [_LT_LANG(F77)], - [Fortran], [_LT_LANG(FC)], - [Windows Resource], [_LT_LANG(RC)], - [m4_ifdef([_LT_LANG_]$1[_CONFIG], - [_LT_LANG($1)], - [m4_fatal([$0: unsupported language: "$1"])])])dnl -])# LT_LANG - - -# _LT_LANG(LANGNAME) -# ------------------ -m4_defun([_LT_LANG], -[m4_ifdef([_LT_LANG_]$1[_enabled], [], - [LT_SUPPORTED_TAG([$1])dnl - m4_append([_LT_TAGS], [$1 ])dnl - m4_define([_LT_LANG_]$1[_enabled], [])dnl - _LT_LANG_$1_CONFIG($1)])dnl -])# _LT_LANG - - -m4_ifndef([AC_PROG_GO], [ -############################################################ -# NOTE: This macro has been submitted for inclusion into # -# GNU Autoconf as AC_PROG_GO. When it is available in # -# a released version of Autoconf we should remove this # -# macro and use it instead. # -############################################################ -m4_defun([AC_PROG_GO], -[AC_LANG_PUSH(Go)dnl -AC_ARG_VAR([GOC], [Go compiler command])dnl -AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl -_AC_ARG_VAR_LDFLAGS()dnl -AC_CHECK_TOOL(GOC, gccgo) -if test -z "$GOC"; then - if test -n "$ac_tool_prefix"; then - AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) - fi -fi -if test -z "$GOC"; then - AC_CHECK_PROG(GOC, gccgo, gccgo, false) -fi -])#m4_defun -])#m4_ifndef - - -# _LT_LANG_DEFAULT_CONFIG -# ----------------------- -m4_defun([_LT_LANG_DEFAULT_CONFIG], -[AC_PROVIDE_IFELSE([AC_PROG_CXX], - [LT_LANG(CXX)], - [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) - -AC_PROVIDE_IFELSE([AC_PROG_F77], - [LT_LANG(F77)], - [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) - -AC_PROVIDE_IFELSE([AC_PROG_FC], - [LT_LANG(FC)], - [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) - -dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal -dnl pulling things in needlessly. -AC_PROVIDE_IFELSE([AC_PROG_GCJ], - [LT_LANG(GCJ)], - [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], - [LT_LANG(GCJ)], - [AC_PROVIDE_IFELSE([LT_PROG_GCJ], - [LT_LANG(GCJ)], - [m4_ifdef([AC_PROG_GCJ], - [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) - m4_ifdef([A][M_PROG_GCJ], - [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) - m4_ifdef([LT_PROG_GCJ], - [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) - -AC_PROVIDE_IFELSE([AC_PROG_GO], - [LT_LANG(GO)], - [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) - -AC_PROVIDE_IFELSE([LT_PROG_RC], - [LT_LANG(RC)], - [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) -])# _LT_LANG_DEFAULT_CONFIG - -# Obsolete macros: -AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) -AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) -AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) -AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) -AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_CXX], []) -dnl AC_DEFUN([AC_LIBTOOL_F77], []) -dnl AC_DEFUN([AC_LIBTOOL_FC], []) -dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) -dnl AC_DEFUN([AC_LIBTOOL_RC], []) - - -# _LT_TAG_COMPILER -# ---------------- -m4_defun([_LT_TAG_COMPILER], -[AC_REQUIRE([AC_PROG_CC])dnl - -_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl -_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl -_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl -_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC -])# _LT_TAG_COMPILER - - -# _LT_COMPILER_BOILERPLATE -# ------------------------ -# Check for compiler boilerplate output or warnings with -# the simple compiler test code. -m4_defun([_LT_COMPILER_BOILERPLATE], -[m4_require([_LT_DECL_SED])dnl -ac_outfile=conftest.$ac_objext -echo "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$RM conftest* -])# _LT_COMPILER_BOILERPLATE - - -# _LT_LINKER_BOILERPLATE -# ---------------------- -# Check for linker boilerplate output or warnings with -# the simple link test code. -m4_defun([_LT_LINKER_BOILERPLATE], -[m4_require([_LT_DECL_SED])dnl -ac_outfile=conftest.$ac_objext -echo "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$RM -r conftest* -])# _LT_LINKER_BOILERPLATE - -# _LT_REQUIRED_DARWIN_CHECKS -# ------------------------- -m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ - case $host_os in - rhapsody* | darwin*) - AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) - AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) - AC_CHECK_TOOL([LIPO], [lipo], [:]) - AC_CHECK_TOOL([OTOOL], [otool], [:]) - AC_CHECK_TOOL([OTOOL64], [otool64], [:]) - _LT_DECL([], [DSYMUTIL], [1], - [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) - _LT_DECL([], [NMEDIT], [1], - [Tool to change global to local symbols on Mac OS X]) - _LT_DECL([], [LIPO], [1], - [Tool to manipulate fat objects and archives on Mac OS X]) - _LT_DECL([], [OTOOL], [1], - [ldd/readelf like tool for Mach-O binaries on Mac OS X]) - _LT_DECL([], [OTOOL64], [1], - [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) - - AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], - [lt_cv_apple_cc_single_mod=no - if test -z "$LT_MULTI_MODULE"; then - # By default we will add the -single_module flag. You can override - # by either setting the environment variable LT_MULTI_MODULE - # non-empty at configure time, or by adding -multi_module to the - # link flags. - rm -rf libconftest.dylib* - echo "int foo(void){return 1;}" > conftest.c - echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ --dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD - $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ - -dynamiclib -Wl,-single_module conftest.c 2>conftest.err - _lt_result=$? - # If there is a non-empty error log, and "single_module" - # appears in it, assume the flag caused a linker warning - if test -s conftest.err && $GREP single_module conftest.err; then - cat conftest.err >&AS_MESSAGE_LOG_FD - # Otherwise, if the output was created with a 0 exit code from - # the compiler, it worked. - elif test -f libconftest.dylib && test 0 = "$_lt_result"; then - lt_cv_apple_cc_single_mod=yes - else - cat conftest.err >&AS_MESSAGE_LOG_FD - fi - rm -rf libconftest.dylib* - rm -f conftest.* - fi]) - - AC_CACHE_CHECK([for -exported_symbols_list linker flag], - [lt_cv_ld_exported_symbols_list], - [lt_cv_ld_exported_symbols_list=no - save_LDFLAGS=$LDFLAGS - echo "_main" > conftest.sym - LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" - AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], - [lt_cv_ld_exported_symbols_list=yes], - [lt_cv_ld_exported_symbols_list=no]) - LDFLAGS=$save_LDFLAGS - ]) - - AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], - [lt_cv_ld_force_load=no - cat > conftest.c << _LT_EOF -int forced_loaded() { return 2;} -_LT_EOF - echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD - $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD - echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD - $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD - echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD - $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD - cat > conftest.c << _LT_EOF -int main() { return 0;} -_LT_EOF - echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD - $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err - _lt_result=$? - if test -s conftest.err && $GREP force_load conftest.err; then - cat conftest.err >&AS_MESSAGE_LOG_FD - elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then - lt_cv_ld_force_load=yes - else - cat conftest.err >&AS_MESSAGE_LOG_FD - fi - rm -f conftest.err libconftest.a conftest conftest.c - rm -rf conftest.dSYM - ]) - case $host_os in - rhapsody* | darwin1.[[012]]) - _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; - darwin1.*) - _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; - darwin*) # darwin 5.x on - # if running on 10.5 or later, the deployment target defaults - # to the OS version, if on x86, and 10.4, the deployment - # target defaults to 10.4. Don't you love it? - case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in - 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) - _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; - 10.[[012]][[,.]]*) - _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; - 10.*) - _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; - esac - ;; - esac - if test yes = "$lt_cv_apple_cc_single_mod"; then - _lt_dar_single_mod='$single_module' - fi - if test yes = "$lt_cv_ld_exported_symbols_list"; then - _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' - else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' - fi - if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then - _lt_dsymutil='~$DSYMUTIL $lib || :' - else - _lt_dsymutil= - fi - ;; - esac -]) - - -# _LT_DARWIN_LINKER_FEATURES([TAG]) -# --------------------------------- -# Checks for linker and compiler features on darwin -m4_defun([_LT_DARWIN_LINKER_FEATURES], -[ - m4_require([_LT_REQUIRED_DARWIN_CHECKS]) - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_automatic, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - if test yes = "$lt_cv_ld_force_load"; then - _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' - m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], - [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) - else - _LT_TAGVAR(whole_archive_flag_spec, $1)='' - fi - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined - case $cc_basename in - ifort*|nagfor*) _lt_dar_can_shared=yes ;; - *) _lt_dar_can_shared=$GCC ;; - esac - if test yes = "$_lt_dar_can_shared"; then - output_verbose_link_cmd=func_echo_all - _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" - _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" - _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" - m4_if([$1], [CXX], -[ if test yes != "$lt_cv_apple_cc_single_mod"; then - _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" - fi -],[]) - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi -]) - -# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) -# ---------------------------------- -# Links a minimal program and checks the executable -# for the system default hardcoded library path. In most cases, -# this is /usr/lib:/lib, but when the MPI compilers are used -# the location of the communication and MPI libs are included too. -# If we don't find anything, use the default library path according -# to the aix ld manual. -# Store the results from the different compilers for each TAGNAME. -# Allow to override them for all tags through lt_cv_aix_libpath. -m4_defun([_LT_SYS_MODULE_PATH_AIX], -[m4_require([_LT_DECL_SED])dnl -if test set = "${lt_cv_aix_libpath+set}"; then - aix_libpath=$lt_cv_aix_libpath -else - AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], - [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ - lt_aix_libpath_sed='[ - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\([^ ]*\) *$/\1/ - p - } - }]' - _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - # Check for a 64-bit object if we didn't find anything. - if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then - _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - fi],[]) - if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then - _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib - fi - ]) - aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) -fi -])# _LT_SYS_MODULE_PATH_AIX - - -# _LT_SHELL_INIT(ARG) -# ------------------- -m4_define([_LT_SHELL_INIT], -[m4_divert_text([M4SH-INIT], [$1 -])])# _LT_SHELL_INIT - - - -# _LT_PROG_ECHO_BACKSLASH -# ----------------------- -# Find how we can fake an echo command that does not interpret backslash. -# In particular, with Autoconf 2.60 or later we add some code to the start -# of the generated configure script that will find a shell with a builtin -# printf (that we can use as an echo command). -m4_defun([_LT_PROG_ECHO_BACKSLASH], -[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO -ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO - -AC_MSG_CHECKING([how to print strings]) -# Test print first, because it will be a builtin if present. -if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ - test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then - ECHO='print -r --' -elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then - ECHO='printf %s\n' -else - # Use this function as a fallback that always works. - func_fallback_echo () - { - eval 'cat <<_LTECHO_EOF -$[]1 -_LTECHO_EOF' - } - ECHO='func_fallback_echo' -fi - -# func_echo_all arg... -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "$*" -} - -case $ECHO in - printf*) AC_MSG_RESULT([printf]) ;; - print*) AC_MSG_RESULT([print -r]) ;; - *) AC_MSG_RESULT([cat]) ;; -esac - -m4_ifdef([_AS_DETECT_SUGGESTED], -[_AS_DETECT_SUGGESTED([ - test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( - ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' - ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO - ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO - PATH=/empty FPATH=/empty; export PATH FPATH - test "X`printf %s $ECHO`" = "X$ECHO" \ - || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) - -_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) -_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) -])# _LT_PROG_ECHO_BACKSLASH - - -# _LT_WITH_SYSROOT -# ---------------- -AC_DEFUN([_LT_WITH_SYSROOT], -[AC_MSG_CHECKING([for sysroot]) -AC_ARG_WITH([sysroot], -[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], - [Search for dependent libraries within DIR (or the compiler's sysroot - if not specified).])], -[], [with_sysroot=no]) - -dnl lt_sysroot will always be passed unquoted. We quote it here -dnl in case the user passed a directory name. -lt_sysroot= -case $with_sysroot in #( - yes) - if test yes = "$GCC"; then - lt_sysroot=`$CC --print-sysroot 2>/dev/null` - fi - ;; #( - /*) - lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` - ;; #( - no|'') - ;; #( - *) - AC_MSG_RESULT([$with_sysroot]) - AC_MSG_ERROR([The sysroot must be an absolute path.]) - ;; -esac - - AC_MSG_RESULT([${lt_sysroot:-no}]) -_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl -[dependent libraries, and where our libraries should be installed.])]) - -# _LT_ENABLE_LOCK -# --------------- -m4_defun([_LT_ENABLE_LOCK], -[AC_ARG_ENABLE([libtool-lock], - [AS_HELP_STRING([--disable-libtool-lock], - [avoid locking (might break parallel builds)])]) -test no = "$enable_libtool_lock" || enable_libtool_lock=yes - -# Some flags need to be propagated to the compiler or linker for good -# libtool support. -case $host in -ia64-*-hpux*) - # Find out what ABI is being produced by ac_compile, and set mode - # options accordingly. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.$ac_objext` in - *ELF-32*) - HPUX_IA64_MODE=32 - ;; - *ELF-64*) - HPUX_IA64_MODE=64 - ;; - esac - fi - rm -rf conftest* - ;; -*-*-irix6*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. - echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - if test yes = "$lt_cv_prog_gnu_ld"; then - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -melf32bsmip" - ;; - *N32*) - LD="${LD-ld} -melf32bmipn32" - ;; - *64-bit*) - LD="${LD-ld} -melf64bmip" - ;; - esac - else - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -32" - ;; - *N32*) - LD="${LD-ld} -n32" - ;; - *64-bit*) - LD="${LD-ld} -64" - ;; - esac - fi - fi - rm -rf conftest* - ;; - -mips64*-*linux*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. - echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - emul=elf - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - emul="${emul}32" - ;; - *64-bit*) - emul="${emul}64" - ;; - esac - case `/usr/bin/file conftest.$ac_objext` in - *MSB*) - emul="${emul}btsmip" - ;; - *LSB*) - emul="${emul}ltsmip" - ;; - esac - case `/usr/bin/file conftest.$ac_objext` in - *N32*) - emul="${emul}n32" - ;; - esac - LD="${LD-ld} -m $emul" - fi - rm -rf conftest* - ;; - -x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ -s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. Note that the listed cases only cover the - # situations where additional linker options are needed (such as when - # doing 32-bit compilation for a host where ld defaults to 64-bit, or - # vice versa); the common cases where no linker options are needed do - # not appear in the list. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.o` in - *32-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_i386_fbsd" - ;; - x86_64-*linux*) - case `/usr/bin/file conftest.o` in - *x86-64*) - LD="${LD-ld} -m elf32_x86_64" - ;; - *) - LD="${LD-ld} -m elf_i386" - ;; - esac - ;; - powerpc64le-*linux*) - LD="${LD-ld} -m elf32lppclinux" - ;; - powerpc64-*linux*) - LD="${LD-ld} -m elf32ppclinux" - ;; - s390x-*linux*) - LD="${LD-ld} -m elf_s390" - ;; - sparc64-*linux*) - LD="${LD-ld} -m elf32_sparc" - ;; - esac - ;; - *64-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_x86_64_fbsd" - ;; - x86_64-*linux*) - LD="${LD-ld} -m elf_x86_64" - ;; - powerpcle-*linux*) - LD="${LD-ld} -m elf64lppc" - ;; - powerpc-*linux*) - LD="${LD-ld} -m elf64ppc" - ;; - s390*-*linux*|s390*-*tpf*) - LD="${LD-ld} -m elf64_s390" - ;; - sparc*-*linux*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; - -*-*-sco3.2v5*) - # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS -belf" - AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, - [AC_LANG_PUSH(C) - AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) - AC_LANG_POP]) - if test yes != "$lt_cv_cc_needs_belf"; then - # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS=$SAVE_CFLAGS - fi - ;; -*-*solaris*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.o` in - *64-bit*) - case $lt_cv_prog_gnu_ld in - yes*) - case $host in - i?86-*-solaris*|x86_64-*-solaris*) - LD="${LD-ld} -m elf_x86_64" - ;; - sparc*-*-solaris*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - # GNU ld 2.21 introduced _sol2 emulations. Use them if available. - if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then - LD=${LD-ld}_sol2 - fi - ;; - *) - if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then - LD="${LD-ld} -64" - fi - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; -esac - -need_locks=$enable_libtool_lock -])# _LT_ENABLE_LOCK - - -# _LT_PROG_AR -# ----------- -m4_defun([_LT_PROG_AR], -[AC_CHECK_TOOLS(AR, [ar], false) -: ${AR=ar} -: ${AR_FLAGS=cru} -_LT_DECL([], [AR], [1], [The archiver]) -_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) - -AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], - [lt_cv_ar_at_file=no - AC_COMPILE_IFELSE([AC_LANG_PROGRAM], - [echo conftest.$ac_objext > conftest.lst - lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' - AC_TRY_EVAL([lt_ar_try]) - if test 0 -eq "$ac_status"; then - # Ensure the archiver fails upon bogus file names. - rm -f conftest.$ac_objext libconftest.a - AC_TRY_EVAL([lt_ar_try]) - if test 0 -ne "$ac_status"; then - lt_cv_ar_at_file=@ - fi - fi - rm -f conftest.* libconftest.a - ]) - ]) - -if test no = "$lt_cv_ar_at_file"; then - archiver_list_spec= -else - archiver_list_spec=$lt_cv_ar_at_file -fi -_LT_DECL([], [archiver_list_spec], [1], - [How to feed a file listing to the archiver]) -])# _LT_PROG_AR - - -# _LT_CMD_OLD_ARCHIVE -# ------------------- -m4_defun([_LT_CMD_OLD_ARCHIVE], -[_LT_PROG_AR - -AC_CHECK_TOOL(STRIP, strip, :) -test -z "$STRIP" && STRIP=: -_LT_DECL([], [STRIP], [1], [A symbol stripping program]) - -AC_CHECK_TOOL(RANLIB, ranlib, :) -test -z "$RANLIB" && RANLIB=: -_LT_DECL([], [RANLIB], [1], - [Commands used to install an old-style archive]) - -# Determine commands to create old-style static archives. -old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' -old_postinstall_cmds='chmod 644 $oldlib' -old_postuninstall_cmds= - -if test -n "$RANLIB"; then - case $host_os in - bitrig* | openbsd*) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" - ;; - *) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" - ;; - esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" -fi - -case $host_os in - darwin*) - lock_old_archive_extraction=yes ;; - *) - lock_old_archive_extraction=no ;; -esac -_LT_DECL([], [old_postinstall_cmds], [2]) -_LT_DECL([], [old_postuninstall_cmds], [2]) -_LT_TAGDECL([], [old_archive_cmds], [2], - [Commands used to build an old-style archive]) -_LT_DECL([], [lock_old_archive_extraction], [0], - [Whether to use a lock for old archive extraction]) -])# _LT_CMD_OLD_ARCHIVE - - -# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) -# ---------------------------------------------------------------- -# Check whether the given compiler option works -AC_DEFUN([_LT_COMPILER_OPTION], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_SED])dnl -AC_CACHE_CHECK([$1], [$2], - [$2=no - m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - $2=yes - fi - fi - $RM conftest* -]) - -if test yes = "[$]$2"; then - m4_if([$5], , :, [$5]) -else - m4_if([$6], , :, [$6]) -fi -])# _LT_COMPILER_OPTION - -# Old name: -AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) - - -# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [ACTION-SUCCESS], [ACTION-FAILURE]) -# ---------------------------------------------------- -# Check whether the given linker option works -AC_DEFUN([_LT_LINKER_OPTION], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_SED])dnl -AC_CACHE_CHECK([$1], [$2], - [$2=no - save_LDFLAGS=$LDFLAGS - LDFLAGS="$LDFLAGS $3" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&AS_MESSAGE_LOG_FD - $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - $2=yes - fi - else - $2=yes - fi - fi - $RM -r conftest* - LDFLAGS=$save_LDFLAGS -]) - -if test yes = "[$]$2"; then - m4_if([$4], , :, [$4]) -else - m4_if([$5], , :, [$5]) -fi -])# _LT_LINKER_OPTION - -# Old name: -AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) - - -# LT_CMD_MAX_LEN -#--------------- -AC_DEFUN([LT_CMD_MAX_LEN], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -# find the maximum length of command line arguments -AC_MSG_CHECKING([the maximum length of command line arguments]) -AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl - i=0 - teststring=ABCD - - case $build_os in - msdosdjgpp*) - # On DJGPP, this test can blow up pretty badly due to problems in libc - # (any single argument exceeding 2000 bytes causes a buffer overrun - # during glob expansion). Even if it were fixed, the result of this - # check would be larger than it should be. - lt_cv_sys_max_cmd_len=12288; # 12K is about right - ;; - - gnu*) - # Under GNU Hurd, this test is not required because there is - # no limit to the length of command line arguments. - # Libtool will interpret -1 as no limit whatsoever - lt_cv_sys_max_cmd_len=-1; - ;; - - cygwin* | mingw* | cegcc*) - # On Win9x/ME, this test blows up -- it succeeds, but takes - # about 5 minutes as the teststring grows exponentially. - # Worse, since 9x/ME are not pre-emptively multitasking, - # you end up with a "frozen" computer, even though with patience - # the test eventually succeeds (with a max line length of 256k). - # Instead, let's just punt: use the minimum linelength reported by - # all of the supported platforms: 8192 (on NT/2K/XP). - lt_cv_sys_max_cmd_len=8192; - ;; - - mint*) - # On MiNT this can take a long time and run out of memory. - lt_cv_sys_max_cmd_len=8192; - ;; - - amigaos*) - # On AmigaOS with pdksh, this test takes hours, literally. - # So we just punt and use a minimum line length of 8192. - lt_cv_sys_max_cmd_len=8192; - ;; - - bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) - # This has been around since 386BSD, at least. Likely further. - if test -x /sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` - elif test -x /usr/sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` - else - lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs - fi - # And add a safety zone - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - ;; - - interix*) - # We know the value 262144 and hardcode it with a safety zone (like BSD) - lt_cv_sys_max_cmd_len=196608 - ;; - - os2*) - # The test takes a long time on OS/2. - lt_cv_sys_max_cmd_len=8192 - ;; - - osf*) - # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure - # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not - # nice to cause kernel panics so lets avoid the loop below. - # First set a reasonable default. - lt_cv_sys_max_cmd_len=16384 - # - if test -x /sbin/sysconfig; then - case `/sbin/sysconfig -q proc exec_disable_arg_limit` in - *1*) lt_cv_sys_max_cmd_len=-1 ;; - esac - fi - ;; - sco3.2v5*) - lt_cv_sys_max_cmd_len=102400 - ;; - sysv5* | sco5v6* | sysv4.2uw2*) - kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` - if test -n "$kargmax"; then - lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` - else - lt_cv_sys_max_cmd_len=32768 - fi - ;; - *) - lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` - if test -n "$lt_cv_sys_max_cmd_len" && \ - test undefined != "$lt_cv_sys_max_cmd_len"; then - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - else - # Make teststring a little bigger before we do anything with it. - # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8; do - teststring=$teststring$teststring - done - SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} - # If test is not a shell built-in, we'll probably end up computing a - # maximum length that is only half of the actual maximum length, but - # we can't tell. - while { test X`env echo "$teststring$teststring" 2>/dev/null` \ - = "X$teststring$teststring"; } >/dev/null 2>&1 && - test 17 != "$i" # 1/2 MB should be enough - do - i=`expr $i + 1` - teststring=$teststring$teststring - done - # Only check the string length outside the loop. - lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` - teststring= - # Add a significant safety factor because C++ compilers can tack on - # massive amounts of additional arguments before passing them to the - # linker. It appears as though 1/2 is a usable value. - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` - fi - ;; - esac -]) -if test -n "$lt_cv_sys_max_cmd_len"; then - AC_MSG_RESULT($lt_cv_sys_max_cmd_len) -else - AC_MSG_RESULT(none) -fi -max_cmd_len=$lt_cv_sys_max_cmd_len -_LT_DECL([], [max_cmd_len], [0], - [What is the maximum length of a command?]) -])# LT_CMD_MAX_LEN - -# Old name: -AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) - - -# _LT_HEADER_DLFCN -# ---------------- -m4_defun([_LT_HEADER_DLFCN], -[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl -])# _LT_HEADER_DLFCN - - -# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, -# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) -# ---------------------------------------------------------------- -m4_defun([_LT_TRY_DLOPEN_SELF], -[m4_require([_LT_HEADER_DLFCN])dnl -if test yes = "$cross_compiling"; then : - [$4] -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext <<_LT_EOF -[#line $LINENO "configure" -#include "confdefs.h" - -#if HAVE_DLFCN_H -#include -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -/* When -fvisibility=hidden is used, assume the code has been annotated - correspondingly for the symbols needed. */ -#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) -int fnord () __attribute__((visibility("default"))); -#endif - -int fnord () { return 42; } -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else - { - if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - else puts (dlerror ()); - } - /* dlclose (self); */ - } - else - puts (dlerror ()); - - return status; -}] -_LT_EOF - if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then - (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) $1 ;; - x$lt_dlneed_uscore) $2 ;; - x$lt_dlunknown|x*) $3 ;; - esac - else : - # compilation failed - $3 - fi -fi -rm -fr conftest* -])# _LT_TRY_DLOPEN_SELF - - -# LT_SYS_DLOPEN_SELF -# ------------------ -AC_DEFUN([LT_SYS_DLOPEN_SELF], -[m4_require([_LT_HEADER_DLFCN])dnl -if test yes != "$enable_dlopen"; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen=load_add_on - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32* | cegcc*) - lt_cv_dlopen=LoadLibrary - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen=dlopen - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ - lt_cv_dlopen=dyld - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ]) - ;; - - tpf*) - # Don't try to run any link tests for TPF. We know it's impossible - # because TPF is a cross-compiler, and we know how we open DSOs. - lt_cv_dlopen=dlopen - lt_cv_dlopen_libs= - lt_cv_dlopen_self=no - ;; - - *) - AC_CHECK_FUNC([shl_load], - [lt_cv_dlopen=shl_load], - [AC_CHECK_LIB([dld], [shl_load], - [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], - [AC_CHECK_FUNC([dlopen], - [lt_cv_dlopen=dlopen], - [AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], - [AC_CHECK_LIB([svld], [dlopen], - [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], - [AC_CHECK_LIB([dld], [dld_link], - [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) - ]) - ]) - ]) - ]) - ]) - ;; - esac - - if test no = "$lt_cv_dlopen"; then - enable_dlopen=no - else - enable_dlopen=yes - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS=$CPPFLAGS - test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS=$LDFLAGS - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS=$LIBS - LIBS="$lt_cv_dlopen_libs $LIBS" - - AC_CACHE_CHECK([whether a program can dlopen itself], - lt_cv_dlopen_self, [dnl - _LT_TRY_DLOPEN_SELF( - lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, - lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) - ]) - - if test yes = "$lt_cv_dlopen_self"; then - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" - AC_CACHE_CHECK([whether a statically linked program can dlopen itself], - lt_cv_dlopen_self_static, [dnl - _LT_TRY_DLOPEN_SELF( - lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, - lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) - ]) - fi - - CPPFLAGS=$save_CPPFLAGS - LDFLAGS=$save_LDFLAGS - LIBS=$save_LIBS - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi -_LT_DECL([dlopen_support], [enable_dlopen], [0], - [Whether dlopen is supported]) -_LT_DECL([dlopen_self], [enable_dlopen_self], [0], - [Whether dlopen of programs is supported]) -_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], - [Whether dlopen of statically linked programs is supported]) -])# LT_SYS_DLOPEN_SELF - -# Old name: -AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) - - -# _LT_COMPILER_C_O([TAGNAME]) -# --------------------------- -# Check to see if options -c and -o are simultaneously supported by compiler. -# This macro does not hard code the compiler like AC_PROG_CC_C_O. -m4_defun([_LT_COMPILER_C_O], -[m4_require([_LT_DECL_SED])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_TAG_COMPILER])dnl -AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], - [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], - [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no - $RM -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes - fi - fi - chmod u+w . 2>&AS_MESSAGE_LOG_FD - $RM conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files - $RM out/* && rmdir out - cd .. - $RM -r conftest - $RM conftest* -]) -_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], - [Does compiler simultaneously support -c and -o options?]) -])# _LT_COMPILER_C_O - - -# _LT_COMPILER_FILE_LOCKS([TAGNAME]) -# ---------------------------------- -# Check to see if we can do hard links to lock some files if needed -m4_defun([_LT_COMPILER_FILE_LOCKS], -[m4_require([_LT_ENABLE_LOCK])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -_LT_COMPILER_C_O([$1]) - -hard_links=nottested -if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then - # do not overwrite the value of need_locks provided by the user - AC_MSG_CHECKING([if we can lock with hard links]) - hard_links=yes - $RM conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - AC_MSG_RESULT([$hard_links]) - if test no = "$hard_links"; then - AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) - need_locks=warn - fi -else - need_locks=no -fi -_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) -])# _LT_COMPILER_FILE_LOCKS - - -# _LT_CHECK_OBJDIR -# ---------------- -m4_defun([_LT_CHECK_OBJDIR], -[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], -[rm -f .libs 2>/dev/null -mkdir .libs 2>/dev/null -if test -d .libs; then - lt_cv_objdir=.libs -else - # MS-DOS does not allow filenames that begin with a dot. - lt_cv_objdir=_libs -fi -rmdir .libs 2>/dev/null]) -objdir=$lt_cv_objdir -_LT_DECL([], [objdir], [0], - [The name of the directory that contains temporary libtool files])dnl -m4_pattern_allow([LT_OBJDIR])dnl -AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", - [Define to the sub-directory where libtool stores uninstalled libraries.]) -])# _LT_CHECK_OBJDIR - - -# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) -# -------------------------------------- -# Check hardcoding attributes. -m4_defun([_LT_LINKER_HARDCODE_LIBPATH], -[AC_MSG_CHECKING([how to hardcode library paths into programs]) -_LT_TAGVAR(hardcode_action, $1)= -if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || - test -n "$_LT_TAGVAR(runpath_var, $1)" || - test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then - - # We can hardcode non-existent directories. - if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && - test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then - # Linking always hardcodes the temporary library directory. - _LT_TAGVAR(hardcode_action, $1)=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - _LT_TAGVAR(hardcode_action, $1)=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - _LT_TAGVAR(hardcode_action, $1)=unsupported -fi -AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) - -if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || - test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then - # Fast installation is not supported - enable_fast_install=no -elif test yes = "$shlibpath_overrides_runpath" || - test no = "$enable_shared"; then - # Fast installation is not necessary - enable_fast_install=needless -fi -_LT_TAGDECL([], [hardcode_action], [0], - [How to hardcode a shared library path into an executable]) -])# _LT_LINKER_HARDCODE_LIBPATH - - -# _LT_CMD_STRIPLIB -# ---------------- -m4_defun([_LT_CMD_STRIPLIB], -[m4_require([_LT_DECL_EGREP]) -striplib= -old_striplib= -AC_MSG_CHECKING([whether stripping libraries is possible]) -if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - AC_MSG_RESULT([yes]) -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP"; then - striplib="$STRIP -x" - old_striplib="$STRIP -S" - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - ;; - *) - AC_MSG_RESULT([no]) - ;; - esac -fi -_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) -_LT_DECL([], [striplib], [1]) -])# _LT_CMD_STRIPLIB - - -# _LT_PREPARE_MUNGE_PATH_LIST -# --------------------------- -# Make sure func_munge_path_list() is defined correctly. -m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], -[[# func_munge_path_list VARIABLE PATH -# ----------------------------------- -# VARIABLE is name of variable containing _space_ separated list of -# directories to be munged by the contents of PATH, which is string -# having a format: -# "DIR[:DIR]:" -# string "DIR[ DIR]" will be prepended to VARIABLE -# ":DIR[:DIR]" -# string "DIR[ DIR]" will be appended to VARIABLE -# "DIRP[:DIRP]::[DIRA:]DIRA" -# string "DIRP[ DIRP]" will be prepended to VARIABLE and string -# "DIRA[ DIRA]" will be appended to VARIABLE -# "DIR[:DIR]" -# VARIABLE will be replaced by "DIR[ DIR]" -func_munge_path_list () -{ - case x@S|@2 in - x) - ;; - *:) - eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" - ;; - x:*) - eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" - ;; - *::*) - eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" - eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" - ;; - *) - eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" - ;; - esac -} -]])# _LT_PREPARE_PATH_LIST - - -# _LT_SYS_DYNAMIC_LINKER([TAG]) -# ----------------------------- -# PORTME Fill in your ld.so characteristics -m4_defun([_LT_SYS_DYNAMIC_LINKER], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_OBJDUMP])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_CHECK_SHELL_FEATURES])dnl -m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl -AC_MSG_CHECKING([dynamic linker characteristics]) -m4_if([$1], - [], [ -if test yes = "$GCC"; then - case $host_os in - darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; - *) lt_awk_arg='/^libraries:/' ;; - esac - case $host_os in - mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; - *) lt_sed_strip_eq='s|=/|/|g' ;; - esac - lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` - case $lt_search_path_spec in - *\;*) - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` - ;; - *) - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` - ;; - esac - # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary... - lt_tmp_lt_search_path_spec= - lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` - # ...but if some path component already ends with the multilib dir we assume - # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). - case "$lt_multi_os_dir; $lt_search_path_spec " in - "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) - lt_multi_os_dir= - ;; - esac - for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" - elif test -n "$lt_multi_os_dir"; then - test -d "$lt_sys_path" && \ - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" - fi - done - lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' -BEGIN {RS = " "; FS = "/|\n";} { - lt_foo = ""; - lt_count = 0; - for (lt_i = NF; lt_i > 0; lt_i--) { - if ($lt_i != "" && $lt_i != ".") { - if ($lt_i == "..") { - lt_count++; - } else { - if (lt_count == 0) { - lt_foo = "/" $lt_i lt_foo; - } else { - lt_count--; - } - } - } - } - if (lt_foo != "") { lt_freq[[lt_foo]]++; } - if (lt_freq[[lt_foo]] == 1) { print lt_foo; } -}'` - # AWK program above erroneously prepends '/' to C:/dos/paths - # for these hosts. - case $host_os in - mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ - $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; - esac - sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi]) -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=.so -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -AC_ARG_VAR([LT_SYS_LIBRARY_PATH], -[User-defined run-time library search path.]) - -case $host_os in -aix3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='$libname$release$shared_ext$major' - ;; - -aix[[4-9]]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test ia64 = "$host_cpu"; then - # AIX 5 supports IA64 - library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line '#! .'. This would cause the generated library to - # depend on '.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[[01]] | aix4.[[01]].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # Using Import Files as archive members, it is possible to support - # filename-based versioning of shared library archives on AIX. While - # this would work for both with and without runtime linking, it will - # prevent static linking of such archives. So we do filename-based - # shared library versioning with .so extension only, which is used - # when both runtime linking and shared linking is enabled. - # Unfortunately, runtime linking may impact performance, so we do - # not want this to be the default eventually. Also, we use the - # versioned .so libs for executables only if there is the -brtl - # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. - # To allow for filename-based versioning support, we need to create - # libNAME.so.V as an archive file, containing: - # *) an Import File, referring to the versioned filename of the - # archive as well as the shared archive member, telling the - # bitwidth (32 or 64) of that shared object, and providing the - # list of exported symbols of that shared object, eventually - # decorated with the 'weak' keyword - # *) the shared object with the F_LOADONLY flag set, to really avoid - # it being seen by the linker. - # At run time we better use the real file rather than another symlink, - # but for link time we create the symlink libNAME.so -> libNAME.so.V - - case $with_aix_soname,$aix_use_runtimelinking in - # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - aix,yes) # traditional libtool - dynamic_linker='AIX unversionable lib.so' - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - ;; - aix,no) # traditional AIX only - dynamic_linker='AIX lib.a[(]lib.so.V[)]' - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='$libname$release.a $libname.a' - soname_spec='$libname$release$shared_ext$major' - ;; - svr4,*) # full svr4 only - dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" - library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' - # We do not specify a path in Import Files, so LIBPATH fires. - shlibpath_overrides_runpath=yes - ;; - *,yes) # both, prefer svr4 - dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" - library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' - # unpreferred sharedlib libNAME.a needs extra handling - postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' - postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' - # We do not specify a path in Import Files, so LIBPATH fires. - shlibpath_overrides_runpath=yes - ;; - *,no) # both, prefer aix - dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" - library_names_spec='$libname$release.a $libname.a' - soname_spec='$libname$release$shared_ext$major' - # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling - postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' - postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' - ;; - esac - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - case $host_cpu in - powerpc) - # Since July 2007 AmigaOS4 officially supports .so libraries. - # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - ;; - m68k) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - esac - ;; - -beos*) - library_names_spec='$libname$shared_ext' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[[45]]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32* | cegcc*) - version_type=windows - shrext_cmds=.dll - need_version=no - need_lib_prefix=no - - case $GCC,$cc_basename in - yes,*) - # gcc - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' -m4_if([$1], [],[ - sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) - ;; - mingw* | cegcc*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' - ;; - esac - dynamic_linker='Win32 ld.exe' - ;; - - *,cl*) - # Native MSVC - libname_spec='$name' - soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' - library_names_spec='$libname.dll.lib' - - case $build_os in - mingw*) - sys_lib_search_path_spec= - lt_save_ifs=$IFS - IFS=';' - for lt_path in $LIB - do - IFS=$lt_save_ifs - # Let DOS variable expansion print the short 8.3 style file name. - lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` - sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" - done - IFS=$lt_save_ifs - # Convert to MSYS style. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` - ;; - cygwin*) - # Convert to unix form, then to dos form, then back to unix form - # but this time dos style (no spaces!) so that the unix form looks - # like /cygdrive/c/PROGRA~1:/cygdr... - sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` - sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` - sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - ;; - *) - sys_lib_search_path_spec=$LIB - if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then - # It is most probably a Windows format PATH. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - # FIXME: find the short name or the path components, as spaces are - # common. (e.g. "Program Files" -> "PROGRA~1") - ;; - esac - - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - dynamic_linker='Win32 link.exe' - ;; - - *) - # Assume MSVC wrapper - library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' - dynamic_linker='Win32 ld.exe' - ;; - esac - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' - soname_spec='$libname$release$major$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' -m4_if([$1], [],[ - sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[[23]].*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2.*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[[01]]* | freebsdelf3.[[01]]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ - freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - *) # from 4.6 on, and DragonFly - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -haiku*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - dynamic_linker="$host_os runtime_loader" - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=no - sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - if test 32 = "$HPUX_IA64_MODE"; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - sys_lib_dlsearch_path_spec=/usr/lib/hpux32 - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - sys_lib_dlsearch_path_spec=/usr/lib/hpux64 - fi - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555, ... - postinstall_cmds='chmod 555 $lib' - # or fails outright, so override atomically: - install_override_mode=555 - ;; - -interix[[3-9]]*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test yes = "$lt_cv_prog_gnu_ld"; then - version_type=linux # correct to gnu/linux during the next big refactor - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='$libname$release$shared_ext$major' - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" - sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -linux*android*) - version_type=none # Android doesn't support versioned libraries. - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext' - soname_spec='$libname$release$shared_ext' - finish_cmds= - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - dynamic_linker='Android linker' - # Don't embed -rpath directories since the linker doesn't support them. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - ;; - -# This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - - # Some binutils ld are patched to set DT_RUNPATH - AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], - [lt_cv_shlibpath_overrides_runpath=no - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ - LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" - AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], - [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], - [lt_cv_shlibpath_overrides_runpath=yes])]) - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir - ]) - shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Ideally, we could use ldconfig to report *all* directores which are - # searched for libraries, however this is still not possible. Aside from not - # being certain /sbin/ldconfig is available, command - # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, - # even though it is searched at run-time. Try to do the best guess by - # appending ld.so.conf contents (and includes) to the search path. - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -netbsdelf*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='NetBSD ld.elf_so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -*nto* | *qnx*) - version_type=qnx - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='ldqnx.so' - ;; - -openbsd* | bitrig*) - version_type=sunos - sys_lib_dlsearch_path_spec=/usr/lib - need_lib_prefix=no - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then - need_version=no - else - need_version=yes - fi - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -os2*) - libname_spec='$name' - version_type=windows - shrext_cmds=.dll - need_version=no - need_lib_prefix=no - # OS/2 can only load a DLL with a base name of 8 characters or less. - soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; - v=$($ECHO $release$versuffix | tr -d .-); - n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); - $ECHO $n$v`$shared_ext' - library_names_spec='${libname}_dll.$libext' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=BEGINLIBPATH - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='$libname$release$shared_ext$major' - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - -rdos*) - dynamic_linker=no - ;; - -solaris*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test yes = "$with_gnu_ld"; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec; then - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' - soname_spec='$libname$shared_ext.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=sco - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - if test yes = "$with_gnu_ld"; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -tpf*) - # TPF is a cross-target only. Preferred cross-host = GNU/Linux. - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -uts4*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -AC_MSG_RESULT([$dynamic_linker]) -test no = "$dynamic_linker" && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test yes = "$GCC"; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then - sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec -fi - -if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then - sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec -fi - -# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... -configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec - -# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code -func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" - -# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool -configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH - -_LT_DECL([], [variables_saved_for_relink], [1], - [Variables whose values should be saved in libtool wrapper scripts and - restored at link time]) -_LT_DECL([], [need_lib_prefix], [0], - [Do we need the "lib" prefix for modules?]) -_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) -_LT_DECL([], [version_type], [0], [Library versioning type]) -_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) -_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) -_LT_DECL([], [shlibpath_overrides_runpath], [0], - [Is shlibpath searched before the hard-coded library search path?]) -_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) -_LT_DECL([], [library_names_spec], [1], - [[List of archive names. First name is the real one, the rest are links. - The last name is the one that the linker finds with -lNAME]]) -_LT_DECL([], [soname_spec], [1], - [[The coded name of the library, if different from the real name]]) -_LT_DECL([], [install_override_mode], [1], - [Permission mode override for installation of shared libraries]) -_LT_DECL([], [postinstall_cmds], [2], - [Command to use after installation of a shared archive]) -_LT_DECL([], [postuninstall_cmds], [2], - [Command to use after uninstallation of a shared archive]) -_LT_DECL([], [finish_cmds], [2], - [Commands used to finish a libtool library installation in a directory]) -_LT_DECL([], [finish_eval], [1], - [[As "finish_cmds", except a single script fragment to be evaled but - not shown]]) -_LT_DECL([], [hardcode_into_libs], [0], - [Whether we should hardcode library paths into libraries]) -_LT_DECL([], [sys_lib_search_path_spec], [2], - [Compile-time system search path for libraries]) -_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], - [Detected run-time system search path for libraries]) -_LT_DECL([], [configure_time_lt_sys_library_path], [2], - [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) -])# _LT_SYS_DYNAMIC_LINKER - - -# _LT_PATH_TOOL_PREFIX(TOOL) -# -------------------------- -# find a file program that can recognize shared library -AC_DEFUN([_LT_PATH_TOOL_PREFIX], -[m4_require([_LT_DECL_EGREP])dnl -AC_MSG_CHECKING([for $1]) -AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, -[case $MAGIC_CMD in -[[\\/*] | ?:[\\/]*]) - lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD=$MAGIC_CMD - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR -dnl $ac_dummy forces splitting on constant user-supplied paths. -dnl POSIX.2 word splitting is done only on the output of word expansions, -dnl not every word. This closes a longstanding sh security hole. - ac_dummy="m4_if([$2], , $PATH, [$2])" - for ac_dir in $ac_dummy; do - IFS=$lt_save_ifs - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$1"; then - lt_cv_path_MAGIC_CMD=$ac_dir/"$1" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD=$lt_cv_path_MAGIC_CMD - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <<_LT_EOF 1>&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -_LT_EOF - fi ;; - esac - fi - break - fi - done - IFS=$lt_save_ifs - MAGIC_CMD=$lt_save_MAGIC_CMD - ;; -esac]) -MAGIC_CMD=$lt_cv_path_MAGIC_CMD -if test -n "$MAGIC_CMD"; then - AC_MSG_RESULT($MAGIC_CMD) -else - AC_MSG_RESULT(no) -fi -_LT_DECL([], [MAGIC_CMD], [0], - [Used to examine libraries when file_magic_cmd begins with "file"])dnl -])# _LT_PATH_TOOL_PREFIX - -# Old name: -AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) - - -# _LT_PATH_MAGIC -# -------------- -# find a file program that can recognize a shared library -m4_defun([_LT_PATH_MAGIC], -[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) -if test -z "$lt_cv_path_MAGIC_CMD"; then - if test -n "$ac_tool_prefix"; then - _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) - else - MAGIC_CMD=: - fi -fi -])# _LT_PATH_MAGIC - - -# LT_PATH_LD -# ---------- -# find the pathname to the GNU or non-GNU linker -AC_DEFUN([LT_PATH_LD], -[AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_PROG_ECHO_BACKSLASH])dnl - -AC_ARG_WITH([gnu-ld], - [AS_HELP_STRING([--with-gnu-ld], - [assume the C compiler uses GNU ld @<:@default=no@:>@])], - [test no = "$withval" || with_gnu_ld=yes], - [with_gnu_ld=no])dnl - -ac_prog=ld -if test yes = "$GCC"; then - # Check if gcc -print-prog-name=ld gives a path. - AC_MSG_CHECKING([for ld used by $CC]) - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return, which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [[\\/]]* | ?:[[\\/]]*) - re_direlt='/[[^/]][[^/]]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` - while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do - ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD=$ac_prog - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test yes = "$with_gnu_ld"; then - AC_MSG_CHECKING([for GNU ld]) -else - AC_MSG_CHECKING([for non-GNU ld]) -fi -AC_CACHE_VAL(lt_cv_path_LD, -[if test -z "$LD"; then - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS=$lt_save_ifs - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD=$ac_dir/$ac_prog - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some variants of GNU ld only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i -cat conftest.i conftest.i >conftest2.i -: ${lt_DD:=$DD} -AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], -[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then - cmp -s conftest.i conftest.out \ - && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: -fi]) -rm -f conftest.i conftest2.i conftest.out]) -])# _LT_PATH_DD - - -# _LT_CMD_TRUNCATE -# ---------------- -# find command to truncate a binary pipe -m4_defun([_LT_CMD_TRUNCATE], -[m4_require([_LT_PATH_DD]) -AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], -[printf 0123456789abcdef0123456789abcdef >conftest.i -cat conftest.i conftest.i >conftest2.i -lt_cv_truncate_bin= -if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then - cmp -s conftest.i conftest.out \ - && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" -fi -rm -f conftest.i conftest2.i conftest.out -test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) -_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], - [Command to truncate a binary pipe]) -])# _LT_CMD_TRUNCATE - - -# _LT_CHECK_MAGIC_METHOD -# ---------------------- -# how to check for library dependencies -# -- PORTME fill in with the dynamic library characteristics -m4_defun([_LT_CHECK_MAGIC_METHOD], -[m4_require([_LT_DECL_EGREP]) -m4_require([_LT_DECL_OBJDUMP]) -AC_CACHE_CHECK([how to recognize dependent libraries], -lt_cv_deplibs_check_method, -[lt_cv_file_magic_cmd='$MAGIC_CMD' -lt_cv_file_magic_test_file= -lt_cv_deplibs_check_method='unknown' -# Need to set the preceding variable on all platforms that support -# interlibrary dependencies. -# 'none' -- dependencies not supported. -# 'unknown' -- same as none, but documents that we really don't know. -# 'pass_all' -- all dependencies passed with no checks. -# 'test_compile' -- check by making test program. -# 'file_magic [[regex]]' -- check by looking for files in library path -# that responds to the $file_magic_cmd with a given extended regex. -# If you have 'file' or equivalent on your system and you're not sure -# whether 'pass_all' will *always* work, you probably want this one. - -case $host_os in -aix[[4-9]]*) - lt_cv_deplibs_check_method=pass_all - ;; - -beos*) - lt_cv_deplibs_check_method=pass_all - ;; - -bsdi[[45]]*) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' - lt_cv_file_magic_cmd='/usr/bin/file -L' - lt_cv_file_magic_test_file=/shlib/libc.so - ;; - -cygwin*) - # func_win32_libid is a shell function defined in ltmain.sh - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - ;; - -mingw* | pw32*) - # Base MSYS/MinGW do not provide the 'file' command needed by - # func_win32_libid shell function, so use a weaker test based on 'objdump', - # unless we find 'file', for example because we are cross-compiling. - if ( file / ) >/dev/null 2>&1; then - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - else - # Keep this pattern in sync with the one in func_win32_libid. - lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' - lt_cv_file_magic_cmd='$OBJDUMP -f' - fi - ;; - -cegcc*) - # use the weaker test based on 'objdump'. See mingw*. - lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' - ;; - -darwin* | rhapsody*) - lt_cv_deplibs_check_method=pass_all - ;; - -freebsd* | dragonfly*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - case $host_cpu in - i*86 ) - # Not sure whether the presence of OpenBSD here was a mistake. - # Let's accept both of them until this is cleared up. - lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - ;; - esac - else - lt_cv_deplibs_check_method=pass_all - fi - ;; - -haiku*) - lt_cv_deplibs_check_method=pass_all - ;; - -hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file - case $host_cpu in - ia64*) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' - lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so - ;; - hppa*64*) - [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] - lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl - ;; - *) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' - lt_cv_file_magic_test_file=/usr/lib/libc.sl - ;; - esac - ;; - -interix[[3-9]]*) - # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' - ;; - -irix5* | irix6* | nonstopux*) - case $LD in - *-32|*"-32 ") libmagic=32-bit;; - *-n32|*"-n32 ") libmagic=N32;; - *-64|*"-64 ") libmagic=64-bit;; - *) libmagic=never-match;; - esac - lt_cv_deplibs_check_method=pass_all - ;; - -# This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - -netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' - fi - ;; - -newos6*) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=/usr/lib/libnls.so - ;; - -*nto* | *qnx*) - lt_cv_deplibs_check_method=pass_all - ;; - -openbsd* | bitrig*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' - fi - ;; - -osf3* | osf4* | osf5*) - lt_cv_deplibs_check_method=pass_all - ;; - -rdos*) - lt_cv_deplibs_check_method=pass_all - ;; - -solaris*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv4 | sysv4.3*) - case $host_vendor in - motorola) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - ncr) - lt_cv_deplibs_check_method=pass_all - ;; - sequent) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' - ;; - sni) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" - lt_cv_file_magic_test_file=/lib/libc.so - ;; - siemens) - lt_cv_deplibs_check_method=pass_all - ;; - pc) - lt_cv_deplibs_check_method=pass_all - ;; - esac - ;; - -tpf*) - lt_cv_deplibs_check_method=pass_all - ;; -os2*) - lt_cv_deplibs_check_method=pass_all - ;; -esac -]) - -file_magic_glob= -want_nocaseglob=no -if test "$build" = "$host"; then - case $host_os in - mingw* | pw32*) - if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then - want_nocaseglob=yes - else - file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` - fi - ;; - esac -fi - -file_magic_cmd=$lt_cv_file_magic_cmd -deplibs_check_method=$lt_cv_deplibs_check_method -test -z "$deplibs_check_method" && deplibs_check_method=unknown - -_LT_DECL([], [deplibs_check_method], [1], - [Method to check whether dependent libraries are shared objects]) -_LT_DECL([], [file_magic_cmd], [1], - [Command to use when deplibs_check_method = "file_magic"]) -_LT_DECL([], [file_magic_glob], [1], - [How to find potential files when deplibs_check_method = "file_magic"]) -_LT_DECL([], [want_nocaseglob], [1], - [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) -])# _LT_CHECK_MAGIC_METHOD - - -# LT_PATH_NM -# ---------- -# find the pathname to a BSD- or MS-compatible name lister -AC_DEFUN([LT_PATH_NM], -[AC_REQUIRE([AC_PROG_CC])dnl -AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, -[if test -n "$NM"; then - # Let the user override the test. - lt_cv_path_NM=$NM -else - lt_nm_to_check=${ac_tool_prefix}nm - if test -n "$ac_tool_prefix" && test "$build" = "$host"; then - lt_nm_to_check="$lt_nm_to_check nm" - fi - for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR - for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS=$lt_save_ifs - test -z "$ac_dir" && ac_dir=. - tmp_nm=$ac_dir/$lt_tmp_nm - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the 'sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - # Tru64's nm complains that /dev/null is an invalid object file - # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty - case $build_os in - mingw*) lt_bad_file=conftest.nm/nofile ;; - *) lt_bad_file=/dev/null ;; - esac - case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in - *$lt_bad_file* | *'Invalid file or object type'*) - lt_cv_path_NM="$tmp_nm -B" - break 2 - ;; - *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in - */dev/null*) - lt_cv_path_NM="$tmp_nm -p" - break 2 - ;; - *) - lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - ;; - esac - ;; - esac - fi - done - IFS=$lt_save_ifs - done - : ${lt_cv_path_NM=no} -fi]) -if test no != "$lt_cv_path_NM"; then - NM=$lt_cv_path_NM -else - # Didn't find any BSD compatible name lister, look for dumpbin. - if test -n "$DUMPBIN"; then : - # Let the user override the test. - else - AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) - case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in - *COFF*) - DUMPBIN="$DUMPBIN -symbols -headers" - ;; - *) - DUMPBIN=: - ;; - esac - fi - AC_SUBST([DUMPBIN]) - if test : != "$DUMPBIN"; then - NM=$DUMPBIN - fi -fi -test -z "$NM" && NM=nm -AC_SUBST([NM]) -_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl - -AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], - [lt_cv_nm_interface="BSD nm" - echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$ac_compile" 2>conftest.err) - cat conftest.err >&AS_MESSAGE_LOG_FD - (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) - (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) - cat conftest.err >&AS_MESSAGE_LOG_FD - (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) - cat conftest.out >&AS_MESSAGE_LOG_FD - if $GREP 'External.*some_variable' conftest.out > /dev/null; then - lt_cv_nm_interface="MS dumpbin" - fi - rm -f conftest*]) -])# LT_PATH_NM - -# Old names: -AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) -AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AM_PROG_NM], []) -dnl AC_DEFUN([AC_PROG_NM], []) - -# _LT_CHECK_SHAREDLIB_FROM_LINKLIB -# -------------------------------- -# how to determine the name of the shared library -# associated with a specific link library. -# -- PORTME fill in with the dynamic library characteristics -m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], -[m4_require([_LT_DECL_EGREP]) -m4_require([_LT_DECL_OBJDUMP]) -m4_require([_LT_DECL_DLLTOOL]) -AC_CACHE_CHECK([how to associate runtime and link libraries], -lt_cv_sharedlib_from_linklib_cmd, -[lt_cv_sharedlib_from_linklib_cmd='unknown' - -case $host_os in -cygwin* | mingw* | pw32* | cegcc*) - # two different shell functions defined in ltmain.sh; - # decide which one to use based on capabilities of $DLLTOOL - case `$DLLTOOL --help 2>&1` in - *--identify-strict*) - lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib - ;; - *) - lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback - ;; - esac - ;; -*) - # fallback: assume linklib IS sharedlib - lt_cv_sharedlib_from_linklib_cmd=$ECHO - ;; -esac -]) -sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd -test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO - -_LT_DECL([], [sharedlib_from_linklib_cmd], [1], - [Command to associate shared and link libraries]) -])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB - - -# _LT_PATH_MANIFEST_TOOL -# ---------------------- -# locate the manifest tool -m4_defun([_LT_PATH_MANIFEST_TOOL], -[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) -test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt -AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], - [lt_cv_path_mainfest_tool=no - echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD - $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out - cat conftest.err >&AS_MESSAGE_LOG_FD - if $GREP 'Manifest Tool' conftest.out > /dev/null; then - lt_cv_path_mainfest_tool=yes - fi - rm -f conftest*]) -if test yes != "$lt_cv_path_mainfest_tool"; then - MANIFEST_TOOL=: -fi -_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl -])# _LT_PATH_MANIFEST_TOOL - - -# _LT_DLL_DEF_P([FILE]) -# --------------------- -# True iff FILE is a Windows DLL '.def' file. -# Keep in sync with func_dll_def_p in the libtool script -AC_DEFUN([_LT_DLL_DEF_P], -[dnl - test DEF = "`$SED -n dnl - -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace - -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments - -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl - -e q dnl Only consider the first "real" line - $1`" dnl -])# _LT_DLL_DEF_P - - -# LT_LIB_M -# -------- -# check for math library -AC_DEFUN([LT_LIB_M], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -LIBM= -case $host in -*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) - # These system don't have libm, or don't need it - ;; -*-ncr-sysv4.3*) - AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) - AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") - ;; -*) - AC_CHECK_LIB(m, cos, LIBM=-lm) - ;; -esac -AC_SUBST([LIBM]) -])# LT_LIB_M - -# Old name: -AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_CHECK_LIBM], []) - - -# _LT_COMPILER_NO_RTTI([TAGNAME]) -# ------------------------------- -m4_defun([_LT_COMPILER_NO_RTTI], -[m4_require([_LT_TAG_COMPILER])dnl - -_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= - -if test yes = "$GCC"; then - case $cc_basename in - nvcc*) - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; - *) - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; - esac - - _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], - lt_cv_prog_compiler_rtti_exceptions, - [-fno-rtti -fno-exceptions], [], - [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) -fi -_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], - [Compiler flag to turn off builtin functions]) -])# _LT_COMPILER_NO_RTTI - - -# _LT_CMD_GLOBAL_SYMBOLS -# ---------------------- -m4_defun([_LT_CMD_GLOBAL_SYMBOLS], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_PROG_AWK])dnl -AC_REQUIRE([LT_PATH_NM])dnl -AC_REQUIRE([LT_PATH_LD])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_TAG_COMPILER])dnl - -# Check for command to grab the raw symbol name followed by C symbol from nm. -AC_MSG_CHECKING([command to parse $NM output from $compiler object]) -AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], -[ -# These are sane defaults that work on at least a few old systems. -# [They come from Ultrix. What could be older than Ultrix?!! ;)] - -# Character class describing NM global symbol codes. -symcode='[[BCDEGRST]]' - -# Regexp to match symbols that can be accessed directly from C. -sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' - -# Define system-specific variables. -case $host_os in -aix*) - symcode='[[BCDT]]' - ;; -cygwin* | mingw* | pw32* | cegcc*) - symcode='[[ABCDGISTW]]' - ;; -hpux*) - if test ia64 = "$host_cpu"; then - symcode='[[ABCDEGRST]]' - fi - ;; -irix* | nonstopux*) - symcode='[[BCDEGRST]]' - ;; -osf*) - symcode='[[BCDEGQRST]]' - ;; -solaris*) - symcode='[[BDRT]]' - ;; -sco3.2v5*) - symcode='[[DT]]' - ;; -sysv4.2uw2*) - symcode='[[DT]]' - ;; -sysv5* | sco5v6* | unixware* | OpenUNIX*) - symcode='[[ABDT]]' - ;; -sysv4) - symcode='[[DFNSTU]]' - ;; -esac - -# If we're using GNU nm, then use its standard symbol codes. -case `$NM -V 2>&1` in -*GNU* | *'with BFD'*) - symcode='[[ABCDGIRSTW]]' ;; -esac - -if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Gets list of data symbols to import. - lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" - # Adjust the below global symbol transforms to fixup imported variables. - lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" - lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" - lt_c_name_lib_hook="\ - -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ - -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" -else - # Disable hooks by default. - lt_cv_sys_global_symbol_to_import= - lt_cdecl_hook= - lt_c_name_hook= - lt_c_name_lib_hook= -fi - -# Transform an extracted symbol line into a proper C declaration. -# Some systems (esp. on ia64) link data and code symbols differently, -# so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n"\ -$lt_cdecl_hook\ -" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" - -# Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ -$lt_c_name_hook\ -" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" - -# Transform an extracted symbol line into symbol name with lib prefix and -# symbol address. -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ -$lt_c_name_lib_hook\ -" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ -" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" - -# Handle CRLF in mingw tool chain -opt_cr= -case $build_os in -mingw*) - opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp - ;; -esac - -# Try without a prefix underscore, then with it. -for ac_symprfx in "" "_"; do - - # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. - symxfrm="\\1 $ac_symprfx\\2 \\2" - - # Write the raw and C identifiers. - if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function, - # D for any global variable and I for any imported variable. - # Also find C++ and __fastcall symbols from MSVC++, - # which start with @ or ?. - lt_cv_sys_global_symbol_pipe="$AWK ['"\ -" {last_section=section; section=\$ 3};"\ -" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ -" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ -" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ -" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ -" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ -" \$ 0!~/External *\|/{next};"\ -" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ -" {if(hide[section]) next};"\ -" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ -" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ -" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ -" ' prfx=^$ac_symprfx]" - else - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" - fi - lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" - - # Check to see that the pipe works correctly. - pipe_works=no - - rm -f conftest* - cat > conftest.$ac_ext <<_LT_EOF -#ifdef __cplusplus -extern "C" { -#endif -char nm_test_var; -void nm_test_func(void); -void nm_test_func(void){} -#ifdef __cplusplus -} -#endif -int main(){nm_test_var='a';nm_test_func();return(0);} -_LT_EOF - - if AC_TRY_EVAL(ac_compile); then - # Now try to grab the symbols. - nlist=conftest.nm - if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then - # Try sorting and uniquifying the output. - if sort "$nlist" | uniq > "$nlist"T; then - mv -f "$nlist"T "$nlist" - else - rm -f "$nlist"T - fi - - # Make sure that we snagged all the symbols we need. - if $GREP ' nm_test_var$' "$nlist" >/dev/null; then - if $GREP ' nm_test_func$' "$nlist" >/dev/null; then - cat <<_LT_EOF > conftest.$ac_ext -/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE -/* DATA imports from DLLs on WIN32 can't be const, because runtime - relocations are performed -- see ld's documentation on pseudo-relocs. */ -# define LT@&t@_DLSYM_CONST -#elif defined __osf__ -/* This system does not cope well with relocations in const data. */ -# define LT@&t@_DLSYM_CONST -#else -# define LT@&t@_DLSYM_CONST const -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -_LT_EOF - # Now generate the symbol file. - eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' - - cat <<_LT_EOF >> conftest.$ac_ext - -/* The mapping between symbol names and symbols. */ -LT@&t@_DLSYM_CONST struct { - const char *name; - void *address; -} -lt__PROGRAM__LTX_preloaded_symbols[[]] = -{ - { "@PROGRAM@", (void *) 0 }, -_LT_EOF - $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext - cat <<\_LT_EOF >> conftest.$ac_ext - {0, (void *) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt__PROGRAM__LTX_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif -_LT_EOF - # Now try linking the two files. - mv conftest.$ac_objext conftstm.$ac_objext - lt_globsym_save_LIBS=$LIBS - lt_globsym_save_CFLAGS=$CFLAGS - LIBS=conftstm.$ac_objext - CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" - if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then - pipe_works=yes - fi - LIBS=$lt_globsym_save_LIBS - CFLAGS=$lt_globsym_save_CFLAGS - else - echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD - fi - else - echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD - fi - else - echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD - fi - else - echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD - cat conftest.$ac_ext >&5 - fi - rm -rf conftest* conftst* - - # Do not use the global_symbol_pipe unless it works. - if test yes = "$pipe_works"; then - break - else - lt_cv_sys_global_symbol_pipe= - fi -done -]) -if test -z "$lt_cv_sys_global_symbol_pipe"; then - lt_cv_sys_global_symbol_to_cdecl= -fi -if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then - AC_MSG_RESULT(failed) -else - AC_MSG_RESULT(ok) -fi - -# Response file support. -if test "$lt_cv_nm_interface" = "MS dumpbin"; then - nm_file_list_spec='@' -elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then - nm_file_list_spec='@' -fi - -_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], - [Take the output of nm and produce a listing of raw symbols and C names]) -_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], - [Transform the output of nm in a proper C declaration]) -_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], - [Transform the output of nm into a list of symbols to manually relocate]) -_LT_DECL([global_symbol_to_c_name_address], - [lt_cv_sys_global_symbol_to_c_name_address], [1], - [Transform the output of nm in a C name address pair]) -_LT_DECL([global_symbol_to_c_name_address_lib_prefix], - [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], - [Transform the output of nm in a C name address pair when lib prefix is needed]) -_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], - [The name lister interface]) -_LT_DECL([], [nm_file_list_spec], [1], - [Specify filename containing input files for $NM]) -]) # _LT_CMD_GLOBAL_SYMBOLS - - -# _LT_COMPILER_PIC([TAGNAME]) -# --------------------------- -m4_defun([_LT_COMPILER_PIC], -[m4_require([_LT_TAG_COMPILER])dnl -_LT_TAGVAR(lt_prog_compiler_wl, $1)= -_LT_TAGVAR(lt_prog_compiler_pic, $1)= -_LT_TAGVAR(lt_prog_compiler_static, $1)= - -m4_if([$1], [CXX], [ - # C++ specific cases for pic, static, wl, etc. - if test yes = "$GXX"; then - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test ia64 = "$host_cpu"; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - m68k) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the '-m68020' flag to GCC prevents building anything better, - # like '-m68040'. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' - ;; - esac - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - mingw* | cygwin* | os2* | pw32* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - case $host_os in - os2*) - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' - ;; - esac - ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - ;; - *djgpp*) - # DJGPP does not support shared libraries at all - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - ;; - haiku*) - # PIC is the default for Haiku. - # The "-static" flag exists, but is broken. - _LT_TAGVAR(lt_prog_compiler_static, $1)= - ;; - interix[[3-9]]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - sysv4*MP*) - if test -d /usr/nec; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic - fi - ;; - hpux*) - # PIC is the default for 64-bit PA HP-UX, but not for 32-bit - # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag - # sets the default TLS model and affects inlining. - case $host_cpu in - hppa*64*) - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - ;; - *qnx* | *nto*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - else - case $host_os in - aix[[4-9]]*) - # All AIX code is PIC. - if test ia64 = "$host_cpu"; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - else - _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' - fi - ;; - chorus*) - case $cc_basename in - cxch68*) - # Green Hills C++ Compiler - # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" - ;; - esac - ;; - mingw* | cygwin* | os2* | pw32* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - ;; - dgux*) - case $cc_basename in - ec++*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - ;; - ghcx*) - # Green Hills C++ Compiler - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - *) - ;; - esac - ;; - freebsd* | dragonfly*) - # FreeBSD uses GNU C++ - ;; - hpux9* | hpux10* | hpux11*) - case $cc_basename in - CC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' - if test ia64 != "$host_cpu"; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - fi - ;; - aCC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - ;; - esac - ;; - *) - ;; - esac - ;; - interix*) - # This is c89, which is MS Visual C++ (no shared libs) - # Anyone wants to do a port? - ;; - irix5* | irix6* | nonstopux*) - case $cc_basename in - CC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - # CC pic flag -KPIC is the default. - ;; - *) - ;; - esac - ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - case $cc_basename in - KCC*) - # KAI C++ Compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - ecpc* ) - # old Intel C++ for x86_64, which still supported -KPIC. - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - icpc* ) - # Intel C++, used to be incompatible with GCC. - # ICC 10 doesn't accept -KPIC any more. - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - pgCC* | pgcpp*) - # Portland Group C++ compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - cxx*) - # Compaq C++ - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) - # IBM XL 8.0, 9.0 on PPC and BlueGene - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - ;; - esac - ;; - esac - ;; - lynxos*) - ;; - m88k*) - ;; - mvs*) - case $cc_basename in - cxx*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' - ;; - *) - ;; - esac - ;; - netbsd* | netbsdelf*-gnu) - ;; - *qnx* | *nto*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' - ;; - RCC*) - # Rational C++ 2.4.1 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - cxx*) - # Digital/Compaq C++ - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - *) - ;; - esac - ;; - psos*) - ;; - solaris*) - case $cc_basename in - CC* | sunCC*) - # Sun C++ 4.2, 5.x and Centerline C++ - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - ;; - gcx*) - # Green Hills C++ Compiler - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - ;; - *) - ;; - esac - ;; - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - lcc*) - # Lucid - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - *) - ;; - esac - ;; - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - case $cc_basename in - CC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - esac - ;; - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - ;; - *) - ;; - esac - ;; - vxworks*) - ;; - *) - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - esac - fi -], -[ - if test yes = "$GCC"; then - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test ia64 = "$host_cpu"; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - m68k) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the '-m68020' flag to GCC prevents building anything better, - # like '-m68040'. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' - ;; - esac - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | cygwin* | pw32* | os2* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - case $host_os in - os2*) - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' - ;; - esac - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - ;; - - haiku*) - # PIC is the default for Haiku. - # The "-static" flag exists, but is broken. - _LT_TAGVAR(lt_prog_compiler_static, $1)= - ;; - - hpux*) - # PIC is the default for 64-bit PA HP-UX, but not for 32-bit - # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag - # sets the default TLS model and affects inlining. - case $host_cpu in - hppa*64*) - # +Z the default - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - ;; - - interix[[3-9]]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - enable_shared=no - ;; - - *nto* | *qnx*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic - fi - ;; - - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - - case $cc_basename in - nvcc*) # Cuda Compiler Driver 2.2 - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' - if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" - fi - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - if test ia64 = "$host_cpu"; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - else - _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' - fi - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - case $cc_basename in - nagfor*) - # NAG Fortran compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - esac - ;; - - mingw* | cygwin* | pw32* | os2* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - case $host_os in - os2*) - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' - ;; - esac - ;; - - hpux9* | hpux10* | hpux11*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # PIC (with -KPIC) is the default. - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - case $cc_basename in - # old Intel for x86_64, which still supported -KPIC. - ecc*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - # icc used to be incompatible with GCC. - # ICC 10 doesn't accept -KPIC any more. - icc* | ifort*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - # Lahey Fortran 8.1. - lf95*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' - _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' - ;; - nagfor*) - # NAG Fortran compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - tcc*) - # Fabrice Bellard et al's Tiny C Compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) - # Portland Group compilers (*not* the Pentium gcc compiler, - # which looks to be a dead project) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - ccc*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # All Alpha code is PIC. - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - xl* | bgxl* | bgf* | mpixl*) - # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='' - ;; - *Sun\ F* | *Sun*Fortran*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - ;; - *Sun\ C*) - # Sun C 5.9 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - ;; - *Intel*\ [[CF]]*Compiler*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - *Portland\ Group*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - esac - ;; - esac - ;; - - newsos6) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - *nto* | *qnx*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - - osf3* | osf4* | osf5*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # All OSF/1 code is PIC. - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - rdos*) - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - solaris*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - case $cc_basename in - f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; - *) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; - esac - ;; - - sunos4*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - unicos*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - - uts4*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - *) - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - esac - fi -]) -case $host_os in - # For platforms that do not support PIC, -DPIC is meaningless: - *djgpp*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" - ;; -esac - -AC_CACHE_CHECK([for $compiler option to produce PIC], - [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], - [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) -_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then - _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], - [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], - [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], - [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in - "" | " "*) ;; - *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; - esac], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) -fi -_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], - [Additional compiler flags for building library objects]) - -_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], - [How to pass a linker flag through the compiler]) -# -# Check to make sure the static flag actually works. -# -wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" -_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], - _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), - $lt_tmp_static_flag, - [], - [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) -_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], - [Compiler flag to prevent dynamic linking]) -])# _LT_COMPILER_PIC - - -# _LT_LINKER_SHLIBS([TAGNAME]) -# ---------------------------- -# See if the linker supports building shared libraries. -m4_defun([_LT_LINKER_SHLIBS], -[AC_REQUIRE([LT_PATH_LD])dnl -AC_REQUIRE([LT_PATH_NM])dnl -m4_require([_LT_PATH_MANIFEST_TOOL])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl -m4_require([_LT_TAG_COMPILER])dnl -AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) -m4_if([$1], [CXX], [ - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] - case $host_os in - aix[[4-9]]*) - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to GNU nm, but means don't demangle to AIX nm. - # Without the "-l" option, or with the "-B" option, AIX nm treats - # weak defined symbols like other global defined symbols, whereas - # GNU nm marks them as "W". - # While the 'weak' keyword is ignored in the Export File, we need - # it in the Import File for the 'aix-soname' feature, so we have - # to replace the "-B" option with "-P" for AIX nm. - if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' - else - _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' - fi - ;; - pw32*) - _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds - ;; - cygwin* | mingw* | cegcc*) - case $cc_basename in - cl*) - _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' - ;; - *) - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' - _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] - ;; - esac - ;; - linux* | k*bsd*-gnu | gnu*) - _LT_TAGVAR(link_all_deplibs, $1)=no - ;; - *) - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - ;; - esac -], [ - runpath_var= - _LT_TAGVAR(allow_undefined_flag, $1)= - _LT_TAGVAR(always_export_symbols, $1)=no - _LT_TAGVAR(archive_cmds, $1)= - _LT_TAGVAR(archive_expsym_cmds, $1)= - _LT_TAGVAR(compiler_needs_object, $1)=no - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - _LT_TAGVAR(export_dynamic_flag_spec, $1)= - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - _LT_TAGVAR(hardcode_automatic, $1)=no - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_TAGVAR(hardcode_libdir_separator, $1)= - _LT_TAGVAR(hardcode_minus_L, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_TAGVAR(inherit_rpath, $1)=no - _LT_TAGVAR(link_all_deplibs, $1)=unknown - _LT_TAGVAR(module_cmds, $1)= - _LT_TAGVAR(module_expsym_cmds, $1)= - _LT_TAGVAR(old_archive_from_new_cmds, $1)= - _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= - _LT_TAGVAR(thread_safe_flag_spec, $1)= - _LT_TAGVAR(whole_archive_flag_spec, $1)= - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - _LT_TAGVAR(include_expsyms, $1)= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ' (' and ')$', so one must not match beginning or - # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', - # as well as any symbol that contains 'd'. - _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - # Exclude shared library initialization/finalization symbols. -dnl Note also adjust exclude_expsyms for C++ above. - extract_expsyms_cmds= - - case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test yes != "$GCC"; then - with_gnu_ld=no - fi - ;; - interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) - with_gnu_ld=yes - ;; - openbsd* | bitrig*) - with_gnu_ld=no - ;; - linux* | k*bsd*-gnu | gnu*) - _LT_TAGVAR(link_all_deplibs, $1)=no - ;; - esac - - _LT_TAGVAR(ld_shlibs, $1)=yes - - # On some targets, GNU ld is compatible enough with the native linker - # that we're better off using the native interface for both. - lt_use_gnu_ld_interface=no - if test yes = "$with_gnu_ld"; then - case $host_os in - aix*) - # The AIX port of GNU ld has always aspired to compatibility - # with the native linker. However, as the warning in the GNU ld - # block says, versions before 2.19.5* couldn't really create working - # shared libraries, regardless of the interface used. - case `$LD -v 2>&1` in - *\ \(GNU\ Binutils\)\ 2.19.5*) ;; - *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; - *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; - *) - lt_use_gnu_ld_interface=yes - ;; - esac - ;; - *) - lt_use_gnu_ld_interface=yes - ;; - esac - fi - - if test yes = "$lt_use_gnu_ld_interface"; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='$wl' - - # Set some defaults for GNU ld with shared library support. These - # are reset later if shared libraries are not supported. Putting them - # here allows them to be overridden if necessary. - runpath_var=LD_RUN_PATH - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' - else - _LT_TAGVAR(whole_archive_flag_spec, $1)= - fi - supports_anon_versioning=no - case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in - *GNU\ gold*) supports_anon_versioning=yes ;; - *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - - # See if GNU ld supports shared libraries. - case $host_os in - aix[[3-9]]*) - # On AIX/PPC, the GNU linker is very broken - if test ia64 != "$host_cpu"; then - _LT_TAGVAR(ld_shlibs, $1)=no - cat <<_LT_EOF 1>&2 - -*** Warning: the GNU linker, at least up to release 2.19, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to install binutils -*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. -*** You will then need to restart the configuration process. - -_LT_EOF - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='' - ;; - m68k) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - ;; - - beos*) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, - # as there is no search path for DLLs. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=no - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' - _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file, use it as - # is; otherwise, prepend EXPORTS... - _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - haiku*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - - os2*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - shrext_cmds=.dll - _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - prefix_cmds="$SED"~ - if test EXPORTS = "`$SED 1q $export_symbols`"; then - prefix_cmds="$prefix_cmds -e 1d"; - fi~ - prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ - cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - ;; - - interix[[3-9]]*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - - gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) - tmp_diet=no - if test linux-dietlibc = "$host_os"; then - case $cc_basename in - diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) - esac - fi - if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test no = "$tmp_diet" - then - tmp_addflag=' $pic_flag' - tmp_sharedflag='-shared' - case $cc_basename,$host_cpu in - pgcc*) # Portland Group C compiler - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - tmp_addflag=' $pic_flag' - ;; - pgf77* | pgf90* | pgf95* | pgfortran*) - # Portland Group f77 and f90 compilers - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - tmp_addflag=' $pic_flag -Mnomain' ;; - ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 - tmp_addflag=' -i_dynamic' ;; - efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 - tmp_addflag=' -i_dynamic -nofor_main' ;; - ifc* | ifort*) # Intel Fortran compiler - tmp_addflag=' -nofor_main' ;; - lf95*) # Lahey Fortran 8.1 - _LT_TAGVAR(whole_archive_flag_spec, $1)= - tmp_sharedflag='--shared' ;; - nagfor*) # NAGFOR 5.3 - tmp_sharedflag='-Wl,-shared' ;; - xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) - tmp_sharedflag='-qmkshrobj' - tmp_addflag= ;; - nvcc*) # Cuda Compiler Driver 2.2 - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - _LT_TAGVAR(compiler_needs_object, $1)=yes - ;; - esac - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) # Sun C 5.9 - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - _LT_TAGVAR(compiler_needs_object, $1)=yes - tmp_sharedflag='-G' ;; - *Sun\ F*) # Sun Fortran 8.3 - tmp_sharedflag='-G' ;; - esac - _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - - if test yes = "$supports_anon_versioning"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' - fi - - case $cc_basename in - tcc*) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' - ;; - xlf* | bgf* | bgxlf* | mpixlf*) - # IBM XL Fortran 10.1 on PPC cannot create shared libs itself - _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' - if test yes = "$supports_anon_versioning"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' - fi - ;; - esac - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris*) - if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then - _LT_TAGVAR(ld_shlibs, $1)=no - cat <<_LT_EOF 1>&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) - case `$LD -v 2>&1` in - *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) - _LT_TAGVAR(ld_shlibs, $1)=no - cat <<_LT_EOF 1>&2 - -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot -*** reliably create shared libraries on SCO systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.16.91.0.3 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - ;; - *) - # For security reasons, it is highly recommended that you always - # use absolute paths for naming shared libraries, and exclude the - # DT_RUNPATH tag from executables and libraries. But doing so - # requires that you compile everything twice, which is a pain. - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - sunos4*) - _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - - if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then - runpath_var= - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_TAGVAR(export_dynamic_flag_spec, $1)= - _LT_TAGVAR(whole_archive_flag_spec, $1)= - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=yes - _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - _LT_TAGVAR(hardcode_direct, $1)=unsupported - fi - ;; - - aix[[4-9]]*) - if test ia64 = "$host_cpu"; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag= - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to GNU nm, but means don't demangle to AIX nm. - # Without the "-l" option, or with the "-B" option, AIX nm treats - # weak defined symbols like other global defined symbols, whereas - # GNU nm marks them as "W". - # While the 'weak' keyword is ignored in the Export File, we need - # it in the Import File for the 'aix-soname' feature, so we have - # to replace the "-B" option with "-P" for AIX nm. - if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' - else - _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # have runtime linking enabled, and use it for executables. - # For shared libraries, we enable/disable runtime linking - # depending on the kind of the shared library created - - # when "with_aix_soname,aix_use_runtimelinking" is: - # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables - # "aix,yes" lib.so shared, rtl:yes, for executables - # lib.a static archive - # "both,no" lib.so.V(shr.o) shared, rtl:yes - # lib.a(lib.so.V) shared, rtl:no, for executables - # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a(lib.so.V) shared, rtl:no - # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a static archive - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) - for ld_flag in $LDFLAGS; do - if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then - aix_use_runtimelinking=yes - break - fi - done - if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then - # With aix-soname=svr4, we create the lib.so.V shared archives only, - # so we don't have lib.a shared libs to link our executables. - # We have to force runtime linking in this case. - aix_use_runtimelinking=yes - LDFLAGS="$LDFLAGS -Wl,-brtl" - fi - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - _LT_TAGVAR(archive_cmds, $1)='' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='$wl-f,' - case $with_aix_soname,$aix_use_runtimelinking in - aix,*) ;; # traditional, no import file - svr4,* | *,yes) # use import file - # The Import File defines what to hardcode. - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=no - ;; - esac - - if test yes = "$GCC"; then - case $host_os in aix4.[[012]]|aix4.[[012]].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`$CC -print-prog-name=collect2` - if test -f "$collect2name" && - strings "$collect2name" | $GREP resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - _LT_TAGVAR(hardcode_direct, $1)=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)= - fi - ;; - esac - shared_flag='-shared' - if test yes = "$aix_use_runtimelinking"; then - shared_flag="$shared_flag "'$wl-G' - fi - # Need to ensure runtime linking is disabled for the traditional - # shared library, or the linker may eventually find shared libraries - # /with/ Import File - we do not want to mix them. - shared_flag_aix='-shared' - shared_flag_svr4='-shared $wl-G' - else - # not using gcc - if test ia64 = "$host_cpu"; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test yes = "$aix_use_runtimelinking"; then - shared_flag='$wl-G' - else - shared_flag='$wl-bM:SRE' - fi - shared_flag_aix='$wl-bM:SRE' - shared_flag_svr4='$wl-G' - fi - fi - - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - _LT_TAGVAR(always_export_symbols, $1)=yes - if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(allow_undefined_flag, $1)='-berok' - # Determine the default libpath from the value encoded in an - # empty executable. - _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag - else - if test ia64 = "$host_cpu"; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' - _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an - # empty executable. - _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' - if test yes = "$with_gnu_ld"; then - # We only use this code for GNU lds that support --whole-archive. - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' - else - # Exported symbols can be pulled into shared objects from archives - _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' - # -brtl affects multiple linker settings, -berok does not and is overridden later - compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' - if test svr4 != "$with_aix_soname"; then - # This is similar to how AIX traditionally builds its shared libraries. - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' - fi - if test aix != "$with_aix_soname"; then - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' - else - # used by -dlpreopen to get the symbols - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' - fi - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' - fi - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='' - ;; - m68k) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - ;; - - bsdi[[45]]*) - _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - case $cc_basename in - cl*) - # Native MSVC - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='@' - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=.dll - # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' - _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then - cp "$export_symbols" "$output_objdir/$soname.def"; - echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; - else - $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' - # The linker will not automatically build a static lib if we build a DLL. - # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' - # Don't use ranlib - _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' - _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile=$lt_outputfile.exe - lt_tool_outputfile=$lt_tool_outputfile.exe - ;; - esac~ - if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' - ;; - *) - # Assume MSVC wrapper - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=.dll - # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' - # FIXME: Should let the user specify the lib program. - _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - ;; - esac - ;; - - darwin* | rhapsody*) - _LT_DARWIN_LINKER_FEATURES($1) - ;; - - dgux*) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2.*) - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - hpux9*) - if test yes = "$GCC"; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' - else - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(hardcode_direct, $1)=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - ;; - - hpux10*) - if test yes,no = "$GCC,$with_gnu_ld"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - fi - if test no = "$with_gnu_ld"; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - fi - ;; - - hpux11*) - if test yes,no = "$GCC,$with_gnu_ld"; then - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - m4_if($1, [], [ - # Older versions of the 11.00 compiler do not understand -b yet - # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) - _LT_LINKER_OPTION([if $CC understands -b], - _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], - [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], - [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], - [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) - ;; - esac - fi - if test no = "$with_gnu_ld"; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - case $host_cpu in - hppa*64*|ia64*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - *) - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test yes = "$GCC"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - # Try to use the -exported_symbol ld option, if it does not - # work, assume that -exports_file does not work either and - # implicitly export all symbols. - # This should be the same for all languages, so no per-tag cache variable. - AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], - [lt_cv_irix_exported_symbol], - [save_LDFLAGS=$LDFLAGS - LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" - AC_LINK_IFELSE( - [AC_LANG_SOURCE( - [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], - [C++], [[int foo (void) { return 0; }]], - [Fortran 77], [[ - subroutine foo - end]], - [Fortran], [[ - subroutine foo - end]])])], - [lt_cv_irix_exported_symbol=yes], - [lt_cv_irix_exported_symbol=no]) - LDFLAGS=$save_LDFLAGS]) - if test yes = "$lt_cv_irix_exported_symbol"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' - fi - _LT_TAGVAR(link_all_deplibs, $1)=no - else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(inherit_rpath, $1)=yes - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - - linux*) - case $cc_basename in - tcc*) - # Fabrice Bellard et al's Tiny C Compiler - _LT_TAGVAR(ld_shlibs, $1)=yes - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - newsos6) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *nto* | *qnx*) - ;; - - openbsd* | bitrig*) - if test -f /usr/libexec/ld.so; then - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - fi - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - os2*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - shrext_cmds=.dll - _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - prefix_cmds="$SED"~ - if test EXPORTS = "`$SED 1q $export_symbols`"; then - prefix_cmds="$prefix_cmds -e 1d"; - fi~ - prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ - cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - ;; - - osf3*) - if test yes = "$GCC"; then - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - else - _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test yes = "$GCC"; then - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - else - _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' - - # Both c and cxx compiler support -rpath directly - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - - solaris*) - _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' - if test yes = "$GCC"; then - wlarc='$wl' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' - else - case `$CC -V 2>&1` in - *"Compilers 5.0"*) - wlarc='' - _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' - ;; - *) - wlarc='$wl' - _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' - ;; - esac - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands '-z linker_flag'. GCC discards it without '$wl', - # but is careful enough not to reorder. - # Supported since Solaris 2.6 (maybe 2.5.1?) - if test yes = "$GCC"; then - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' - else - _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' - fi - ;; - esac - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - - sunos4*) - if test sequent = "$host_vendor"; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv4) - case $host_vendor in - sni) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' - _LT_TAGVAR(hardcode_direct, $1)=no - ;; - motorola) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv4.3*) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - _LT_TAGVAR(ld_shlibs, $1)=yes - fi - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var='LD_RUN_PATH' - - if test yes = "$GCC"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We CANNOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' - runpath_var='LD_RUN_PATH' - - if test yes = "$GCC"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - uts4*) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *) - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - - if test sni = "$host_vendor"; then - case $host in - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' - ;; - esac - fi - fi -]) -AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) -test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no - -_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld - -_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl -_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl -_LT_DECL([], [extract_expsyms_cmds], [2], - [The commands to extract the exported symbol list from a shared archive]) - -# -# Do we need to explicitly link libc? -# -case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in -x|xyes) - # Assume -lc should be added - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - - if test yes,yes = "$GCC,$enable_shared"; then - case $_LT_TAGVAR(archive_cmds, $1) in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - AC_CACHE_CHECK([whether -lc should be explicitly linked in], - [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), - [$RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if AC_TRY_EVAL(ac_compile) 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) - pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) - _LT_TAGVAR(allow_undefined_flag, $1)= - if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) - then - lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no - else - lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes - fi - _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - ]) - _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) - ;; - esac - fi - ;; -esac - -_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], - [Whether or not to add -lc for building shared libraries]) -_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], - [enable_shared_with_static_runtimes], [0], - [Whether or not to disallow shared libs when runtime libs are static]) -_LT_TAGDECL([], [export_dynamic_flag_spec], [1], - [Compiler flag to allow reflexive dlopens]) -_LT_TAGDECL([], [whole_archive_flag_spec], [1], - [Compiler flag to generate shared objects directly from archives]) -_LT_TAGDECL([], [compiler_needs_object], [1], - [Whether the compiler copes with passing no objects directly]) -_LT_TAGDECL([], [old_archive_from_new_cmds], [2], - [Create an old-style archive from a shared archive]) -_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], - [Create a temporary old-style archive to link instead of a shared archive]) -_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) -_LT_TAGDECL([], [archive_expsym_cmds], [2]) -_LT_TAGDECL([], [module_cmds], [2], - [Commands used to build a loadable module if different from building - a shared archive.]) -_LT_TAGDECL([], [module_expsym_cmds], [2]) -_LT_TAGDECL([], [with_gnu_ld], [1], - [Whether we are building with GNU ld or not]) -_LT_TAGDECL([], [allow_undefined_flag], [1], - [Flag that allows shared libraries with undefined symbols to be built]) -_LT_TAGDECL([], [no_undefined_flag], [1], - [Flag that enforces no undefined symbols]) -_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], - [Flag to hardcode $libdir into a binary during linking. - This must work even if $libdir does not exist]) -_LT_TAGDECL([], [hardcode_libdir_separator], [1], - [Whether we need a single "-rpath" flag with a separated argument]) -_LT_TAGDECL([], [hardcode_direct], [0], - [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes - DIR into the resulting binary]) -_LT_TAGDECL([], [hardcode_direct_absolute], [0], - [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes - DIR into the resulting binary and the resulting library dependency is - "absolute", i.e impossible to change by setting $shlibpath_var if the - library is relocated]) -_LT_TAGDECL([], [hardcode_minus_L], [0], - [Set to "yes" if using the -LDIR flag during linking hardcodes DIR - into the resulting binary]) -_LT_TAGDECL([], [hardcode_shlibpath_var], [0], - [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR - into the resulting binary]) -_LT_TAGDECL([], [hardcode_automatic], [0], - [Set to "yes" if building a shared library automatically hardcodes DIR - into the library and all subsequent libraries and executables linked - against it]) -_LT_TAGDECL([], [inherit_rpath], [0], - [Set to yes if linker adds runtime paths of dependent libraries - to runtime path list]) -_LT_TAGDECL([], [link_all_deplibs], [0], - [Whether libtool must link a program against all its dependency libraries]) -_LT_TAGDECL([], [always_export_symbols], [0], - [Set to "yes" if exported symbols are required]) -_LT_TAGDECL([], [export_symbols_cmds], [2], - [The commands to list exported symbols]) -_LT_TAGDECL([], [exclude_expsyms], [1], - [Symbols that should not be listed in the preloaded symbols]) -_LT_TAGDECL([], [include_expsyms], [1], - [Symbols that must always be exported]) -_LT_TAGDECL([], [prelink_cmds], [2], - [Commands necessary for linking programs (against libraries) with templates]) -_LT_TAGDECL([], [postlink_cmds], [2], - [Commands necessary for finishing linking programs]) -_LT_TAGDECL([], [file_list_spec], [1], - [Specify filename containing input files]) -dnl FIXME: Not yet implemented -dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], -dnl [Compiler flag to generate thread safe objects]) -])# _LT_LINKER_SHLIBS - - -# _LT_LANG_C_CONFIG([TAG]) -# ------------------------ -# Ensure that the configuration variables for a C compiler are suitably -# defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to 'libtool'. -m4_defun([_LT_LANG_C_CONFIG], -[m4_require([_LT_DECL_EGREP])dnl -lt_save_CC=$CC -AC_LANG_PUSH(C) - -# Source file extension for C test sources. -ac_ext=c - -# Object file extension for compiled C test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(){return(0);}' - -_LT_TAG_COMPILER -# Save the default compiler, since it gets overwritten when the other -# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. -compiler_DEFAULT=$CC - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... -if test -n "$compiler"; then - _LT_COMPILER_NO_RTTI($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - LT_SYS_DLOPEN_SELF - _LT_CMD_STRIPLIB - - # Report what library types will actually be built - AC_MSG_CHECKING([if libtool supports shared libraries]) - AC_MSG_RESULT([$can_build_shared]) - - AC_MSG_CHECKING([whether to build shared libraries]) - test no = "$can_build_shared" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test yes = "$enable_shared" && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - - aix[[4-9]]*) - if test ia64 != "$host_cpu"; then - case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in - yes,aix,yes) ;; # shared object as lib.so file only - yes,svr4,*) ;; # shared object as lib.so archive member only - yes,*) enable_static=no ;; # shared object in lib.a archive as well - esac - fi - ;; - esac - AC_MSG_RESULT([$enable_shared]) - - AC_MSG_CHECKING([whether to build static libraries]) - # Make sure either enable_shared or enable_static is yes. - test yes = "$enable_shared" || enable_static=yes - AC_MSG_RESULT([$enable_static]) - - _LT_CONFIG($1) -fi -AC_LANG_POP -CC=$lt_save_CC -])# _LT_LANG_C_CONFIG - - -# _LT_LANG_CXX_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for a C++ compiler are suitably -# defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to 'libtool'. -m4_defun([_LT_LANG_CXX_CONFIG], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_PATH_MANIFEST_TOOL])dnl -if test -n "$CXX" && ( test no != "$CXX" && - ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || - (test g++ != "$CXX"))); then - AC_PROG_CXXCPP -else - _lt_caught_CXX_error=yes -fi - -AC_LANG_PUSH(C++) -_LT_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_TAGVAR(allow_undefined_flag, $1)= -_LT_TAGVAR(always_export_symbols, $1)=no -_LT_TAGVAR(archive_expsym_cmds, $1)= -_LT_TAGVAR(compiler_needs_object, $1)=no -_LT_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_TAGVAR(hardcode_direct, $1)=no -_LT_TAGVAR(hardcode_direct_absolute, $1)=no -_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_separator, $1)= -_LT_TAGVAR(hardcode_minus_L, $1)=no -_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported -_LT_TAGVAR(hardcode_automatic, $1)=no -_LT_TAGVAR(inherit_rpath, $1)=no -_LT_TAGVAR(module_cmds, $1)= -_LT_TAGVAR(module_expsym_cmds, $1)= -_LT_TAGVAR(link_all_deplibs, $1)=unknown -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(reload_flag, $1)=$reload_flag -_LT_TAGVAR(reload_cmds, $1)=$reload_cmds -_LT_TAGVAR(no_undefined_flag, $1)= -_LT_TAGVAR(whole_archive_flag_spec, $1)= -_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Source file extension for C++ test sources. -ac_ext=cpp - -# Object file extension for compiled C++ test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# No sense in running all these tests if we already determined that -# the CXX compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test yes != "$_lt_caught_CXX_error"; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="int some_variable = 0;" - - # Code to be used in simple link tests - lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - _LT_TAG_COMPILER - - # save warnings/boilerplate of simple test code - _LT_COMPILER_BOILERPLATE - _LT_LINKER_BOILERPLATE - - # Allow CC to be a program name with arguments. - lt_save_CC=$CC - lt_save_CFLAGS=$CFLAGS - lt_save_LD=$LD - lt_save_GCC=$GCC - GCC=$GXX - lt_save_with_gnu_ld=$with_gnu_ld - lt_save_path_LD=$lt_cv_path_LD - if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then - lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx - else - $as_unset lt_cv_prog_gnu_ld - fi - if test -n "${lt_cv_path_LDCXX+set}"; then - lt_cv_path_LD=$lt_cv_path_LDCXX - else - $as_unset lt_cv_path_LD - fi - test -z "${LDCXX+set}" || LD=$LDCXX - CC=${CXX-"c++"} - CFLAGS=$CXXFLAGS - compiler=$CC - _LT_TAGVAR(compiler, $1)=$CC - _LT_CC_BASENAME([$compiler]) - - if test -n "$compiler"; then - # We don't want -fno-exception when compiling C++ code, so set the - # no_builtin_flag separately - if test yes = "$GXX"; then - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' - else - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= - fi - - if test yes = "$GXX"; then - # Set up default GNU C++ configuration - - LT_PATH_LD - - # Check if GNU C++ uses GNU ld as the underlying linker, since the - # archiving commands below assume that GNU ld is being used. - if test yes = "$with_gnu_ld"; then - _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' - - # If archive_cmds runs LD, not CC, wlarc should be empty - # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to - # investigate it a little bit more. (MM) - wlarc='$wl' - - # ancient GNU ld didn't support --whole-archive et. al. - if eval "`$CC -print-prog-name=ld` --help 2>&1" | - $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' - else - _LT_TAGVAR(whole_archive_flag_spec, $1)= - fi - else - with_gnu_ld=no - wlarc= - - # A generic and very simple default shared library creation - # command for GNU C++ for the case where it uses the native - # linker, instead of GNU ld. If possible, this setting should - # overridden to take advantage of the native linker features on - # the platform it is being used on. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - fi - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' - - else - GXX=no - with_gnu_ld=no - wlarc= - fi - - # PORTME: fill in a description of your system's C++ link characteristics - AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) - _LT_TAGVAR(ld_shlibs, $1)=yes - case $host_os in - aix3*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - aix[[4-9]]*) - if test ia64 = "$host_cpu"; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag= - else - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # have runtime linking enabled, and use it for executables. - # For shared libraries, we enable/disable runtime linking - # depending on the kind of the shared library created - - # when "with_aix_soname,aix_use_runtimelinking" is: - # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables - # "aix,yes" lib.so shared, rtl:yes, for executables - # lib.a static archive - # "both,no" lib.so.V(shr.o) shared, rtl:yes - # lib.a(lib.so.V) shared, rtl:no, for executables - # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a(lib.so.V) shared, rtl:no - # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a static archive - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) - for ld_flag in $LDFLAGS; do - case $ld_flag in - *-brtl*) - aix_use_runtimelinking=yes - break - ;; - esac - done - if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then - # With aix-soname=svr4, we create the lib.so.V shared archives only, - # so we don't have lib.a shared libs to link our executables. - # We have to force runtime linking in this case. - aix_use_runtimelinking=yes - LDFLAGS="$LDFLAGS -Wl,-brtl" - fi - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - _LT_TAGVAR(archive_cmds, $1)='' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='$wl-f,' - case $with_aix_soname,$aix_use_runtimelinking in - aix,*) ;; # no import file - svr4,* | *,yes) # use import file - # The Import File defines what to hardcode. - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=no - ;; - esac - - if test yes = "$GXX"; then - case $host_os in aix4.[[012]]|aix4.[[012]].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`$CC -print-prog-name=collect2` - if test -f "$collect2name" && - strings "$collect2name" | $GREP resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - _LT_TAGVAR(hardcode_direct, $1)=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)= - fi - esac - shared_flag='-shared' - if test yes = "$aix_use_runtimelinking"; then - shared_flag=$shared_flag' $wl-G' - fi - # Need to ensure runtime linking is disabled for the traditional - # shared library, or the linker may eventually find shared libraries - # /with/ Import File - we do not want to mix them. - shared_flag_aix='-shared' - shared_flag_svr4='-shared $wl-G' - else - # not using gcc - if test ia64 = "$host_cpu"; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test yes = "$aix_use_runtimelinking"; then - shared_flag='$wl-G' - else - shared_flag='$wl-bM:SRE' - fi - shared_flag_aix='$wl-bM:SRE' - shared_flag_svr4='$wl-G' - fi - fi - - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to - # export. - _LT_TAGVAR(always_export_symbols, $1)=yes - if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - # The "-G" linker flag allows undefined symbols. - _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' - # Determine the default libpath from the value encoded in an empty - # executable. - _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" - - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag - else - if test ia64 = "$host_cpu"; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' - _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an - # empty executable. - _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' - if test yes = "$with_gnu_ld"; then - # We only use this code for GNU lds that support --whole-archive. - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' - else - # Exported symbols can be pulled into shared objects from archives - _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' - # -brtl affects multiple linker settings, -berok does not and is overridden later - compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' - if test svr4 != "$with_aix_soname"; then - # This is similar to how AIX traditionally builds its shared - # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' - fi - if test aix != "$with_aix_soname"; then - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' - else - # used by -dlpreopen to get the symbols - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' - fi - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' - fi - fi - ;; - - beos*) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - chorus*) - case $cc_basename in - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - cygwin* | mingw* | pw32* | cegcc*) - case $GXX,$cc_basename in - ,cl* | no,cl*) - # Native MSVC - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='@' - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=.dll - # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' - _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then - cp "$export_symbols" "$output_objdir/$soname.def"; - echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; - else - $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' - # The linker will not automatically build a static lib if we build a DLL. - # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - # Don't use ranlib - _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' - _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile=$lt_outputfile.exe - lt_tool_outputfile=$lt_tool_outputfile.exe - ;; - esac~ - func_to_tool_file "$lt_outputfile"~ - if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' - ;; - *) - # g++ - # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, - # as there is no search path for DLLs. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=no - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file, use it as - # is; otherwise, prepend EXPORTS... - _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - darwin* | rhapsody*) - _LT_DARWIN_LINKER_FEATURES($1) - ;; - - os2*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - shrext_cmds=.dll - _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - prefix_cmds="$SED"~ - if test EXPORTS = "`$SED 1q $export_symbols`"; then - prefix_cmds="$prefix_cmds -e 1d"; - fi~ - prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ - cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - ;; - - dgux*) - case $cc_basename in - ec++*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - ghcx*) - # Green Hills C++ Compiler - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - freebsd2.*) - # C++ shared libraries reported to be fairly broken before - # switch to ELF - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - freebsd-elf*) - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - ;; - - freebsd* | dragonfly*) - # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF - # conventions - _LT_TAGVAR(ld_shlibs, $1)=yes - ;; - - haiku*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - - hpux9*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - aCC*) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test yes = "$GXX"; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' - else - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - hpux10*|hpux11*) - if test no = "$with_gnu_ld"; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - case $host_cpu in - hppa*64*|ia64*) - ;; - *) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - ;; - esac - fi - case $host_cpu in - hppa*64*|ia64*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - *) - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; - esac - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - aCC*) - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test yes = "$GXX"; then - if test no = "$with_gnu_ld"; then - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - fi - else - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - interix[[3-9]]*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - irix5* | irix6*) - case $cc_basename in - CC*) - # SGI C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - - # Archives containing C++ object files must be created using - # "CC -ar", where "CC" is the IRIX C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' - ;; - *) - if test yes = "$GXX"; then - if test no = "$with_gnu_ld"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' - fi - fi - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - esac - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(inherit_rpath, $1)=yes - ;; - - linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' - ;; - icpc* | ecpc* ) - # Intel C++ - with_gnu_ld=yes - # version 8.0 and above of icpc choke on multiply defined symbols - # if we add $predep_objects and $postdep_objects, however 7.1 and - # earlier do not add the objects themselves. - case `$CC -V 2>&1` in - *"Version 7."*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - ;; - *) # Version 8.0 or newer - tmp_idyn= - case $host_cpu in - ia64*) tmp_idyn=' -i_dynamic';; - esac - _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - ;; - esac - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' - ;; - pgCC* | pgcpp*) - # Portland Group C++ compiler - case `$CC -V` in - *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) - _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ - compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' - _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ - $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ - $RANLIB $oldlib' - _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - ;; - *) # Version 6 and above use weak symbols - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' - ;; - esac - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - ;; - cxx*) - # Compaq C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' - - runpath_var=LD_RUN_PATH - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' - ;; - xl* | mpixl* | bgxl*) - # IBM XL 8.0 on PPC, with GNU ld - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' - _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - if test yes = "$supports_anon_versioning"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' - fi - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - _LT_TAGVAR(compiler_needs_object, $1)=yes - - # Not sure whether something based on - # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 - # would be better. - output_verbose_link_cmd='func_echo_all' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' - ;; - esac - ;; - esac - ;; - - lynxos*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - m88k*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - mvs*) - case $cc_basename in - cxx*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' - wlarc= - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - fi - # Workaround some broken pre-1.5 toolchains - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' - ;; - - *nto* | *qnx*) - _LT_TAGVAR(ld_shlibs, $1)=yes - ;; - - openbsd* | bitrig*) - if test -f /usr/libexec/ld.so; then - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' - fi - output_verbose_link_cmd=func_echo_all - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Archives containing C++ object files must be created using - # the KAI C++ compiler. - case $host in - osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; - *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; - esac - ;; - RCC*) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - cxx*) - case $host in - osf3*) - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - ;; - *) - _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ - $RM $lib.exp' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - ;; - esac - - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - ;; - *) - if test yes,no = "$GXX,$with_gnu_ld"; then - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' - case $host in - osf3*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - ;; - esac - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' - - else - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - psos*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - lcc*) - # Lucid - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - solaris*) - case $cc_basename in - CC* | sunCC*) - # Sun C++ 4.2, 5.x and Centerline C++ - _LT_TAGVAR(archive_cmds_need_lc,$1)=yes - _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands '-z linker_flag'. - # Supported since Solaris 2.6 (maybe 2.5.1?) - _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' - ;; - esac - _LT_TAGVAR(link_all_deplibs, $1)=yes - - output_verbose_link_cmd='func_echo_all' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' - ;; - gcx*) - # Green Hills C++ Compiler - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' - - # The C++ compiler must be used to create the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' - ;; - *) - # GNU C++ compiler with Solaris linker - if test yes,no = "$GXX,$with_gnu_ld"; then - _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' - if $CC --version | $GREP -v '^2\.7' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' - else - # g++ 2.7 appears to require '-G' NOT '-shared' on this - # platform. - _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' - fi - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' - ;; - esac - fi - ;; - esac - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We CANNOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ - '"$_LT_TAGVAR(old_archive_cmds, $1)" - _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ - '"$_LT_TAGVAR(reload_cmds, $1)" - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - vxworks*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - - AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) - test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no - - _LT_TAGVAR(GCC, $1)=$GXX - _LT_TAGVAR(LD, $1)=$LD - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - _LT_SYS_HIDDEN_LIBDEPS($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) - fi # test -n "$compiler" - - CC=$lt_save_CC - CFLAGS=$lt_save_CFLAGS - LDCXX=$LD - LD=$lt_save_LD - GCC=$lt_save_GCC - with_gnu_ld=$lt_save_with_gnu_ld - lt_cv_path_LDCXX=$lt_cv_path_LD - lt_cv_path_LD=$lt_save_path_LD - lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld - lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld -fi # test yes != "$_lt_caught_CXX_error" - -AC_LANG_POP -])# _LT_LANG_CXX_CONFIG - - -# _LT_FUNC_STRIPNAME_CNF -# ---------------------- -# func_stripname_cnf prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -# -# This function is identical to the (non-XSI) version of func_stripname, -# except this one can be used by m4 code that may be executed by configure, -# rather than the libtool script. -m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl -AC_REQUIRE([_LT_DECL_SED]) -AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) -func_stripname_cnf () -{ - case @S|@2 in - .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; - *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; - esac -} # func_stripname_cnf -])# _LT_FUNC_STRIPNAME_CNF - - -# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) -# --------------------------------- -# Figure out "hidden" library dependencies from verbose -# compiler output when linking a shared library. -# Parse the compiler output and extract the necessary -# objects, libraries and library flags. -m4_defun([_LT_SYS_HIDDEN_LIBDEPS], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl -# Dependencies to place before and after the object being linked: -_LT_TAGVAR(predep_objects, $1)= -_LT_TAGVAR(postdep_objects, $1)= -_LT_TAGVAR(predeps, $1)= -_LT_TAGVAR(postdeps, $1)= -_LT_TAGVAR(compiler_lib_search_path, $1)= - -dnl we can't use the lt_simple_compile_test_code here, -dnl because it contains code intended for an executable, -dnl not a library. It's possible we should let each -dnl tag define a new lt_????_link_test_code variable, -dnl but it's only used here... -m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF -int a; -void foo (void) { a = 0; } -_LT_EOF -], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF -class Foo -{ -public: - Foo (void) { a = 0; } -private: - int a; -}; -_LT_EOF -], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF - subroutine foo - implicit none - integer*4 a - a=0 - return - end -_LT_EOF -], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF - subroutine foo - implicit none - integer a - a=0 - return - end -_LT_EOF -], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF -public class foo { - private int a; - public void bar (void) { - a = 0; - } -}; -_LT_EOF -], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF -package foo -func foo() { -} -_LT_EOF -]) - -_lt_libdeps_save_CFLAGS=$CFLAGS -case "$CC $CFLAGS " in #( -*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; -*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; -*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; -esac - -dnl Parse the compiler output and extract the necessary -dnl objects, libraries and library flags. -if AC_TRY_EVAL(ac_compile); then - # Parse the compiler output and extract the necessary - # objects, libraries and library flags. - - # Sentinel used to keep track of whether or not we are before - # the conftest object file. - pre_test_object_deps_done=no - - for p in `eval "$output_verbose_link_cmd"`; do - case $prev$p in - - -L* | -R* | -l*) - # Some compilers place space between "-{L,R}" and the path. - # Remove the space. - if test x-L = "$p" || - test x-R = "$p"; then - prev=$p - continue - fi - - # Expand the sysroot to ease extracting the directories later. - if test -z "$prev"; then - case $p in - -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; - -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; - -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; - esac - fi - case $p in - =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; - esac - if test no = "$pre_test_object_deps_done"; then - case $prev in - -L | -R) - # Internal compiler library paths should come after those - # provided the user. The postdeps already come after the - # user supplied libs so there is no need to process them. - if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then - _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p - else - _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" - fi - ;; - # The "-l" case would never come before the object being - # linked, so don't bother handling this case. - esac - else - if test -z "$_LT_TAGVAR(postdeps, $1)"; then - _LT_TAGVAR(postdeps, $1)=$prev$p - else - _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" - fi - fi - prev= - ;; - - *.lto.$objext) ;; # Ignore GCC LTO objects - *.$objext) - # This assumes that the test object file only shows up - # once in the compiler output. - if test "$p" = "conftest.$objext"; then - pre_test_object_deps_done=yes - continue - fi - - if test no = "$pre_test_object_deps_done"; then - if test -z "$_LT_TAGVAR(predep_objects, $1)"; then - _LT_TAGVAR(predep_objects, $1)=$p - else - _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" - fi - else - if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then - _LT_TAGVAR(postdep_objects, $1)=$p - else - _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" - fi - fi - ;; - - *) ;; # Ignore the rest. - - esac - done - - # Clean up. - rm -f a.out a.exe -else - echo "libtool.m4: error: problem compiling $1 test program" -fi - -$RM -f confest.$objext -CFLAGS=$_lt_libdeps_save_CFLAGS - -# PORTME: override above test on systems where it is broken -m4_if([$1], [CXX], -[case $host_os in -interix[[3-9]]*) - # Interix 3.5 installs completely hosed .la files for C++, so rather than - # hack all around it, let's just trust "g++" to DTRT. - _LT_TAGVAR(predep_objects,$1)= - _LT_TAGVAR(postdep_objects,$1)= - _LT_TAGVAR(postdeps,$1)= - ;; -esac -]) - -case " $_LT_TAGVAR(postdeps, $1) " in -*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; -esac - _LT_TAGVAR(compiler_lib_search_dirs, $1)= -if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then - _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` -fi -_LT_TAGDECL([], [compiler_lib_search_dirs], [1], - [The directories searched by this compiler when creating a shared library]) -_LT_TAGDECL([], [predep_objects], [1], - [Dependencies to place before and after the objects being linked to - create a shared library]) -_LT_TAGDECL([], [postdep_objects], [1]) -_LT_TAGDECL([], [predeps], [1]) -_LT_TAGDECL([], [postdeps], [1]) -_LT_TAGDECL([], [compiler_lib_search_path], [1], - [The library search path used internally by the compiler when linking - a shared library]) -])# _LT_SYS_HIDDEN_LIBDEPS - - -# _LT_LANG_F77_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for a Fortran 77 compiler are -# suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to 'libtool'. -m4_defun([_LT_LANG_F77_CONFIG], -[AC_LANG_PUSH(Fortran 77) -if test -z "$F77" || test no = "$F77"; then - _lt_disable_F77=yes -fi - -_LT_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_TAGVAR(allow_undefined_flag, $1)= -_LT_TAGVAR(always_export_symbols, $1)=no -_LT_TAGVAR(archive_expsym_cmds, $1)= -_LT_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_TAGVAR(hardcode_direct, $1)=no -_LT_TAGVAR(hardcode_direct_absolute, $1)=no -_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_separator, $1)= -_LT_TAGVAR(hardcode_minus_L, $1)=no -_LT_TAGVAR(hardcode_automatic, $1)=no -_LT_TAGVAR(inherit_rpath, $1)=no -_LT_TAGVAR(module_cmds, $1)= -_LT_TAGVAR(module_expsym_cmds, $1)= -_LT_TAGVAR(link_all_deplibs, $1)=unknown -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(reload_flag, $1)=$reload_flag -_LT_TAGVAR(reload_cmds, $1)=$reload_cmds -_LT_TAGVAR(no_undefined_flag, $1)= -_LT_TAGVAR(whole_archive_flag_spec, $1)= -_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Source file extension for f77 test sources. -ac_ext=f - -# Object file extension for compiled f77 test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# No sense in running all these tests if we already determined that -# the F77 compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test yes != "$_lt_disable_F77"; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="\ - subroutine t - return - end -" - - # Code to be used in simple link tests - lt_simple_link_test_code="\ - program t - end -" - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - _LT_TAG_COMPILER - - # save warnings/boilerplate of simple test code - _LT_COMPILER_BOILERPLATE - _LT_LINKER_BOILERPLATE - - # Allow CC to be a program name with arguments. - lt_save_CC=$CC - lt_save_GCC=$GCC - lt_save_CFLAGS=$CFLAGS - CC=${F77-"f77"} - CFLAGS=$FFLAGS - compiler=$CC - _LT_TAGVAR(compiler, $1)=$CC - _LT_CC_BASENAME([$compiler]) - GCC=$G77 - if test -n "$compiler"; then - AC_MSG_CHECKING([if libtool supports shared libraries]) - AC_MSG_RESULT([$can_build_shared]) - - AC_MSG_CHECKING([whether to build shared libraries]) - test no = "$can_build_shared" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test yes = "$enable_shared" && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - aix[[4-9]]*) - if test ia64 != "$host_cpu"; then - case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in - yes,aix,yes) ;; # shared object as lib.so file only - yes,svr4,*) ;; # shared object as lib.so archive member only - yes,*) enable_static=no ;; # shared object in lib.a archive as well - esac - fi - ;; - esac - AC_MSG_RESULT([$enable_shared]) - - AC_MSG_CHECKING([whether to build static libraries]) - # Make sure either enable_shared or enable_static is yes. - test yes = "$enable_shared" || enable_static=yes - AC_MSG_RESULT([$enable_static]) - - _LT_TAGVAR(GCC, $1)=$G77 - _LT_TAGVAR(LD, $1)=$LD - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) - fi # test -n "$compiler" - - GCC=$lt_save_GCC - CC=$lt_save_CC - CFLAGS=$lt_save_CFLAGS -fi # test yes != "$_lt_disable_F77" - -AC_LANG_POP -])# _LT_LANG_F77_CONFIG - - -# _LT_LANG_FC_CONFIG([TAG]) -# ------------------------- -# Ensure that the configuration variables for a Fortran compiler are -# suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to 'libtool'. -m4_defun([_LT_LANG_FC_CONFIG], -[AC_LANG_PUSH(Fortran) - -if test -z "$FC" || test no = "$FC"; then - _lt_disable_FC=yes -fi - -_LT_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_TAGVAR(allow_undefined_flag, $1)= -_LT_TAGVAR(always_export_symbols, $1)=no -_LT_TAGVAR(archive_expsym_cmds, $1)= -_LT_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_TAGVAR(hardcode_direct, $1)=no -_LT_TAGVAR(hardcode_direct_absolute, $1)=no -_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_separator, $1)= -_LT_TAGVAR(hardcode_minus_L, $1)=no -_LT_TAGVAR(hardcode_automatic, $1)=no -_LT_TAGVAR(inherit_rpath, $1)=no -_LT_TAGVAR(module_cmds, $1)= -_LT_TAGVAR(module_expsym_cmds, $1)= -_LT_TAGVAR(link_all_deplibs, $1)=unknown -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(reload_flag, $1)=$reload_flag -_LT_TAGVAR(reload_cmds, $1)=$reload_cmds -_LT_TAGVAR(no_undefined_flag, $1)= -_LT_TAGVAR(whole_archive_flag_spec, $1)= -_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Source file extension for fc test sources. -ac_ext=${ac_fc_srcext-f} - -# Object file extension for compiled fc test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# No sense in running all these tests if we already determined that -# the FC compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test yes != "$_lt_disable_FC"; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="\ - subroutine t - return - end -" - - # Code to be used in simple link tests - lt_simple_link_test_code="\ - program t - end -" - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - _LT_TAG_COMPILER - - # save warnings/boilerplate of simple test code - _LT_COMPILER_BOILERPLATE - _LT_LINKER_BOILERPLATE - - # Allow CC to be a program name with arguments. - lt_save_CC=$CC - lt_save_GCC=$GCC - lt_save_CFLAGS=$CFLAGS - CC=${FC-"f95"} - CFLAGS=$FCFLAGS - compiler=$CC - GCC=$ac_cv_fc_compiler_gnu - - _LT_TAGVAR(compiler, $1)=$CC - _LT_CC_BASENAME([$compiler]) - - if test -n "$compiler"; then - AC_MSG_CHECKING([if libtool supports shared libraries]) - AC_MSG_RESULT([$can_build_shared]) - - AC_MSG_CHECKING([whether to build shared libraries]) - test no = "$can_build_shared" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test yes = "$enable_shared" && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - aix[[4-9]]*) - if test ia64 != "$host_cpu"; then - case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in - yes,aix,yes) ;; # shared object as lib.so file only - yes,svr4,*) ;; # shared object as lib.so archive member only - yes,*) enable_static=no ;; # shared object in lib.a archive as well - esac - fi - ;; - esac - AC_MSG_RESULT([$enable_shared]) - - AC_MSG_CHECKING([whether to build static libraries]) - # Make sure either enable_shared or enable_static is yes. - test yes = "$enable_shared" || enable_static=yes - AC_MSG_RESULT([$enable_static]) - - _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu - _LT_TAGVAR(LD, $1)=$LD - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - _LT_SYS_HIDDEN_LIBDEPS($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) - fi # test -n "$compiler" - - GCC=$lt_save_GCC - CC=$lt_save_CC - CFLAGS=$lt_save_CFLAGS -fi # test yes != "$_lt_disable_FC" - -AC_LANG_POP -])# _LT_LANG_FC_CONFIG - - -# _LT_LANG_GCJ_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for the GNU Java Compiler compiler -# are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to 'libtool'. -m4_defun([_LT_LANG_GCJ_CONFIG], -[AC_REQUIRE([LT_PROG_GCJ])dnl -AC_LANG_SAVE - -# Source file extension for Java test sources. -ac_ext=java - -# Object file extension for compiled Java test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="class foo {}" - -# Code to be used in simple link tests -lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_TAG_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -# Allow CC to be a program name with arguments. -lt_save_CC=$CC -lt_save_CFLAGS=$CFLAGS -lt_save_GCC=$GCC -GCC=yes -CC=${GCJ-"gcj"} -CFLAGS=$GCJFLAGS -compiler=$CC -_LT_TAGVAR(compiler, $1)=$CC -_LT_TAGVAR(LD, $1)=$LD -_LT_CC_BASENAME([$compiler]) - -# GCJ did not exist at the time GCC didn't implicitly link libc in. -_LT_TAGVAR(archive_cmds_need_lc, $1)=no - -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(reload_flag, $1)=$reload_flag -_LT_TAGVAR(reload_cmds, $1)=$reload_cmds - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... -if test -n "$compiler"; then - _LT_COMPILER_NO_RTTI($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) -fi - -AC_LANG_RESTORE - -GCC=$lt_save_GCC -CC=$lt_save_CC -CFLAGS=$lt_save_CFLAGS -])# _LT_LANG_GCJ_CONFIG - - -# _LT_LANG_GO_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for the GNU Go compiler -# are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to 'libtool'. -m4_defun([_LT_LANG_GO_CONFIG], -[AC_REQUIRE([LT_PROG_GO])dnl -AC_LANG_SAVE - -# Source file extension for Go test sources. -ac_ext=go - -# Object file extension for compiled Go test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="package main; func main() { }" - -# Code to be used in simple link tests -lt_simple_link_test_code='package main; func main() { }' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_TAG_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -# Allow CC to be a program name with arguments. -lt_save_CC=$CC -lt_save_CFLAGS=$CFLAGS -lt_save_GCC=$GCC -GCC=yes -CC=${GOC-"gccgo"} -CFLAGS=$GOFLAGS -compiler=$CC -_LT_TAGVAR(compiler, $1)=$CC -_LT_TAGVAR(LD, $1)=$LD -_LT_CC_BASENAME([$compiler]) - -# Go did not exist at the time GCC didn't implicitly link libc in. -_LT_TAGVAR(archive_cmds_need_lc, $1)=no - -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(reload_flag, $1)=$reload_flag -_LT_TAGVAR(reload_cmds, $1)=$reload_cmds - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... -if test -n "$compiler"; then - _LT_COMPILER_NO_RTTI($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) -fi - -AC_LANG_RESTORE - -GCC=$lt_save_GCC -CC=$lt_save_CC -CFLAGS=$lt_save_CFLAGS -])# _LT_LANG_GO_CONFIG - - -# _LT_LANG_RC_CONFIG([TAG]) -# ------------------------- -# Ensure that the configuration variables for the Windows resource compiler -# are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to 'libtool'. -m4_defun([_LT_LANG_RC_CONFIG], -[AC_REQUIRE([LT_PROG_RC])dnl -AC_LANG_SAVE - -# Source file extension for RC test sources. -ac_ext=rc - -# Object file extension for compiled RC test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' - -# Code to be used in simple link tests -lt_simple_link_test_code=$lt_simple_compile_test_code - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_TAG_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -# Allow CC to be a program name with arguments. -lt_save_CC=$CC -lt_save_CFLAGS=$CFLAGS -lt_save_GCC=$GCC -GCC= -CC=${RC-"windres"} -CFLAGS= -compiler=$CC -_LT_TAGVAR(compiler, $1)=$CC -_LT_CC_BASENAME([$compiler]) -_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes - -if test -n "$compiler"; then - : - _LT_CONFIG($1) -fi - -GCC=$lt_save_GCC -AC_LANG_RESTORE -CC=$lt_save_CC -CFLAGS=$lt_save_CFLAGS -])# _LT_LANG_RC_CONFIG - - -# LT_PROG_GCJ -# ----------- -AC_DEFUN([LT_PROG_GCJ], -[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], - [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], - [AC_CHECK_TOOL(GCJ, gcj,) - test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" - AC_SUBST(GCJFLAGS)])])[]dnl -]) - -# Old name: -AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([LT_AC_PROG_GCJ], []) - - -# LT_PROG_GO -# ---------- -AC_DEFUN([LT_PROG_GO], -[AC_CHECK_TOOL(GOC, gccgo,) -]) - - -# LT_PROG_RC -# ---------- -AC_DEFUN([LT_PROG_RC], -[AC_CHECK_TOOL(RC, windres,) -]) - -# Old name: -AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([LT_AC_PROG_RC], []) - - -# _LT_DECL_EGREP -# -------------- -# If we don't have a new enough Autoconf to choose the best grep -# available, choose the one first in the user's PATH. -m4_defun([_LT_DECL_EGREP], -[AC_REQUIRE([AC_PROG_EGREP])dnl -AC_REQUIRE([AC_PROG_FGREP])dnl -test -z "$GREP" && GREP=grep -_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) -_LT_DECL([], [EGREP], [1], [An ERE matcher]) -_LT_DECL([], [FGREP], [1], [A literal string matcher]) -dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too -AC_SUBST([GREP]) -]) - - -# _LT_DECL_OBJDUMP -# -------------- -# If we don't have a new enough Autoconf to choose the best objdump -# available, choose the one first in the user's PATH. -m4_defun([_LT_DECL_OBJDUMP], -[AC_CHECK_TOOL(OBJDUMP, objdump, false) -test -z "$OBJDUMP" && OBJDUMP=objdump -_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) -AC_SUBST([OBJDUMP]) -]) - -# _LT_DECL_DLLTOOL -# ---------------- -# Ensure DLLTOOL variable is set. -m4_defun([_LT_DECL_DLLTOOL], -[AC_CHECK_TOOL(DLLTOOL, dlltool, false) -test -z "$DLLTOOL" && DLLTOOL=dlltool -_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) -AC_SUBST([DLLTOOL]) -]) - -# _LT_DECL_SED -# ------------ -# Check for a fully-functional sed program, that truncates -# as few characters as possible. Prefer GNU sed if found. -m4_defun([_LT_DECL_SED], -[AC_PROG_SED -test -z "$SED" && SED=sed -Xsed="$SED -e 1s/^X//" -_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) -_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], - [Sed that helps us avoid accidentally triggering echo(1) options like -n]) -])# _LT_DECL_SED - -m4_ifndef([AC_PROG_SED], [ -############################################################ -# NOTE: This macro has been submitted for inclusion into # -# GNU Autoconf as AC_PROG_SED. When it is available in # -# a released version of Autoconf we should remove this # -# macro and use it instead. # -############################################################ - -m4_defun([AC_PROG_SED], -[AC_MSG_CHECKING([for a sed that does not truncate output]) -AC_CACHE_VAL(lt_cv_path_SED, -[# Loop through the user's path and test for sed and gsed. -# Then use that list of sed's as ones to test for truncation. -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for lt_ac_prog in sed gsed; do - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then - lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" - fi - done - done -done -IFS=$as_save_IFS -lt_ac_max=0 -lt_ac_count=0 -# Add /usr/xpg4/bin/sed as it is typically found on Solaris -# along with /bin/sed that truncates output. -for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do - test ! -f "$lt_ac_sed" && continue - cat /dev/null > conftest.in - lt_ac_count=0 - echo $ECHO_N "0123456789$ECHO_C" >conftest.in - # Check for GNU sed and select it if it is found. - if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then - lt_cv_path_SED=$lt_ac_sed - break - fi - while true; do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo >>conftest.nl - $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break - cmp -s conftest.out conftest.nl || break - # 10000 chars as input seems more than enough - test 10 -lt "$lt_ac_count" && break - lt_ac_count=`expr $lt_ac_count + 1` - if test "$lt_ac_count" -gt "$lt_ac_max"; then - lt_ac_max=$lt_ac_count - lt_cv_path_SED=$lt_ac_sed - fi - done -done -]) -SED=$lt_cv_path_SED -AC_SUBST([SED]) -AC_MSG_RESULT([$SED]) -])#AC_PROG_SED -])#m4_ifndef - -# Old name: -AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([LT_AC_PROG_SED], []) - - -# _LT_CHECK_SHELL_FEATURES -# ------------------------ -# Find out whether the shell is Bourne or XSI compatible, -# or has some other useful features. -m4_defun([_LT_CHECK_SHELL_FEATURES], -[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - lt_unset=unset -else - lt_unset=false -fi -_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl - -# test EBCDIC or ASCII -case `echo X|tr X '\101'` in - A) # ASCII based system - # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr - lt_SP2NL='tr \040 \012' - lt_NL2SP='tr \015\012 \040\040' - ;; - *) # EBCDIC based system - lt_SP2NL='tr \100 \n' - lt_NL2SP='tr \r\n \100\100' - ;; -esac -_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl -_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl -])# _LT_CHECK_SHELL_FEATURES - - -# _LT_PATH_CONVERSION_FUNCTIONS -# ----------------------------- -# Determine what file name conversion functions should be used by -# func_to_host_file (and, implicitly, by func_to_host_path). These are needed -# for certain cross-compile configurations and native mingw. -m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -AC_MSG_CHECKING([how to convert $build file names to $host format]) -AC_CACHE_VAL(lt_cv_to_host_file_cmd, -[case $host in - *-*-mingw* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 - ;; - *-*-cygwin* ) - lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 - ;; - * ) # otherwise, assume *nix - lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 - ;; - esac - ;; - *-*-cygwin* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin - ;; - *-*-cygwin* ) - lt_cv_to_host_file_cmd=func_convert_file_noop - ;; - * ) # otherwise, assume *nix - lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin - ;; - esac - ;; - * ) # unhandled hosts (and "normal" native builds) - lt_cv_to_host_file_cmd=func_convert_file_noop - ;; -esac -]) -to_host_file_cmd=$lt_cv_to_host_file_cmd -AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) -_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], - [0], [convert $build file names to $host format])dnl - -AC_MSG_CHECKING([how to convert $build file names to toolchain format]) -AC_CACHE_VAL(lt_cv_to_tool_file_cmd, -[#assume ordinary cross tools, or native build. -lt_cv_to_tool_file_cmd=func_convert_file_noop -case $host in - *-*-mingw* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 - ;; - esac - ;; -esac -]) -to_tool_file_cmd=$lt_cv_to_tool_file_cmd -AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) -_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], - [0], [convert $build files to toolchain format])dnl -])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4 deleted file mode 100644 index 94b08297..00000000 --- a/m4/ltoptions.m4 +++ /dev/null @@ -1,437 +0,0 @@ -# Helper functions for option handling. -*- Autoconf -*- -# -# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software -# Foundation, Inc. -# Written by Gary V. Vaughan, 2004 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 8 ltoptions.m4 - -# This is to help aclocal find these macros, as it can't see m4_define. -AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) - - -# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) -# ------------------------------------------ -m4_define([_LT_MANGLE_OPTION], -[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) - - -# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) -# --------------------------------------- -# Set option OPTION-NAME for macro MACRO-NAME, and if there is a -# matching handler defined, dispatch to it. Other OPTION-NAMEs are -# saved as a flag. -m4_define([_LT_SET_OPTION], -[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl -m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), - _LT_MANGLE_DEFUN([$1], [$2]), - [m4_warning([Unknown $1 option '$2'])])[]dnl -]) - - -# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) -# ------------------------------------------------------------ -# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. -m4_define([_LT_IF_OPTION], -[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) - - -# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) -# ------------------------------------------------------- -# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME -# are set. -m4_define([_LT_UNLESS_OPTIONS], -[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), - [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), - [m4_define([$0_found])])])[]dnl -m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 -])[]dnl -]) - - -# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) -# ---------------------------------------- -# OPTION-LIST is a space-separated list of Libtool options associated -# with MACRO-NAME. If any OPTION has a matching handler declared with -# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about -# the unknown option and exit. -m4_defun([_LT_SET_OPTIONS], -[# Set options -m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), - [_LT_SET_OPTION([$1], _LT_Option)]) - -m4_if([$1],[LT_INIT],[ - dnl - dnl Simply set some default values (i.e off) if boolean options were not - dnl specified: - _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no - ]) - _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no - ]) - dnl - dnl If no reference was made to various pairs of opposing options, then - dnl we run the default mode handler for the pair. For example, if neither - dnl 'shared' nor 'disable-shared' was passed, we enable building of shared - dnl archives by default: - _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) - _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) - _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) - _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], - [_LT_ENABLE_FAST_INSTALL]) - _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], - [_LT_WITH_AIX_SONAME([aix])]) - ]) -])# _LT_SET_OPTIONS - - -## --------------------------------- ## -## Macros to handle LT_INIT options. ## -## --------------------------------- ## - -# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) -# ----------------------------------------- -m4_define([_LT_MANGLE_DEFUN], -[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) - - -# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) -# ----------------------------------------------- -m4_define([LT_OPTION_DEFINE], -[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl -])# LT_OPTION_DEFINE - - -# dlopen -# ------ -LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes -]) - -AU_DEFUN([AC_LIBTOOL_DLOPEN], -[_LT_SET_OPTION([LT_INIT], [dlopen]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you -put the 'dlopen' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) - - -# win32-dll -# --------- -# Declare package support for building win32 dll's. -LT_OPTION_DEFINE([LT_INIT], [win32-dll], -[enable_win32_dll=yes - -case $host in -*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) - AC_CHECK_TOOL(AS, as, false) - AC_CHECK_TOOL(DLLTOOL, dlltool, false) - AC_CHECK_TOOL(OBJDUMP, objdump, false) - ;; -esac - -test -z "$AS" && AS=as -_LT_DECL([], [AS], [1], [Assembler program])dnl - -test -z "$DLLTOOL" && DLLTOOL=dlltool -_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl - -test -z "$OBJDUMP" && OBJDUMP=objdump -_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl -])# win32-dll - -AU_DEFUN([AC_LIBTOOL_WIN32_DLL], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -_LT_SET_OPTION([LT_INIT], [win32-dll]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you -put the 'win32-dll' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) - - -# _LT_ENABLE_SHARED([DEFAULT]) -# ---------------------------- -# implement the --enable-shared flag, and supports the 'shared' and -# 'disable-shared' LT_INIT options. -# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. -m4_define([_LT_ENABLE_SHARED], -[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl -AC_ARG_ENABLE([shared], - [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], - [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_shared=yes ;; - no) enable_shared=no ;; - *) - enable_shared=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, - for pkg in $enableval; do - IFS=$lt_save_ifs - if test "X$pkg" = "X$p"; then - enable_shared=yes - fi - done - IFS=$lt_save_ifs - ;; - esac], - [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) - - _LT_DECL([build_libtool_libs], [enable_shared], [0], - [Whether or not to build shared libraries]) -])# _LT_ENABLE_SHARED - -LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) -LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) - -# Old names: -AC_DEFUN([AC_ENABLE_SHARED], -[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) -]) - -AC_DEFUN([AC_DISABLE_SHARED], -[_LT_SET_OPTION([LT_INIT], [disable-shared]) -]) - -AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) -AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AM_ENABLE_SHARED], []) -dnl AC_DEFUN([AM_DISABLE_SHARED], []) - - - -# _LT_ENABLE_STATIC([DEFAULT]) -# ---------------------------- -# implement the --enable-static flag, and support the 'static' and -# 'disable-static' LT_INIT options. -# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. -m4_define([_LT_ENABLE_STATIC], -[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl -AC_ARG_ENABLE([static], - [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], - [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_static=yes ;; - no) enable_static=no ;; - *) - enable_static=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, - for pkg in $enableval; do - IFS=$lt_save_ifs - if test "X$pkg" = "X$p"; then - enable_static=yes - fi - done - IFS=$lt_save_ifs - ;; - esac], - [enable_static=]_LT_ENABLE_STATIC_DEFAULT) - - _LT_DECL([build_old_libs], [enable_static], [0], - [Whether or not to build static libraries]) -])# _LT_ENABLE_STATIC - -LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) -LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) - -# Old names: -AC_DEFUN([AC_ENABLE_STATIC], -[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) -]) - -AC_DEFUN([AC_DISABLE_STATIC], -[_LT_SET_OPTION([LT_INIT], [disable-static]) -]) - -AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) -AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AM_ENABLE_STATIC], []) -dnl AC_DEFUN([AM_DISABLE_STATIC], []) - - - -# _LT_ENABLE_FAST_INSTALL([DEFAULT]) -# ---------------------------------- -# implement the --enable-fast-install flag, and support the 'fast-install' -# and 'disable-fast-install' LT_INIT options. -# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. -m4_define([_LT_ENABLE_FAST_INSTALL], -[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl -AC_ARG_ENABLE([fast-install], - [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], - [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_fast_install=yes ;; - no) enable_fast_install=no ;; - *) - enable_fast_install=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, - for pkg in $enableval; do - IFS=$lt_save_ifs - if test "X$pkg" = "X$p"; then - enable_fast_install=yes - fi - done - IFS=$lt_save_ifs - ;; - esac], - [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) - -_LT_DECL([fast_install], [enable_fast_install], [0], - [Whether or not to optimize for fast installation])dnl -])# _LT_ENABLE_FAST_INSTALL - -LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) -LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) - -# Old names: -AU_DEFUN([AC_ENABLE_FAST_INSTALL], -[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you put -the 'fast-install' option into LT_INIT's first parameter.]) -]) - -AU_DEFUN([AC_DISABLE_FAST_INSTALL], -[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you put -the 'disable-fast-install' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) -dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) - - -# _LT_WITH_AIX_SONAME([DEFAULT]) -# ---------------------------------- -# implement the --with-aix-soname flag, and support the `aix-soname=aix' -# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT -# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. -m4_define([_LT_WITH_AIX_SONAME], -[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl -shared_archive_member_spec= -case $host,$enable_shared in -power*-*-aix[[5-9]]*,yes) - AC_MSG_CHECKING([which variant of shared library versioning to provide]) - AC_ARG_WITH([aix-soname], - [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], - [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], - [case $withval in - aix|svr4|both) - ;; - *) - AC_MSG_ERROR([Unknown argument to --with-aix-soname]) - ;; - esac - lt_cv_with_aix_soname=$with_aix_soname], - [AC_CACHE_VAL([lt_cv_with_aix_soname], - [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) - with_aix_soname=$lt_cv_with_aix_soname]) - AC_MSG_RESULT([$with_aix_soname]) - if test aix != "$with_aix_soname"; then - # For the AIX way of multilib, we name the shared archive member - # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', - # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. - # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, - # the AIX toolchain works better with OBJECT_MODE set (default 32). - if test 64 = "${OBJECT_MODE-32}"; then - shared_archive_member_spec=shr_64 - else - shared_archive_member_spec=shr - fi - fi - ;; -*) - with_aix_soname=aix - ;; -esac - -_LT_DECL([], [shared_archive_member_spec], [0], - [Shared archive member basename, for filename based shared library versioning on AIX])dnl -])# _LT_WITH_AIX_SONAME - -LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) -LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) -LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) - - -# _LT_WITH_PIC([MODE]) -# -------------------- -# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' -# LT_INIT options. -# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. -m4_define([_LT_WITH_PIC], -[AC_ARG_WITH([pic], - [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], - [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], - [lt_p=${PACKAGE-default} - case $withval in - yes|no) pic_mode=$withval ;; - *) - pic_mode=default - # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, - for lt_pkg in $withval; do - IFS=$lt_save_ifs - if test "X$lt_pkg" = "X$lt_p"; then - pic_mode=yes - fi - done - IFS=$lt_save_ifs - ;; - esac], - [pic_mode=m4_default([$1], [default])]) - -_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl -])# _LT_WITH_PIC - -LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) -LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) - -# Old name: -AU_DEFUN([AC_LIBTOOL_PICMODE], -[_LT_SET_OPTION([LT_INIT], [pic-only]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you -put the 'pic-only' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) - -## ----------------- ## -## LTDL_INIT Options ## -## ----------------- ## - -m4_define([_LTDL_MODE], []) -LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], - [m4_define([_LTDL_MODE], [nonrecursive])]) -LT_OPTION_DEFINE([LTDL_INIT], [recursive], - [m4_define([_LTDL_MODE], [recursive])]) -LT_OPTION_DEFINE([LTDL_INIT], [subproject], - [m4_define([_LTDL_MODE], [subproject])]) - -m4_define([_LTDL_TYPE], []) -LT_OPTION_DEFINE([LTDL_INIT], [installable], - [m4_define([_LTDL_TYPE], [installable])]) -LT_OPTION_DEFINE([LTDL_INIT], [convenience], - [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/m4/ltsugar.m4 b/m4/ltsugar.m4 deleted file mode 100644 index 48bc9344..00000000 --- a/m4/ltsugar.m4 +++ /dev/null @@ -1,124 +0,0 @@ -# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- -# -# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software -# Foundation, Inc. -# Written by Gary V. Vaughan, 2004 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 6 ltsugar.m4 - -# This is to help aclocal find these macros, as it can't see m4_define. -AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) - - -# lt_join(SEP, ARG1, [ARG2...]) -# ----------------------------- -# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their -# associated separator. -# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier -# versions in m4sugar had bugs. -m4_define([lt_join], -[m4_if([$#], [1], [], - [$#], [2], [[$2]], - [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) -m4_define([_lt_join], -[m4_if([$#$2], [2], [], - [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) - - -# lt_car(LIST) -# lt_cdr(LIST) -# ------------ -# Manipulate m4 lists. -# These macros are necessary as long as will still need to support -# Autoconf-2.59, which quotes differently. -m4_define([lt_car], [[$1]]) -m4_define([lt_cdr], -[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], - [$#], 1, [], - [m4_dquote(m4_shift($@))])]) -m4_define([lt_unquote], $1) - - -# lt_append(MACRO-NAME, STRING, [SEPARATOR]) -# ------------------------------------------ -# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. -# Note that neither SEPARATOR nor STRING are expanded; they are appended -# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). -# No SEPARATOR is output if MACRO-NAME was previously undefined (different -# than defined and empty). -# -# This macro is needed until we can rely on Autoconf 2.62, since earlier -# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. -m4_define([lt_append], -[m4_define([$1], - m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) - - - -# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) -# ---------------------------------------------------------- -# Produce a SEP delimited list of all paired combinations of elements of -# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list -# has the form PREFIXmINFIXSUFFIXn. -# Needed until we can rely on m4_combine added in Autoconf 2.62. -m4_define([lt_combine], -[m4_if(m4_eval([$# > 3]), [1], - [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl -[[m4_foreach([_Lt_prefix], [$2], - [m4_foreach([_Lt_suffix], - ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, - [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) - - -# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) -# ----------------------------------------------------------------------- -# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited -# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. -m4_define([lt_if_append_uniq], -[m4_ifdef([$1], - [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], - [lt_append([$1], [$2], [$3])$4], - [$5])], - [lt_append([$1], [$2], [$3])$4])]) - - -# lt_dict_add(DICT, KEY, VALUE) -# ----------------------------- -m4_define([lt_dict_add], -[m4_define([$1($2)], [$3])]) - - -# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) -# -------------------------------------------- -m4_define([lt_dict_add_subkey], -[m4_define([$1($2:$3)], [$4])]) - - -# lt_dict_fetch(DICT, KEY, [SUBKEY]) -# ---------------------------------- -m4_define([lt_dict_fetch], -[m4_ifval([$3], - m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), - m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) - - -# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) -# ----------------------------------------------------------------- -m4_define([lt_if_dict_fetch], -[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], - [$5], - [$6])]) - - -# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) -# -------------------------------------------------------------- -m4_define([lt_dict_filter], -[m4_if([$5], [], [], - [lt_join(m4_quote(m4_default([$4], [[, ]])), - lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), - [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl -]) diff --git a/m4/ltversion.m4 b/m4/ltversion.m4 deleted file mode 100644 index fa04b52a..00000000 --- a/m4/ltversion.m4 +++ /dev/null @@ -1,23 +0,0 @@ -# ltversion.m4 -- version numbers -*- Autoconf -*- -# -# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. -# Written by Scott James Remnant, 2004 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# @configure_input@ - -# serial 4179 ltversion.m4 -# This file is part of GNU Libtool - -m4_define([LT_PACKAGE_VERSION], [2.4.6]) -m4_define([LT_PACKAGE_REVISION], [2.4.6]) - -AC_DEFUN([LTVERSION_VERSION], -[macro_version='2.4.6' -macro_revision='2.4.6' -_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) -_LT_DECL(, macro_revision, 0) -]) diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4 deleted file mode 100644 index c6b26f88..00000000 --- a/m4/lt~obsolete.m4 +++ /dev/null @@ -1,99 +0,0 @@ -# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- -# -# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software -# Foundation, Inc. -# Written by Scott James Remnant, 2004. -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 5 lt~obsolete.m4 - -# These exist entirely to fool aclocal when bootstrapping libtool. -# -# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), -# which have later been changed to m4_define as they aren't part of the -# exported API, or moved to Autoconf or Automake where they belong. -# -# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN -# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us -# using a macro with the same name in our local m4/libtool.m4 it'll -# pull the old libtool.m4 in (it doesn't see our shiny new m4_define -# and doesn't know about Autoconf macros at all.) -# -# So we provide this file, which has a silly filename so it's always -# included after everything else. This provides aclocal with the -# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything -# because those macros already exist, or will be overwritten later. -# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. -# -# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. -# Yes, that means every name once taken will need to remain here until -# we give up compatibility with versions before 1.7, at which point -# we need to keep only those names which we still refer to. - -# This is to help aclocal find these macros, as it can't see m4_define. -AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) - -m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) -m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) -m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) -m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) -m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) -m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) -m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) -m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) -m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) -m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) -m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) -m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) -m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) -m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) -m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) -m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) -m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) -m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) -m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) -m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) -m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) -m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) -m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) -m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) -m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) -m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) -m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) -m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) -m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) -m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) -m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) -m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) -m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) -m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) -m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) -m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) -m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) -m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) -m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) -m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) -m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) -m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) -m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) -m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) -m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) -m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) -m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) -m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) -m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) -m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) -m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) -m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) -m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) -m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) -m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) -m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) -m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) From bad1139ef700ddfd2994aa864b9a7906636a6ccd Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 11 Aug 2018 15:16:32 +0200 Subject: [PATCH 204/210] fixs .travis.yml --- .travis.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index c4dd1f3d..9977be99 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,12 +18,12 @@ matrix: - os: linux env: HOST="" API="jack" compiler: clang - - os: linux - env: HOST="--host=i686-w64-mingw32" API="winmm" - compiler: gcc - - os: linux - env: HOST="--host=x86_64-w64-mingw32" API="winmm" - compiler: gcc + # - os: linux + # env: HOST="--host=i686-w64-mingw32" API="winmm" + # compiler: gcc + # - os: linux + # env: HOST="--host=x86_64-w64-mingw32" API="winmm" + # compiler: gcc # jack and asound not found on ARM gnueabihf # - os: linux # env: HOST="--host=arm-linux-gnueabihf" API="alsa" @@ -70,6 +70,6 @@ before_install: script: - mkdir -p config - touch config/config.rpath - - ./autogen.sh --disable-apisearchv --with-$API $HOST && make && make -j4 && $TEST_RUNNER make check || (cat test-suite.log ; false) + - ./autogen.sh --disable-apisearch --with-$API $HOST && make && make -j4 && $TEST_RUNNER make check || (cat test-suite.log ; false) - make distcheck - cat tests/errors.log From 74fe28b65dfa71ce6de0554b1ad9d25d1b40d1f3 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 11 Aug 2018 15:16:55 +0200 Subject: [PATCH 205/210] remove --force from autogen.sh --- autogen.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autogen.sh b/autogen.sh index 1fb839cf..8bd52e88 100755 --- a/autogen.sh +++ b/autogen.sh @@ -87,8 +87,8 @@ autoconf || exit 1 else # autoreconf instead - echo "Running autoreconf --verbose --install --force ..." - autoreconf --verbose --install --force || exit 1 + echo "Running autoreconf --verbose --install ..." + autoreconf --verbose --install || exit 1 fi From a939acb33a8407a436e51b4db943a4b533d019c8 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 11 Aug 2018 15:17:28 +0200 Subject: [PATCH 206/210] check for sem_timedwait as this is not available on Mac OS X --- configure.library | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.library b/configure.library index d5751b94..b84b5393 100644 --- a/configure.library +++ b/configure.library @@ -227,10 +227,10 @@ dnl esac - +dnl sem_timedwait may not be availlable on Mac OS X # Check for POSIX semaphore support AC_CHECK_HEADER([semaphore.h], [ - AC_CHECK_LIB(pthread, sem_init, + AC_CHECK_LIB(pthread, sem_timedwait, AC_DEFINE([HAVE_SEMAPHORE],[1],[Define to 1 if you have POSIX semaphore support on your system.]), AC_MSG_WARN([POSIX semaphore support not found; data may be lost on closePort])) ]) From 204849d524e7c34b80a6a272401ca0361e171d62 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 11 Aug 2018 15:17:48 +0200 Subject: [PATCH 207/210] Fix some minor Mac OS X issues --- RtMidi.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 020a645b..9e745509 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1881,7 +1881,6 @@ void MidiInCore :: openPort( unsigned int portNumber, midiInputCallback, (void *)this, &port ); if ( result != noErr ) { MIDIClientDispose( data->client ); - data->client = 0; error(RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI input port."), Error::DRIVER_ERROR)); return; @@ -1893,7 +1892,6 @@ void MidiInCore :: openPort( unsigned int portNumber, MIDIPortDispose( port ); port = 0; MIDIClientDispose( data->client ); - data->client = 0; error(RTMIDI_ERROR(gettext_noopt("Error getting MIDI input source reference."), Error::DRIVER_ERROR) ); return; @@ -1905,7 +1903,6 @@ void MidiInCore :: openPort( unsigned int portNumber, MIDIPortDispose( port ); port = 0; MIDIClientDispose( data->client ); - data -> client = 0; error(RTMIDI_ERROR(gettext_noopt("Error connecting OS-X MIDI input port."), Error::DRIVER_ERROR) ); return; @@ -2141,7 +2138,6 @@ void MidiOutCore :: openPort( unsigned int portNumber, &port ); if ( result != noErr ) { MIDIClientDispose( data->client ); - data->client = 0; error(RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI output port."), Error::DRIVER_ERROR) ); return; @@ -2153,7 +2149,6 @@ void MidiOutCore :: openPort( unsigned int portNumber, MIDIPortDispose( port ); port = 0; MIDIClientDispose( data->client ); - data->client = 0; error(RTMIDI_ERROR(gettext_noopt("Error getting MIDI output destination reference."), Error::DRIVER_ERROR) ); return; @@ -2300,7 +2295,7 @@ void MidiOutCore :: sendMessage( const unsigned char *message, size_t size ) CoreMidiData *data = static_cast (apiData_); OSStatus result; - if ( message.at(0) != 0xF0 && size > 3 ) { + if ( message[0] != 0xF0 && size > 3 ) { error(RTMIDI_ERROR(gettext_noopt("message format problem ... not sysex but > 3 bytes?"), Error::WARNING )); return; @@ -5430,7 +5425,7 @@ struct JackMidiData:public JackPortDescriptor { if (state_response != JackMidiData::CLOSING2) { /* output the transferred data */ state_response = JackMidiData::CLOSING2; - return 0; + return; } deletePort(); state_response = JackMidiData::CLOSED; @@ -5443,7 +5438,7 @@ struct JackMidiData:public JackPortDescriptor { if (state_response != JackMidiData::DELETING2) { state_response = JackMidiData::DELETING2; /* output the transferred data */ - return 0; + return; } delete this; From a888e47e9b0f9d523e78f32226a633e14750574f Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 11 Aug 2018 15:37:04 +0200 Subject: [PATCH 208/210] Fix coremidi and build multi-api binaries. --- .travis.yml | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9977be99..c3318992 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,12 @@ matrix: - os: linux env: HOST="" API="jack" compiler: clang + - os: linux + env: HOST="--with-jack" API="alsa" + compiler: gcc + - os: linux + env: HOST="--with-jack" API="alsa" + compiler: clang # - os: linux # env: HOST="--host=i686-w64-mingw32" API="winmm" # compiler: gcc @@ -32,10 +38,22 @@ matrix: # env: HOST="--host=arm-linux-gnueabihf" API="jack" # compiler: gcc - os: osx - env: HOST="" API="core" + env: HOST="" API="coremidi" + compiler: gcc + - os: osx + env: HOST="" API="coremidi" + compiler: clang + - os: osx + env: HOST="" API="jack" + compiler: gcc + - os: osx + env: HOST="" API="jack" + compiler: clang + - os: osx + env: HOST="--with-jack" API="coremidi" compiler: gcc - os: osx - env: HOST="" API="core" + env: HOST="--with-jack" API="coremidi" compiler: clang language: c++ group: travis_latest From c4a05d353f8bf3938859d1d1d3bbe1bbd27df9ec Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Mon, 13 Aug 2018 18:55:00 +0200 Subject: [PATCH 209/210] Fix Dummy interface --- RtMidi.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 3ed0ed74..f4256d80 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -64,7 +64,7 @@ // // **************************************************************** // -#if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__) +#if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_COREMIDI__) && !defined(__WINDOWS_MM__) #define __RTMIDI_DUMMY__ #endif @@ -293,7 +293,7 @@ class MidiInDummy: public MidiInApi error( RTMIDI_ERROR(rtmidi_gettext("No valid MIDI interfaces. I'm using a dummy input interface that never receives anything."), Error::WARNING) ); } - ApiType getCurrentApi( void ) throw() { return rtmidi::RTMIDI_DUMMY; } + ApiType getCurrentApi( void ) throw() { return rtmidi::DUMMY; } bool hasVirtualPorts() const { return false; } void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {} void openVirtualPort( const std::string &/*portName*/ ) {} @@ -322,7 +322,7 @@ class MidiOutDummy: public MidiOutApi error( RTMIDI_ERROR(rtmidi_gettext("No valid MIDI interfaces. I'm using a dummy output interface that does nothing."), Error::WARNING) ); } - ApiType getCurrentApi( void ) throw() { return rtmidi::RTMIDI_DUMMY; } + ApiType getCurrentApi( void ) throw() { return rtmidi::DUMMY; } bool hasVirtualPorts() const { return false; } void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {} void openVirtualPort( const std::string &/*portName*/ ) {} From 3f6ef4eb18e90593f6e3cc083b736f027766cb42 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Mon, 13 Aug 2018 19:07:03 +0200 Subject: [PATCH 210/210] Update translations --- po/de.gmo | Bin 13272 -> 14907 bytes po/de.mo | Bin 13440 -> 14907 bytes po/de.po | 312 ++++++++++++++++++++++++++++------------------- po/rtmidi-ts.pot | 293 +++++++++++++++++++++++++------------------- 4 files changed, 356 insertions(+), 249 deletions(-) diff --git a/po/de.gmo b/po/de.gmo index a00aac037ac9e60177b16177f6326b3e08c62126..ba5cfe203f4d82fc08b3b237ba26327b6113dd55 100644 GIT binary patch delta 4151 zcmb`|Z){a(9l-IYrG?Ql{*6-FGWryYg{}9tr3JdefYKIL`Ukf1e0XQ_8e=wIDAml6EPJ5|;-*pj{?0vx zGQlmz6Q28d&gpsn{hr@*cyIK)pZ)#PlCLSQ3}q$d%{fYa3lsDB;hLVWR15wAKZo~} zDYY6m;Tk-GC3pfqk0-GgU%?1o!)mNAr!8(nx>7?ps8m)RrP9cQSMWZ(gtb_*K&d9I zM;T}zHsF&;L-ieO#J}JsTy?inU3dWHy)!5a`Z=z^%eWRl!gW};P$ryJs*j2c=%U6K zP&&?I9Zq8v7B4E?uf#3fZ^e!HWvs{7P$v2=uEKw!47hS}VPQRZKlf>riG33zjIVx5 zr4z59L}1+#rJ8XcN{1&=CUOpCrSG70P`b3R6{}I+>%n_*JoGt~EqfVj@NJX{TtR7n z5Brgo7n-Ta0Q*oTFoDwHw^1VT7Rq~9Q9`$3Sz%>6kbi1Cygz}G3*Se{fmcyN{}DseX7)NtlKndLD$2|&mlsyjg|gCPC<8o&((W`eN0mnj z{abh#|BQQZcV%I#&YSV_AD~7qV^Y>-ZR+ z!&Y2C7-Ychc(9nQz#ZIAkvu)Dwj}Z+C(DAX)q`eIf-&! z&)^X}ivxHaWnu&DlVtx(xDBUJA~c7DX~)ed5%p32{w6+*B{ZUaRvn-s4PHj+=rTV< zS(T81GQhpqj}A8Dd2GWEQ9@kDS4Zr{2k`OGbD@92V?3|rC7D1L<-Ioovr2s&K4>Ll zWFkqFz4>nFG}dxoL+Z=lH>0e;Lz&PoLa(88+`xX&L|M2Szk=)Wx3~rGB9omBq znxG;pdI{yl-yoA#b2)nw!U!@)HG(pMQy9fxq9oN{Q3h;d!({?TQTlrkrTs;G2uo?i z9MvE;;S-oGq4GT{66zmdCH@Q9UbURJ#CGh(Be)39B6C!)qioqUGKMN;Sz;^7->vZe zd6WsBN76&RA3Cpv{ntFWkFzB!>%%d81|P)_!{-kX7KzLWeyT8!9BK6qp1}9<5E_oe zG5i@y=vNVj!)W6daSF$AHJNVk)CS_Osa)kjH&$#coaZC>1@2!(qN~c8-BE1ENj!}b z(uKrVPR&7-0iQ>C?>$_K8`+Np_F@cwj2f#+up(srh4c704#)#8j(%{_N6?8E-gD%G z&Z_VrWfg^m2NQQtt~mvQkD62^8fBCuMIt8oLLRDllnP2#!ZQ2vx#5VaIAxf!fHHIK zp<;(OoIaHb>uhK6U$P|We98)nL_scgFu1Dul?ceT_E01rI%WNvsmQgTlA(M_Zn%aD z1mE*VsNYR-!)L-0N;!pG4YGP0%2ih&*k__0e3m5{<>S>)nM;vtU+_!(mj#u=k&)_N z3fmj(f2lm+;;R~5J459h%QZsjqAaG!H$yH-;KwL(5+pZft{qe?${~uJriUqM+5cLK zB$*_TT$L0#R^(oA+#tx-V%$ZMZv!VzJxDoBk!w3eQ%HO@N|EH0tB-P5P%9k0pxUVi z_xJbfbjo(}jq`t3w9s}&Qrh#~Ow7-?Cig+vkE%NRhdOz~^|k!bOWpVQquSE(Ofq?#!P6O;LimpM$1GnvX2Q7IH8EpP7*AWyaes_PQ8k#- z6IQ~G>w(_x-kYs%+jA=8OV>4@=sTXGM;0a>=KfxxbHA!sldE2y%^KgAiNzAOahQUY zmMn&4Y;kFO7-QD62QKConUrhY;;Bhb4-DMe?#5hYoSI;>XAg9$Ff9kCo$&TiPSd?U9yN-SR+3b6fr&)y+kv>!U5vmVEQd>&3;k$!)J)QQ^$WRXuFR zQ%QCux48CiEi#A+5;Zau8*^;mXUIgt+_r_JdH#BBThXSzl*6umT06&%jrn@&tP?kG za7Oa$>n;{o=(Rh|Sb|4nvT=jlkE-0$^;P+*`it}O4ULzJvVFn4MyD<$e4E%wvfMgB zJ!(cWbnI|CVq>J5?c2sRns&N}oUn$?sBx#x`i(knk&d=WS_w}Zf08?sOph?FQ9r6~ zKT!9qQ2e)%Iy2sXj>Mup?PvVl#mIxX&gdVr-3&SPY!C$<=XeZqNE|Py1`F#8&W>@& zCtr_DUAWCjVF41$8z+jjGWk1nEU}}HnV4m7?CSq(09nMXGoQ5GxSmKk!7&Rbn~|@R z=TBuX_)p$>vUlt&sc)Pl`DzVV=`^b<#9^lEPwBZ3gsq>*oN%t6wf}rw)9I4xK`S=q X${v{Tvmc)04xRhP{kwBNX|4M=*rX?j delta 2679 zcmZwIe@xVM9LMp`A)+F`BmvQgFG^a<$=&JkD@71Q5r2?BF)c+n-~>+P?ohLKwpMew zvUOHYW?QsXf294mmO1;Q*;sATkFCvUrBu_FjrCW#SuK0M?!LCM_1WG$KA-P>zu(WV z_vg!n&`4+GYIgFAhSE*kO@t;GqYJ|+{GnJ=jB#TT&cTg18xP>UcnXv8W1Nda*ob53 z#IjUlW@0m^am!QY=Sx(23k=p2ZUU9?Nk`nlW`)iyHV- zI0FaqKD>bU<2BU4GSU<8_o796GnUZ5>8Db}h1W12hwSz!E}`wnFlHWBV=;E126hbZ z!FN#|eubLIEnI-bnTdflqmyL_ylTZ=TS?38P)ME zEWpBP374X_W;@Qp2xdTIZK9(3~(cF(kBbij}q@)Kb5SEAVyPjAN()E++$ZY7QccWlo}w*BN{W&!GmA%}rXF zHe7~Bu^c0xQPGlUditRmAH?TT5B`LDa1oiqG-HJ}s@y(~w) zuM3qUgSZ+mp-1OGm*Hy98c`2CjhewZ{%A&{sO+82(>!BVVg&|J_q~A{z?ZlXCvkMD zu?)Fn!l(hff_mQw>iKjMVHN$G1}a=L$FUU8V=~^rX8aBFa2ZE})izsg4`Czi0j$OA z$T!8zV>zjsa%8bg8!ESs+J0dFehnk~A&Wm6X*IGvrqlKrv}m6}&F~A`6sD;asm6TV zj~pO#43FR-cH-2o8eTMQk9HM;(Ovj~^TA@nf@970Nb39g~ys zLQci^b}8!kt&CqaCdpQ_Rna!7bP-C%J7p)8^+YS7mHw}2|7!@%PUR6|1(8M+5}kyS zMXRIYCp2R%`<LFYzSQCs_NI zPO!4^GTC;Wtsqb1pW{?izLXJs*Txm)NhUFYSflgbPGt+xK&VV4G6)?>l{!L6nL=a{ zI!feWyyy$pM(FfxCw3D$qRWYCgieQw75{6@1Gc11yv)!v$+7rWE&=m=;aTN{wC0d~c$At-syh7^n~T_8zLTHg)-f zR$EVNFlg=T+uQGN_XVxMUaKPtR>E?+RzUD_Aw<)x|3>o+;;`h2Z=(pldc@>N+Lm%GgA@;E&embgsg6#Kj5<(!hvp$$``O64fk37zP^r6KI#ky cI%9*SKRTjK?uzIU&-K`B?}_B-@7|(+0lW@E8vpY^Vc@U1dj>CKzwH(7;u09#x}&*XGqNdl#=t^*xveX@3OaN zmsHU?N_a@5P$}0W6-pzuqD?E(NXZy8D7P;_$jW##wwX`Ua4LRGN6MRUqtD+ zh>bXfby&K(>7abEe-x`w>UHD2I2!mI%8|W}_4onG1g@d9U&49h zr9vwO8Q>tw1jbN0{4UB)ypK}vI?C29Tk5ZDH}X%72G0{HvG6057pw+_fkoB6 z&A5r@z18eL$E}{?g$(>0%FNzI39?@XUPqaEZH>Q@PL!3NL>b^Ily)y8b5uo?t$!bn z;a_k+?yL2W>MTl(T&iXNIbL;*7fe#!K&eU24f*;`)oJT-x!VVn3aXgG4 zpe$q+%asA5DD`qE{hddRf5xp?nde}7DeS>L_#(>LUqKnTf@K}Ry~wetZ{y>59yj8A zwm}Bmg-1#`3f#@}BoQ6L+1fwCw!j$55uL$q%oiveqHqOerY!`5+y;ZPBd1aB>sdUG z=P-(&qf9KyIZ5=thC6W*Wrt=FFzvVvWk+3S{QpI3(|NQ2i=I=adayR6EH zKpEg(>_Zz{@dCEtCn#Io$X7?~!3Xh)!1IBB#FM;lppr}=k5ccFXI`n#f)^W!7@0^4 z=Ycm+I&R`TXrf}c51+>k_-ovbbBSbW*Nsh#uf{0I zie5vh_$y@6YBqOIwlIXuQ4OI?;0%WG7brpXHV_eH=I^!ue}ntmkgY%6f4GpTWoQli>ZsY>Vv71V43HM6R^@5GU|sJc@=ZaT4D_ z+4_}i!!fk*t2l|HxQa+OcxDs(uPI#TMHg0Y_V4p?{0h%+BDdBOlGuZB{3&W&PJopl>-X>D6Bv~jB(A=f=)>zI8$5I6z0T_J z2ze!$g?kgXQPM0Q@1rI~*^LTviYz-O@j@J`Ipk_`Ubba=a(Up2sswqEJfD0s?WbS` z58OVL4$2&-_g}IE={)i>vh0E+PS8us`IQ}zW9=qOJaowVw^5LEh@2yTO&&-CKHm5I zQOfs_o#36Yh+Ih~R=ud+iIN(9ymMx^z0a})qkO#j$g|0k4tl@r|5C5uUl}PLAalIl z`IpNJ5?@s>?Fp27ENO_`NnS{nZ-yiZ;K#{w6C^fnrri``a{diu2{H*F zNws9TR>Yon-N1|1Qrt_HZv!_@Jw!f6mb8nk$ppR{CQEQi>Lt(hO8(XJiXFQDP+yC+{7%XW=36pNc| zSobugbS`Vz!#buDxm4;DgJ*Iwg`kdhM`EtF&6shtW8%gdGg%$8Pq`yB3akFK9*ZTd zgpT%f_1tcC*PhckSGunMLf?rrJ+d(AuuxH>3sco=3hQg~dE>e=v3SxlHdBbDsAqXq zwUx>wO^Vkhq1h`Pjm7o;0ew_=rX3?w39EsixwoVLOJnwFnAMx<6Sz5kHkXlp8GZ1S z-q+FDdwaYu)8dF_C(`3t9gW`E?$%sooO4d>_dRnv+lr64dh(o|Fpl4NtnqSbwO+f&j3jwQP#VVzHWmJo%Mu4T{iw@&r{ zHGnMQ&Y6!}PC}2RZSTeelg-J8ChJb-FS<|8JlPrhO6gmdLOwvzSSG`&{C&9D^?&Kv U--I1sh@4=qU$+0EX{j&&7i~!dW&i*H delta 2690 zcmZ|QdrXye9LMn=2pEXm6cH79yyTT5=bTWHydj7IUQpD`EG2xzBXB6r0aU`n)Y+CZ zS113{R;w+W)Yd$6>9SV&Po`a#x!fYnHf^b`EZ17v>iv1n<7Qj^#`nB_&+obYF5ln7 zyW!qIcy$q z#uQ+&>k`z`G~-CzkLo}l>i)0Y^S4mXAD$EMKp95#K$}Vt?nOQ5IBM$pQ6o!X;f7){ z>bMfM=B-$b?Wn0giCXLPuD{@Pjt6nGAIp)|Ghx&W^bTeI)x$m-G{TQvucJngksBXT z8EV9s6H=# z;|`q8@#{Dj`_aOYyuA!(V=Z=J6`n#brjbCi@jMQ)?*3oMlHb!*ULDI z<5Ut%R>X~%9xCf;cn3A&Jl>)UDqVND9!GWbS1iLRWUjQ4F_>3S=RZJo{0~%zYS{d; z8}-~bQMqyzYqb9}>87%CEo$xdp>FsD`7^iq(TK)zm#$lb+-vq?DIP^#cOBJ%A#9y# zSc`LUJ95gLKy~1I)bmD>0HwU&ET{4iK8u_)=dc+6!X)&t73$EBdAJLib#u`5J*?*V z5|-m+rjc)pX-1k%H!^AFFeG%QURR-;hq3Iv+a#d$0??LCsJ- zZ&S7(!W#S%bzK2_DhIo<1)sx4yp0yFXTB3~3sFmqA=nURgVuiq6(!Opg7-Vy2b}Hm zuqu>C2z7uQbqcxVtnnONMJ#e!jY)J>Csgv{n9Zo9yj#{&Sw=Ky{WazHmiZiLlq!!C z3yE~1kZ2;5bebiV0HKj<`tKIyj1ug>it?bGSVJf|^?qkh-^Z;M8$G``Apv(DtY7-ec8x0=f6~4 zyvg~;<5nGV`5i&j6YFB%rrt=1{yyl1=-cVnVjm5@ln}j`ksVFXN{gMzJeurV64)51 z4pw%wwr(r4R&EZ2tj3mxP{?|+y{$8_(GFR`HfvKyurVBH3pTU_!rNlqxw{ggpXOyn ze;k&J`(s=4=OnEQZ?;3>=Hm8nD-TSoTei|u(QY^BE>C4c*esmXceGobcKfDNC!0Eg YO|e&tFDFE6eWlS}|CQL->G{e30BN~M)c^nh diff --git a/po/de.po b/po/de.po index 768e545f..8a4f2fed 100644 --- a/po/de.po +++ b/po/de.po @@ -6,9 +6,9 @@ msgid "" msgstr "" "Project-Id-Version: rtmidi 2.1.0\n" -"Report-Msgid-Bugs-To: https://github.com/thestk/rtmidi\n" -"POT-Creation-Date: 2016-02-28 19:22+0100\n" -"PO-Revision-Date: 2016-02-28 19:24+0100\n" +"Report-Msgid-Bugs-To: https://github.com/keinstein/rtmidi\n" +"POT-Creation-Date: 2018-08-13 18:56+0200\n" +"PO-Revision-Date: 2018-08-13 19:04+0200\n" "Last-Translator: Tobias Schlemmer \n" "Language-Team: German translation team \n" "Language: de\n" @@ -16,77 +16,89 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 1.8.6\n" +"X-Generator: Poedit 2.1.1\n" "X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-Basepath: .\n" "X-Poedit-KeywordsList: gettext_noopt\n" "X-Poedit-SearchPath-0: /home/tobias/macbookbackup/Entwicklung/rtmidi-beides\n" -#: RtMidi.h:107 +#: RtMidi.h:129 msgid "Automatic selection" msgstr "Automatische Auswahl" -#: RtMidi.h:108 +#: RtMidi.h:130 msgid "Core MIDI" msgstr "Core MIDI" -#: RtMidi.h:109 +#: RtMidi.h:131 msgid "ALSA" msgstr "ALSA" -#: RtMidi.h:110 +#: RtMidi.h:132 msgid "JACK" msgstr "JACK" -#: RtMidi.h:111 +#: RtMidi.h:133 msgid "Windows Multimedia" msgstr "Windows Multimedia" -#: RtMidi.h:112 +#: RtMidi.h:134 msgid "DirectX/Kernel Streaming" msgstr "DirectX/Kernel Streaming" -#: RtMidi.h:113 +#: RtMidi.h:135 msgid "NULL device" msgstr "Keine Funktion." -#: RtMidi.h:114 +#: RtMidi.h:136 msgid "All available MIDI systems" msgstr "Alle verfügbaren MIDI-Systeme." -#: RtMidi.h:530 RtMidi.h:692 RtMidi.h:1221 RtMidi.h:1313 +#: RtMidi.h:1106 RtMidi.h:1277 RtMidi.h:1490 RtMidi.h:1511 msgid "Passed NULL pointer." msgstr "Nullzeiger übergeben." -#: RtMidi.h:724 RtMidi.cpp:2165 +#: RtMidi.h:1308 RtMidi.h:1317 RtMidi.cpp:2596 msgid "No data in message argument." msgstr "Keine Daten in der MIDI-Nachricht." -#: RtMidi.h:1083 +#: RtMidi.h:1432 msgid "A NULL pointer has been passed as port descriptor" msgstr "Ein leerer Zeiger wurde als Schnittstellenbeschreibung übergeben." -#: RtMidi.h:1115 RtMidi.h:1346 RtMidi.h:1370 RtMidi.h:1383 +#: RtMidi.h:1452 RtMidi.h:1531 RtMidi.h:1543 msgid "No valid MIDI system has been selected." msgstr "Es wurde kein benutzbares MIDI-System ausgewählt." -#: RtMidi.h:1185 +#: RtMidi.h:1473 msgid "Could not find any valid MIDI system." msgstr "Es konnte kein benutzbares MIDI-System gefunden werden." -#: RtMidi.h:1226 +#: RtMidi.h:1495 msgid "No valid MIDI system has been found." msgstr "Es konnte kein benutzbares MIDI-System gefunden werden." -#: RtMidi.h:1364 +#: RtMidi.h:1537 msgid "No data in MIDI message." msgstr "Keine Daten in der MIDI-Nachricht." -#: RtMidi.h:1610 RtMidi.h:1632 -msgid "MidiInDummy: This class provides no functionality." -msgstr "MidiInDummy: Diese Klasse stellt keine Funktionen zur verfügung." +#: RtMidi.cpp:293 +msgid "" +"No valid MIDI interfaces. I'm using a dummy input interface that never " +"receives anything." +msgstr "" +"Keine gültige MIDI-Schnittstelle gefunden. Ich imitiere ein Eingabegerät, " +"das niemals etwas empfängt." + +#: RtMidi.cpp:322 +msgid "" +"No valid MIDI interfaces. I'm using a dummy output interface that does " +"nothing." +msgstr "" +"Keine gültige MIDI-Schnittstelle gefunden. Ich imitiere ein Ausgabegerät, " +"das nichts tut." -#: RtMidi.cpp:87 +#: RtMidi.cpp:396 #, c-format msgid "" "Error formatting the error string:\n" @@ -99,11 +111,11 @@ msgstr "" "gefunden in %s::%s bei \n" "%s:%d" -#: RtMidi.cpp:99 +#: RtMidi.cpp:408 msgid "Error: could not format the error message" msgstr "Fehler: Ich konnte eine Fehlermeldung nicht formatieren." -#: RtMidi.cpp:267 RtMidi.cpp:370 +#: RtMidi.cpp:579 RtMidi.cpp:692 #, c-format msgid "" "Support for the selected MIDI system %d has not been compiled into the " @@ -112,23 +124,23 @@ msgstr "" "Die Unterstützung für das gewählte MIDI-System %d wurde nicht in die RtMidi-" "Bibliothek eingebaut." -#: RtMidi.cpp:285 RtMidi.cpp:387 +#: RtMidi.cpp:597 RtMidi.cpp:709 msgid "No supported MIDI system has been found." msgstr "Es konnte kein benutzbares MIDI-System gefunden werden." -#: RtMidi.cpp:476 RtMidi.cpp:493 +#: RtMidi.cpp:798 RtMidi.cpp:815 msgid "A callback function is already set." msgstr "Es wurde schon eine Rückruffunktion gesetzt." -#: RtMidi.cpp:482 RtMidi.cpp:499 +#: RtMidi.cpp:804 RtMidi.cpp:821 msgid "The callback function value is invalid." msgstr "Der Funktionswert einer aufgerufenen Rückruffunktion ist ungültig." -#: RtMidi.cpp:510 +#: RtMidi.cpp:832 msgid "No callback function was set." msgstr "Es wurde keine Rückruffunktion gesetzt." -#: RtMidi.cpp:532 +#: RtMidi.cpp:854 msgid "" "Returning an empty MIDI message as all input is handled by a callback " "function." @@ -136,13 +148,13 @@ msgstr "" "Es wird eine leere MIDI-Nachricht generiert, weil alle Eingaben durch eine " "Rückruf-Funktion (engl. callback) abgefangen werden." -#: RtMidi.cpp:1187 +#: RtMidi.cpp:1585 msgid "Could not get the unique identifier of a midi endpoint." msgstr "" "Konnte die eindeutige Identifikation (UUID) eines MIDI-Endpunktes nicht " "bekommen." -#: RtMidi.cpp:1197 +#: RtMidi.cpp:1595 msgid "" "Could not get the endpoint back from the unique identifier of a midi " "endpoint." @@ -150,69 +162,70 @@ msgstr "" "Konnte den MIDI-Endpunkt einer eindeutige Identifikation (UUID) nicht " "bekommen." -#: RtMidi.cpp:1212 +#: RtMidi.cpp:1610 msgid "Could not get the entity of a midi endpoint." msgstr "Konnte die Geräteeinheit eines MIDI-Endpunktes nicht bekommen." -#: RtMidi.cpp:1277 RtMidi.cpp:1317 +#: RtMidi.cpp:1671 RtMidi.cpp:1707 msgid "Error creating OS X MIDI port because of invalid port flags." msgstr "" "Konnte die OS X-MIDI-Schnittstelle nicht anlegen, da ungültige Eigenschaften " "angegeben wurden." -#: RtMidi.cpp:1281 RtMidi.cpp:1321 RtMidi.cpp:1862 +#: RtMidi.cpp:1675 RtMidi.cpp:1711 RtMidi.cpp:2254 msgid "Error creating OS-X MIDI port." msgstr "Es gab einen Fehler beim Erzeugen der MIDI-Schnittstelle." -#: RtMidi.cpp:1374 -msgid "Error creating OS-X MIDI client object." -msgstr "Fehler beim erzeugen des OS-X-MIDI-Klienten." +#: RtMidi.cpp:1760 +#, c-format +msgid "Error creating OS-X MIDI client object (Error no: %d)." +msgstr "Fehler beim erzeugen des OS-X-MIDI-Klienten (Fehlernummer: %d)." -#: RtMidi.cpp:1630 RtMidi.cpp:1700 RtMidi.cpp:2983 RtMidi.cpp:4162 -#: RtMidi.cpp:5236 +#: RtMidi.cpp:2014 RtMidi.cpp:2080 RtMidi.cpp:3476 RtMidi.cpp:4720 +#: RtMidi.cpp:5931 msgid "Error: Message queue limit reached." msgstr "Fehler: Die Nachrichten-Warteschlange ist überlang." -#: RtMidi.cpp:1751 RtMidi.cpp:1843 RtMidi.cpp:2001 RtMidi.cpp:2094 -#: RtMidi.cpp:3127 RtMidi.cpp:3244 RtMidi.cpp:3512 RtMidi.cpp:3660 -#: RtMidi.cpp:4218 RtMidi.cpp:4521 RtMidi.cpp:4580 RtMidi.cpp:5424 -#: RtMidi.cpp:5641 +#: RtMidi.cpp:2141 RtMidi.cpp:2235 RtMidi.cpp:2412 RtMidi.cpp:2526 +#: RtMidi.cpp:3623 RtMidi.cpp:3740 RtMidi.cpp:4032 RtMidi.cpp:4194 +#: RtMidi.cpp:4777 RtMidi.cpp:5089 RtMidi.cpp:5161 RtMidi.cpp:6084 +#: RtMidi.cpp:6317 msgid "A valid connection already exists." msgstr "Es existiert schon eine gültige Verbindung." -#: RtMidi.cpp:1759 RtMidi.cpp:3134 RtMidi.cpp:4225 +#: RtMidi.cpp:2149 RtMidi.cpp:3630 RtMidi.cpp:4784 msgid "No MIDI input sources found." msgstr "Keine MIDI-Eingabe-Geräte gefunden." -#: RtMidi.cpp:1768 RtMidi.cpp:1926 RtMidi.cpp:1984 RtMidi.cpp:2015 -#: RtMidi.cpp:3144 RtMidi.cpp:3532 RtMidi.cpp:4413 RtMidi.cpp:4491 -#: RtMidi.cpp:4534 RtMidi.cpp:5520 RtMidi.cpp:5732 +#: RtMidi.cpp:2158 RtMidi.cpp:2337 RtMidi.cpp:2395 RtMidi.cpp:2426 +#: RtMidi.cpp:3640 RtMidi.cpp:4052 RtMidi.cpp:4989 RtMidi.cpp:5063 +#: RtMidi.cpp:5102 RtMidi.cpp:6182 RtMidi.cpp:6408 #, c-format msgid "The 'portNumber' argument (%d) is invalid." msgstr "Die Portnummer %d ist ungültig." -#: RtMidi.cpp:1780 +#: RtMidi.cpp:2170 msgid "Error creating OS-X MIDI input port." msgstr "Fehler beim Erzeugen der OS-X-MIDI-Eingabe-Schnittstelle." -#: RtMidi.cpp:1790 +#: RtMidi.cpp:2181 msgid "Error getting MIDI input source reference." msgstr "Konnte keine Referenz zum MIDI-Eingang bekommen." -#: RtMidi.cpp:1800 +#: RtMidi.cpp:2192 msgid "Error connecting OS-X MIDI input port." msgstr "Fehler beim verbinden mit dem OS-X-MIDI-Eingang." -#: RtMidi.cpp:1822 +#: RtMidi.cpp:2214 msgid "Error creating virtual OS-X MIDI destination." msgstr "Konnte den virtuellen OS-X-MIDI-Ausgang nicht erzeugen." -#: RtMidi.cpp:1838 RtMidi.cpp:2089 RtMidi.cpp:3239 RtMidi.cpp:3655 -#: RtMidi.cpp:5418 RtMidi.cpp:5635 +#: RtMidi.cpp:2230 RtMidi.cpp:2521 RtMidi.cpp:3735 RtMidi.cpp:4189 +#: RtMidi.cpp:6078 RtMidi.cpp:6311 msgid "Data has not been allocated." msgstr "Daten konnten nicht angelegt werden." -#: RtMidi.cpp:1848 RtMidi.cpp:2099 +#: RtMidi.cpp:2240 RtMidi.cpp:2531 msgid "" "Core MIDI has been instructed to open a non-Core MIDI port. This doesn't " "work." @@ -220,80 +233,103 @@ msgstr "" "Core-MIDI wurde angewiesen, eine nicht-Core-MIDI-Schnittstelle zu öffnen. " "Das geht nicht." -#: RtMidi.cpp:2009 +#: RtMidi.cpp:2312 RtMidi.cpp:2479 +msgid "Setting client names is not implemented for Mac OS X CoreMIDI." +msgstr "" +"Das Ändern des Namens des MIDI-Klienten ist für Mac OS X CoreMIDI nicht " +"implementiert." + +#: RtMidi.cpp:2318 RtMidi.cpp:2485 +msgid "Setting port names is not implemented for Mac OS X CoreMIDI." +msgstr "" +"Das Ändern des Namens einer MIDI-Schnittstelle ist für Mac OS X CoreMIDI " +"nicht implementiert." + +#: RtMidi.cpp:2420 msgid "No MIDI output destinations found." msgstr "Es wurden keine MIDI-Ausgabegeräte gefunden." -#: RtMidi.cpp:2027 +#: RtMidi.cpp:2438 msgid "Error creating OS-X MIDI output port." msgstr "Fehler beim Erzeugen der OS-X-MIDI-Ausgabe-Schnittstelle." -#: RtMidi.cpp:2037 +#: RtMidi.cpp:2449 msgid "Error getting MIDI output destination reference." msgstr "Konnte keine Referenz zum MIDI-Ausgang bekommen." -#: RtMidi.cpp:2062 +#: RtMidi.cpp:2494 msgid "A virtual output port already exists." msgstr "Es gibt schon einen virtuellen MIDI-Ausgang." -#: RtMidi.cpp:2073 +#: RtMidi.cpp:2505 msgid "Error creating OS-X virtual MIDI source." msgstr "Konnte den virtuellen OS-X-MIDI-Eingang nicht erzeugen." -#: RtMidi.cpp:2177 +#: RtMidi.cpp:2608 msgid "message format problem ... not sysex but > 3 bytes?" msgstr "" "Nachrichtenformatproblem: Eine MIDI-Nachricht ist größer als 3 Bytes (und " "keine SysEx-Nachricht)." -#: RtMidi.cpp:2196 +#: RtMidi.cpp:2627 msgid "Could not allocate packet list." msgstr "Konnte die Paketliste nicht anlegen." -#: RtMidi.cpp:2205 +#: RtMidi.cpp:2636 msgid "Error sending MIDI to virtual destinations." msgstr "Konnte MIDI-Daten nicht zu virtuellen Ausgängen senden." -#: RtMidi.cpp:2214 RtMidi.cpp:3641 +#: RtMidi.cpp:2645 RtMidi.cpp:4175 msgid "Error sending MIDI message to port." msgstr "Fehler beim Senden der MIDI-Nachricht zum Ausgang." -#: RtMidi.cpp:2418 RtMidi.cpp:2681 RtMidi.cpp:3188 RtMidi.cpp:3249 -#: RtMidi.cpp:3558 +#: RtMidi.cpp:2810 +msgid "Could not allocate ALSA port info structure." +msgstr "" +"Konnte keinen Speicher für die ALSA-MIDI-Schnittstelleninformation bekommen." + +#: RtMidi.cpp:2814 +#, c-format +msgid "Could not get ALSA port information: %s" +msgstr "Konnte keine ALSA-Schnittstelleninformation bekommen: %s" + +#: RtMidi.cpp:2820 +#, c-format +msgid "Could not set ALSA port information: %s" +msgstr "Konnte ALSA-Schnittstelleninformation nicht ändern: %s" + +#: RtMidi.cpp:2873 RtMidi.cpp:3149 RtMidi.cpp:3684 RtMidi.cpp:3745 +#: RtMidi.cpp:4079 msgid "Could not allocate ALSA port subscription." msgstr "" "Konnte keinen Speicher für das Abonnoment der ALSA-MIDI-Schnittstelle " "bekommen." -#: RtMidi.cpp:2433 RtMidi.cpp:3197 RtMidi.cpp:3568 +#: RtMidi.cpp:2888 RtMidi.cpp:3693 RtMidi.cpp:4090 msgid "Error making ALSA port connection." msgstr "Konnte zwei ALSA-Schnittstellen nicht miteinander verbinden." -#: RtMidi.cpp:2503 RtMidi.cpp:3439 -msgid "Error creating ALSA sequencer client object." -msgstr "Fehler beim erzeugen des ALSA-Klienten." - -#: RtMidi.cpp:2743 RtMidi.cpp:3223 RtMidi.cpp:3372 +#: RtMidi.cpp:3219 RtMidi.cpp:3719 RtMidi.cpp:3868 msgid "Error starting MIDI input thread!" msgstr "Konnte den MIDI-Eingabe-Prozess nicht starten." -#: RtMidi.cpp:2781 RtMidi.cpp:3456 +#: RtMidi.cpp:3257 RtMidi.cpp:3974 msgid "Error initializing MIDI event parser." msgstr "Fehler bei der Initialisierung des MIDI-Ereeignisparsers." -#: RtMidi.cpp:2794 +#: RtMidi.cpp:3270 msgid "Error initializing buffer memory." msgstr "Fehler beim Anlegen des Pufferspeichers." -#: RtMidi.cpp:2828 +#: RtMidi.cpp:3304 msgid "MIDI input buffer overrun." msgstr "MIDI-Eingabepuffer übergelaufen." -#: RtMidi.cpp:2838 +#: RtMidi.cpp:3314 msgid "ALSA returned without providing a MIDI event." msgstr "ALSA kam zurück ohne ein MIDI-Ereignis mitzubringen." -#: RtMidi.cpp:2848 +#: RtMidi.cpp:3324 #, c-format msgid "" "Unknown MIDI input error.\n" @@ -304,111 +340,115 @@ msgstr "" "Das System meldet:\n" "%s" -#: RtMidi.cpp:2906 +#: RtMidi.cpp:3382 msgid "Error resizing buffer memory." msgstr "Fehler beim Ändern der Grüße des Pufferspeichers." -#: RtMidi.cpp:2957 +#: RtMidi.cpp:3455 msgid "Event parsing error or not a MIDI event." msgstr "" "Analyse eines Ereignisses fehlgeschlagen oder es war kein MIDI-Ereignis." -#: RtMidi.cpp:3038 +#: RtMidi.cpp:3532 msgid "Error creating pipe objects." msgstr "Fehler beim anlegen einer Pipe." -#: RtMidi.cpp:3119 RtMidi.cpp:3504 +#: RtMidi.cpp:3615 RtMidi.cpp:4024 msgid "Error looking for port name." msgstr "Fehler beim Suchen nach einem Schnittstellennamen." -#: RtMidi.cpp:3175 +#: RtMidi.cpp:3671 msgid "Error creating ALSA input port." msgstr "Fehler beim Erzeugen der ALSA-Eingabe-Schnittstelle." -#: RtMidi.cpp:3254 RtMidi.cpp:3670 +#: RtMidi.cpp:3750 RtMidi.cpp:4204 msgid "" "ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work." msgstr "" "ALSA wurde angewiesen, eine nicht-ALSA-MIDI-Schnittstelle zu öffnen. Das " "geht nicht." -#: RtMidi.cpp:3338 RtMidi.cpp:3595 +#: RtMidi.cpp:3834 RtMidi.cpp:4130 msgid "Error creating ALSA virtual port." msgstr "Fehler beim Erzeugen einer virtuellen ALSA-Schnittstelle." -#: RtMidi.cpp:3463 RtMidi.cpp:3619 +#: RtMidi.cpp:3957 +msgid "Error creating ALSA sequencer client object." +msgstr "Fehler beim erzeugen des ALSA-Klienten." + +#: RtMidi.cpp:3981 RtMidi.cpp:4153 msgid "Error while allocating buffer memory." msgstr "Fehler beim Anlegen des Pufferspeichers." -#: RtMidi.cpp:3520 +#: RtMidi.cpp:4040 msgid "No MIDI output sinks found." msgstr "Es wurden kiene Midi-Ausgabegeräte gefunden." -#: RtMidi.cpp:3547 +#: RtMidi.cpp:4067 msgid "Error creating ALSA output port." msgstr "Fehler beim Erzeugen der ALSA-Ausgangs." -#: RtMidi.cpp:3612 +#: RtMidi.cpp:4146 msgid "ALSA error resizing MIDI event buffer." msgstr "ALSA-Fehler beim Verändern der Größe des MIDI-Nachrichten-Puffers." -#: RtMidi.cpp:3633 +#: RtMidi.cpp:4167 msgid "Event parsing error." msgstr "Fehler bei der Analyse eines Ereignisses." -#: RtMidi.cpp:3665 +#: RtMidi.cpp:4199 msgid "Error allocating ALSA port subscription." msgstr "" "Konnte keinen Speicher für das Abonnoment der ALSA-MIDI-Schnittstelle " "bekommen." -#: RtMidi.cpp:3815 +#: RtMidi.cpp:4377 #, c-format msgid "The port argument %d is invalid." msgstr "Das Schnittstellenargument %d ist ungültig." -#: RtMidi.cpp:4137 +#: RtMidi.cpp:4698 msgid "Error sending sysex to Midi device." msgstr "Fehler beim Senden der SysEx-Nachricht zum MIDI-Gerät." -#: RtMidi.cpp:4200 +#: RtMidi.cpp:4759 msgid "No MIDI input devices currently available." msgstr "Es gibt momentan keine MIDI-Eingabegeräte." -#: RtMidi.cpp:4210 +#: RtMidi.cpp:4769 msgid "Failed to initialize a critical section." msgstr "Konnte kritischen Bereich nicht initialisieren." -#: RtMidi.cpp:4234 +#: RtMidi.cpp:4793 #, c-format msgid "the 'portNumber' argument (%d) is invalid." msgstr "Die Portnummer %d ist ungültig." -#: RtMidi.cpp:4246 +#: RtMidi.cpp:4805 msgid "Error creating Windows MM MIDI input port." msgstr "Konnte den Windows-Multimedia-MIDI-Eingang nicht erzeugen." -#: RtMidi.cpp:4262 +#: RtMidi.cpp:4822 msgid "Error initializing data for Windows MM MIDI input port." msgstr "" "Fehler beim Erzeugen der daten für einen Windows Multimedia MIDI-Eingang." -#: RtMidi.cpp:4271 +#: RtMidi.cpp:4832 msgid "Could not register the input buffer for Windows MM MIDI input port." msgstr "" "Konnte den Eingabe-Puffer eines Windows-Multimedia-MIDI-Eingangs nicht " "erzeugen." -#: RtMidi.cpp:4280 +#: RtMidi.cpp:4842 msgid "Error starting Windows MM MIDI input port." msgstr "Konnte einen Windows-Multimedia-MIDI-Eingang nicht aktivieren." -#: RtMidi.cpp:4291 RtMidi.cpp:4567 +#: RtMidi.cpp:4853 RtMidi.cpp:5148 msgid "Virtual ports are not available Windows Multimedia MIDI API." msgstr "" "Windows Multimedia unterstützt keine virtuellen MIDI-Ein- und -Ausgänge." -#: RtMidi.cpp:4298 RtMidi.cpp:4575 +#: RtMidi.cpp:4860 RtMidi.cpp:5156 msgid "" "Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI " "port. This doesn't work." @@ -416,7 +456,7 @@ msgstr "" "Windows Multimedia (WinMM) wurde angewiesen, eine nicht-WinMM-MIDI-" "Schnittstelle zu öffnen. Das geht nicht." -#: RtMidi.cpp:4303 +#: RtMidi.cpp:4865 msgid "" "We are overwriting an existing connection. This is probably a programming " "error." @@ -424,12 +464,12 @@ msgstr "" "Wir überschreiben eine vorhandene MIDI-Verbindung. Das ist vermutlich ein " "Programmierfehler." -#: RtMidi.cpp:4308 +#: RtMidi.cpp:4870 msgid "Trying to open a non-input port as input MIDI port. This doesn't work." msgstr "" "Versuche eine Nicht-Eingang als MIDI-Eingang zu öffnen. Das geht nicht." -#: RtMidi.cpp:4322 RtMidi.cpp:4599 +#: RtMidi.cpp:4884 RtMidi.cpp:5180 msgid "" "Some change in the arrangement of MIDI input ports invalidated the port " "descriptor." @@ -437,108 +477,128 @@ msgstr "" "Eine Veränderung bei den MIDI-Schnittstellen hat die interne " "Schnittstellenbeschreibung ungültig gemacht." -#: RtMidi.cpp:4337 +#: RtMidi.cpp:4899 msgid "The handle is invalid. Did you disconnect the device?" msgstr "" "Ein Schnittstellenverweis ist ungültig. Haben Sie das zugehörige Gerät " "entfernt?" -#: RtMidi.cpp:4341 RtMidi.cpp:4618 +#: RtMidi.cpp:4903 RtMidi.cpp:5199 msgid "" "The system has no driver for our handle :-(. Did you disconnect the device?" msgstr "" "Das System hat keinen Treiber für unseren Schnittstellenverweis (mehr) :-(. " "Haben Sie das zugehörige Gerät entfernt?" -#: RtMidi.cpp:4345 RtMidi.cpp:4622 +#: RtMidi.cpp:4907 RtMidi.cpp:5203 msgid "Out of memory." msgstr "Hauptspeicher erschöpft." -#: RtMidi.cpp:4391 +#: RtMidi.cpp:4954 msgid "Error closing Windows MM MIDI input port." msgstr "" "Konnte den Windows Multimedia MIDI-Eingang nicht ordnungsgemäß schließen." -#: RtMidi.cpp:4469 +#: RtMidi.cpp:4969 RtMidi.cpp:5135 +msgid "Setting the client name is not supported by Windows MM." +msgstr "" +"Das Ändern des Namens des MIDI-Klienten wird vom Windows MIDI Mapper nicht " +"unterstützt." + +#: RtMidi.cpp:4975 RtMidi.cpp:5141 +msgid "Setting the port name is not supported by Windows MM." +msgstr "" +"Das Ändern des Namens der MIDI-Schnittstelle wird vom Windows MIDI Mapper " +"nicht unterstützt." + +#: RtMidi.cpp:5041 msgid "No MIDI output devices currently available." msgstr "Es gibt momentan keine MIDI-Ausgabegeräte." -#: RtMidi.cpp:4528 +#: RtMidi.cpp:5096 msgid "No MIDI output destinations found!" msgstr "Es wurden keine MIDI-Ausgabegeräte gefunden." -#: RtMidi.cpp:4546 +#: RtMidi.cpp:5114 msgid "Error creating Windows MM MIDI output port." msgstr "Konnte den Windows Multimedia MIDI-Ausgang nicht erzeugen." -#: RtMidi.cpp:4585 +#: RtMidi.cpp:5166 msgid "The port descriptor cannot be used to open an output port." msgstr "" "Eine Schnittstellenbeschreibung kann nicht benutzt werden, um einen MIDI-" "Ausgang zu erzeugen." -#: RtMidi.cpp:4614 +#: RtMidi.cpp:5195 msgid "The internal handle is invalid. Did you disconnect the device?" msgstr "" "Ein interner Schnittstellenverweis ist ungültig. Haben sie das zugehörige " "Gerät entfernt?" -#: RtMidi.cpp:4650 +#: RtMidi.cpp:5230 msgid "Message argument is empty." msgstr "Das Nachrichtenargument ist leer." -#: RtMidi.cpp:4662 +#: RtMidi.cpp:5242 msgid "Error while allocating sysex message memory." msgstr "Fehler beim Anlegen des Speichers für SysEx-Nachrichten." -#: RtMidi.cpp:4678 +#: RtMidi.cpp:5258 msgid "Error preparing sysex header." msgstr "Fehler beim Erstellen des SysEx-Kopfes." -#: RtMidi.cpp:4687 +#: RtMidi.cpp:5267 msgid "Error sending sysex message." msgstr "Fehler beim Senden der SysEx-Nachricht." -#: RtMidi.cpp:4700 +#: RtMidi.cpp:5280 msgid "Message size is greater than 3 bytes (and not sysex)." msgstr "" "Eine MIDI-Nachricht ist größer als 3 Bytes (und keine SysEx-Nachricht)." -#: RtMidi.cpp:4716 +#: RtMidi.cpp:5296 msgid "Error sending MIDI message." msgstr "Fehler beim Senden der MIDI-Nachricht." -#: RtMidi.cpp:4947 +#: RtMidi.cpp:5535 msgid "Could not connect to JACK server. Is it runnig?" msgstr "Ich konnte mich nicht mit dem JACK-Server verbinden. Läuft er?" -#: RtMidi.cpp:5158 +#: RtMidi.cpp:5767 msgid "Error opening JACK port subscription." msgstr "Fehler beim abonnieren einer JACK-Schnittstelle." -#: RtMidi.cpp:5342 RtMidi.cpp:5570 +#: RtMidi.cpp:6002 RtMidi.cpp:6248 msgid "JACK server not running?" msgstr "Läuft der JACK-Server?" -#: RtMidi.cpp:5386 RtMidi.cpp:5603 +#: RtMidi.cpp:6046 RtMidi.cpp:6279 msgid "Error creating JACK port." msgstr "Es gab einen Fehler beim Erzeugen der JACK-Schnittstelle." -#: RtMidi.cpp:5406 RtMidi.cpp:5623 +#: RtMidi.cpp:6066 RtMidi.cpp:6299 msgid "Error creating JACK virtual port." msgstr "Fehler beim Erzeugen einer virtuellen JACK-Schnittstelle." -#: RtMidi.cpp:5430 RtMidi.cpp:5647 +#: RtMidi.cpp:6090 RtMidi.cpp:6323 msgid "" "JACK has been instructed to open a non-JACK MIDI port. This doesn't work." msgstr "" "JACK wurde angewiesen, eine nicht-JACK-Schnittstelle zu öffnen. Das geht " "nicht." -#: RtMidi.cpp:5513 RtMidi.cpp:5725 +#: RtMidi.cpp:6173 RtMidi.cpp:6401 msgid "No ports available." msgstr "Keine Schnittstellen verfügbar." +#: RtMidi.cpp:6201 RtMidi.cpp:6429 +msgid "Setting the client name is not supported by JACK." +msgstr "" +"Das Ändern des Namens des MIDI-Klienten wird von JACK nicht unterstützt." + +#~ msgid "MidiInDummy: This class provides no functionality." +#~ msgstr "MidiInDummy: Diese Klasse stellt keine Funktionen zur verfügung." + #, fuzzy #~ msgid "InitializeCriticalSectionAndSpinCount failed." #~ msgstr "%s: malloc ist fehlgeschlagen: %s\n" diff --git a/po/rtmidi-ts.pot b/po/rtmidi-ts.pot index ce383b81..ff848fa5 100644 --- a/po/rtmidi-ts.pot +++ b/po/rtmidi-ts.pot @@ -1,14 +1,14 @@ # SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR Gary P. Scavone +# Copyright (C) YEAR Gary P. Scavone, Tobias Schlemmer # This file is distributed under the same license as the rtmidi-ts package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: rtmidi-ts 3.0\n" -"Report-Msgid-Bugs-To: https://github.com/thestk/rtmidi\n" -"POT-Creation-Date: 2015-10-14 22:01+0200\n" +"Project-Id-Version: rtmidi-ts 5.0.0\n" +"Report-Msgid-Bugs-To: https://github.com/keinstein/rtmidi\n" +"POT-Creation-Date: 2018-08-13 18:56+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,71 +17,79 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: RtMidi.h:107 +#: RtMidi.h:129 msgid "Automatic selection" msgstr "" -#: RtMidi.h:108 +#: RtMidi.h:130 msgid "Core MIDI" msgstr "" -#: RtMidi.h:109 +#: RtMidi.h:131 msgid "ALSA" msgstr "" -#: RtMidi.h:110 +#: RtMidi.h:132 msgid "JACK" msgstr "" -#: RtMidi.h:111 +#: RtMidi.h:133 msgid "Windows Multimedia" msgstr "" -#: RtMidi.h:112 +#: RtMidi.h:134 msgid "DirectX/Kernel Streaming" msgstr "" -#: RtMidi.h:113 +#: RtMidi.h:135 msgid "NULL device" msgstr "" -#: RtMidi.h:114 +#: RtMidi.h:136 msgid "All available MIDI systems" msgstr "" -#: RtMidi.h:530 RtMidi.h:691 RtMidi.h:1220 RtMidi.h:1312 +#: RtMidi.h:1106 RtMidi.h:1277 RtMidi.h:1490 RtMidi.h:1511 msgid "Passed NULL pointer." msgstr "" -#: RtMidi.h:723 RtMidi.cpp:2161 +#: RtMidi.h:1308 RtMidi.h:1317 RtMidi.cpp:2596 msgid "No data in message argument." msgstr "" -#: RtMidi.h:1082 +#: RtMidi.h:1432 msgid "A NULL pointer has been passed as port descriptor" msgstr "" -#: RtMidi.h:1114 RtMidi.h:1345 RtMidi.h:1369 RtMidi.h:1382 +#: RtMidi.h:1452 RtMidi.h:1531 RtMidi.h:1543 msgid "No valid MIDI system has been selected." msgstr "" -#: RtMidi.h:1184 +#: RtMidi.h:1473 msgid "Could not find any valid MIDI system." msgstr "" -#: RtMidi.h:1225 +#: RtMidi.h:1495 msgid "No valid MIDI system has been found." msgstr "" -#: RtMidi.h:1363 +#: RtMidi.h:1537 msgid "No data in MIDI message." msgstr "" -#: RtMidi.h:1608 RtMidi.h:1630 -msgid "MidiInDummy: This class provides no functionality." +#: RtMidi.cpp:293 +msgid "" +"No valid MIDI interfaces. I'm using a dummy input interface that never " +"receives anything." +msgstr "" + +#: RtMidi.cpp:322 +msgid "" +"No valid MIDI interfaces. I'm using a dummy output interface that does " +"nothing." msgstr "" -#: RtMidi.cpp:87 +#: RtMidi.cpp:396 #, c-format msgid "" "Error formatting the error string:\n" @@ -90,181 +98,204 @@ msgid "" "%s:%d" msgstr "" -#: RtMidi.cpp:99 +#: RtMidi.cpp:408 msgid "Error: could not format the error message" msgstr "" -#: RtMidi.cpp:267 RtMidi.cpp:370 +#: RtMidi.cpp:579 RtMidi.cpp:692 #, c-format msgid "" "Support for the selected MIDI system %d has not been compiled into the " "RtMidi library." msgstr "" -#: RtMidi.cpp:285 RtMidi.cpp:387 +#: RtMidi.cpp:597 RtMidi.cpp:709 msgid "No supported MIDI system has been found." msgstr "" -#: RtMidi.cpp:474 RtMidi.cpp:491 +#: RtMidi.cpp:798 RtMidi.cpp:815 msgid "A callback function is already set." msgstr "" -#: RtMidi.cpp:480 RtMidi.cpp:497 +#: RtMidi.cpp:804 RtMidi.cpp:821 msgid "The callback function value is invalid." msgstr "" -#: RtMidi.cpp:508 +#: RtMidi.cpp:832 msgid "No callback function was set." msgstr "" -#: RtMidi.cpp:530 +#: RtMidi.cpp:854 msgid "" "Returning an empty MIDI message as all input is handled by a callback " "function." msgstr "" -#: RtMidi.cpp:1183 +#: RtMidi.cpp:1585 msgid "Could not get the unique identifier of a midi endpoint." msgstr "" -#: RtMidi.cpp:1193 +#: RtMidi.cpp:1595 msgid "" "Could not get the endpoint back from the unique identifier of a midi " "endpoint." msgstr "" -#: RtMidi.cpp:1208 +#: RtMidi.cpp:1610 msgid "Could not get the entity of a midi endpoint." msgstr "" -#: RtMidi.cpp:1273 RtMidi.cpp:1313 +#: RtMidi.cpp:1671 RtMidi.cpp:1707 msgid "Error creating OS X MIDI port because of invalid port flags." msgstr "" -#: RtMidi.cpp:1277 RtMidi.cpp:1317 RtMidi.cpp:1858 +#: RtMidi.cpp:1675 RtMidi.cpp:1711 RtMidi.cpp:2254 msgid "Error creating OS-X MIDI port." msgstr "" -#: RtMidi.cpp:1370 -msgid "Error creating OS-X MIDI client object." +#: RtMidi.cpp:1760 +#, c-format +msgid "Error creating OS-X MIDI client object (Error no: %d)." msgstr "" -#: RtMidi.cpp:1626 RtMidi.cpp:1696 RtMidi.cpp:3006 RtMidi.cpp:4184 -#: RtMidi.cpp:5250 +#: RtMidi.cpp:2014 RtMidi.cpp:2080 RtMidi.cpp:3476 RtMidi.cpp:4720 +#: RtMidi.cpp:5931 msgid "Error: Message queue limit reached." msgstr "" -#: RtMidi.cpp:1747 RtMidi.cpp:1839 RtMidi.cpp:1997 RtMidi.cpp:2090 -#: RtMidi.cpp:3149 RtMidi.cpp:3266 RtMidi.cpp:3534 RtMidi.cpp:3682 -#: RtMidi.cpp:4240 RtMidi.cpp:4535 RtMidi.cpp:4594 RtMidi.cpp:5438 -#: RtMidi.cpp:5655 +#: RtMidi.cpp:2141 RtMidi.cpp:2235 RtMidi.cpp:2412 RtMidi.cpp:2526 +#: RtMidi.cpp:3623 RtMidi.cpp:3740 RtMidi.cpp:4032 RtMidi.cpp:4194 +#: RtMidi.cpp:4777 RtMidi.cpp:5089 RtMidi.cpp:5161 RtMidi.cpp:6084 +#: RtMidi.cpp:6317 msgid "A valid connection already exists." msgstr "" -#: RtMidi.cpp:1755 RtMidi.cpp:3156 RtMidi.cpp:4247 +#: RtMidi.cpp:2149 RtMidi.cpp:3630 RtMidi.cpp:4784 msgid "No MIDI input sources found." msgstr "" -#: RtMidi.cpp:1764 RtMidi.cpp:1922 RtMidi.cpp:1980 RtMidi.cpp:2011 -#: RtMidi.cpp:3166 RtMidi.cpp:3554 RtMidi.cpp:4435 RtMidi.cpp:4513 -#: RtMidi.cpp:4548 RtMidi.cpp:5534 RtMidi.cpp:5746 +#: RtMidi.cpp:2158 RtMidi.cpp:2337 RtMidi.cpp:2395 RtMidi.cpp:2426 +#: RtMidi.cpp:3640 RtMidi.cpp:4052 RtMidi.cpp:4989 RtMidi.cpp:5063 +#: RtMidi.cpp:5102 RtMidi.cpp:6182 RtMidi.cpp:6408 #, c-format msgid "The 'portNumber' argument (%d) is invalid." msgstr "" -#: RtMidi.cpp:1776 +#: RtMidi.cpp:2170 msgid "Error creating OS-X MIDI input port." msgstr "" -#: RtMidi.cpp:1786 +#: RtMidi.cpp:2181 msgid "Error getting MIDI input source reference." msgstr "" -#: RtMidi.cpp:1796 +#: RtMidi.cpp:2192 msgid "Error connecting OS-X MIDI input port." msgstr "" -#: RtMidi.cpp:1818 +#: RtMidi.cpp:2214 msgid "Error creating virtual OS-X MIDI destination." msgstr "" -#: RtMidi.cpp:1834 RtMidi.cpp:2085 RtMidi.cpp:3261 RtMidi.cpp:3677 -#: RtMidi.cpp:5432 RtMidi.cpp:5649 +#: RtMidi.cpp:2230 RtMidi.cpp:2521 RtMidi.cpp:3735 RtMidi.cpp:4189 +#: RtMidi.cpp:6078 RtMidi.cpp:6311 msgid "Data has not been allocated." msgstr "" -#: RtMidi.cpp:1844 RtMidi.cpp:2095 +#: RtMidi.cpp:2240 RtMidi.cpp:2531 msgid "" "Core MIDI has been instructed to open a non-Core MIDI port. This doesn't " "work." msgstr "" -#: RtMidi.cpp:2005 +#: RtMidi.cpp:2312 RtMidi.cpp:2479 +msgid "Setting client names is not implemented for Mac OS X CoreMIDI." +msgstr "" + +#: RtMidi.cpp:2318 RtMidi.cpp:2485 +msgid "Setting port names is not implemented for Mac OS X CoreMIDI." +msgstr "" + +#: RtMidi.cpp:2420 msgid "No MIDI output destinations found." msgstr "" -#: RtMidi.cpp:2023 +#: RtMidi.cpp:2438 msgid "Error creating OS-X MIDI output port." msgstr "" -#: RtMidi.cpp:2033 +#: RtMidi.cpp:2449 msgid "Error getting MIDI output destination reference." msgstr "" -#: RtMidi.cpp:2058 +#: RtMidi.cpp:2494 msgid "A virtual output port already exists." msgstr "" -#: RtMidi.cpp:2069 +#: RtMidi.cpp:2505 msgid "Error creating OS-X virtual MIDI source." msgstr "" -#: RtMidi.cpp:2221 +#: RtMidi.cpp:2608 +msgid "message format problem ... not sysex but > 3 bytes?" +msgstr "" + +#: RtMidi.cpp:2627 msgid "Could not allocate packet list." msgstr "" -#: RtMidi.cpp:2230 +#: RtMidi.cpp:2636 msgid "Error sending MIDI to virtual destinations." msgstr "" -#: RtMidi.cpp:2239 RtMidi.cpp:3663 +#: RtMidi.cpp:2645 RtMidi.cpp:4175 msgid "Error sending MIDI message to port." msgstr "" -#: RtMidi.cpp:2443 RtMidi.cpp:2704 RtMidi.cpp:3210 RtMidi.cpp:3271 -#: RtMidi.cpp:3580 -msgid "Could not allocate ALSA port subscription." +#: RtMidi.cpp:2810 +msgid "Could not allocate ALSA port info structure." msgstr "" -#: RtMidi.cpp:2458 RtMidi.cpp:3219 RtMidi.cpp:3590 -msgid "Error making ALSA port connection." +#: RtMidi.cpp:2814 +#, c-format +msgid "Could not get ALSA port information: %s" msgstr "" -#: RtMidi.cpp:2528 RtMidi.cpp:3461 -msgid "Error creating ALSA sequencer client object." +#: RtMidi.cpp:2820 +#, c-format +msgid "Could not set ALSA port information: %s" msgstr "" -#: RtMidi.cpp:2766 RtMidi.cpp:3245 RtMidi.cpp:3394 +#: RtMidi.cpp:2873 RtMidi.cpp:3149 RtMidi.cpp:3684 RtMidi.cpp:3745 +#: RtMidi.cpp:4079 +msgid "Could not allocate ALSA port subscription." +msgstr "" + +#: RtMidi.cpp:2888 RtMidi.cpp:3693 RtMidi.cpp:4090 +msgid "Error making ALSA port connection." +msgstr "" + +#: RtMidi.cpp:3219 RtMidi.cpp:3719 RtMidi.cpp:3868 msgid "Error starting MIDI input thread!" msgstr "" -#: RtMidi.cpp:2804 RtMidi.cpp:3478 +#: RtMidi.cpp:3257 RtMidi.cpp:3974 msgid "Error initializing MIDI event parser." msgstr "" -#: RtMidi.cpp:2817 +#: RtMidi.cpp:3270 msgid "Error initializing buffer memory." msgstr "" -#: RtMidi.cpp:2851 +#: RtMidi.cpp:3304 msgid "MIDI input buffer overrun." msgstr "" -#: RtMidi.cpp:2861 +#: RtMidi.cpp:3314 msgid "ALSA returned without providing a MIDI event." msgstr "" -#: RtMidi.cpp:2871 +#: RtMidi.cpp:3324 #, c-format msgid "" "Unknown MIDI input error.\n" @@ -272,209 +303,225 @@ msgid "" "%s" msgstr "" -#: RtMidi.cpp:2929 +#: RtMidi.cpp:3382 msgid "Error resizing buffer memory." msgstr "" -#: RtMidi.cpp:2980 +#: RtMidi.cpp:3455 msgid "Event parsing error or not a MIDI event." msgstr "" -#: RtMidi.cpp:3061 +#: RtMidi.cpp:3532 msgid "Error creating pipe objects." msgstr "" -#: RtMidi.cpp:3141 RtMidi.cpp:3526 +#: RtMidi.cpp:3615 RtMidi.cpp:4024 msgid "Error looking for port name." msgstr "" -#: RtMidi.cpp:3197 +#: RtMidi.cpp:3671 msgid "Error creating ALSA input port." msgstr "" -#: RtMidi.cpp:3276 RtMidi.cpp:3692 +#: RtMidi.cpp:3750 RtMidi.cpp:4204 msgid "" "ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work." msgstr "" -#: RtMidi.cpp:3360 RtMidi.cpp:3617 +#: RtMidi.cpp:3834 RtMidi.cpp:4130 msgid "Error creating ALSA virtual port." msgstr "" -#: RtMidi.cpp:3485 RtMidi.cpp:3641 +#: RtMidi.cpp:3957 +msgid "Error creating ALSA sequencer client object." +msgstr "" + +#: RtMidi.cpp:3981 RtMidi.cpp:4153 msgid "Error while allocating buffer memory." msgstr "" -#: RtMidi.cpp:3542 +#: RtMidi.cpp:4040 msgid "No MIDI output sinks found." msgstr "" -#: RtMidi.cpp:3569 +#: RtMidi.cpp:4067 msgid "Error creating ALSA output port." msgstr "" -#: RtMidi.cpp:3634 +#: RtMidi.cpp:4146 msgid "ALSA error resizing MIDI event buffer." msgstr "" -#: RtMidi.cpp:3655 +#: RtMidi.cpp:4167 msgid "Event parsing error." msgstr "" -#: RtMidi.cpp:3687 +#: RtMidi.cpp:4199 msgid "Error allocating ALSA port subscription." msgstr "" -#: RtMidi.cpp:3837 +#: RtMidi.cpp:4377 #, c-format msgid "The port argument %d is invalid." msgstr "" -#: RtMidi.cpp:4159 +#: RtMidi.cpp:4698 msgid "Error sending sysex to Midi device." msgstr "" -#: RtMidi.cpp:4222 +#: RtMidi.cpp:4759 msgid "No MIDI input devices currently available." msgstr "" -#: RtMidi.cpp:4232 +#: RtMidi.cpp:4769 msgid "Failed to initialize a critical section." msgstr "" -#: RtMidi.cpp:4256 +#: RtMidi.cpp:4793 #, c-format msgid "the 'portNumber' argument (%d) is invalid." msgstr "" -#: RtMidi.cpp:4268 +#: RtMidi.cpp:4805 msgid "Error creating Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4284 +#: RtMidi.cpp:4822 msgid "Error initializing data for Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4293 +#: RtMidi.cpp:4832 msgid "Could not register the input buffer for Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4302 +#: RtMidi.cpp:4842 msgid "Error starting Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4313 RtMidi.cpp:4581 +#: RtMidi.cpp:4853 RtMidi.cpp:5148 msgid "Virtual ports are not available Windows Multimedia MIDI API." msgstr "" -#: RtMidi.cpp:4320 RtMidi.cpp:4589 +#: RtMidi.cpp:4860 RtMidi.cpp:5156 msgid "" "Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI " "port. This doesn't work." msgstr "" -#: RtMidi.cpp:4325 +#: RtMidi.cpp:4865 msgid "" "We are overwriting an existing connection. This is probably a programming " "error." msgstr "" -#: RtMidi.cpp:4330 +#: RtMidi.cpp:4870 msgid "Trying to open a non-input port as input MIDI port. This doesn't work." msgstr "" -#: RtMidi.cpp:4344 RtMidi.cpp:4613 +#: RtMidi.cpp:4884 RtMidi.cpp:5180 msgid "" "Some change in the arrangement of MIDI input ports invalidated the port " "descriptor." msgstr "" -#: RtMidi.cpp:4359 +#: RtMidi.cpp:4899 msgid "The handle is invalid. Did you disconnect the device?" msgstr "" -#: RtMidi.cpp:4363 RtMidi.cpp:4632 +#: RtMidi.cpp:4903 RtMidi.cpp:5199 msgid "" "The system has no driver for our handle :-(. Did you disconnect the device?" msgstr "" -#: RtMidi.cpp:4367 RtMidi.cpp:4636 +#: RtMidi.cpp:4907 RtMidi.cpp:5203 msgid "Out of memory." msgstr "" -#: RtMidi.cpp:4413 +#: RtMidi.cpp:4954 msgid "Error closing Windows MM MIDI input port." msgstr "" -#: RtMidi.cpp:4491 +#: RtMidi.cpp:4969 RtMidi.cpp:5135 +msgid "Setting the client name is not supported by Windows MM." +msgstr "" + +#: RtMidi.cpp:4975 RtMidi.cpp:5141 +msgid "Setting the port name is not supported by Windows MM." +msgstr "" + +#: RtMidi.cpp:5041 msgid "No MIDI output devices currently available." msgstr "" -#: RtMidi.cpp:4542 +#: RtMidi.cpp:5096 msgid "No MIDI output destinations found!" msgstr "" -#: RtMidi.cpp:4560 +#: RtMidi.cpp:5114 msgid "Error creating Windows MM MIDI output port." msgstr "" -#: RtMidi.cpp:4599 +#: RtMidi.cpp:5166 msgid "The port descriptor cannot be used to open an output port." msgstr "" -#: RtMidi.cpp:4628 +#: RtMidi.cpp:5195 msgid "The internal handle is invalid. Did you disconnect the device?" msgstr "" -#: RtMidi.cpp:4664 +#: RtMidi.cpp:5230 msgid "Message argument is empty." msgstr "" -#: RtMidi.cpp:4676 +#: RtMidi.cpp:5242 msgid "Error while allocating sysex message memory." msgstr "" -#: RtMidi.cpp:4692 +#: RtMidi.cpp:5258 msgid "Error preparing sysex header." msgstr "" -#: RtMidi.cpp:4701 +#: RtMidi.cpp:5267 msgid "Error sending sysex message." msgstr "" -#: RtMidi.cpp:4714 +#: RtMidi.cpp:5280 msgid "Message size is greater than 3 bytes (and not sysex)." msgstr "" -#: RtMidi.cpp:4730 +#: RtMidi.cpp:5296 msgid "Error sending MIDI message." msgstr "" -#: RtMidi.cpp:4961 +#: RtMidi.cpp:5535 msgid "Could not connect to JACK server. Is it runnig?" msgstr "" -#: RtMidi.cpp:5172 +#: RtMidi.cpp:5767 msgid "Error opening JACK port subscription." msgstr "" -#: RtMidi.cpp:5356 RtMidi.cpp:5584 +#: RtMidi.cpp:6002 RtMidi.cpp:6248 msgid "JACK server not running?" msgstr "" -#: RtMidi.cpp:5400 RtMidi.cpp:5617 +#: RtMidi.cpp:6046 RtMidi.cpp:6279 msgid "Error creating JACK port." msgstr "" -#: RtMidi.cpp:5420 RtMidi.cpp:5637 +#: RtMidi.cpp:6066 RtMidi.cpp:6299 msgid "Error creating JACK virtual port." msgstr "" -#: RtMidi.cpp:5444 RtMidi.cpp:5661 +#: RtMidi.cpp:6090 RtMidi.cpp:6323 msgid "" "JACK has been instructed to open a non-JACK MIDI port. This doesn't work." msgstr "" -#: RtMidi.cpp:5527 RtMidi.cpp:5739 +#: RtMidi.cpp:6173 RtMidi.cpp:6401 msgid "No ports available." msgstr "" + +#: RtMidi.cpp:6201 RtMidi.cpp:6429 +msgid "Setting the client name is not supported by JACK." +msgstr ""