From d07f6011cfdb3ba59cbd409b7005d5676cdca4d4 Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Sun, 30 Mar 2014 11:46:35 -0400 Subject: [PATCH 001/388] Removed Windows kernel streaming code because it was incomplete and uncompilable. The code still exists in the winks branch. --- RtMidi.cpp | 1045 -------------------------------------- RtMidi.h | 40 +- doc/doxygen/tutorial.txt | 13 +- doc/release.txt | 1 + readme | 2 +- 5 files changed, 6 insertions(+), 1095 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 2101c377..07e23168 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -78,9 +78,6 @@ void RtMidi :: getCompiledApi( std::vector &apis ) throw() #if defined(__WINDOWS_MM__) apis.push_back( WINDOWS_MM ); #endif -#if defined(__WINDOWS_KS__) - apis.push_back( WINDOWS_KS ); -#endif #if defined(__RTMIDI_DUMMY__) apis.push_back( RTMIDI_DUMMY ); #endif @@ -108,10 +105,6 @@ void RtMidiIn :: openMidiApi( RtMidi::Api api, const std::string clientName, uns if ( api == WINDOWS_MM ) rtapi_ = new MidiInWinMM( clientName, queueSizeLimit ); #endif -#if defined(__WINDOWS_KS__) - if ( api == WINDOWS_KS ) - rtapi_ = new MidiInWinKS( clientName, queueSizeLimit ); -#endif #if defined(__MACOSX_CORE__) if ( api == MACOSX_CORE ) rtapi_ = new MidiInCore( clientName, queueSizeLimit ); @@ -181,10 +174,6 @@ void RtMidiOut :: openMidiApi( RtMidi::Api api, const std::string clientName ) if ( api == WINDOWS_MM ) rtapi_ = new MidiOutWinMM( clientName ); #endif -#if defined(__WINDOWS_KS__) - if ( api == WINDOWS_KS ) - rtapi_ = new MidiOutWinKS( clientName ); -#endif #if defined(__MACOSX_CORE__) if ( api == MACOSX_CORE ) rtapi_ = new MidiOutCore( clientName ); @@ -2434,1040 +2423,6 @@ void MidiOutWinMM :: sendMessage( std::vector *message ) #endif // __WINDOWS_MM__ -// *********************************************************************// -// API: WINDOWS Kernel Streaming -// -// Written by Sebastien Alaiwan, 2012. -// -// NOTE BY GARY: much of the KS-specific code below probably should go in a separate file. -// -// *********************************************************************// - -#if defined(__WINDOWS_KS__) - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ks.h" -#include "ksmedia.h" - -#define INSTANTIATE_GUID(a) GUID const a = { STATIC_ ## a } - -INSTANTIATE_GUID(GUID_NULL); -INSTANTIATE_GUID(KSPROPSETID_Pin); -INSTANTIATE_GUID(KSPROPSETID_Connection); -INSTANTIATE_GUID(KSPROPSETID_Topology); -INSTANTIATE_GUID(KSINTERFACESETID_Standard); -INSTANTIATE_GUID(KSMEDIUMSETID_Standard); -INSTANTIATE_GUID(KSDATAFORMAT_TYPE_MUSIC); -INSTANTIATE_GUID(KSDATAFORMAT_SUBTYPE_MIDI); -INSTANTIATE_GUID(KSDATAFORMAT_SPECIFIER_NONE); - -#undef INSTANTIATE_GUID - -typedef std::basic_string tstring; - -inline bool IsValid(HANDLE handle) -{ - return handle != NULL && handle != INVALID_HANDLE_VALUE; -} - -class ComException : public std::runtime_error -{ -private: - static std::string MakeString(std::string const& s, HRESULT hr) - { - std::stringstream ss; - ss << "(error 0x" << std::hex << hr << ")"; - return s + ss.str(); - } - -public: - ComException(std::string const& s, HRESULT hr) : - std::runtime_error(MakeString(s, hr)) - { - } -}; - -template -class CKsEnumFilters -{ -public: - ~CKsEnumFilters() - { - DestroyLists(); - } - - void EnumFilters(GUID const* categories, size_t numCategories) - { - DestroyLists(); - - if (categories == 0) - throw std::runtime_error("CKsEnumFilters: invalid argument"); - - // Get a handle to the device set specified by the guid - HDEVINFO hDevInfo = ::SetupDiGetClassDevs(&categories[0], NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - if (!IsValid(hDevInfo)) - throw std::runtime_error("CKsEnumFilters: no devices found"); - - // Loop through members of the set and get details for each - for ( int iClassMember=0; iClassMember++ ) { - try { - SP_DEVICE_INTERFACE_DATA DID; - DID.cbSize = sizeof(DID); - DID.Reserved = 0; - - bool fRes = ::SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &categories[0], iClassMember, &DID); - if (!fRes) - break; - - // Get filter friendly name - HKEY hRegKey = ::SetupDiOpenDeviceInterfaceRegKey(hDevInfo, &DID, 0, KEY_READ); - if (hRegKey == INVALID_HANDLE_VALUE) - throw std::runtime_error("CKsEnumFilters: interface has no registry"); - - char friendlyName[256]; - DWORD dwSize = sizeof friendlyName; - LONG lval = ::RegQueryValueEx(hRegKey, TEXT("FriendlyName"), NULL, NULL, (LPBYTE)friendlyName, &dwSize); - ::RegCloseKey(hRegKey); - if (lval != ERROR_SUCCESS) - throw std::runtime_error("CKsEnumFilters: interface has no friendly name"); - - // Get details for the device registered in this class - DWORD const cbItfDetails = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(WCHAR); - std::vector buffer(cbItfDetails); - - SP_DEVICE_INTERFACE_DETAIL_DATA* pDevInterfaceDetails = reinterpret_cast(&buffer[0]); - pDevInterfaceDetails->cbSize = sizeof(*pDevInterfaceDetails); - - SP_DEVINFO_DATA DevInfoData; - DevInfoData.cbSize = sizeof(DevInfoData); - DevInfoData.Reserved = 0; - - fRes = ::SetupDiGetDeviceInterfaceDetail(hDevInfo, &DID, pDevInterfaceDetails, cbItfDetails, NULL, &DevInfoData); - if (!fRes) - throw std::runtime_error("CKsEnumFilters: could not get interface details"); - - // check additional category guids which may (or may not) have been supplied - for (size_t i=1; i < numCategories; ++i) { - SP_DEVICE_INTERFACE_DATA DIDAlias; - DIDAlias.cbSize = sizeof(DIDAlias); - DIDAlias.Reserved = 0; - - fRes = ::SetupDiGetDeviceInterfaceAlias(hDevInfo, &DID, &categories[i], &DIDAlias); - if (!fRes) - throw std::runtime_error("CKsEnumFilters: could not get interface alias"); - - // Check if the this interface alias is enabled. - if (!DIDAlias.Flags || (DIDAlias.Flags & SPINT_REMOVED)) - throw std::runtime_error("CKsEnumFilters: interface alias is not enabled"); - } - - std::auto_ptr pFilter(new TFilterType(pDevInterfaceDetails->DevicePath, friendlyName)); - - pFilter->Instantiate(); - pFilter->FindMidiPins(); - pFilter->Validate(); - - m_Filters.push_back(pFilter.release()); - } - catch (std::runtime_error const& e) { - } - } - - ::SetupDiDestroyDeviceInfoList(hDevInfo); - } - -private: - void DestroyLists() - { - for (size_t i=0;i < m_Filters.size();++i) - delete m_Filters[i]; - m_Filters.clear(); - } - -public: - // TODO: make this private. - std::vector m_Filters; -}; - -class CKsObject -{ -public: - CKsObject(HANDLE handle) : m_handle(handle) - { - } - -protected: - HANDLE m_handle; - - void SetProperty(REFGUID guidPropertySet, ULONG nProperty, void* pvValue, ULONG cbValue) - { - KSPROPERTY ksProperty; - memset(&ksProperty, 0, sizeof ksProperty); - ksProperty.Set = guidPropertySet; - ksProperty.Id = nProperty; - ksProperty.Flags = KSPROPERTY_TYPE_SET; - - HRESULT hr = DeviceIoControlKsProperty(ksProperty, pvValue, cbValue); - if (FAILED(hr)) - throw ComException("CKsObject::SetProperty: could not set property", hr); - } - -private: - - HRESULT DeviceIoControlKsProperty(KSPROPERTY& ksProperty, void* pvValue, ULONG cbValue) - { - ULONG ulReturned; - return ::DeviceIoControl( - m_handle, - IOCTL_KS_PROPERTY, - &ksProperty, - sizeof(ksProperty), - pvValue, - cbValue, - &ulReturned, - NULL); - } -}; - -class CKsPin; - -class CKsFilter : public CKsObject -{ - friend class CKsPin; - -public: - CKsFilter(tstring const& name, std::string const& sFriendlyName); - virtual ~CKsFilter(); - - virtual void Instantiate(); - - template - T GetPinProperty(ULONG nPinId, ULONG nProperty) - { - ULONG ulReturned = 0; - T value; - - KSP_PIN ksPProp; - ksPProp.Property.Set = KSPROPSETID_Pin; - ksPProp.Property.Id = nProperty; - ksPProp.Property.Flags = KSPROPERTY_TYPE_GET; - ksPProp.PinId = nPinId; - ksPProp.Reserved = 0; - - HRESULT hr = ::DeviceIoControl( - m_handle, - IOCTL_KS_PROPERTY, - &ksPProp, - sizeof(KSP_PIN), - &value, - sizeof(value), - &ulReturned, - NULL); - if (FAILED(hr)) - throw ComException("CKsFilter::GetPinProperty: failed to retrieve property", hr); - - return value; - } - - void GetPinPropertyMulti(ULONG nPinId, REFGUID guidPropertySet, ULONG nProperty, PKSMULTIPLE_ITEM* ppKsMultipleItem) - { - HRESULT hr; - - KSP_PIN ksPProp; - ksPProp.Property.Set = guidPropertySet; - ksPProp.Property.Id = nProperty; - ksPProp.Property.Flags = KSPROPERTY_TYPE_GET; - ksPProp.PinId = nPinId; - ksPProp.Reserved = 0; - - ULONG cbMultipleItem = 0; - hr = ::DeviceIoControl(m_handle, - IOCTL_KS_PROPERTY, - &ksPProp.Property, - sizeof(KSP_PIN), - NULL, - 0, - &cbMultipleItem, - NULL); - if (FAILED(hr)) - throw ComException("CKsFilter::GetPinPropertyMulti: cannot get property", hr); - - *ppKsMultipleItem = (PKSMULTIPLE_ITEM) new BYTE[cbMultipleItem]; - - ULONG ulReturned = 0; - hr = ::DeviceIoControl( - m_handle, - IOCTL_KS_PROPERTY, - &ksPProp, - sizeof(KSP_PIN), - (PVOID)*ppKsMultipleItem, - cbMultipleItem, - &ulReturned, - NULL); - if (FAILED(hr)) - throw ComException("CKsFilter::GetPinPropertyMulti: cannot get property", hr); - } - - std::string const& GetFriendlyName() const - { - return m_sFriendlyName; - } - -protected: - - std::vector m_Pins; // this list owns the pins. - - std::vector m_RenderPins; - std::vector m_CapturePins; - -private: - std::string const m_sFriendlyName; // friendly name eg "Virus TI Synth" - tstring const m_sName; // Filter path, eg "\\?\usb#vid_133e&pid_0815...\vtimidi02" -}; - -class CKsPin : public CKsObject -{ -public: - CKsPin(CKsFilter* pFilter, ULONG nId); - virtual ~CKsPin(); - - virtual void Instantiate(); - - void ClosePin(); - - void SetState(KSSTATE ksState); - - void WriteData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED); - void ReadData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED); - - KSPIN_DATAFLOW GetDataFlow() const - { - return m_DataFlow; - } - - bool IsSink() const - { - return m_Communication == KSPIN_COMMUNICATION_SINK - || m_Communication == KSPIN_COMMUNICATION_BOTH; - } - - -protected: - PKSPIN_CONNECT m_pKsPinConnect; // creation parameters of pin - CKsFilter* const m_pFilter; - - ULONG m_cInterfaces; - PKSIDENTIFIER m_pInterfaces; - PKSMULTIPLE_ITEM m_pmiInterfaces; - - ULONG m_cMediums; - PKSIDENTIFIER m_pMediums; - PKSMULTIPLE_ITEM m_pmiMediums; - - ULONG m_cDataRanges; - PKSDATARANGE m_pDataRanges; - PKSMULTIPLE_ITEM m_pmiDataRanges; - - KSPIN_DATAFLOW m_DataFlow; - KSPIN_COMMUNICATION m_Communication; -}; - -CKsFilter::CKsFilter(tstring const& sName, std::string const& sFriendlyName) : - CKsObject(INVALID_HANDLE_VALUE), - m_sFriendlyName(sFriendlyName), - m_sName(sName) -{ - if (sName.empty()) - throw std::runtime_error("CKsFilter::CKsFilter: name can't be empty"); -} - -CKsFilter::~CKsFilter() -{ - for (size_t i=0;i < m_Pins.size();++i) - delete m_Pins[i]; - - if (IsValid(m_handle)) - ::CloseHandle(m_handle); -} - -void CKsFilter::Instantiate() -{ - m_handle = CreateFile( - m_sName.c_str(), - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, - NULL); - - if (!IsValid(m_handle)) - { - DWORD const dwError = GetLastError(); - throw ComException("CKsFilter::Instantiate: can't open driver", HRESULT_FROM_WIN32(dwError)); - } -} - -CKsPin::CKsPin(CKsFilter* pFilter, ULONG PinId) : - CKsObject(INVALID_HANDLE_VALUE), - m_pKsPinConnect(NULL), - m_pFilter(pFilter) -{ - m_Communication = m_pFilter->GetPinProperty(PinId, KSPROPERTY_PIN_COMMUNICATION); - m_DataFlow = m_pFilter->GetPinProperty(PinId, KSPROPERTY_PIN_DATAFLOW); - - // Interfaces - m_pFilter->GetPinPropertyMulti( - PinId, - KSPROPSETID_Pin, - KSPROPERTY_PIN_INTERFACES, - &m_pmiInterfaces); - - m_cInterfaces = m_pmiInterfaces->Count; - m_pInterfaces = (PKSPIN_INTERFACE)(m_pmiInterfaces + 1); - - // Mediums - m_pFilter->GetPinPropertyMulti( - PinId, - KSPROPSETID_Pin, - KSPROPERTY_PIN_MEDIUMS, - &m_pmiMediums); - - m_cMediums = m_pmiMediums->Count; - m_pMediums = (PKSPIN_MEDIUM)(m_pmiMediums + 1); - - // Data ranges - m_pFilter->GetPinPropertyMulti( - PinId, - KSPROPSETID_Pin, - KSPROPERTY_PIN_DATARANGES, - &m_pmiDataRanges); - - m_cDataRanges = m_pmiDataRanges->Count; - m_pDataRanges = (PKSDATARANGE)(m_pmiDataRanges + 1); -} - -CKsPin::~CKsPin() -{ - ClosePin(); - - delete[] (BYTE*)m_pKsPinConnect; - delete[] (BYTE*)m_pmiDataRanges; - delete[] (BYTE*)m_pmiInterfaces; - delete[] (BYTE*)m_pmiMediums; -} - -void CKsPin::ClosePin() -{ - if (IsValid(m_handle)) { - SetState(KSSTATE_STOP); - ::CloseHandle(m_handle); - } - m_handle = INVALID_HANDLE_VALUE; -} - -void CKsPin::SetState(KSSTATE ksState) -{ - SetProperty(KSPROPSETID_Connection, KSPROPERTY_CONNECTION_STATE, &ksState, sizeof(ksState)); -} - -void CKsPin::Instantiate() -{ - if (!m_pKsPinConnect) - throw std::runtime_error("CKsPin::Instanciate: abstract pin"); - - DWORD const dwResult = KsCreatePin(m_pFilter->m_handle, m_pKsPinConnect, GENERIC_WRITE | GENERIC_READ, &m_handle); - if (dwResult != ERROR_SUCCESS) - throw ComException("CKsMidiCapFilter::CreateRenderPin: Pin instanciation failed", HRESULT_FROM_WIN32(dwResult)); -} - -void CKsPin::WriteData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED) -{ - DWORD cbWritten; - BOOL fRes = ::DeviceIoControl( - m_handle, - IOCTL_KS_WRITE_STREAM, - NULL, - 0, - pKSSTREAM_HEADER, - pKSSTREAM_HEADER->Size, - &cbWritten, - pOVERLAPPED); - if (!fRes) { - DWORD const dwError = GetLastError(); - if (dwError != ERROR_IO_PENDING) - throw ComException("CKsPin::WriteData: DeviceIoControl failed", HRESULT_FROM_WIN32(dwError)); - } -} - -void CKsPin::ReadData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED) -{ - DWORD cbReturned; - BOOL fRes = ::DeviceIoControl( - m_handle, - IOCTL_KS_READ_STREAM, - NULL, - 0, - pKSSTREAM_HEADER, - pKSSTREAM_HEADER->Size, - &cbReturned, - pOVERLAPPED); - if (!fRes) { - DWORD const dwError = GetLastError(); - if (dwError != ERROR_IO_PENDING) - throw ComException("CKsPin::ReadData: DeviceIoControl failed", HRESULT_FROM_WIN32(dwError)); - } -} - -class CKsMidiFilter : public CKsFilter -{ -public: - void FindMidiPins(); - -protected: - CKsMidiFilter(tstring const& sPath, std::string const& sFriendlyName); -}; - -class CKsMidiPin : public CKsPin -{ -public: - CKsMidiPin(CKsFilter* pFilter, ULONG nId); -}; - -class CKsMidiRenFilter : public CKsMidiFilter -{ -public: - CKsMidiRenFilter(tstring const& sPath, std::string const& sFriendlyName); - CKsMidiPin* CreateRenderPin(); - - void Validate() - { - if (m_RenderPins.empty()) - throw std::runtime_error("Could not find a MIDI render pin"); - } -}; - -class CKsMidiCapFilter : public CKsMidiFilter -{ -public: - CKsMidiCapFilter(tstring const& sPath, std::string const& sFriendlyName); - CKsMidiPin* CreateCapturePin(); - - void Validate() - { - if (m_CapturePins.empty()) - throw std::runtime_error("Could not find a MIDI capture pin"); - } -}; - -CKsMidiFilter::CKsMidiFilter(tstring const& sPath, std::string const& sFriendlyName) : - CKsFilter(sPath, sFriendlyName) -{ -} - -void CKsMidiFilter::FindMidiPins() -{ - ULONG numPins = GetPinProperty(0, KSPROPERTY_PIN_CTYPES); - - for (ULONG iPin = 0; iPin < numPins; ++iPin) { - try { - KSPIN_COMMUNICATION com = GetPinProperty(iPin, KSPROPERTY_PIN_COMMUNICATION); - if (com != KSPIN_COMMUNICATION_SINK && com != KSPIN_COMMUNICATION_BOTH) - throw std::runtime_error("Unknown pin communication value"); - - m_Pins.push_back(new CKsMidiPin(this, iPin)); - } - catch (std::runtime_error const&) { - // pin instanciation has failed, continue to the next pin. - } - } - - m_RenderPins.clear(); - m_CapturePins.clear(); - - for (size_t i = 0; i < m_Pins.size(); ++i) { - CKsPin* const pPin = m_Pins[i]; - - if (pPin->IsSink()) { - if (pPin->GetDataFlow() == KSPIN_DATAFLOW_IN) - m_RenderPins.push_back(pPin); - else - m_CapturePins.push_back(pPin); - } - } - - if (m_RenderPins.empty() && m_CapturePins.empty()) - throw std::runtime_error("No valid pins found on the filter."); -} - -CKsMidiRenFilter::CKsMidiRenFilter(tstring const& sPath, std::string const& sFriendlyName) : - CKsMidiFilter(sPath, sFriendlyName) -{ -} - -CKsMidiPin* CKsMidiRenFilter::CreateRenderPin() -{ - if (m_RenderPins.empty()) - throw std::runtime_error("Could not find a MIDI render pin"); - - CKsMidiPin* pPin = (CKsMidiPin*)m_RenderPins[0]; - pPin->Instantiate(); - return pPin; -} - -CKsMidiCapFilter::CKsMidiCapFilter(tstring const& sPath, std::string const& sFriendlyName) : - CKsMidiFilter(sPath, sFriendlyName) -{ -} - -CKsMidiPin* CKsMidiCapFilter::CreateCapturePin() -{ - if (m_CapturePins.empty()) - throw std::runtime_error("Could not find a MIDI capture pin"); - - CKsMidiPin* pPin = (CKsMidiPin*)m_CapturePins[0]; - pPin->Instantiate(); - return pPin; -} - -CKsMidiPin::CKsMidiPin(CKsFilter* pFilter, ULONG nId) : - CKsPin(pFilter, nId) -{ - DWORD const cbPinCreateSize = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT); - m_pKsPinConnect = (PKSPIN_CONNECT) new BYTE[cbPinCreateSize]; - - m_pKsPinConnect->Interface.Set = KSINTERFACESETID_Standard; - m_pKsPinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING; - m_pKsPinConnect->Interface.Flags = 0; - m_pKsPinConnect->Medium.Set = KSMEDIUMSETID_Standard; - m_pKsPinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE; - m_pKsPinConnect->Medium.Flags = 0; - m_pKsPinConnect->PinId = nId; - m_pKsPinConnect->PinToHandle = NULL; - m_pKsPinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL; - m_pKsPinConnect->Priority.PrioritySubClass = 1; - - // point m_pDataFormat to just after the pConnect struct - KSDATAFORMAT* m_pDataFormat = (KSDATAFORMAT*)(m_pKsPinConnect + 1); - m_pDataFormat->FormatSize = sizeof(KSDATAFORMAT); - m_pDataFormat->Flags = 0; - m_pDataFormat->SampleSize = 0; - m_pDataFormat->Reserved = 0; - m_pDataFormat->MajorFormat = GUID(KSDATAFORMAT_TYPE_MUSIC); - m_pDataFormat->SubFormat = GUID(KSDATAFORMAT_SUBTYPE_MIDI); - m_pDataFormat->Specifier = GUID(KSDATAFORMAT_SPECIFIER_NONE); - - bool hasStdStreamingInterface = false; - bool hasStdStreamingMedium = false; - - for ( ULONG i = 0; i < m_cInterfaces; i++ ) { - if (m_pInterfaces[i].Set == KSINTERFACESETID_Standard - && m_pInterfaces[i].Id == KSINTERFACE_STANDARD_STREAMING) - hasStdStreamingInterface = true; - } - - for (ULONG i = 0; i < m_cMediums; i++) { - if (m_pMediums[i].Set == KSMEDIUMSETID_Standard - && m_pMediums[i].Id == KSMEDIUM_STANDARD_DEVIO) - hasStdStreamingMedium = true; - } - - if (!hasStdStreamingInterface) // No standard streaming interfaces on the pin - throw std::runtime_error("CKsMidiPin::CKsMidiPin: no standard streaming interface"); - - if (!hasStdStreamingMedium) // No standard streaming mediums on the pin - throw std::runtime_error("CKsMidiPin::CKsMidiPin: no standard streaming medium"); - - bool hasMidiDataRange = false; - - BYTE const* pDataRangePtr = reinterpret_cast(m_pDataRanges); - - for (ULONG i = 0; i < m_cDataRanges; ++i) { - KSDATARANGE const* pDataRange = reinterpret_cast(pDataRangePtr); - - if (pDataRange->SubFormat == KSDATAFORMAT_SUBTYPE_MIDI) { - hasMidiDataRange = true; - break; - } - - pDataRangePtr += pDataRange->FormatSize; - } - - if (!hasMidiDataRange) // No MIDI dataranges on the pin - throw std::runtime_error("CKsMidiPin::CKsMidiPin: no MIDI datarange"); -} - - -struct WindowsKsData -{ - WindowsKsData() : m_pPin(NULL), m_Buffer(1024), m_hInputThread(NULL) - { - memset(&overlapped, 0, sizeof(OVERLAPPED)); - m_hExitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); - overlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); - m_hInputThread = NULL; - } - - ~WindowsKsData() - { - ::CloseHandle(overlapped.hEvent); - ::CloseHandle(m_hExitEvent); - } - - OVERLAPPED overlapped; - CKsPin* m_pPin; - std::vector m_Buffer; - std::auto_ptr > m_pCaptureEnum; - std::auto_ptr > m_pRenderEnum; - HANDLE m_hInputThread; - HANDLE m_hExitEvent; -}; - -// *********************************************************************// -// API: WINDOWS Kernel Streaming -// Class Definitions: MidiInWinKS -// *********************************************************************// - -static DWORD WINAPI midiKsInputThread(VOID* pUser) -{ - MidiInApi::RtMidiInData* data = static_cast(pUser); - WindowsKsData* apiData = static_cast(data->apiData); - - HANDLE hEvents[] = { apiData->overlapped.hEvent, apiData->m_hExitEvent }; - - while ( true ) { - KSSTREAM_HEADER packet; - memset(&packet, 0, sizeof packet); - packet.Size = sizeof(KSSTREAM_HEADER); - packet.PresentationTime.Time = 0; - packet.PresentationTime.Numerator = 1; - packet.PresentationTime.Denominator = 1; - packet.Data = &apiData->m_Buffer[0]; - packet.DataUsed = 0; - packet.FrameExtent = apiData->m_Buffer.size(); - apiData->m_pPin->ReadData(&packet, &apiData->overlapped); - - DWORD dwRet = ::WaitForMultipleObjects(2, hEvents, FALSE, INFINITE); - - if ( dwRet == WAIT_OBJECT_0 ) { - // parse packet - unsigned char* pData = (unsigned char*)packet.Data; - unsigned int iOffset = 0; - - while ( iOffset < packet.DataUsed ) { - KSMUSICFORMAT* pMusic = (KSMUSICFORMAT*)&pData[iOffset]; - iOffset += sizeof(KSMUSICFORMAT); - - MidiInApi::MidiMessage message; - message.timeStamp = 0; - for(size_t i=0;i < pMusic->ByteCount;++i) - message.bytes.push_back(pData[iOffset+i]); - - 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 << "\nRtMidiIn: message queue limit reached!!\n\n"; - } - - iOffset += pMusic->ByteCount; - - // re-align on 32 bits - if ( iOffset % 4 != 0 ) - iOffset += (4 - iOffset % 4); - } - } - else - break; - } - return 0; -} - -MidiInWinKS :: MidiInWinKS( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) -{ - initialize( clientName ); -} - -void MidiInWinKS :: initialize( const std::string& clientName ) -{ - WindowsKsData* data = new WindowsKsData; - apiData_ = (void*)data; - inputData_.apiData = data; - - GUID const aguidEnumCats[] = - { - { STATIC_KSCATEGORY_AUDIO }, { STATIC_KSCATEGORY_CAPTURE } - }; - data->m_pCaptureEnum.reset(new CKsEnumFilters ); - data->m_pCaptureEnum->EnumFilters(aguidEnumCats, 2); -} - -MidiInWinKS :: ~MidiInWinKS() -{ - WindowsKsData* data = static_cast(apiData_); - try { - if ( data->m_pPin ) - closePort(); - } - catch(...) { - } - - delete data; -} - -void MidiInWinKS :: openPort( unsigned int portNumber, const std::string portName ) -{ - WindowsKsData* data = static_cast(apiData_); - - if ( portNumber < 0 || portNumber >= data->m_pCaptureEnum->m_Filters.size() ) { - std::stringstream ost; - ost << "MidiInWinKS::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return; - } - - CKsMidiCapFilter* pFilter = data->m_pCaptureEnum->m_Filters[portNumber]; - data->m_pPin = pFilter->CreateCapturePin(); - - if ( data->m_pPin == NULL ) { - std::stringstream ost; - ost << "MidiInWinKS::openPort: KS error opening port (could not create pin)"; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return; - } - - data->m_pPin->SetState(KSSTATE_RUN); - - DWORD threadId; - data->m_hInputThread = ::CreateThread(NULL, 0, &midiKsInputThread, &inputData_, 0, &threadId); - if ( data->m_hInputThread == NULL ) { - std::stringstream ost; - ost << "MidiInWinKS::openPort: Could not create input thread : Windows error " << GetLastError() << std::endl;; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return; - } - - connected_ = true; -} - -void MidiInWinKS :: openVirtualPort( const std::string portName ) -{ - // This function cannot be implemented for the Windows KS MIDI API. - errorString_ = "MidiInWinKS::openVirtualPort: cannot be implemented in Windows KS MIDI API!"; - error( RtMidiError::WARNING, errorString_ ); -} - -unsigned int MidiInWinKS :: getPortCount() -{ - WindowsKsData* data = static_cast(apiData_); - return (unsigned int)data->m_pCaptureEnum->m_Filters.size(); -} - -std::string MidiInWinKS :: getPortName(unsigned int portNumber) -{ - WindowsKsData* data = static_cast(apiData_); - - if (portNumber < 0 || portNumber >= data->m_pCaptureEnum->m_Filters.size()) { - std::stringstream ost; - ost << "MidiInWinKS::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return; - } - - CKsMidiCapFilter* pFilter = data->m_pCaptureEnum->m_Filters[portNumber]; - return pFilter->GetFriendlyName(); -} - -void MidiInWinKS :: closePort() -{ - WindowsKsData* data = static_cast(apiData_); - connected_ = false; - - if (data->m_hInputThread) { - ::SignalObjectAndWait(data->m_hExitEvent, data->m_hInputThread, INFINITE, FALSE); - ::CloseHandle(data->m_hInputThread); - } - - if (data->m_pPin) { - data->m_pPin->SetState(KSSTATE_PAUSE); - data->m_pPin->SetState(KSSTATE_STOP); - data->m_pPin->ClosePin(); - data->m_pPin = NULL; - } -} - -// *********************************************************************// -// API: WINDOWS Kernel Streaming -// Class Definitions: MidiOutWinKS -// *********************************************************************// - -MidiOutWinKS :: MidiOutWinKS( const std::string clientName ) : MidiOutApi() -{ - initialize( clientName ); -} - -void MidiOutWinKS :: initialize( const std::string& clientName ) -{ - WindowsKsData* data = new WindowsKsData; - - data->m_pPin = NULL; - data->m_pRenderEnum.reset(new CKsEnumFilters ); - GUID const aguidEnumCats[] = - { - { STATIC_KSCATEGORY_AUDIO }, { STATIC_KSCATEGORY_RENDER } - }; - data->m_pRenderEnum->EnumFilters(aguidEnumCats, 2); - - apiData_ = (void*)data; -} - -MidiOutWinKS :: ~MidiOutWinKS() -{ - // Close a connection if it exists. - closePort(); - - // Cleanup. - WindowsKsData* data = static_cast(apiData_); - delete data; -} - -void MidiOutWinKS :: openPort( unsigned int portNumber, const std::string portName ) -{ - WindowsKsData* data = static_cast(apiData_); - - if (portNumber < 0 || portNumber >= data->m_pRenderEnum->m_Filters.size()) { - std::stringstream ost; - ost << "MidiOutWinKS::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return; - } - - CKsMidiRenFilter* pFilter = data->m_pRenderEnum->m_Filters[portNumber]; - data->m_pPin = pFilter->CreateRenderPin(); - - if (data->m_pPin == NULL) { - std::stringstream ost; - ost << "MidiOutWinKS::openPort: KS error opening port (could not create pin)"; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return; - } - - data->m_pPin->SetState(KSSTATE_RUN); - connected_ = true; -} - -void MidiOutWinKS :: openVirtualPort( const std::string portName ) -{ - // This function cannot be implemented for the Windows KS MIDI API. - errorString_ = "MidiOutWinKS::openVirtualPort: cannot be implemented in Windows KS MIDI API!"; - error( RtMidiError::WARNING, errorString_ ); -} - -unsigned int MidiOutWinKS :: getPortCount() -{ - WindowsKsData* data = static_cast(apiData_); - return (unsigned int)data->m_pRenderEnum->m_Filters.size(); -} - -std::string MidiOutWinKS :: getPortName( unsigned int portNumber ) -{ - WindowsKsData* data = static_cast(apiData_); - - if ( portNumber < 0 || portNumber >= data->m_pRenderEnum->m_Filters.size() ) { - std::stringstream ost; - ost << "MidiOutWinKS::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return; - } - - CKsMidiRenFilter* pFilter = data->m_pRenderEnum->m_Filters[portNumber]; - return pFilter->GetFriendlyName(); -} - -void MidiOutWinKS :: closePort() -{ - WindowsKsData* data = static_cast(apiData_); - connected_ = false; - - if ( data->m_pPin ) { - data->m_pPin->SetState(KSSTATE_PAUSE); - data->m_pPin->SetState(KSSTATE_STOP); - data->m_pPin->ClosePin(); - data->m_pPin = NULL; - } -} - -void MidiOutWinKS :: sendMessage(std::vector* pMessage) -{ - std::vector const& msg = *pMessage; - WindowsKsData* data = static_cast(apiData_); - size_t iNumMidiBytes = msg.size(); - size_t pos = 0; - - // write header - KSMUSICFORMAT* pKsMusicFormat = reinterpret_cast(&data->m_Buffer[pos]); - pKsMusicFormat->TimeDeltaMs = 0; - pKsMusicFormat->ByteCount = iNumMidiBytes; - pos += sizeof(KSMUSICFORMAT); - - // write MIDI bytes - if ( pos + iNumMidiBytes > data->m_Buffer.size() ) { - std::stringstream ost; - ost << "KsMidiInput::Write: MIDI buffer too small. Required " << pos + iNumMidiBytes << " bytes, only has " << data->m_Buffer.size(); - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return; - } - - if ( data->m_pPin == NULL ) { - std::stringstream ost; - ost << "MidiOutWinKS::sendMessage: port is not open"; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return; - } - - memcpy(&data->m_Buffer[pos], &msg[0], iNumMidiBytes); - pos += iNumMidiBytes; - - KSSTREAM_HEADER packet; - memset(&packet, 0, sizeof packet); - packet.Size = sizeof(packet); - packet.PresentationTime.Time = 0; - packet.PresentationTime.Numerator = 1; - packet.PresentationTime.Denominator = 1; - packet.Data = const_cast(&data->m_Buffer[0]); - packet.DataUsed = ((pos+3)/4)*4; - packet.FrameExtent = data->m_Buffer.size(); - - data->m_pPin->WriteData(&packet, NULL); -} - -#endif // __WINDOWS_KS__ //*********************************************************************// // API: UNIX JACK diff --git a/RtMidi.h b/RtMidi.h index 99dc38c1..61418350 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -124,7 +124,6 @@ class RtMidi LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ - WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ RTMIDI_DUMMY /*!< A compilable but non-functional API. */ }; @@ -566,7 +565,7 @@ inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback ) { // // **************************************************************** // -#if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__) && !defined(__WINDOWS_KS__) +#if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__) #define __RTMIDI_DUMMY__ #endif @@ -724,43 +723,6 @@ class MidiOutWinMM: public MidiOutApi #endif -#if defined(__WINDOWS_KS__) - -class MidiInWinKS: public MidiInApi -{ - public: - MidiInWinKS( const std::string clientName, unsigned int queueSizeLimit ); - ~MidiInWinKS( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_KS; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - - protected: - void initialize( const std::string& clientName ); -}; - -class MidiOutWinKS: public MidiOutApi -{ - public: - MidiOutWinKS( const std::string clientName ); - ~MidiOutWinKS( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_KS; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector *message ); - - protected: - void initialize( const std::string& clientName ); -}; - -#endif - #if defined(__RTMIDI_DUMMY__) class MidiInDummy: public MidiInApi diff --git a/doc/doxygen/tutorial.txt b/doc/doxygen/tutorial.txt index d6dc8266..aba7f3bd 100644 --- a/doc/doxygen/tutorial.txt +++ b/doc/doxygen/tutorial.txt @@ -4,7 +4,7 @@ \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 & Kernel Streaming) 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 (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
  • @@ -19,7 +19,7 @@ MIDI input and output functionality are separated into two classes, RtMidiIn and \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. +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 @@ -375,13 +375,6 @@ In order to compile RtMidi for a specific OS and API, it is necessary to supply winmm.lib, multithreaded compiler specific - - Windows - Kernel Streaming - __WINDOWS_KS__ - ks.h, ksmedia.h, setupapi.lib, ksuser.lib, multithreaded - compiler specific -

    @@ -393,7 +386,7 @@ 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 Windows, the search order is WinMM and then WinKS). 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 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. 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. diff --git a/doc/release.txt b/doc/release.txt index 83debcc9..d08f706e 100644 --- a/doc/release.txt +++ b/doc/release.txt @@ -16,6 +16,7 @@ v2.1.0: (30 March 2014) - Windows update to avoid lockups when shutting down while sending/receiving sysex messages (ptarabbia) - OS-X fix to avoid empty messages in callbacks when ignoring sysex messages and split sysexes are received (codepainters) - ALSA openPort fix to better distinguish sender and receiver (Russell Smyth) +- Windows Kernel Streaming support removed because it was uncompilable and incomplete v2.0.1: (26 July 2012) - small fixes for problems reported by Chris Arndt (scoping, preprocessor, and include) diff --git a/readme b/readme index 69f095b0..4d56ed58 100644 --- a/readme +++ b/readme @@ -1,4 +1,4 @@ -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 & Kernel Streaming). +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. From 290db6cd3ead705fd117a72d589426d22ba23f8e Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Sun, 30 Mar 2014 13:02:08 -0400 Subject: [PATCH 002/388] Deleted include directory with kernel streaming files. --- include/ks.h | 3577 --------------------------------- include/ksmedia.h | 4824 --------------------------------------------- 2 files changed, 8401 deletions(-) delete mode 100644 include/ks.h delete mode 100644 include/ksmedia.h diff --git a/include/ks.h b/include/ks.h deleted file mode 100644 index 1f8b8b45..00000000 --- a/include/ks.h +++ /dev/null @@ -1,3577 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the w64 mingw-runtime package. - * No warranty is given. - */ -#ifndef _KS_ -#define _KS_ - -#include - -#if __GNUC__ >= 3 - # pragma GCC system_header -#endif - -#ifndef __MINGW_EXTENSION - # if defined(__GNUC__) || defined(__GNUG__) - # define __MINGW_EXTENSION __extension__ - # else - # define __MINGW_EXTENSION - # endif -#endif - -#ifdef __TCS__ - # define _KS_NO_ANONYMOUS_STRUCTURES_ 1 -#endif - -#ifdef _KS_NO_ANONYMOUS_STRUCTURES_ - # define _KS_ANON_STRUCT(X) struct X -#else - # define _KS_ANON_STRUCT(X) __MINGW_EXTENSION struct -#endif - -#ifndef _NTRTL_ - # ifndef DEFINE_GUIDEX - # define DEFINE_GUIDEX(name) EXTERN_C const GUID name - # endif - # ifndef STATICGUIDOF - # define STATICGUIDOF(guid) STATIC_ ## guid - # endif -#endif /* _NTRTL_ */ - -#ifndef SIZEOF_ARRAY - # define SIZEOF_ARRAY(ar) (sizeof(ar) / sizeof((ar)[0])) -#endif - -#define DEFINE_GUIDSTRUCT(g, n) DEFINE_GUIDEX(n) -#define DEFINE_GUIDNAMED(n) n - -#define STATIC_GUID_NULL \ - 0x00000000L, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - -DEFINE_GUIDSTRUCT("00000000-0000-0000-0000-000000000000", GUID_NULL); -#define GUID_NULL DEFINE_GUIDNAMED(GUID_NULL) - -#define IOCTL_KS_PROPERTY CTL_CODE(FILE_DEVICE_KS, 0x000, METHOD_NEITHER, FILE_ANY_ACCESS) -#define IOCTL_KS_ENABLE_EVENT CTL_CODE(FILE_DEVICE_KS, 0x001, METHOD_NEITHER, FILE_ANY_ACCESS) -#define IOCTL_KS_DISABLE_EVENT CTL_CODE(FILE_DEVICE_KS, 0x002, METHOD_NEITHER, FILE_ANY_ACCESS) -#define IOCTL_KS_METHOD CTL_CODE(FILE_DEVICE_KS, 0x003, METHOD_NEITHER, FILE_ANY_ACCESS) -#define IOCTL_KS_WRITE_STREAM CTL_CODE(FILE_DEVICE_KS, 0x004, METHOD_NEITHER, FILE_WRITE_ACCESS) -#define IOCTL_KS_READ_STREAM CTL_CODE(FILE_DEVICE_KS, 0x005, METHOD_NEITHER, FILE_READ_ACCESS) -#define IOCTL_KS_RESET_STATE CTL_CODE(FILE_DEVICE_KS, 0x006, METHOD_NEITHER, FILE_ANY_ACCESS) - -typedef enum -{ - KSRESET_BEGIN, - KSRESET_END -}KSRESET; - -typedef enum -{ - KSSTATE_STOP, - KSSTATE_ACQUIRE, - KSSTATE_PAUSE, - KSSTATE_RUN -}KSSTATE, * PKSSTATE; - -#define KSPRIORITY_LOW 0x00000001 -#define KSPRIORITY_NORMAL 0x40000000 -#define KSPRIORITY_HIGH 0x80000000 -#define KSPRIORITY_EXCLUSIVE 0xFFFFFFFF - -typedef struct -{ - ULONG PriorityClass; - ULONG PrioritySubClass; -}KSPRIORITY, * PKSPRIORITY; - -typedef struct -{ - __MINGW_EXTENSION union - { - _KS_ANON_STRUCT(_IDENTIFIER) - { - GUID Set; - ULONG Id; - ULONG Flags; - }; - LONGLONG Alignment; - }; -}KSIDENTIFIER, * PKSIDENTIFIER; - -typedef KSIDENTIFIER KSPROPERTY, * PKSPROPERTY, KSMETHOD, * PKSMETHOD, KSEVENT, * PKSEVENT; - -#define KSMETHOD_TYPE_NONE 0x00000000 -#define KSMETHOD_TYPE_READ 0x00000001 -#define KSMETHOD_TYPE_WRITE 0x00000002 -#define KSMETHOD_TYPE_MODIFY 0x00000003 -#define KSMETHOD_TYPE_SOURCE 0x00000004 - -#define KSMETHOD_TYPE_SEND 0x00000001 -#define KSMETHOD_TYPE_SETSUPPORT 0x00000100 -#define KSMETHOD_TYPE_BASICSUPPORT 0x00000200 - -#define KSMETHOD_TYPE_TOPOLOGY 0x10000000 - -#define KSPROPERTY_TYPE_GET 0x00000001 -#define KSPROPERTY_TYPE_SET 0x00000002 -#define KSPROPERTY_TYPE_SETSUPPORT 0x00000100 -#define KSPROPERTY_TYPE_BASICSUPPORT 0x00000200 -#define KSPROPERTY_TYPE_RELATIONS 0x00000400 -#define KSPROPERTY_TYPE_SERIALIZESET 0x00000800 -#define KSPROPERTY_TYPE_UNSERIALIZESET 0x00001000 -#define KSPROPERTY_TYPE_SERIALIZERAW 0x00002000 -#define KSPROPERTY_TYPE_UNSERIALIZERAW 0x00004000 -#define KSPROPERTY_TYPE_SERIALIZESIZE 0x00008000 -#define KSPROPERTY_TYPE_DEFAULTVALUES 0x00010000 - -#define KSPROPERTY_TYPE_TOPOLOGY 0x10000000 - -typedef struct -{ - KSPROPERTY Property; - ULONG NodeId; - ULONG Reserved; -}KSP_NODE, * PKSP_NODE; - -typedef struct -{ - KSMETHOD Method; - ULONG NodeId; - ULONG Reserved; -}KSM_NODE, * PKSM_NODE; - -typedef struct -{ - KSEVENT Event; - ULONG NodeId; - ULONG Reserved; -}KSE_NODE, * PKSE_NODE; - -#define STATIC_KSPROPTYPESETID_General \ - 0x97E99BA0L, 0xBDEA, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("97E99BA0-BDEA-11CF-A5D6-28DB04C10000", KSPROPTYPESETID_General); -#define KSPROPTYPESETID_General DEFINE_GUIDNAMED(KSPROPTYPESETID_General) - -typedef struct -{ - ULONG Size; - ULONG Count; -}KSMULTIPLE_ITEM, * PKSMULTIPLE_ITEM; - -typedef struct -{ - ULONG AccessFlags; - ULONG DescriptionSize; - KSIDENTIFIER PropTypeSet; - ULONG MembersListCount; - ULONG Reserved; -}KSPROPERTY_DESCRIPTION, * PKSPROPERTY_DESCRIPTION; - -#define KSPROPERTY_MEMBER_RANGES 0x00000001 -#define KSPROPERTY_MEMBER_STEPPEDRANGES 0x00000002 -#define KSPROPERTY_MEMBER_VALUES 0x00000003 - -#define KSPROPERTY_MEMBER_FLAG_DEFAULT 0x00000001 -#define KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL 0x00000002 -#define KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM 0x00000004 - -typedef struct -{ - ULONG MembersFlags; - ULONG MembersSize; - ULONG MembersCount; - ULONG Flags; -}KSPROPERTY_MEMBERSHEADER, * PKSPROPERTY_MEMBERSHEADER; - -typedef union -{ - _KS_ANON_STRUCT(_SIGNED) - { - LONG SignedMinimum; - LONG SignedMaximum; - }; - _KS_ANON_STRUCT(_UNSIGNED) - { - ULONG UnsignedMinimum; - ULONG UnsignedMaximum; - }; -}KSPROPERTY_BOUNDS_LONG, * PKSPROPERTY_BOUNDS_LONG; - -typedef union -{ - _KS_ANON_STRUCT(_SIGNED64) - { - LONGLONG SignedMinimum; - LONGLONG SignedMaximum; - }; - _KS_ANON_STRUCT(_UNSIGNED64) - { - DWORDLONG UnsignedMinimum; - DWORDLONG UnsignedMaximum; - }; -}KSPROPERTY_BOUNDS_LONGLONG, * PKSPROPERTY_BOUNDS_LONGLONG; - -typedef struct -{ - ULONG SteppingDelta; - ULONG Reserved; - KSPROPERTY_BOUNDS_LONG Bounds; -}KSPROPERTY_STEPPING_LONG, * PKSPROPERTY_STEPPING_LONG; - -typedef struct -{ - DWORDLONG SteppingDelta; - KSPROPERTY_BOUNDS_LONGLONG Bounds; -}KSPROPERTY_STEPPING_LONGLONG, * PKSPROPERTY_STEPPING_LONGLONG; - -#if defined(_NTDDK_) -typedef struct _KSDEVICE_DESCRIPTOR KSDEVICE_DESCRIPTOR, * PKSDEVICE_DESCRIPTOR; -typedef struct _KSDEVICE_DISPATCH KSDEVICE_DISPATCH, * PKSDEVICE_DISPATCH; -typedef struct _KSDEVICE KSDEVICE, * PKSDEVICE; -typedef struct _KSFILTERFACTORY KSFILTERFACTORY, * PKSFILTERFACTORY; -typedef struct _KSFILTER_DESCRIPTOR KSFILTER_DESCRIPTOR, * PKSFILTER_DESCRIPTOR; -typedef struct _KSFILTER_DISPATCH KSFILTER_DISPATCH, * PKSFILTER_DISPATCH; -typedef struct _KSFILTER KSFILTER, * PKSFILTER; -typedef struct _KSPIN_DESCRIPTOR_EX KSPIN_DESCRIPTOR_EX, * PKSPIN_DESCRIPTOR_EX; -typedef struct _KSPIN_DISPATCH KSPIN_DISPATCH, * PKSPIN_DISPATCH; -typedef struct _KSCLOCK_DISPATCH KSCLOCK_DISPATCH, * PKSCLOCK_DISPATCH; -typedef struct _KSALLOCATOR_DISPATCH KSALLOCATOR_DISPATCH, * PKSALLOCATOR_DISPATCH; -typedef struct _KSPIN KSPIN, * PKSPIN; -typedef struct _KSNODE_DESCRIPTOR KSNODE_DESCRIPTOR, * PKSNODE_DESCRIPTOR; -typedef struct _KSSTREAM_POINTER_OFFSET KSSTREAM_POINTER_OFFSET, * PKSSTREAM_POINTER_OFFSET; -typedef struct _KSSTREAM_POINTER KSSTREAM_POINTER, * PKSSTREAM_POINTER; -typedef struct _KSMAPPING KSMAPPING, * PKSMAPPING; -typedef struct _KSPROCESSPIN KSPROCESSPIN, * PKSPROCESSPIN; -typedef struct _KSPROCESSPIN_INDEXENTRY KSPROCESSPIN_INDEXENTRY, * PKSPROCESSPIN_INDEXENTRY; -#endif /* _NTDDK_ */ - -typedef PVOID PKSWORKER; - -typedef struct -{ - ULONG NotificationType; - __MINGW_EXTENSION union - { - struct - { - HANDLE Event; - ULONG_PTR Reserved[2]; - }EventHandle; - struct - { - HANDLE Semaphore; - ULONG Reserved; - LONG Adjustment; - }SemaphoreHandle; -#if defined(_NTDDK_) - struct - { - PVOID Event; - KPRIORITY Increment; - ULONG_PTR Reserved; - }EventObject; - struct - { - PVOID Semaphore; - KPRIORITY Increment; - LONG Adjustment; - }SemaphoreObject; - struct - { - PKDPC Dpc; - ULONG ReferenceCount; - ULONG_PTR Reserved; - }Dpc; - struct - { - PWORK_QUEUE_ITEM WorkQueueItem; - WORK_QUEUE_TYPE WorkQueueType; - ULONG_PTR Reserved; - }WorkItem; - struct - { - PWORK_QUEUE_ITEM WorkQueueItem; - PKSWORKER KsWorkerObject; - ULONG_PTR Reserved; - }KsWorkItem; -#endif /* _NTDDK_ */ - struct - { - PVOID Unused; - LONG_PTR Alignment[2]; - }Alignment; - }; -}KSEVENTDATA, * PKSEVENTDATA; - -#define KSEVENTF_EVENT_HANDLE 0x00000001 -#define KSEVENTF_SEMAPHORE_HANDLE 0x00000002 -#if defined(_NTDDK_) - # define KSEVENTF_EVENT_OBJECT 0x00000004 - # define KSEVENTF_SEMAPHORE_OBJECT 0x00000008 - # define KSEVENTF_DPC 0x00000010 - # define KSEVENTF_WORKITEM 0x00000020 - # define KSEVENTF_KSWORKITEM 0x00000080 -#endif /* _NTDDK_ */ - -#define KSEVENT_TYPE_ENABLE 0x00000001 -#define KSEVENT_TYPE_ONESHOT 0x00000002 -#define KSEVENT_TYPE_ENABLEBUFFERED 0x00000004 -#define KSEVENT_TYPE_SETSUPPORT 0x00000100 -#define KSEVENT_TYPE_BASICSUPPORT 0x00000200 -#define KSEVENT_TYPE_QUERYBUFFER 0x00000400 - -#define KSEVENT_TYPE_TOPOLOGY 0x10000000 - -typedef struct -{ - KSEVENT Event; - PKSEVENTDATA EventData; - PVOID Reserved; -}KSQUERYBUFFER, * PKSQUERYBUFFER; - -typedef struct -{ - ULONG Size; - ULONG Flags; - __MINGW_EXTENSION union - { - HANDLE ObjectHandle; - PVOID ObjectPointer; - }; - PVOID Reserved; - KSEVENT Event; - KSEVENTDATA EventData; -}KSRELATIVEEVENT; - -#define KSRELATIVEEVENT_FLAG_HANDLE 0x00000001 -#define KSRELATIVEEVENT_FLAG_POINTER 0x00000002 - -typedef struct -{ - KSEVENTDATA EventData; - LONGLONG MarkTime; -}KSEVENT_TIME_MARK, * PKSEVENT_TIME_MARK; - -typedef struct -{ - KSEVENTDATA EventData; - LONGLONG TimeBase; - LONGLONG Interval; -}KSEVENT_TIME_INTERVAL, * PKSEVENT_TIME_INTERVAL; - -typedef struct -{ - LONGLONG TimeBase; - LONGLONG Interval; -}KSINTERVAL, * PKSINTERVAL; - -#define STATIC_KSPROPSETID_General \ - 0x1464EDA5L, 0x6A8F, 0x11D1, 0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("1464EDA5-6A8F-11D1-9AA7-00A0C9223196", KSPROPSETID_General); -#define KSPROPSETID_General DEFINE_GUIDNAMED(KSPROPSETID_General) - -typedef enum -{ - KSPROPERTY_GENERAL_COMPONENTID -}KSPROPERTY_GENERAL; - -typedef struct -{ - GUID Manufacturer; - GUID Product; - GUID Component; - GUID Name; - ULONG Version; - ULONG Revision; -}KSCOMPONENTID, * PKSCOMPONENTID; - -#define DEFINE_KSPROPERTY_ITEM_GENERAL_COMPONENTID(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_GENERAL_COMPONENTID, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSCOMPONENTID), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define STATIC_KSMETHODSETID_StreamIo \ - 0x65D003CAL, 0x1523, 0x11D2, 0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("65D003CA-1523-11D2-B27A-00A0C9223196", KSMETHODSETID_StreamIo); -#define KSMETHODSETID_StreamIo DEFINE_GUIDNAMED(KSMETHODSETID_StreamIo) - -typedef enum -{ - KSMETHOD_STREAMIO_READ, - KSMETHOD_STREAMIO_WRITE -}KSMETHOD_STREAMIO; - -#define DEFINE_KSMETHOD_ITEM_STREAMIO_READ(Handler) \ - DEFINE_KSMETHOD_ITEM( \ - KSMETHOD_STREAMIO_READ, \ - KSMETHOD_TYPE_WRITE, \ - (Handler), \ - sizeof(KSMETHOD), \ - 0, \ - NULL) - -#define DEFINE_KSMETHOD_ITEM_STREAMIO_WRITE(Handler) \ - DEFINE_KSMETHOD_ITEM( \ - KSMETHOD_STREAMIO_WRITE, \ - KSMETHOD_TYPE_READ, \ - (Handler), \ - sizeof(KSMETHOD), \ - 0, \ - NULL) - -#define STATIC_KSPROPSETID_MediaSeeking \ - 0xEE904F0CL, 0xD09B, 0x11D0, 0xAB, 0xE9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("EE904F0C-D09B-11D0-ABE9-00A0C9223196", KSPROPSETID_MediaSeeking); -#define KSPROPSETID_MediaSeeking DEFINE_GUIDNAMED(KSPROPSETID_MediaSeeking) - -typedef enum -{ - KSPROPERTY_MEDIASEEKING_CAPABILITIES, - KSPROPERTY_MEDIASEEKING_FORMATS, - KSPROPERTY_MEDIASEEKING_TIMEFORMAT, - KSPROPERTY_MEDIASEEKING_POSITION, - KSPROPERTY_MEDIASEEKING_STOPPOSITION, - KSPROPERTY_MEDIASEEKING_POSITIONS, - KSPROPERTY_MEDIASEEKING_DURATION, - KSPROPERTY_MEDIASEEKING_AVAILABLE, - KSPROPERTY_MEDIASEEKING_PREROLL, - KSPROPERTY_MEDIASEEKING_CONVERTTIMEFORMAT -}KSPROPERTY_MEDIASEEKING; - -typedef enum -{ - KS_SEEKING_NoPositioning, - KS_SEEKING_AbsolutePositioning, - KS_SEEKING_RelativePositioning, - KS_SEEKING_IncrementalPositioning, - KS_SEEKING_PositioningBitsMask = 0x3, - KS_SEEKING_SeekToKeyFrame, - KS_SEEKING_ReturnTime = 0x8 -}KS_SEEKING_FLAGS; - -typedef enum -{ - KS_SEEKING_CanSeekAbsolute = 0x1, - KS_SEEKING_CanSeekForwards = 0x2, - KS_SEEKING_CanSeekBackwards = 0x4, - KS_SEEKING_CanGetCurrentPos = 0x8, - KS_SEEKING_CanGetStopPos = 0x10, - KS_SEEKING_CanGetDuration = 0x20, - KS_SEEKING_CanPlayBackwards = 0x40 -}KS_SEEKING_CAPABILITIES; - -typedef struct -{ - LONGLONG Current; - LONGLONG Stop; - KS_SEEKING_FLAGS CurrentFlags; - KS_SEEKING_FLAGS StopFlags; -}KSPROPERTY_POSITIONS, * PKSPROPERTY_POSITIONS; - -typedef struct -{ - LONGLONG Earliest; - LONGLONG Latest; -}KSPROPERTY_MEDIAAVAILABLE, * PKSPROPERTY_MEDIAAVAILABLE; - -typedef struct -{ - KSPROPERTY Property; - GUID SourceFormat; - GUID TargetFormat; - LONGLONG Time; -}KSP_TIMEFORMAT, * PKSP_TIMEFORMAT; - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_CAPABILITIES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_CAPABILITIES, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KS_SEEKING_CAPABILITIES), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_FORMATS(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_FORMATS, \ - (Handler), \ - sizeof(KSPROPERTY), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_TIMEFORMAT(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_TIMEFORMAT, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(GUID), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_POSITION(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_POSITION, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(LONGLONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_STOPPOSITION(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_STOPPOSITION, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(LONGLONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_POSITIONS(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_POSITIONS, \ - NULL, \ - sizeof(KSPROPERTY), \ - sizeof(KSPROPERTY_POSITIONS), \ - (Handler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_DURATION(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_DURATION, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(LONGLONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_AVAILABLE(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_AVAILABLE, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSPROPERTY_MEDIAAVAILABLE), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_PREROLL(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_PREROLL, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(LONGLONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_CONVERTTIMEFORMAT(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_CONVERTTIMEFORMAT, \ - (Handler), \ - sizeof(KSP_TIMEFORMAT), \ - sizeof(LONGLONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define STATIC_KSPROPSETID_Topology \ - 0x720D4AC0L, 0x7533, 0x11D0, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 } -DEFINE_GUIDSTRUCT("720D4AC0-7533-11D0-A5D6-28DB04C10000", KSPROPSETID_Topology); -#define KSPROPSETID_Topology DEFINE_GUIDNAMED(KSPROPSETID_Topology) - -typedef enum -{ - KSPROPERTY_TOPOLOGY_CATEGORIES, - KSPROPERTY_TOPOLOGY_NODES, - KSPROPERTY_TOPOLOGY_CONNECTIONS, - KSPROPERTY_TOPOLOGY_NAME -}KSPROPERTY_TOPOLOGY; - -#define DEFINE_KSPROPERTY_ITEM_TOPOLOGY_CATEGORIES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_TOPOLOGY_CATEGORIES, \ - (Handler), \ - sizeof(KSPROPERTY), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_TOPOLOGY_NODES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_TOPOLOGY_NODES, \ - (Handler), \ - sizeof(KSPROPERTY), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_TOPOLOGY_CONNECTIONS(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_TOPOLOGY_CONNECTIONS, \ - (Handler), \ - sizeof(KSPROPERTY), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_TOPOLOGY_NAME(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_TOPOLOGY_NAME, \ - (Handler), \ - sizeof(KSP_NODE), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_TOPOLOGYSET(TopologySet, Handler) \ - DEFINE_KSPROPERTY_TABLE(TopologySet) { \ - DEFINE_KSPROPERTY_ITEM_TOPOLOGY_CATEGORIES(Handler), \ - DEFINE_KSPROPERTY_ITEM_TOPOLOGY_NODES(Handler), \ - DEFINE_KSPROPERTY_ITEM_TOPOLOGY_CONNECTIONS(Handler), \ - DEFINE_KSPROPERTY_ITEM_TOPOLOGY_NAME(Handler) \ - } - -#define STATIC_KSCATEGORY_BRIDGE \ - 0x085AFF00L, 0x62CE, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("085AFF00-62CE-11CF-A5D6-28DB04C10000", KSCATEGORY_BRIDGE); -#define KSCATEGORY_BRIDGE DEFINE_GUIDNAMED(KSCATEGORY_BRIDGE) - -#define STATIC_KSCATEGORY_CAPTURE \ - 0x65E8773DL, 0x8F56, 0x11D0, { 0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 } -DEFINE_GUIDSTRUCT("65E8773D-8F56-11D0-A3B9-00A0C9223196", KSCATEGORY_CAPTURE); -#define KSCATEGORY_CAPTURE DEFINE_GUIDNAMED(KSCATEGORY_CAPTURE) - -#define STATIC_KSCATEGORY_RENDER \ - 0x65E8773EL, 0x8F56, 0x11D0, { 0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 } -DEFINE_GUIDSTRUCT("65E8773E-8F56-11D0-A3B9-00A0C9223196", KSCATEGORY_RENDER); -#define KSCATEGORY_RENDER DEFINE_GUIDNAMED(KSCATEGORY_RENDER) - -#define STATIC_KSCATEGORY_MIXER \ - 0xAD809C00L, 0x7B88, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("AD809C00-7B88-11D0-A5D6-28DB04C10000", KSCATEGORY_MIXER); -#define KSCATEGORY_MIXER DEFINE_GUIDNAMED(KSCATEGORY_MIXER) - -#define STATIC_KSCATEGORY_SPLITTER \ - 0x0A4252A0L, 0x7E70, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("0A4252A0-7E70-11D0-A5D6-28DB04C10000", KSCATEGORY_SPLITTER); -#define KSCATEGORY_SPLITTER DEFINE_GUIDNAMED(KSCATEGORY_SPLITTER) - -#define STATIC_KSCATEGORY_DATACOMPRESSOR \ - 0x1E84C900L, 0x7E70, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("1E84C900-7E70-11D0-A5D6-28DB04C10000", KSCATEGORY_DATACOMPRESSOR); -#define KSCATEGORY_DATACOMPRESSOR DEFINE_GUIDNAMED(KSCATEGORY_DATACOMPRESSOR) - -#define STATIC_KSCATEGORY_DATADECOMPRESSOR \ - 0x2721AE20L, 0x7E70, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("2721AE20-7E70-11D0-A5D6-28DB04C10000", KSCATEGORY_DATADECOMPRESSOR); -#define KSCATEGORY_DATADECOMPRESSOR DEFINE_GUIDNAMED(KSCATEGORY_DATADECOMPRESSOR) - -#define STATIC_KSCATEGORY_DATATRANSFORM \ - 0x2EB07EA0L, 0x7E70, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("2EB07EA0-7E70-11D0-A5D6-28DB04C10000", KSCATEGORY_DATATRANSFORM); -#define KSCATEGORY_DATATRANSFORM DEFINE_GUIDNAMED(KSCATEGORY_DATATRANSFORM) - -#define STATIC_KSCATEGORY_COMMUNICATIONSTRANSFORM \ - 0xCF1DDA2CL, 0x9743, 0x11D0, 0xA3, 0xEE, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("CF1DDA2C-9743-11D0-A3EE-00A0C9223196", KSCATEGORY_COMMUNICATIONSTRANSFORM); -#define KSCATEGORY_COMMUNICATIONSTRANSFORM DEFINE_GUIDNAMED(KSCATEGORY_COMMUNICATIONSTRANSFORM) - -#define STATIC_KSCATEGORY_INTERFACETRANSFORM \ - 0xCF1DDA2DL, 0x9743, 0x11D0, 0xA3, 0xEE, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("CF1DDA2D-9743-11D0-A3EE-00A0C9223196", KSCATEGORY_INTERFACETRANSFORM); -#define KSCATEGORY_INTERFACETRANSFORM DEFINE_GUIDNAMED(KSCATEGORY_INTERFACETRANSFORM) - -#define STATIC_KSCATEGORY_MEDIUMTRANSFORM \ - 0xCF1DDA2EL, 0x9743, 0x11D0, 0xA3, 0xEE, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("CF1DDA2E-9743-11D0-A3EE-00A0C9223196", KSCATEGORY_MEDIUMTRANSFORM); -#define KSCATEGORY_MEDIUMTRANSFORM DEFINE_GUIDNAMED(KSCATEGORY_MEDIUMTRANSFORM) - -#define STATIC_KSCATEGORY_FILESYSTEM \ - 0x760FED5EL, 0x9357, 0x11D0, 0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("760FED5E-9357-11D0-A3CC-00A0C9223196", KSCATEGORY_FILESYSTEM); -#define KSCATEGORY_FILESYSTEM DEFINE_GUIDNAMED(KSCATEGORY_FILESYSTEM) - -#define STATIC_KSCATEGORY_CLOCK \ - 0x53172480L, 0x4791, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("53172480-4791-11D0-A5D6-28DB04C10000", KSCATEGORY_CLOCK); -#define KSCATEGORY_CLOCK DEFINE_GUIDNAMED(KSCATEGORY_CLOCK) - -#define STATIC_KSCATEGORY_PROXY \ - 0x97EBAACAL, 0x95BD, 0x11D0, 0xA3, 0xEA, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("97EBAACA-95BD-11D0-A3EA-00A0C9223196", KSCATEGORY_PROXY); -#define KSCATEGORY_PROXY DEFINE_GUIDNAMED(KSCATEGORY_PROXY) - -#define STATIC_KSCATEGORY_QUALITY \ - 0x97EBAACBL, 0x95BD, 0x11D0, 0xA3, 0xEA, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("97EBAACB-95BD-11D0-A3EA-00A0C9223196", KSCATEGORY_QUALITY); -#define KSCATEGORY_QUALITY DEFINE_GUIDNAMED(KSCATEGORY_QUALITY) - -typedef struct -{ - ULONG FromNode; - ULONG FromNodePin; - ULONG ToNode; - ULONG ToNodePin; -}KSTOPOLOGY_CONNECTION, * PKSTOPOLOGY_CONNECTION; - -typedef struct -{ - ULONG CategoriesCount; - const GUID* Categories; - ULONG TopologyNodesCount; - const GUID* TopologyNodes; - ULONG TopologyConnectionsCount; - const KSTOPOLOGY_CONNECTION* TopologyConnections; - const GUID* TopologyNodesNames; - ULONG Reserved; -}KSTOPOLOGY, * PKSTOPOLOGY; - -#define KSFILTER_NODE ((ULONG)-1) -#define KSALL_NODES ((ULONG)-1) - -typedef struct -{ - ULONG CreateFlags; - ULONG Node; -}KSNODE_CREATE, * PKSNODE_CREATE; - -#define STATIC_KSTIME_FORMAT_NONE STATIC_GUID_NULL -#define KSTIME_FORMAT_NONE GUID_NULL - -#define STATIC_KSTIME_FORMAT_FRAME \ - 0x7b785570L, 0x8c82, 0x11cf, 0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6 -DEFINE_GUIDSTRUCT("7b785570-8c82-11cf-bc0c-00aa00ac74f6", KSTIME_FORMAT_FRAME); -#define KSTIME_FORMAT_FRAME DEFINE_GUIDNAMED(KSTIME_FORMAT_FRAME) - -#define STATIC_KSTIME_FORMAT_BYTE \ - 0x7b785571L, 0x8c82, 0x11cf, 0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6 -DEFINE_GUIDSTRUCT("7b785571-8c82-11cf-bc0c-00aa00ac74f6", KSTIME_FORMAT_BYTE); -#define KSTIME_FORMAT_BYTE DEFINE_GUIDNAMED(KSTIME_FORMAT_BYTE) - -#define STATIC_KSTIME_FORMAT_SAMPLE \ - 0x7b785572L, 0x8c82, 0x11cf, 0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6 -DEFINE_GUIDSTRUCT("7b785572-8c82-11cf-bc0c-00aa00ac74f6", KSTIME_FORMAT_SAMPLE); -#define KSTIME_FORMAT_SAMPLE DEFINE_GUIDNAMED(KSTIME_FORMAT_SAMPLE) - -#define STATIC_KSTIME_FORMAT_FIELD \ - 0x7b785573L, 0x8c82, 0x11cf, 0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6 -DEFINE_GUIDSTRUCT("7b785573-8c82-11cf-bc0c-00aa00ac74f6", KSTIME_FORMAT_FIELD); -#define KSTIME_FORMAT_FIELD DEFINE_GUIDNAMED(KSTIME_FORMAT_FIELD) - -#define STATIC_KSTIME_FORMAT_MEDIA_TIME \ - 0x7b785574L, 0x8c82, 0x11cf, 0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6 -DEFINE_GUIDSTRUCT("7b785574-8c82-11cf-bc0c-00aa00ac74f6", KSTIME_FORMAT_MEDIA_TIME); -#define KSTIME_FORMAT_MEDIA_TIME DEFINE_GUIDNAMED(KSTIME_FORMAT_MEDIA_TIME) - -typedef KSIDENTIFIER KSPIN_INTERFACE, * PKSPIN_INTERFACE; - -#define STATIC_KSINTERFACESETID_Standard \ - 0x1A8766A0L, 0x62CE, 0x11CF, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 } -DEFINE_GUIDSTRUCT("1A8766A0-62CE-11CF-A5D6-28DB04C10000", KSINTERFACESETID_Standard); -#define KSINTERFACESETID_Standard DEFINE_GUIDNAMED(KSINTERFACESETID_Standard) - -typedef enum -{ - KSINTERFACE_STANDARD_STREAMING, - KSINTERFACE_STANDARD_LOOPED_STREAMING, - KSINTERFACE_STANDARD_CONTROL -}KSINTERFACE_STANDARD; - -#define STATIC_KSINTERFACESETID_FileIo \ - 0x8C6F932CL, 0xE771, 0x11D0, 0xB8, 0xFF, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("8C6F932C-E771-11D0-B8FF-00A0C9223196", KSINTERFACESETID_FileIo); -#define KSINTERFACESETID_FileIo DEFINE_GUIDNAMED(KSINTERFACESETID_FileIo) - -typedef enum -{ - KSINTERFACE_FILEIO_STREAMING -}KSINTERFACE_FILEIO; - -#define KSMEDIUM_TYPE_ANYINSTANCE 0 - -#define STATIC_KSMEDIUMSETID_Standard \ - 0x4747B320L, 0x62CE, 0x11CF, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 } -DEFINE_GUIDSTRUCT("4747B320-62CE-11CF-A5D6-28DB04C10000", KSMEDIUMSETID_Standard); -#define KSMEDIUMSETID_Standard DEFINE_GUIDNAMED(KSMEDIUMSETID_Standard) - -#define KSMEDIUM_STANDARD_DEVIO KSMEDIUM_TYPE_ANYINSTANCE - -#define STATIC_KSPROPSETID_Pin \ - 0x8C134960L, 0x51AD, 0x11CF, { 0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00 } -DEFINE_GUIDSTRUCT("8C134960-51AD-11CF-878A-94F801C10000", KSPROPSETID_Pin); -#define KSPROPSETID_Pin DEFINE_GUIDNAMED(KSPROPSETID_Pin) - -typedef enum -{ - KSPROPERTY_PIN_CINSTANCES, - KSPROPERTY_PIN_CTYPES, - KSPROPERTY_PIN_DATAFLOW, - KSPROPERTY_PIN_DATARANGES, - KSPROPERTY_PIN_DATAINTERSECTION, - KSPROPERTY_PIN_INTERFACES, - KSPROPERTY_PIN_MEDIUMS, - KSPROPERTY_PIN_COMMUNICATION, - KSPROPERTY_PIN_GLOBALCINSTANCES, - KSPROPERTY_PIN_NECESSARYINSTANCES, - KSPROPERTY_PIN_PHYSICALCONNECTION, - KSPROPERTY_PIN_CATEGORY, - KSPROPERTY_PIN_NAME, - KSPROPERTY_PIN_CONSTRAINEDDATARANGES, - KSPROPERTY_PIN_PROPOSEDATAFORMAT -}KSPROPERTY_PIN; - -typedef struct -{ - KSPROPERTY Property; - ULONG PinId; - ULONG Reserved; -}KSP_PIN, * PKSP_PIN; - -#define KSINSTANCE_INDETERMINATE ((ULONG)-1) - -typedef struct -{ - ULONG PossibleCount; - ULONG CurrentCount; -}KSPIN_CINSTANCES, * PKSPIN_CINSTANCES; - -typedef enum -{ - KSPIN_DATAFLOW_IN = 1, - KSPIN_DATAFLOW_OUT -}KSPIN_DATAFLOW, * PKSPIN_DATAFLOW; - -#define KSDATAFORMAT_BIT_TEMPORAL_COMPRESSION 0 -#define KSDATAFORMAT_TEMPORAL_COMPRESSION (1 << KSDATAFORMAT_BIT_TEMPORAL_COMPRESSION) -#define KSDATAFORMAT_BIT_ATTRIBUTES 1 -#define KSDATAFORMAT_ATTRIBUTES (1 << KSDATAFORMAT_BIT_ATTRIBUTES) - -#define KSDATARANGE_BIT_ATTRIBUTES 1 -#define KSDATARANGE_ATTRIBUTES (1 << KSDATARANGE_BIT_ATTRIBUTES) -#define KSDATARANGE_BIT_REQUIRED_ATTRIBUTES 2 -#define KSDATARANGE_REQUIRED_ATTRIBUTES (1 << KSDATARANGE_BIT_REQUIRED_ATTRIBUTES) - -typedef union -{ - __MINGW_EXTENSION struct - { - ULONG FormatSize; - ULONG Flags; - ULONG SampleSize; - ULONG Reserved; - GUID MajorFormat; - GUID SubFormat; - GUID Specifier; - }; - LONGLONG Alignment; -}KSDATAFORMAT, * PKSDATAFORMAT, KSDATARANGE, * PKSDATARANGE; - -#define KSATTRIBUTE_REQUIRED 0x00000001 - -typedef struct -{ - ULONG Size; - ULONG Flags; - GUID Attribute; -}KSATTRIBUTE, * PKSATTRIBUTE; - -#if defined(_NTDDK_) -typedef struct -{ - ULONG Count; - PKSATTRIBUTE* Attributes; -}KSATTRIBUTE_LIST, * PKSATTRIBUTE_LIST; -#endif /* _NTDDK_ */ - -typedef enum -{ - KSPIN_COMMUNICATION_NONE, - KSPIN_COMMUNICATION_SINK, - KSPIN_COMMUNICATION_SOURCE, - KSPIN_COMMUNICATION_BOTH, - KSPIN_COMMUNICATION_BRIDGE -}KSPIN_COMMUNICATION, * PKSPIN_COMMUNICATION; - -typedef KSIDENTIFIER KSPIN_MEDIUM, * PKSPIN_MEDIUM; - -typedef struct -{ - KSPIN_INTERFACE Interface; - KSPIN_MEDIUM Medium; - ULONG PinId; - HANDLE PinToHandle; - KSPRIORITY Priority; -}KSPIN_CONNECT, * PKSPIN_CONNECT; - -typedef struct -{ - ULONG Size; - ULONG Pin; - WCHAR SymbolicLinkName[1]; -}KSPIN_PHYSICALCONNECTION, * PKSPIN_PHYSICALCONNECTION; - -#if defined(_NTDDK_) -typedef NTSTATUS (*PFNKSINTERSECTHANDLER)(PIRP Irp, PKSP_PIN Pin, - PKSDATARANGE DataRange, - PVOID Data); -typedef NTSTATUS (*PFNKSINTERSECTHANDLEREX)(PVOID Context, PIRP Irp, - PKSP_PIN Pin, - PKSDATARANGE DataRange, - PKSDATARANGE MatchingDataRange, - ULONG DataBufferSize, - PVOID Data, - PULONG DataSize); -#endif /* _NTDDK_ */ - -#define DEFINE_KSPIN_INTERFACE_TABLE(tablename) \ - const KSPIN_INTERFACE tablename[] = - -#define DEFINE_KSPIN_INTERFACE_ITEM(guid, _interFace) \ - { \ - STATICGUIDOF(guid), \ - (_interFace), \ - 0 \ - } - -#define DEFINE_KSPIN_MEDIUM_TABLE(tablename) \ - const KSPIN_MEDIUM tablename[] = - -#define DEFINE_KSPIN_MEDIUM_ITEM(guid, medium) \ - DEFINE_KSPIN_INTERFACE_ITEM(guid, medium) - -#define DEFINE_KSPROPERTY_ITEM_PIN_CINSTANCES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_CINSTANCES, \ - (Handler), \ - sizeof(KSP_PIN), \ - sizeof(KSPIN_CINSTANCES), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_CTYPES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_CTYPES, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(ULONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_DATAFLOW(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_DATAFLOW, \ - (Handler), \ - sizeof(KSP_PIN), \ - sizeof(KSPIN_DATAFLOW), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_DATARANGES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_DATARANGES, \ - (Handler), \ - sizeof(KSP_PIN), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_DATAINTERSECTION(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_DATAINTERSECTION, \ - (Handler), \ - sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_INTERFACES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_INTERFACES, \ - (Handler), \ - sizeof(KSP_PIN), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_MEDIUMS(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_MEDIUMS, \ - (Handler), \ - sizeof(KSP_PIN), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_COMMUNICATION(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_COMMUNICATION, \ - (Handler), \ - sizeof(KSP_PIN), \ - sizeof(KSPIN_COMMUNICATION), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_GLOBALCINSTANCES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_GLOBALCINSTANCES, \ - (Handler), \ - sizeof(KSP_PIN), \ - sizeof(KSPIN_CINSTANCES), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_NECESSARYINSTANCES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_NECESSARYINSTANCES, \ - (Handler), \ - sizeof(KSP_PIN), \ - sizeof(ULONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_PHYSICALCONNECTION(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_PHYSICALCONNECTION, \ - (Handler), \ - sizeof(KSP_PIN), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_CATEGORY(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_CATEGORY, \ - (Handler), \ - sizeof(KSP_PIN), \ - sizeof(GUID), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_NAME(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_NAME, \ - (Handler), \ - sizeof(KSP_PIN), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_CONSTRAINEDDATARANGES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_CONSTRAINEDDATARANGES, \ - (Handler), \ - sizeof(KSP_PIN), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_PROPOSEDATAFORMAT(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_PROPOSEDATAFORMAT, \ - NULL, \ - sizeof(KSP_PIN), \ - sizeof(KSDATAFORMAT), \ - (Handler), NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_PINSET(PinSet, PropGeneral, PropInstances, PropIntersection) \ - DEFINE_KSPROPERTY_TABLE(PinSet) { \ - DEFINE_KSPROPERTY_ITEM_PIN_CINSTANCES(PropInstances), \ - DEFINE_KSPROPERTY_ITEM_PIN_CTYPES(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_DATAFLOW(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_DATARANGES(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_DATAINTERSECTION(PropIntersection), \ - DEFINE_KSPROPERTY_ITEM_PIN_INTERFACES(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_MEDIUMS(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_COMMUNICATION(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_CATEGORY(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_NAME(PropGeneral) \ - } - -#define DEFINE_KSPROPERTY_PINSETCONSTRAINED(PinSet, PropGeneral, PropInstances, PropIntersection) \ - DEFINE_KSPROPERTY_TABLE(PinSet) { \ - DEFINE_KSPROPERTY_ITEM_PIN_CINSTANCES(PropInstances), \ - DEFINE_KSPROPERTY_ITEM_PIN_CTYPES(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_DATAFLOW(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_DATARANGES(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_DATAINTERSECTION(PropIntersection), \ - DEFINE_KSPROPERTY_ITEM_PIN_INTERFACES(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_MEDIUMS(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_COMMUNICATION(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_CATEGORY(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_NAME(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_CONSTRAINEDDATARANGES(PropGeneral) \ - } - -#define STATIC_KSNAME_Filter \ - 0x9b365890L, 0x165f, 0x11d0, 0xa1, 0x95, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4 -DEFINE_GUIDSTRUCT("9b365890-165f-11d0-a195-0020afd156e4", KSNAME_Filter); -#define KSNAME_Filter DEFINE_GUIDNAMED(KSNAME_Filter) - -#define KSSTRING_Filter L"{9B365890-165F-11D0-A195-0020AFD156E4}" - -#define STATIC_KSNAME_Pin \ - 0x146F1A80L, 0x4791, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("146F1A80-4791-11D0-A5D6-28DB04C10000", KSNAME_Pin); -#define KSNAME_Pin DEFINE_GUIDNAMED(KSNAME_Pin) - -#define KSSTRING_Pin L"{146F1A80-4791-11D0-A5D6-28DB04C10000}" - -#define STATIC_KSNAME_Clock \ - 0x53172480L, 0x4791, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("53172480-4791-11D0-A5D6-28DB04C10000", KSNAME_Clock); -#define KSNAME_Clock DEFINE_GUIDNAMED(KSNAME_Clock) - -#define KSSTRING_Clock L"{53172480-4791-11D0-A5D6-28DB04C10000}" - -#define STATIC_KSNAME_Allocator \ - 0x642F5D00L, 0x4791, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("642F5D00-4791-11D0-A5D6-28DB04C10000", KSNAME_Allocator); -#define KSNAME_Allocator DEFINE_GUIDNAMED(KSNAME_Allocator) - -#define KSSTRING_Allocator L"{642F5D00-4791-11D0-A5D6-28DB04C10000}" - -#define KSSTRING_AllocatorEx L"{091BB63B-603F-11D1-B067-00A0C9062802}" - -#define STATIC_KSNAME_TopologyNode \ - 0x0621061AL, 0xEE75, 0x11D0, 0xB9, 0x15, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("0621061A-EE75-11D0-B915-00A0C9223196", KSNAME_TopologyNode); -#define KSNAME_TopologyNode DEFINE_GUIDNAMED(KSNAME_TopologyNode) - -#define KSSTRING_TopologyNode L"{0621061A-EE75-11D0-B915-00A0C9223196}" - -#if defined(_NTDDK_) -typedef struct -{ - ULONG InterfacesCount; - const KSPIN_INTERFACE* Interfaces; - ULONG MediumsCount; - const KSPIN_MEDIUM* Mediums; - ULONG DataRangesCount; - const PKSDATARANGE* DataRanges; - KSPIN_DATAFLOW DataFlow; - KSPIN_COMMUNICATION Communication; - const GUID* Category; - const GUID* Name; - __MINGW_EXTENSION union - { - LONGLONG Reserved; - __MINGW_EXTENSION struct - { - ULONG ConstrainedDataRangesCount; - PKSDATARANGE* ConstrainedDataRanges; - }; - }; -}KSPIN_DESCRIPTOR, * PKSPIN_DESCRIPTOR; -typedef const KSPIN_DESCRIPTOR* PCKSPIN_DESCRIPTOR; - - # define DEFINE_KSPIN_DESCRIPTOR_TABLE(tablename) \ - const KSPIN_DESCRIPTOR tablename[] = - - # define DEFINE_KSPIN_DESCRIPTOR_ITEM(InterfacesCount, Interfaces, MediumsCount, Mediums, DataRangesCount, DataRanges, DataFlow, Communication) \ - { \ - InterfacesCount, Interfaces, MediumsCount, Mediums, \ - DataRangesCount, DataRanges, DataFlow, Communication, \ - NULL, NULL, 0 \ - } - - # define DEFINE_KSPIN_DESCRIPTOR_ITEMEX(InterfacesCount, Interfaces, MediumsCount, Mediums, DataRangesCount, DataRanges, DataFlow, Communication, Category, Name) \ - { \ - InterfacesCount, Interfaces, MediumsCount, Mediums, \ - DataRangesCount, DataRanges, DataFlow, Communication, \ - Category, Name, 0 \ - } -#endif /* _NTDDK_ */ - -#define STATIC_KSDATAFORMAT_TYPE_WILDCARD STATIC_GUID_NULL -#define KSDATAFORMAT_TYPE_WILDCARD GUID_NULL - -#define STATIC_KSDATAFORMAT_SUBTYPE_WILDCARD STATIC_GUID_NULL -#define KSDATAFORMAT_SUBTYPE_WILDCARD GUID_NULL - -#define STATIC_KSDATAFORMAT_TYPE_STREAM \ - 0xE436EB83L, 0x524F, 0x11CE, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 -DEFINE_GUIDSTRUCT("E436EB83-524F-11CE-9F53-0020AF0BA770", KSDATAFORMAT_TYPE_STREAM); -#define KSDATAFORMAT_TYPE_STREAM DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_STREAM) - -#define STATIC_KSDATAFORMAT_SUBTYPE_NONE \ - 0xE436EB8EL, 0x524F, 0x11CE, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 -DEFINE_GUIDSTRUCT("E436EB8E-524F-11CE-9F53-0020AF0BA770", KSDATAFORMAT_SUBTYPE_NONE); -#define KSDATAFORMAT_SUBTYPE_NONE DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_NONE) - -#define STATIC_KSDATAFORMAT_SPECIFIER_WILDCARD STATIC_GUID_NULL -#define KSDATAFORMAT_SPECIFIER_WILDCARD GUID_NULL - -#define STATIC_KSDATAFORMAT_SPECIFIER_FILENAME \ - 0xAA797B40L, 0xE974, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("AA797B40-E974-11CF-A5D6-28DB04C10000", KSDATAFORMAT_SPECIFIER_FILENAME); -#define KSDATAFORMAT_SPECIFIER_FILENAME DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_FILENAME) - -#define STATIC_KSDATAFORMAT_SPECIFIER_FILEHANDLE \ - 0x65E8773CL, 0x8F56, 0x11D0, 0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("65E8773C-8F56-11D0-A3B9-00A0C9223196", KSDATAFORMAT_SPECIFIER_FILEHANDLE); -#define KSDATAFORMAT_SPECIFIER_FILEHANDLE DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_FILEHANDLE) - -#define STATIC_KSDATAFORMAT_SPECIFIER_NONE \ - 0x0F6417D6L, 0xC318, 0x11D0, { 0xA4, 0x3F, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 } -DEFINE_GUIDSTRUCT("0F6417D6-C318-11D0-A43F-00A0C9223196", KSDATAFORMAT_SPECIFIER_NONE); -#define KSDATAFORMAT_SPECIFIER_NONE DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_NONE) - -#define STATIC_KSPROPSETID_Quality \ - 0xD16AD380L, 0xAC1A, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("D16AD380-AC1A-11CF-A5D6-28DB04C10000", KSPROPSETID_Quality); -#define KSPROPSETID_Quality DEFINE_GUIDNAMED(KSPROPSETID_Quality) - -typedef enum -{ - KSPROPERTY_QUALITY_REPORT, - KSPROPERTY_QUALITY_ERROR -}KSPROPERTY_QUALITY; - -#define DEFINE_KSPROPERTY_ITEM_QUALITY_REPORT(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_QUALITY_REPORT, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(KSQUALITY), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_QUALITY_ERROR(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_QUALITY_ERROR, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(KSERROR), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define STATIC_KSPROPSETID_Connection \ - 0x1D58C920L, 0xAC9B, 0x11CF, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 } -DEFINE_GUIDSTRUCT("1D58C920-AC9B-11CF-A5D6-28DB04C10000", KSPROPSETID_Connection); -#define KSPROPSETID_Connection DEFINE_GUIDNAMED(KSPROPSETID_Connection) - -typedef enum -{ - KSPROPERTY_CONNECTION_STATE, - KSPROPERTY_CONNECTION_PRIORITY, - KSPROPERTY_CONNECTION_DATAFORMAT, - KSPROPERTY_CONNECTION_ALLOCATORFRAMING, - KSPROPERTY_CONNECTION_PROPOSEDATAFORMAT, - KSPROPERTY_CONNECTION_ACQUIREORDERING, - KSPROPERTY_CONNECTION_ALLOCATORFRAMING_EX, - KSPROPERTY_CONNECTION_STARTAT -}KSPROPERTY_CONNECTION; - -#define DEFINE_KSPROPERTY_ITEM_CONNECTION_STATE(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CONNECTION_STATE, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(KSSTATE), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_CONNECTION_PRIORITY(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CONNECTION_PRIORITY, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(KSPRIORITY), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_CONNECTION_DATAFORMAT(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CONNECTION_DATAFORMAT, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - 0, \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_CONNECTION_ALLOCATORFRAMING(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CONNECTION_ALLOCATORFRAMING, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSALLOCATOR_FRAMING), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_CONNECTION_ALLOCATORFRAMING_EX(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CONNECTION_ALLOCATORFRAMING_EX, \ - (Handler), \ - sizeof(KSPROPERTY), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_CONNECTION_PROPOSEDATAFORMAT(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CONNECTION_PROPOSEDATAFORMAT, \ - NULL, \ - sizeof(KSPROPERTY), \ - sizeof(KSDATAFORMAT), \ - (Handler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_CONNECTION_ACQUIREORDERING(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CONNECTION_ACQUIREORDERING, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(int), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_CONNECTION_STARTAT(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CONNECTION_STARTAT, \ - NULL, \ - sizeof(KSPROPERTY), \ - sizeof(KSRELATIVEEVENT), \ - (Handler), \ - NULL, 0, NULL, NULL, 0) - -#define KSALLOCATOR_REQUIREMENTF_INPLACE_MODIFIER 0x00000001 -#define KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY 0x00000002 -#define KSALLOCATOR_REQUIREMENTF_FRAME_INTEGRITY 0x00000004 -#define KSALLOCATOR_REQUIREMENTF_MUST_ALLOCATE 0x00000008 -#define KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY 0x80000000 - -#define KSALLOCATOR_OPTIONF_COMPATIBLE 0x00000001 -#define KSALLOCATOR_OPTIONF_SYSTEM_MEMORY 0x00000002 -#define KSALLOCATOR_OPTIONF_VALID 0x00000003 - -#define KSALLOCATOR_FLAG_PARTIAL_READ_SUPPORT 0x00000010 -#define KSALLOCATOR_FLAG_DEVICE_SPECIFIC 0x00000020 -#define KSALLOCATOR_FLAG_CAN_ALLOCATE 0x00000040 -#define KSALLOCATOR_FLAG_INSIST_ON_FRAMESIZE_RATIO 0x00000080 -#define KSALLOCATOR_FLAG_NO_FRAME_INTEGRITY 0x00000100 -#define KSALLOCATOR_FLAG_MULTIPLE_OUTPUT 0x00000200 -#define KSALLOCATOR_FLAG_CYCLE 0x00000400 -#define KSALLOCATOR_FLAG_ALLOCATOR_EXISTS 0x00000800 -#define KSALLOCATOR_FLAG_INDEPENDENT_RANGES 0x00001000 -#define KSALLOCATOR_FLAG_ATTENTION_STEPPING 0x00002000 - -typedef struct -{ - __MINGW_EXTENSION union - { - ULONG OptionsFlags; - ULONG RequirementsFlags; - }; -#if defined(_NTDDK_) - POOL_TYPE PoolType; -#else - ULONG PoolType; -#endif /* _NTDDK_ */ - ULONG Frames; - ULONG FrameSize; - ULONG FileAlignment; - ULONG Reserved; -}KSALLOCATOR_FRAMING, * PKSALLOCATOR_FRAMING; - -#if defined(_NTDDK_) -typedef PVOID (*PFNKSDEFAULTALLOCATE)(PVOID Context); -typedef VOID (*PFNKSDEFAULTFREE)(PVOID Context, PVOID Buffer); -typedef NTSTATUS (*PFNKSINITIALIZEALLOCATOR)(PVOID InitialContext, - PKSALLOCATOR_FRAMING AllocatorFraming, - PVOID* Context); -typedef VOID (*PFNKSDELETEALLOCATOR)(PVOID Context); -#endif /* _NTDDK_ */ - -typedef struct -{ - ULONG MinFrameSize; - ULONG MaxFrameSize; - ULONG Stepping; -}KS_FRAMING_RANGE, * PKS_FRAMING_RANGE; - -typedef struct -{ - KS_FRAMING_RANGE Range; - ULONG InPlaceWeight; - ULONG NotInPlaceWeight; -}KS_FRAMING_RANGE_WEIGHTED, * PKS_FRAMING_RANGE_WEIGHTED; - -typedef struct -{ - ULONG RatioNumerator; - ULONG RatioDenominator; - ULONG RatioConstantMargin; -}KS_COMPRESSION, * PKS_COMPRESSION; - -typedef struct -{ - GUID MemoryType; - GUID BusType; - ULONG MemoryFlags; - ULONG BusFlags; - ULONG Flags; - ULONG Frames; - ULONG FileAlignment; - ULONG MemoryTypeWeight; - KS_FRAMING_RANGE PhysicalRange; - KS_FRAMING_RANGE_WEIGHTED FramingRange; -}KS_FRAMING_ITEM, * PKS_FRAMING_ITEM; - -typedef struct -{ - ULONG CountItems; - ULONG PinFlags; - KS_COMPRESSION OutputCompression; - ULONG PinWeight; - KS_FRAMING_ITEM FramingItem[1]; -}KSALLOCATOR_FRAMING_EX, * PKSALLOCATOR_FRAMING_EX; - -#define KSMEMORY_TYPE_WILDCARD GUID_NULL -#define STATIC_KSMEMORY_TYPE_WILDCARD STATIC_GUID_NULL - -#define KSMEMORY_TYPE_DONT_CARE GUID_NULL -#define STATIC_KSMEMORY_TYPE_DONT_CARE STATIC_GUID_NULL - -#define KS_TYPE_DONT_CARE GUID_NULL -#define STATIC_KS_TYPE_DONT_CARE STATIC_GUID_NULL - -#define STATIC_KSMEMORY_TYPE_SYSTEM \ - 0x091bb638L, 0x603f, 0x11d1, 0xb0, 0x67, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02 -DEFINE_GUIDSTRUCT("091bb638-603f-11d1-b067-00a0c9062802", KSMEMORY_TYPE_SYSTEM); -#define KSMEMORY_TYPE_SYSTEM DEFINE_GUIDNAMED(KSMEMORY_TYPE_SYSTEM) - -#define STATIC_KSMEMORY_TYPE_USER \ - 0x8cb0fc28L, 0x7893, 0x11d1, 0xb0, 0x69, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02 -DEFINE_GUIDSTRUCT("8cb0fc28-7893-11d1-b069-00a0c9062802", KSMEMORY_TYPE_USER); -#define KSMEMORY_TYPE_USER DEFINE_GUIDNAMED(KSMEMORY_TYPE_USER) - -#define STATIC_KSMEMORY_TYPE_KERNEL_PAGED \ - 0xd833f8f8L, 0x7894, 0x11d1, 0xb0, 0x69, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02 -DEFINE_GUIDSTRUCT("d833f8f8-7894-11d1-b069-00a0c9062802", KSMEMORY_TYPE_KERNEL_PAGED); -#define KSMEMORY_TYPE_KERNEL_PAGED DEFINE_GUIDNAMED(KSMEMORY_TYPE_KERNEL_PAGED) - -#define STATIC_KSMEMORY_TYPE_KERNEL_NONPAGED \ - 0x4a6d5fc4L, 0x7895, 0x11d1, 0xb0, 0x69, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02 -DEFINE_GUIDSTRUCT("4a6d5fc4-7895-11d1-b069-00a0c9062802", KSMEMORY_TYPE_KERNEL_NONPAGED); -#define KSMEMORY_TYPE_KERNEL_NONPAGED DEFINE_GUIDNAMED(KSMEMORY_TYPE_KERNEL_NONPAGED) - -#define STATIC_KSMEMORY_TYPE_DEVICE_UNKNOWN \ - 0x091bb639L, 0x603f, 0x11d1, 0xb0, 0x67, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02 -DEFINE_GUIDSTRUCT("091bb639-603f-11d1-b067-00a0c9062802", KSMEMORY_TYPE_DEVICE_UNKNOWN); -#define KSMEMORY_TYPE_DEVICE_UNKNOWN DEFINE_GUIDNAMED(KSMEMORY_TYPE_DEVICE_UNKNOWN) - -#define DECLARE_SIMPLE_FRAMING_EX(FramingExName, MemoryType, Flags, Frames, Alignment, MinFrameSize, MaxFrameSize) \ - const KSALLOCATOR_FRAMING_EX FramingExName = \ - { \ - 1, \ - 0, \ - { \ - 1, \ - 1, \ - 0 \ - }, \ - 0, \ - { \ - { \ - MemoryType, \ - STATIC_KS_TYPE_DONT_CARE, \ - 0, \ - 0, \ - Flags, \ - Frames, \ - Alignment, \ - 0, \ - { \ - 0, \ - (ULONG)-1, \ - 1 \ - }, \ - { \ - { \ - MinFrameSize, \ - MaxFrameSize, \ - 1 \ - }, \ - 0, \ - 0 \ - } \ - } \ - } \ - } - -#define SetDefaultKsCompression(KsCompressionPointer) \ - { \ - KsCompressionPointer->RatioNumerator = 1; \ - KsCompressionPointer->RatioDenominator = 1; \ - KsCompressionPointer->RatioConstantMargin = 0; \ - } - -#define SetDontCareKsFramingRange(KsFramingRangePointer) \ - { \ - KsFramingRangePointer->MinFrameSize = 0; \ - KsFramingRangePointer->MaxFrameSize = (ULONG)-1; \ - KsFramingRangePointer->Stepping = 1; \ - } - -#define SetKsFramingRange(KsFramingRangePointer, P_MinFrameSize, P_MaxFrameSize) \ - { \ - KsFramingRangePointer->MinFrameSize = P_MinFrameSize; \ - KsFramingRangePointer->MaxFrameSize = P_MaxFrameSize; \ - KsFramingRangePointer->Stepping = 1; \ - } - -#define SetKsFramingRangeWeighted(KsFramingRangeWeightedPointer, P_MinFrameSize, P_MaxFrameSize) \ - { \ - KS_FRAMING_RANGE* KsFramingRange = \ - &KsFramingRangeWeightedPointer->Range; \ - SetKsFramingRange(KsFramingRange, P_MinFrameSize, P_MaxFrameSize); \ - KsFramingRangeWeightedPointer->InPlaceWeight = 0; \ - KsFramingRangeWeightedPointer->NotInPlaceWeight = 0; \ - } - -#define INITIALIZE_SIMPLE_FRAMING_EX(FramingExPointer, P_MemoryType, P_Flags, P_Frames, P_Alignment, P_MinFrameSize, P_MaxFrameSize) \ - { \ - KS_COMPRESSION* KsCompression = \ - &FramingExPointer->OutputCompression; \ - KS_FRAMING_RANGE* KsFramingRange = \ - &FramingExPointer->FramingItem[0].PhysicalRange; \ - KS_FRAMING_RANGE_WEIGHTED* KsFramingRangeWeighted = \ - &FramingExPointer->FramingItem[0].FramingRange; \ - FramingExPointer->CountItems = 1; \ - FramingExPointer->PinFlags = 0; \ - SetDefaultKsCompression(KsCompression); \ - FramingExPointer->PinWeight = 0; \ - FramingExPointer->FramingItem[0].MemoryType = P_MemoryType; \ - FramingExPointer->FramingItem[0].BusType = KS_TYPE_DONT_CARE; \ - FramingExPointer->FramingItem[0].MemoryFlags = 0; \ - FramingExPointer->FramingItem[0].BusFlags = 0; \ - FramingExPointer->FramingItem[0].Flags = P_Flags; \ - FramingExPointer->FramingItem[0].Frames = P_Frames; \ - FramingExPointer->FramingItem[0].FileAlignment = P_Alignment; \ - FramingExPointer->FramingItem[0].MemoryTypeWeight = 0; \ - SetDontCareKsFramingRange(KsFramingRange); \ - SetKsFramingRangeWeighted(KsFramingRangeWeighted, \ - P_MinFrameSize, P_MaxFrameSize); \ - } - -#define STATIC_KSEVENTSETID_StreamAllocator \ - 0x75d95571L, 0x073c, 0x11d0, 0xa1, 0x61, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4 -DEFINE_GUIDSTRUCT("75d95571-073c-11d0-a161-0020afd156e4", KSEVENTSETID_StreamAllocator); -#define KSEVENTSETID_StreamAllocator DEFINE_GUIDNAMED(KSEVENTSETID_StreamAllocator) - -typedef enum -{ - KSEVENT_STREAMALLOCATOR_INTERNAL_FREEFRAME, - KSEVENT_STREAMALLOCATOR_FREEFRAME -}KSEVENT_STREAMALLOCATOR; - -#define STATIC_KSMETHODSETID_StreamAllocator \ - 0xcf6e4341L, 0xec87, 0x11cf, 0xa1, 0x30, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4 -DEFINE_GUIDSTRUCT("cf6e4341-ec87-11cf-a130-0020afd156e4", KSMETHODSETID_StreamAllocator); -#define KSMETHODSETID_StreamAllocator DEFINE_GUIDNAMED(KSMETHODSETID_StreamAllocator) - -typedef enum -{ - KSMETHOD_STREAMALLOCATOR_ALLOC, - KSMETHOD_STREAMALLOCATOR_FREE -}KSMETHOD_STREAMALLOCATOR; - -#define DEFINE_KSMETHOD_ITEM_STREAMALLOCATOR_ALLOC(Handler) \ - DEFINE_KSMETHOD_ITEM( \ - KSMETHOD_STREAMALLOCATOR_ALLOC, \ - KSMETHOD_TYPE_WRITE, \ - (Handler), \ - sizeof(KSMETHOD), \ - sizeof(PVOID), \ - NULL) - -#define DEFINE_KSMETHOD_ITEM_STREAMALLOCATOR_FREE(Handler) \ - DEFINE_KSMETHOD_ITEM( \ - KSMETHOD_STREAMALLOCATOR_FREE, \ - KSMETHOD_TYPE_READ, \ - (Handler), \ - sizeof(KSMETHOD), \ - sizeof(PVOID), \ - NULL) - -#define DEFINE_KSMETHOD_ALLOCATORSET(AllocatorSet, MethodAlloc, MethodFree) \ - DEFINE_KSMETHOD_TABLE(AllocatorSet) { \ - DEFINE_KSMETHOD_ITEM_STREAMALLOCATOR_ALLOC(MethodAlloc), \ - DEFINE_KSMETHOD_ITEM_STREAMALLOCATOR_FREE(MethodFree) \ - } - -#define STATIC_KSPROPSETID_StreamAllocator \ - 0xcf6e4342L, 0xec87, 0x11cf, 0xa1, 0x30, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4 -DEFINE_GUIDSTRUCT("cf6e4342-ec87-11cf-a130-0020afd156e4", KSPROPSETID_StreamAllocator); -#define KSPROPSETID_StreamAllocator DEFINE_GUIDNAMED(KSPROPSETID_StreamAllocator) - -#if defined(_NTDDK_) -typedef enum -{ - KSPROPERTY_STREAMALLOCATOR_FUNCTIONTABLE, - KSPROPERTY_STREAMALLOCATOR_STATUS -}KSPROPERTY_STREAMALLOCATOR; - - # define DEFINE_KSPROPERTY_ITEM_STREAMALLOCATOR_FUNCTIONTABLE(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAMALLOCATOR_FUNCTIONTABLE, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSSTREAMALLOCATOR_FUNCTIONTABLE), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_STREAMALLOCATOR_STATUS(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAMALLOCATOR_STATUS, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSSTREAMALLOCATOR_STATUS), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ALLOCATORSET(AllocatorSet, PropFunctionTable, PropStatus) \ - DEFINE_KSPROPERTY_TABLE(AllocatorSet) { \ - DEFINE_KSPROPERTY_ITEM_STREAMALLOCATOR_STATUS(PropStatus), \ - DEFINE_KSPROPERTY_ITEM_STREAMALLOCATOR_FUNCTIONTABLE(PropFunctionTable) \ - } - -typedef NTSTATUS (*PFNALLOCATOR_ALLOCATEFRAME)(PFILE_OBJECT FileObject, - PVOID* Frame); -typedef VOID (*PFNALLOCATOR_FREEFRAME)(PFILE_OBJECT FileObject, PVOID Frame); - -typedef struct -{ - PFNALLOCATOR_ALLOCATEFRAME AllocateFrame; - PFNALLOCATOR_FREEFRAME FreeFrame; -}KSSTREAMALLOCATOR_FUNCTIONTABLE, * PKSSTREAMALLOCATOR_FUNCTIONTABLE; -#endif /* _NTDDK_ */ - -typedef struct -{ - KSALLOCATOR_FRAMING Framing; - ULONG AllocatedFrames; - ULONG Reserved; -}KSSTREAMALLOCATOR_STATUS, * PKSSTREAMALLOCATOR_STATUS; - -typedef struct -{ - KSALLOCATOR_FRAMING_EX Framing; - ULONG AllocatedFrames; - ULONG Reserved; -}KSSTREAMALLOCATOR_STATUS_EX, * PKSSTREAMALLOCATOR_STATUS_EX; - -#define KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT 0x00000001 -#define KSSTREAM_HEADER_OPTIONSF_PREROLL 0x00000002 -#define KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY 0x00000004 -#define KSSTREAM_HEADER_OPTIONSF_TYPECHANGED 0x00000008 -#define KSSTREAM_HEADER_OPTIONSF_TIMEVALID 0x00000010 -#define KSSTREAM_HEADER_OPTIONSF_TIMEDISCONTINUITY 0x00000040 -#define KSSTREAM_HEADER_OPTIONSF_FLUSHONPAUSE 0x00000080 -#define KSSTREAM_HEADER_OPTIONSF_DURATIONVALID 0x00000100 -#define KSSTREAM_HEADER_OPTIONSF_ENDOFSTREAM 0x00000200 -#define KSSTREAM_HEADER_OPTIONSF_LOOPEDDATA 0x80000000 - -typedef struct -{ - LONGLONG Time; - ULONG Numerator; - ULONG Denominator; -}KSTIME, * PKSTIME; - -typedef struct -{ - ULONG Size; - ULONG TypeSpecificFlags; - KSTIME PresentationTime; - LONGLONG Duration; - ULONG FrameExtent; - ULONG DataUsed; - PVOID Data; - ULONG OptionsFlags; -#ifdef _WIN64 - ULONG Reserved; -#endif -}KSSTREAM_HEADER, * PKSSTREAM_HEADER; - -#define STATIC_KSPROPSETID_StreamInterface \ - 0x1fdd8ee1L, 0x9cd3, 0x11d0, 0x82, 0xaa, 0x00, 0x00, 0xf8, 0x22, 0xfe, 0x8a -DEFINE_GUIDSTRUCT("1fdd8ee1-9cd3-11d0-82aa-0000f822fe8a", KSPROPSETID_StreamInterface); -#define KSPROPSETID_StreamInterface DEFINE_GUIDNAMED(KSPROPSETID_StreamInterface) - -typedef enum -{ - KSPROPERTY_STREAMINTERFACE_HEADERSIZE -}KSPROPERTY_STREAMINTERFACE; - -#define DEFINE_KSPROPERTY_ITEM_STREAMINTERFACE_HEADERSIZE(GetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAMINTERFACE_HEADERSIZE, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(ULONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_STREAMINTERFACESET(StreamInterfaceSet, HeaderSizeHandler) \ - DEFINE_KSPROPERTY_TABLE(StreamInterfaceSet) { \ - DEFINE_KSPROPERTY_ITEM_STREAMINTERFACE_HEADERSIZE(HeaderSizeHandler) \ - } - -#define STATIC_KSPROPSETID_Stream \ - 0x65aaba60L, 0x98ae, 0x11cf, 0xa1, 0x0d, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4 -DEFINE_GUIDSTRUCT("65aaba60-98ae-11cf-a10d-0020afd156e4", KSPROPSETID_Stream); -#define KSPROPSETID_Stream DEFINE_GUIDNAMED(KSPROPSETID_Stream) - -typedef enum -{ - KSPROPERTY_STREAM_ALLOCATOR, - KSPROPERTY_STREAM_QUALITY, - KSPROPERTY_STREAM_DEGRADATION, - KSPROPERTY_STREAM_MASTERCLOCK, - KSPROPERTY_STREAM_TIMEFORMAT, - KSPROPERTY_STREAM_PRESENTATIONTIME, - KSPROPERTY_STREAM_PRESENTATIONEXTENT, - KSPROPERTY_STREAM_FRAMETIME, - KSPROPERTY_STREAM_RATECAPABILITY, - KSPROPERTY_STREAM_RATE, - KSPROPERTY_STREAM_PIPE_ID -}KSPROPERTY_STREAM; - -#define DEFINE_KSPROPERTY_ITEM_STREAM_ALLOCATOR(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_ALLOCATOR, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(HANDLE), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_QUALITY(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_QUALITY, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSQUALITY_MANAGER), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_DEGRADATION(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_DEGRADATION, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - 0, \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_MASTERCLOCK(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_MASTERCLOCK, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(HANDLE), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_TIMEFORMAT(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_TIMEFORMAT, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(GUID), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_PRESENTATIONTIME(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_PRESENTATIONTIME, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(KSTIME), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_PRESENTATIONEXTENT(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_PRESENTATIONEXTENT, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(LONGLONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_FRAMETIME(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_FRAMETIME, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSFRAMETIME), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_RATECAPABILITY(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_RATECAPABILITY, \ - (Handler), \ - sizeof(KSRATE_CAPABILITY), \ - sizeof(KSRATE), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_RATE(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_RATE, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(KSRATE), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_PIPE_ID(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_PIPE_ID, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(HANDLE), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -typedef struct -{ - HANDLE QualityManager; - PVOID Context; -}KSQUALITY_MANAGER, * PKSQUALITY_MANAGER; - -typedef struct -{ - LONGLONG Duration; - ULONG FrameFlags; - ULONG Reserved; -}KSFRAMETIME, * PKSFRAMETIME; - -#define KSFRAMETIME_VARIABLESIZE 0x00000001 - -typedef struct -{ - LONGLONG PresentationStart; - LONGLONG Duration; - KSPIN_INTERFACE Interface; - LONG Rate; - ULONG Flags; -}KSRATE, * PKSRATE; - -#define KSRATE_NOPRESENTATIONSTART 0x00000001 -#define KSRATE_NOPRESENTATIONDURATION 0x00000002 - -typedef struct -{ - KSPROPERTY Property; - KSRATE Rate; -}KSRATE_CAPABILITY, * PKSRATE_CAPABILITY; - -#define STATIC_KSPROPSETID_Clock \ - 0xDF12A4C0L, 0xAC17, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("DF12A4C0-AC17-11CF-A5D6-28DB04C10000", KSPROPSETID_Clock); -#define KSPROPSETID_Clock DEFINE_GUIDNAMED(KSPROPSETID_Clock) - -#define NANOSECONDS 10000000 -#define KSCONVERT_PERFORMANCE_TIME(Frequency, PerformanceTime) \ - ((((ULONGLONG)(ULONG)(PerformanceTime).HighPart * NANOSECONDS / (Frequency)) << 32) + \ - ((((((ULONGLONG)(ULONG)(PerformanceTime).HighPart * NANOSECONDS) % (Frequency)) << 32) + \ - ((ULONGLONG)(PerformanceTime).LowPart * NANOSECONDS)) / (Frequency))) - -typedef struct -{ - ULONG CreateFlags; -}KSCLOCK_CREATE, * PKSCLOCK_CREATE; - -typedef struct -{ - LONGLONG Time; - LONGLONG SystemTime; -}KSCORRELATED_TIME, * PKSCORRELATED_TIME; - -typedef struct -{ - LONGLONG Granularity; - LONGLONG Error; -}KSRESOLUTION, * PKSRESOLUTION; - -typedef enum -{ - KSPROPERTY_CLOCK_TIME, - KSPROPERTY_CLOCK_PHYSICALTIME, - KSPROPERTY_CLOCK_CORRELATEDTIME, - KSPROPERTY_CLOCK_CORRELATEDPHYSICALTIME, - KSPROPERTY_CLOCK_RESOLUTION, - KSPROPERTY_CLOCK_STATE, -#if defined(_NTDDK_) - KSPROPERTY_CLOCK_FUNCTIONTABLE -#endif /* _NTDDK_ */ -}KSPROPERTY_CLOCK; - -#if defined(_NTDDK_) -typedef LONGLONG (FASTCALL * PFNKSCLOCK_GETTIME)(PFILE_OBJECT FileObject); -typedef LONGLONG (FASTCALL * PFNKSCLOCK_CORRELATEDTIME)(PFILE_OBJECT FileObject, - PLONGLONG SystemTime); - -typedef struct -{ - PFNKSCLOCK_GETTIME GetTime; - PFNKSCLOCK_GETTIME GetPhysicalTime; - PFNKSCLOCK_CORRELATEDTIME GetCorrelatedTime; - PFNKSCLOCK_CORRELATEDTIME GetCorrelatedPhysicalTime; -}KSCLOCK_FUNCTIONTABLE, * PKSCLOCK_FUNCTIONTABLE; - -typedef BOOLEAN (*PFNKSSETTIMER)(PVOID Context, PKTIMER Timer, - LARGE_INTEGER DueTime, PKDPC Dpc); -typedef BOOLEAN (*PFNKSCANCELTIMER)(PVOID Context, PKTIMER Timer); -typedef LONGLONG (FASTCALL * PFNKSCORRELATEDTIME)(PVOID Context, - PLONGLONG SystemTime); - -typedef PVOID PKSDEFAULTCLOCK; - - # define DEFINE_KSPROPERTY_ITEM_CLOCK_TIME(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CLOCK_TIME, \ - (Handler), \ - sizeof(KSPROPERTY), sizeof(LONGLONG), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_CLOCK_PHYSICALTIME(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CLOCK_PHYSICALTIME, \ - (Handler), \ - sizeof(KSPROPERTY), sizeof(LONGLONG), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_CLOCK_CORRELATEDTIME(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CLOCK_CORRELATEDTIME, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSCORRELATED_TIME), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_CLOCK_CORRELATEDPHYSICALTIME(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CLOCK_CORRELATEDPHYSICALTIME, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSCORRELATED_TIME), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_CLOCK_RESOLUTION(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CLOCK_RESOLUTION, \ - (Handler), \ - sizeof(KSPROPERTY), sizeof(KSRESOLUTION), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_CLOCK_STATE(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CLOCK_STATE, \ - (Handler), \ - sizeof(KSPROPERTY), sizeof(KSSTATE), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_CLOCK_FUNCTIONTABLE(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CLOCK_FUNCTIONTABLE, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSCLOCK_FUNCTIONTABLE), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_CLOCKSET(ClockSet, PropTime, PropPhysicalTime, PropCorrelatedTime, PropCorrelatedPhysicalTime, PropResolution, PropState, PropFunctionTable) \ - DEFINE_KSPROPERTY_TABLE(ClockSet) { \ - DEFINE_KSPROPERTY_ITEM_CLOCK_TIME(PropTime), \ - DEFINE_KSPROPERTY_ITEM_CLOCK_PHYSICALTIME(PropPhysicalTime), \ - DEFINE_KSPROPERTY_ITEM_CLOCK_CORRELATEDTIME(PropCorrelatedTime), \ - DEFINE_KSPROPERTY_ITEM_CLOCK_CORRELATEDPHYSICALTIME(PropCorrelatedPhysicalTime), \ - DEFINE_KSPROPERTY_ITEM_CLOCK_RESOLUTION(PropResolution), \ - DEFINE_KSPROPERTY_ITEM_CLOCK_STATE(PropState), \ - DEFINE_KSPROPERTY_ITEM_CLOCK_FUNCTIONTABLE(PropFunctionTable), \ - } -#endif /* _NTDDK_ */ - -#define STATIC_KSEVENTSETID_Clock \ - 0x364D8E20L, 0x62C7, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("364D8E20-62C7-11CF-A5D6-28DB04C10000", KSEVENTSETID_Clock); -#define KSEVENTSETID_Clock DEFINE_GUIDNAMED(KSEVENTSETID_Clock) - -typedef enum -{ - KSEVENT_CLOCK_INTERVAL_MARK, - KSEVENT_CLOCK_POSITION_MARK -}KSEVENT_CLOCK_POSITION; - -#define STATIC_KSEVENTSETID_Connection \ - 0x7f4bcbe0L, 0x9ea5, 0x11cf, 0xa5, 0xd6, 0x28, 0xdb, 0x04, 0xc1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("7f4bcbe0-9ea5-11cf-a5d6-28db04c10000", KSEVENTSETID_Connection); -#define KSEVENTSETID_Connection DEFINE_GUIDNAMED(KSEVENTSETID_Connection) - -typedef enum -{ - KSEVENT_CONNECTION_POSITIONUPDATE, - KSEVENT_CONNECTION_DATADISCONTINUITY, - KSEVENT_CONNECTION_TIMEDISCONTINUITY, - KSEVENT_CONNECTION_PRIORITY, - KSEVENT_CONNECTION_ENDOFSTREAM -}KSEVENT_CONNECTION; - -typedef struct -{ - PVOID Context; - ULONG Proportion; - LONGLONG DeltaTime; -}KSQUALITY, * PKSQUALITY; - -typedef struct -{ - PVOID Context; - ULONG Status; -}KSERROR, * PKSERROR; - -typedef KSIDENTIFIER KSDEGRADE, * PKSDEGRADE; - -#define STATIC_KSDEGRADESETID_Standard \ - 0x9F564180L, 0x704C, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("9F564180-704C-11D0-A5D6-28DB04C10000", KSDEGRADESETID_Standard); -#define KSDEGRADESETID_Standard DEFINE_GUIDNAMED(KSDEGRADESETID_Standard) - -typedef enum -{ - KSDEGRADE_STANDARD_SAMPLE, - KSDEGRADE_STANDARD_QUALITY, - KSDEGRADE_STANDARD_COMPUTATION, - KSDEGRADE_STANDARD_SKIP -}KSDEGRADE_STANDARD; - -#if defined(_NTDDK_) - - # define KSPROBE_STREAMREAD 0x00000000 - # define KSPROBE_STREAMWRITE 0x00000001 - # define KSPROBE_ALLOCATEMDL 0x00000010 - # define KSPROBE_PROBEANDLOCK 0x00000020 - # define KSPROBE_SYSTEMADDRESS 0x00000040 - # define KSPROBE_MODIFY 0x00000200 - # define KSPROBE_STREAMWRITEMODIFY (KSPROBE_MODIFY | KSPROBE_STREAMWRITE) - # define KSPROBE_ALLOWFORMATCHANGE 0x00000080 - # define KSSTREAM_READ KSPROBE_STREAMREAD - # define KSSTREAM_WRITE KSPROBE_STREAMWRITE - # define KSSTREAM_PAGED_DATA 0x00000000 - # define KSSTREAM_NONPAGED_DATA 0x00000100 - # define KSSTREAM_SYNCHRONOUS 0x00001000 - # define KSSTREAM_FAILUREEXCEPTION 0x00002000 - -typedef NTSTATUS (*PFNKSCONTEXT_DISPATCH)(PVOID Context, PIRP Irp); -typedef NTSTATUS (*PFNKSHANDLER)(PIRP Irp, PKSIDENTIFIER Request, PVOID Data); -typedef BOOLEAN (*PFNKSFASTHANDLER)(PFILE_OBJECT FileObject, - PKSIDENTIFIER Request, - ULONG RequestLength, PVOID Data, - ULONG DataLength, - PIO_STATUS_BLOCK IoStatus); -typedef NTSTATUS (*PFNKSALLOCATOR)(PIRP Irp, ULONG BufferSize, - BOOLEAN InputOperation); - -typedef struct -{ - KSPROPERTY_MEMBERSHEADER MembersHeader; - const VOID* Members; -}KSPROPERTY_MEMBERSLIST, * PKSPROPERTY_MEMBERSLIST; - -typedef struct -{ - KSIDENTIFIER PropTypeSet; - ULONG MembersListCount; - const KSPROPERTY_MEMBERSLIST* MembersList; -}KSPROPERTY_VALUES, * PKSPROPERTY_VALUES; - - # define DEFINE_KSPROPERTY_TABLE(tablename) \ - const KSPROPERTY_ITEM tablename[] = - - # define DEFINE_KSPROPERTY_ITEM(PropertyId, GetHandler, MinProperty, MinData, SetHandler, Values, RelationsCount, Relations, SupportHandler, SerializedSize) \ - { \ - PropertyId, (PFNKSHANDLER)GetHandler, \ - MinProperty, MinData, \ - (PFNKSHANDLER)SetHandler, \ - (PKSPROPERTY_VALUES)Values, RelationsCount, \ - (PKSPROPERTY)Relations, \ - (PFNKSHANDLER)SupportHandler, \ - (ULONG)SerializedSize \ - } - -typedef struct -{ - ULONG PropertyId; - __MINGW_EXTENSION union - { - PFNKSHANDLER GetPropertyHandler; - BOOLEAN GetSupported; - }; - ULONG MinProperty; - ULONG MinData; - __MINGW_EXTENSION union - { - PFNKSHANDLER SetPropertyHandler; - BOOLEAN SetSupported; - }; - const KSPROPERTY_VALUES* Values; - ULONG RelationsCount; - const KSPROPERTY* Relations; - PFNKSHANDLER SupportHandler; - ULONG SerializedSize; -}KSPROPERTY_ITEM, * PKSPROPERTY_ITEM; - - # define DEFINE_KSFASTPROPERTY_ITEM(PropertyId, GetHandler, SetHandler) \ - { \ - PropertyId, (PFNKSFASTHANDLER)GetHandler, \ - (PFNKSFASTHANDLER)SetHandler, 0 \ - } - -typedef struct -{ - ULONG PropertyId; - __MINGW_EXTENSION union - { - PFNKSFASTHANDLER GetPropertyHandler; - BOOLEAN GetSupported; - }; - __MINGW_EXTENSION union - { - PFNKSFASTHANDLER SetPropertyHandler; - BOOLEAN SetSupported; - }; - ULONG Reserved; -}KSFASTPROPERTY_ITEM, * PKSFASTPROPERTY_ITEM; - - # define DEFINE_KSPROPERTY_SET(Set, PropertiesCount, PropertyItem, FastIoCount, FastIoTable) \ - { \ - Set, \ - PropertiesCount, PropertyItem, \ - FastIoCount, FastIoTable \ - } - - # define DEFINE_KSPROPERTY_SET_TABLE(tablename) \ - const KSPROPERTY_SET tablename[] = - -typedef struct -{ - const GUID* Set; - ULONG PropertiesCount; - const KSPROPERTY_ITEM* PropertyItem; - ULONG FastIoCount; - const KSFASTPROPERTY_ITEM* FastIoTable; -}KSPROPERTY_SET, * PKSPROPERTY_SET; - - # define DEFINE_KSMETHOD_TABLE(tablename) \ - const KSMETHOD_ITEM tablename[] = - - # define DEFINE_KSMETHOD_ITEM(MethodId, Flags, MethodHandler, MinMethod, MinData, SupportHandler) \ - { \ - MethodId, (PFNKSHANDLER)MethodHandler, \ - MinMethod, MinData, \ - SupportHandler, Flags \ - } - -typedef struct -{ - ULONG MethodId; - __MINGW_EXTENSION union - { - PFNKSHANDLER MethodHandler; - BOOLEAN MethodSupported; - }; - ULONG MinMethod; - ULONG MinData; - PFNKSHANDLER SupportHandler; - ULONG Flags; -}KSMETHOD_ITEM, * PKSMETHOD_ITEM; - - # define DEFINE_KSFASTMETHOD_ITEM(MethodId, MethodHandler) \ - { \ - MethodId, (PFNKSFASTHANDLER)MethodHandler \ - } - -typedef struct -{ - ULONG MethodId; - __MINGW_EXTENSION union - { - PFNKSFASTHANDLER MethodHandler; - BOOLEAN MethodSupported; - }; -}KSFASTMETHOD_ITEM, * PKSFASTMETHOD_ITEM; - - # define DEFINE_KSMETHOD_SET(Set, MethodsCount, MethodItem, FastIoCount, FastIoTable) \ - { \ - Set, \ - MethodsCount, MethodItem, \ - FastIoCount, FastIoTable \ - } - - # define DEFINE_KSMETHOD_SET_TABLE(tablename) \ - const KSMETHOD_SET tablename[] = - -typedef struct -{ - const GUID* Set; - ULONG MethodsCount; - const KSMETHOD_ITEM* MethodItem; - ULONG FastIoCount; - const KSFASTMETHOD_ITEM* FastIoTable; -}KSMETHOD_SET, * PKSMETHOD_SET; - -typedef struct _KSEVENT_ENTRY KSEVENT_ENTRY, * PKSEVENT_ENTRY; -typedef NTSTATUS (*PFNKSADDEVENT)(PIRP Irp, PKSEVENTDATA EventData, - struct _KSEVENT_ENTRY* EventEntry); -typedef VOID (*PFNKSREMOVEEVENT)(PFILE_OBJECT FileObject, - struct _KSEVENT_ENTRY* EventEntry); - - # define DEFINE_KSEVENT_TABLE(tablename) \ - const KSEVENT_ITEM tablename[] = - - # define DEFINE_KSEVENT_ITEM(EventId, DataInput, ExtraEntryData, AddHandler, RemoveHandler, SupportHandler) \ - { \ - EventId, DataInput, ExtraEntryData, \ - AddHandler, RemoveHandler, SupportHandler \ - } - -typedef struct -{ - ULONG EventId; - ULONG DataInput; - ULONG ExtraEntryData; - PFNKSADDEVENT AddHandler; - PFNKSREMOVEEVENT RemoveHandler; - PFNKSHANDLER SupportHandler; -}KSEVENT_ITEM, * PKSEVENT_ITEM; - - # define DEFINE_KSEVENT_SET(Set, EventsCount, EventItem) \ - { \ - Set, EventsCount, EventItem \ - } - - # define DEFINE_KSEVENT_SET_TABLE(tablename) \ - const KSEVENT_SET tablename[] = - -typedef struct -{ - const GUID* Set; - ULONG EventsCount; - const KSEVENT_ITEM* EventItem; -}KSEVENT_SET, * PKSEVENT_SET; - -typedef struct -{ - KDPC Dpc; - ULONG ReferenceCount; - KSPIN_LOCK AccessLock; -}KSDPC_ITEM, * PKSDPC_ITEM; - -typedef struct -{ - KSDPC_ITEM DpcItem; - LIST_ENTRY BufferList; -}KSBUFFER_ITEM, * PKSBUFFER_ITEM; - - # define KSEVENT_ENTRY_DELETED 1 - # define KSEVENT_ENTRY_ONESHOT 2 - # define KSEVENT_ENTRY_BUFFERED 4 - -struct _KSEVENT_ENTRY -{ - LIST_ENTRY ListEntry; - PVOID Object; - __MINGW_EXTENSION union - { - PKSDPC_ITEM DpcItem; - PKSBUFFER_ITEM BufferItem; - }; - PKSEVENTDATA EventData; - ULONG NotificationType; - const KSEVENT_SET* EventSet; - const KSEVENT_ITEM* EventItem; - PFILE_OBJECT FileObject; - ULONG SemaphoreAdjustment; - ULONG Reserved; - ULONG Flags; -}; - -typedef enum -{ - KSEVENTS_NONE, - KSEVENTS_SPINLOCK, - KSEVENTS_MUTEX, - KSEVENTS_FMUTEX, - KSEVENTS_FMUTEXUNSAFE, - KSEVENTS_INTERRUPT, - KSEVENTS_ERESOURCE -}KSEVENTS_LOCKTYPE; - - # define KSDISPATCH_FASTIO 0x80000000 - -typedef struct -{ - PDRIVER_DISPATCH Create; - PVOID Context; - UNICODE_STRING ObjectClass; - PSECURITY_DESCRIPTOR SecurityDescriptor; - ULONG Flags; -}KSOBJECT_CREATE_ITEM, * PKSOBJECT_CREATE_ITEM; - -typedef VOID (*PFNKSITEMFREECALLBACK)(PKSOBJECT_CREATE_ITEM CreateItem); - - # define KSCREATE_ITEM_SECURITYCHANGED 0x00000001 - # define KSCREATE_ITEM_WILDCARD 0x00000002 - # define KSCREATE_ITEM_NOPARAMETERS 0x00000004 - # define KSCREATE_ITEM_FREEONSTOP 0x00000008 - - # define DEFINE_KSCREATE_DISPATCH_TABLE(tablename) \ - KSOBJECT_CREATE_ITEM tablename[] = - - # define DEFINE_KSCREATE_ITEM(DispatchCreate, TypeName, Context) \ - { \ - (DispatchCreate), (PVOID)(Context), \ - { \ - sizeof(TypeName) - sizeof(UNICODE_NULL), \ - sizeof(TypeName), \ - (PWCHAR)(TypeName) \ - }, \ - NULL, 0 \ - } - - # define DEFINE_KSCREATE_ITEMEX(DispatchCreate, TypeName, Context, Flags) \ - { \ - (DispatchCreate), \ - (PVOID)(Context), \ - { \ - sizeof(TypeName) - sizeof(UNICODE_NULL), \ - sizeof(TypeName), \ - (PWCHAR)(TypeName) \ - }, \ - NULL, (Flags) \ - } - - # define DEFINE_KSCREATE_ITEMNULL(DispatchCreate, Context) \ - { \ - DispatchCreate, Context, \ - { \ - 0, 0, NULL, \ - }, \ - NULL, 0 \ - } - -typedef struct -{ - ULONG CreateItemsCount; - PKSOBJECT_CREATE_ITEM CreateItemsList; -}KSOBJECT_CREATE, * PKSOBJECT_CREATE; - -typedef struct -{ - PDRIVER_DISPATCH DeviceIoControl; - PDRIVER_DISPATCH Read; - PDRIVER_DISPATCH Write; - PDRIVER_DISPATCH Flush; - PDRIVER_DISPATCH Close; - PDRIVER_DISPATCH QuerySecurity; - PDRIVER_DISPATCH SetSecurity; - PFAST_IO_DEVICE_CONTROL FastDeviceIoControl; - PFAST_IO_READ FastRead; - PFAST_IO_WRITE FastWrite; -}KSDISPATCH_TABLE, * PKSDISPATCH_TABLE; - - # define DEFINE_KSDISPATCH_TABLE(tablename, DeviceIoControl, Read, Write, Flush, Close, QuerySecurity, SetSecurity, FastDeviceIoControl, FastRead, FastWrite) \ - const KSDISPATCH_TABLE tablename = \ - { \ - DeviceIoControl, \ - Read, \ - Write, \ - Flush, \ - Close, \ - QuerySecurity, \ - SetSecurity, \ - FastDeviceIoControl, \ - FastRead, \ - FastWrite, \ - } - - # define KSCREATE_ITEM_IRP_STORAGE(Irp) \ - (*(PKSOBJECT_CREATE_ITEM*)&(Irp)->Tail.Overlay.DriverContext[0]) - # define KSEVENT_SET_IRP_STORAGE(Irp) \ - (*(const KSEVENT_SET**)&(Irp)->Tail.Overlay.DriverContext[0]) - # define KSEVENT_ITEM_IRP_STORAGE(Irp) \ - (*(const KSEVENT_ITEM**)&(Irp)->Tail.Overlay.DriverContext[3]) - # define KSEVENT_ENTRY_IRP_STORAGE(Irp) \ - (*(PKSEVENT_ENTRY*)&(Irp)->Tail.Overlay.DriverContext[0]) - # define KSMETHOD_SET_IRP_STORAGE(Irp) \ - (*(const KSMETHOD_SET**)&(Irp)->Tail.Overlay.DriverContext[0]) - # define KSMETHOD_ITEM_IRP_STORAGE(Irp) \ - (*(const KSMETHOD_ITEM**)&(Irp)->Tail.Overlay.DriverContext[3]) - # define KSMETHOD_TYPE_IRP_STORAGE(Irp) \ - (*(ULONG_PTR*)(&(Irp)->Tail.Overlay.DriverContext[2])) - # define KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) \ - (*(PKSPIN_LOCK*)&(Irp)->Tail.Overlay.DriverContext[1]) - # define KSPROPERTY_SET_IRP_STORAGE(Irp) \ - (*(const KSPROPERTY_SET**)&(Irp)->Tail.Overlay.DriverContext[0]) - # define KSPROPERTY_ITEM_IRP_STORAGE(Irp) \ - (*(const KSPROPERTY_ITEM**)&(Irp)->Tail.Overlay.DriverContext[3]) - # define KSPROPERTY_ATTRIBUTES_IRP_STORAGE(Irp) \ - (*(PKSATTRIBUTE_LIST*)&(Irp)->Tail.Overlay.DriverContext[2]) - -typedef PVOID KSDEVICE_HEADER, KSOBJECT_HEADER; - -typedef enum -{ - KsInvokeOnSuccess = 1, - KsInvokeOnError = 2, - KsInvokeOnCancel = 4 -}KSCOMPLETION_INVOCATION; - -typedef enum -{ - KsListEntryTail, - KsListEntryHead -}KSLIST_ENTRY_LOCATION; - -typedef enum -{ - KsAcquireOnly, - KsAcquireAndRemove, - KsAcquireOnlySingleItem, - KsAcquireAndRemoveOnlySingleItem -}KSIRP_REMOVAL_OPERATION; - -typedef enum -{ - KsStackCopyToNewLocation, - KsStackReuseCurrentLocation, - KsStackUseNewLocation -}KSSTACK_USE; - -typedef enum -{ - KSTARGET_STATE_DISABLED, - KSTARGET_STATE_ENABLED -}KSTARGET_STATE; - -typedef NTSTATUS (*PFNKSIRPLISTCALLBACK)(PIRP Irp, PVOID Context); -typedef VOID (*PFNREFERENCEDEVICEOBJECT)(PVOID Context); -typedef VOID (*PFNDEREFERENCEDEVICEOBJECT)(PVOID Context); -typedef NTSTATUS (*PFNQUERYREFERENCESTRING)(PVOID Context, PWCHAR* String); - - # define BUS_INTERFACE_REFERENCE_VERSION 0x100 - -typedef struct -{ - INTERFACE Interface; - - PFNREFERENCEDEVICEOBJECT ReferenceDeviceObject; - PFNDEREFERENCEDEVICEOBJECT DereferenceDeviceObject; - PFNQUERYREFERENCESTRING QueryReferenceString; -}BUS_INTERFACE_REFERENCE, * PBUS_INTERFACE_REFERENCE; - - # define STATIC_REFERENCE_BUS_INTERFACE STATIC_KSMEDIUMSETID_Standard - # define REFERENCE_BUS_INTERFACE KSMEDIUMSETID_Standard - -#endif /* _NTDDK_ */ - -#ifndef PACK_PRAGMAS_NOT_SUPPORTED - # include -#endif - -typedef struct -{ - GUID PropertySet; - ULONG Count; -}KSPROPERTY_SERIALHDR, * PKSPROPERTY_SERIALHDR; - -#ifndef PACK_PRAGMAS_NOT_SUPPORTED - # include -#endif - -typedef struct -{ - KSIDENTIFIER PropTypeSet; - ULONG Id; - ULONG PropertyLength; -}KSPROPERTY_SERIAL, * PKSPROPERTY_SERIAL; - -#if defined(_NTDDK_) - - # define IOCTL_KS_HANDSHAKE \ - CTL_CODE(FILE_DEVICE_KS, 0x007, METHOD_NEITHER, FILE_ANY_ACCESS) - -typedef struct -{ - GUID ProtocolId; - PVOID Argument1; - PVOID Argument2; -}KSHANDSHAKE, * PKSHANDSHAKE; - -typedef struct _KSGATE KSGATE, * PKSGATE; - -struct _KSGATE -{ - LONG Count; - PKSGATE NextGate; -}; - -typedef PVOID KSOBJECT_BAG; - -typedef BOOLEAN (*PFNKSGENERATEEVENTCALLBACK)(PVOID Context, - PKSEVENT_ENTRY EventEntry); - -typedef NTSTATUS (*PFNKSDEVICECREATE)(PKSDEVICE Device); - -typedef NTSTATUS (*PFNKSDEVICEPNPSTART)(PKSDEVICE Device, PIRP Irp, - PCM_RESOURCE_LIST TranslatedResourceList, - PCM_RESOURCE_LIST UntranslatedResourceList); - -typedef NTSTATUS (*PFNKSDEVICE)(PKSDEVICE Device); - -typedef NTSTATUS (*PFNKSDEVICEIRP)(PKSDEVICE Device, PIRP Irp); - -typedef void (*PFNKSDEVICEIRPVOID)(PKSDEVICE Device, PIRP Irp); - -typedef NTSTATUS (*PFNKSDEVICEQUERYCAPABILITIES)(PKSDEVICE Device, PIRP Irp, - PDEVICE_CAPABILITIES Capabilities); - -typedef NTSTATUS (*PFNKSDEVICEQUERYPOWER)(PKSDEVICE Device, PIRP Irp, - DEVICE_POWER_STATE DeviceTo, - DEVICE_POWER_STATE DeviceFrom, - SYSTEM_POWER_STATE SystemTo, - SYSTEM_POWER_STATE SystemFrom, - POWER_ACTION Action); - -typedef void (*PFNKSDEVICESETPOWER)(PKSDEVICE Device, PIRP Irp, - DEVICE_POWER_STATE To, - DEVICE_POWER_STATE From); - -typedef NTSTATUS (*PFNKSFILTERFACTORYVOID)(PKSFILTERFACTORY FilterFactory); - -typedef void (*PFNKSFILTERFACTORYPOWER)(PKSFILTERFACTORY FilterFactory, - DEVICE_POWER_STATE State); - -typedef NTSTATUS (*PFNKSFILTERIRP)(PKSFILTER Filter, PIRP Irp); - -typedef NTSTATUS (*PFNKSFILTERPROCESS)(PKSFILTER Filter, - PKSPROCESSPIN_INDEXENTRY Index); - -typedef NTSTATUS (*PFNKSFILTERVOID)(PKSFILTER Filter); - -typedef void (*PFNKSFILTERPOWER)(PKSFILTER Filter, DEVICE_POWER_STATE State); - -typedef NTSTATUS (*PFNKSPINIRP)(PKSPIN Pin, PIRP Irp); - -typedef NTSTATUS (*PFNKSPINSETDEVICESTATE)(PKSPIN Pin, KSSTATE ToState, - KSSTATE FromState); - -typedef NTSTATUS (*PFNKSPINSETDATAFORMAT)(PKSPIN Pin, PKSDATAFORMAT OldFormat, - PKSMULTIPLE_ITEM OldAttributeList, - const KSDATARANGE* DataRange, - const KSATTRIBUTE_LIST* AttributeRange); - -typedef NTSTATUS (*PFNKSPINHANDSHAKE)(PKSPIN Pin, PKSHANDSHAKE In, - PKSHANDSHAKE Out); - -typedef NTSTATUS (*PFNKSPIN)(PKSPIN Pin); - -typedef void (*PFNKSPINVOID)(PKSPIN Pin); - -typedef void (*PFNKSPINPOWER)(PKSPIN Pin, DEVICE_POWER_STATE State); - -typedef BOOLEAN (*PFNKSPINSETTIMER)(PKSPIN Pin, PKTIMER Timer, - LARGE_INTEGER DueTime, PKDPC Dpc); - -typedef BOOLEAN (*PFNKSPINCANCELTIMER)(PKSPIN Pin, PKTIMER Timer); - -typedef LONGLONG (FASTCALL * PFNKSPINCORRELATEDTIME)(PKSPIN Pin, - PLONGLONG SystemTime); - -typedef void (*PFNKSPINRESOLUTION)(PKSPIN Pin, PKSRESOLUTION Resolution); - -typedef NTSTATUS (*PFNKSPININITIALIZEALLOCATOR)(PKSPIN Pin, - PKSALLOCATOR_FRAMING AllocatorFraming, - PVOID* Context); - -typedef void (*PFNKSSTREAMPOINTER)(PKSSTREAM_POINTER StreamPointer); - -typedef struct KSAUTOMATION_TABLE_ KSAUTOMATION_TABLE, * PKSAUTOMATION_TABLE; - -struct KSAUTOMATION_TABLE_ -{ - ULONG PropertySetsCount; - ULONG PropertyItemSize; - const KSPROPERTY_SET* PropertySets; - ULONG MethodSetsCount; - ULONG MethodItemSize; - const KSMETHOD_SET* MethodSets; - ULONG EventSetsCount; - ULONG EventItemSize; - const KSEVENT_SET* EventSets; - # ifndef _WIN64 - PVOID Alignment; - # endif -}; - - # define DEFINE_KSAUTOMATION_TABLE(table) \ - const KSAUTOMATION_TABLE table = - - # define DEFINE_KSAUTOMATION_PROPERTIES(table) \ - SIZEOF_ARRAY(table), \ - sizeof(KSPROPERTY_ITEM), \ - table - - # define DEFINE_KSAUTOMATION_METHODS(table) \ - SIZEOF_ARRAY(table), \ - sizeof(KSMETHOD_ITEM), \ - table - - # define DEFINE_KSAUTOMATION_EVENTS(table) \ - SIZEOF_ARRAY(table), \ - sizeof(KSEVENT_ITEM), \ - table - - # define DEFINE_KSAUTOMATION_PROPERTIES_NULL \ - 0, \ - sizeof(KSPROPERTY_ITEM), \ - NULL - - # define DEFINE_KSAUTOMATION_METHODS_NULL \ - 0, \ - sizeof(KSMETHOD_ITEM), \ - NULL - - # define DEFINE_KSAUTOMATION_EVENTS_NULL \ - 0, \ - sizeof(KSEVENT_ITEM), \ - NULL - - # define MIN_DEV_VER_FOR_QI (0x100) - -struct _KSDEVICE_DISPATCH -{ - PFNKSDEVICECREATE Add; - PFNKSDEVICEPNPSTART Start; - PFNKSDEVICE PostStart; - PFNKSDEVICEIRP QueryStop; - PFNKSDEVICEIRPVOID CancelStop; - PFNKSDEVICEIRPVOID Stop; - PFNKSDEVICEIRP QueryRemove; - PFNKSDEVICEIRPVOID CancelRemove; - PFNKSDEVICEIRPVOID Remove; - PFNKSDEVICEQUERYCAPABILITIES QueryCapabilities; - PFNKSDEVICEIRPVOID SurpriseRemoval; - PFNKSDEVICEQUERYPOWER QueryPower; - PFNKSDEVICESETPOWER SetPower; - PFNKSDEVICEIRP QueryInterface; -}; - -struct _KSFILTER_DISPATCH -{ - PFNKSFILTERIRP Create; - PFNKSFILTERIRP Close; - PFNKSFILTERPROCESS Process; - PFNKSFILTERVOID Reset; -}; - -struct _KSPIN_DISPATCH -{ - PFNKSPINIRP Create; - PFNKSPINIRP Close; - PFNKSPIN Process; - PFNKSPINVOID Reset; - PFNKSPINSETDATAFORMAT SetDataFormat; - PFNKSPINSETDEVICESTATE SetDeviceState; - PFNKSPIN Connect; - PFNKSPINVOID Disconnect; - const KSCLOCK_DISPATCH* Clock; - const KSALLOCATOR_DISPATCH* Allocator; -}; - -struct _KSCLOCK_DISPATCH -{ - PFNKSPINSETTIMER SetTimer; - PFNKSPINCANCELTIMER CancelTimer; - PFNKSPINCORRELATEDTIME CorrelatedTime; - PFNKSPINRESOLUTION Resolution; -}; - -struct _KSALLOCATOR_DISPATCH -{ - PFNKSPININITIALIZEALLOCATOR InitializeAllocator; - PFNKSDELETEALLOCATOR DeleteAllocator; - PFNKSDEFAULTALLOCATE Allocate; - PFNKSDEFAULTFREE Free; -}; - - # define KSDEVICE_DESCRIPTOR_VERSION (0x100) - -struct _KSDEVICE_DESCRIPTOR -{ - const KSDEVICE_DISPATCH* Dispatch; - ULONG FilterDescriptorsCount; - const KSFILTER_DESCRIPTOR* const* FilterDescriptors; - ULONG Version; -}; - -struct _KSFILTER_DESCRIPTOR -{ - const KSFILTER_DISPATCH* Dispatch; - const KSAUTOMATION_TABLE* AutomationTable; - ULONG Version; - # define KSFILTER_DESCRIPTOR_VERSION ((ULONG)-1) - ULONG Flags; - # define KSFILTER_FLAG_DISPATCH_LEVEL_PROCESSING 0x00000001 - # define KSFILTER_FLAG_CRITICAL_PROCESSING 0x00000002 - # define KSFILTER_FLAG_HYPERCRITICAL_PROCESSING 0x00000004 - # define KSFILTER_FLAG_RECEIVE_ZERO_LENGTH_SAMPLES 0x00000008 - # define KSFILTER_FLAG_DENY_USERMODE_ACCESS 0x80000000 - const GUID* ReferenceGuid; - ULONG PinDescriptorsCount; - ULONG PinDescriptorSize; - const KSPIN_DESCRIPTOR_EX* PinDescriptors; - ULONG CategoriesCount; - const GUID* Categories; - ULONG NodeDescriptorsCount; - ULONG NodeDescriptorSize; - const KSNODE_DESCRIPTOR* NodeDescriptors; - ULONG ConnectionsCount; - const KSTOPOLOGY_CONNECTION* Connections; - const KSCOMPONENTID* ComponentId; -}; - - # define DEFINE_KSFILTER_DESCRIPTOR(descriptor) \ - const KSFILTER_DESCRIPTOR descriptor = - - # define DEFINE_KSFILTER_PIN_DESCRIPTORS(table) \ - SIZEOF_ARRAY(table), \ - sizeof(table[0]), \ - table - - # define DEFINE_KSFILTER_CATEGORIES(table) \ - SIZEOF_ARRAY(table), \ - table - - # define DEFINE_KSFILTER_CATEGORY(category) \ - 1, \ - &(category) - - # define DEFINE_KSFILTER_CATEGORIES_NULL \ - 0, \ - NULL - - # define DEFINE_KSFILTER_NODE_DESCRIPTORS(table) \ - SIZEOF_ARRAY(table), \ - sizeof(table[0]), \ - table - - # define DEFINE_KSFILTER_NODE_DESCRIPTORS_NULL \ - 0, \ - sizeof(KSNODE_DESCRIPTOR), \ - NULL - - # define DEFINE_KSFILTER_CONNECTIONS(table) \ - SIZEOF_ARRAY(table), \ - table - - # define DEFINE_KSFILTER_DEFAULT_CONNECTIONS \ - 0, \ - NULL - - # define DEFINE_KSFILTER_DESCRIPTOR_TABLE(table) \ - const KSFILTER_DESCRIPTOR * const table[] = - -struct _KSPIN_DESCRIPTOR_EX -{ - const KSPIN_DISPATCH* Dispatch; - const KSAUTOMATION_TABLE* AutomationTable; - KSPIN_DESCRIPTOR PinDescriptor; - ULONG Flags; - # define KSPIN_FLAG_DISPATCH_LEVEL_PROCESSING KSFILTER_FLAG_DISPATCH_LEVEL_PROCESSING - # define KSPIN_FLAG_CRITICAL_PROCESSING KSFILTER_FLAG_CRITICAL_PROCESSING - # define KSPIN_FLAG_HYPERCRITICAL_PROCESSING KSFILTER_FLAG_HYPERCRITICAL_PROCESSING - # define KSPIN_FLAG_ASYNCHRONOUS_PROCESSING 0x00000008 - # define KSPIN_FLAG_DO_NOT_INITIATE_PROCESSING 0x00000010 - # define KSPIN_FLAG_INITIATE_PROCESSING_ON_EVERY_ARRIVAL 0x00000020 - # define KSPIN_FLAG_FRAMES_NOT_REQUIRED_FOR_PROCESSING 0x00000040 - # define KSPIN_FLAG_ENFORCE_FIFO 0x00000080 - # define KSPIN_FLAG_GENERATE_MAPPINGS 0x00000100 - # define KSPIN_FLAG_DISTINCT_TRAILING_EDGE 0x00000200 - # define KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY 0x00010000 - # define KSPIN_FLAG_SPLITTER 0x00020000 - # define KSPIN_FLAG_USE_STANDARD_TRANSPORT 0x00040000 - # define KSPIN_FLAG_DO_NOT_USE_STANDARD_TRANSPORT 0x00080000 - # define KSPIN_FLAG_FIXED_FORMAT 0x00100000 - # define KSPIN_FLAG_GENERATE_EOS_EVENTS 0x00200000 - # define KSPIN_FLAG_RENDERER (KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY | KSPIN_FLAG_GENERATE_EOS_EVENTS) - # define KSPIN_FLAG_IMPLEMENT_CLOCK 0x00400000 - # define KSPIN_FLAG_SOME_FRAMES_REQUIRED_FOR_PROCESSING 0x00800000 - # define KSPIN_FLAG_PROCESS_IF_ANY_IN_RUN_STATE 0x01000000 - # define KSPIN_FLAG_DENY_USERMODE_ACCESS 0x80000000 - ULONG InstancesPossible; - ULONG InstancesNecessary; - const KSALLOCATOR_FRAMING_EX* AllocatorFraming; - PFNKSINTERSECTHANDLEREX IntersectHandler; -}; - - # define DEFINE_KSPIN_DEFAULT_INTERFACES \ - 0, \ - NULL - - # define DEFINE_KSPIN_DEFAULT_MEDIUMS \ - 0, \ - NULL - -struct _KSNODE_DESCRIPTOR -{ - const KSAUTOMATION_TABLE* AutomationTable; - const GUID* Type; - const GUID* Name; - # ifndef _WIN64 - PVOID Alignment; - # endif -}; - - # ifndef _WIN64 - # define DEFINE_NODE_DESCRIPTOR(automation, type, name) \ - { (automation), (type), (name), NULL } - # else - # define DEFINE_NODE_DESCRIPTOR(automation, type, name) \ - { (automation), (type), (name) } - # endif - -struct _KSDEVICE -{ - const KSDEVICE_DESCRIPTOR* Descriptor; - KSOBJECT_BAG Bag; - PVOID Context; - PDEVICE_OBJECT FunctionalDeviceObject; - PDEVICE_OBJECT PhysicalDeviceObject; - PDEVICE_OBJECT NextDeviceObject; - BOOLEAN Started; - SYSTEM_POWER_STATE SystemPowerState; - DEVICE_POWER_STATE DevicePowerState; -}; - -struct _KSFILTERFACTORY -{ - const KSFILTER_DESCRIPTOR* FilterDescriptor; - KSOBJECT_BAG Bag; - PVOID Context; -}; - -struct _KSFILTER -{ - const KSFILTER_DESCRIPTOR* Descriptor; - KSOBJECT_BAG Bag; - PVOID Context; -}; - -struct _KSPIN -{ - const KSPIN_DESCRIPTOR_EX* Descriptor; - KSOBJECT_BAG Bag; - PVOID Context; - ULONG Id; - KSPIN_COMMUNICATION Communication; - BOOLEAN ConnectionIsExternal; - KSPIN_INTERFACE ConnectionInterface; - KSPIN_MEDIUM ConnectionMedium; - KSPRIORITY ConnectionPriority; - PKSDATAFORMAT ConnectionFormat; - PKSMULTIPLE_ITEM AttributeList; - ULONG StreamHeaderSize; - KSPIN_DATAFLOW DataFlow; - KSSTATE DeviceState; - KSRESET ResetState; - KSSTATE ClientState; -}; - -struct _KSMAPPING -{ - PHYSICAL_ADDRESS PhysicalAddress; - ULONG ByteCount; - ULONG Alignment; -}; - -struct _KSSTREAM_POINTER_OFFSET -{ - # if defined(_NTDDK_) - __MINGW_EXTENSION union - { - PUCHAR Data; - PKSMAPPING Mappings; - }; - # else - PUCHAR Data; - # endif /* _NTDDK_ */ - # ifndef _WIN64 - PVOID Alignment; - # endif - ULONG Count; - ULONG Remaining; -}; - -struct _KSSTREAM_POINTER -{ - PVOID Context; - PKSPIN Pin; - PKSSTREAM_HEADER StreamHeader; - PKSSTREAM_POINTER_OFFSET Offset; - KSSTREAM_POINTER_OFFSET OffsetIn; - KSSTREAM_POINTER_OFFSET OffsetOut; -}; - -struct _KSPROCESSPIN -{ - PKSPIN Pin; - PKSSTREAM_POINTER StreamPointer; - PKSPROCESSPIN InPlaceCounterpart; - PKSPROCESSPIN DelegateBranch; - PKSPROCESSPIN CopySource; - PVOID Data; - ULONG BytesAvailable; - ULONG BytesUsed; - ULONG Flags; - BOOLEAN Terminate; -}; - -struct _KSPROCESSPIN_INDEXENTRY -{ - PKSPROCESSPIN* Pins; - ULONG Count; -}; - -typedef enum -{ - KsObjectTypeDevice, - KsObjectTypeFilterFactory, - KsObjectTypeFilter, - KsObjectTypePin -}KSOBJECTTYPE; - -typedef void (*PFNKSFREE)(PVOID Data); - -typedef void (*PFNKSPINFRAMERETURN)(PKSPIN Pin, PVOID Data, ULONG Size, PMDL Mdl, - PVOID Context, NTSTATUS Status); - -typedef void (*PFNKSPINIRPCOMPLETION)(PKSPIN Pin, PIRP Irp); - - # if defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__) - # ifndef _IKsControl_ - # define _IKsControl_ - -typedef struct IKsControl* PIKSCONTROL; - - # ifndef DEFINE_ABSTRACT_UNKNOWN - # define DEFINE_ABSTRACT_UNKNOWN() \ - STDMETHOD_(NTSTATUS, QueryInterface) (THIS_ \ - REFIID InterfaceId, \ - PVOID * Interface \ - )PURE; \ - STDMETHOD_(ULONG, AddRef) (THIS)PURE; \ - STDMETHOD_(ULONG, Release) (THIS)PURE; - # endif - - # undef INTERFACE - # define INTERFACE IKsControl -DECLARE_INTERFACE_(IKsControl, IUnknown) -{ - DEFINE_ABSTRACT_UNKNOWN() - STDMETHOD_(NTSTATUS, KsProperty) (THIS_ - PKSPROPERTY Property, - ULONG PropertyLength, - PVOID PropertyData, - ULONG DataLength, - ULONG * BytesReturned - ) PURE; - STDMETHOD_(NTSTATUS, KsMethod) (THIS_ - PKSMETHOD Method, - ULONG MethodLength, - PVOID MethodData, - ULONG DataLength, - ULONG * BytesReturned - ) PURE; - STDMETHOD_(NTSTATUS, KsEvent) (THIS_ - PKSEVENT Event, - ULONG EventLength, - PVOID EventData, - ULONG DataLength, - ULONG * BytesReturned - ) PURE; -}; -typedef struct IKsReferenceClock* PIKSREFERENCECLOCK; - - # undef INTERFACE - # define INTERFACE IKsReferenceClock -DECLARE_INTERFACE_(IKsReferenceClock, IUnknown) -{ - DEFINE_ABSTRACT_UNKNOWN() - STDMETHOD_(LONGLONG, GetTime) (THIS) PURE; - STDMETHOD_(LONGLONG, GetPhysicalTime) (THIS) PURE; - STDMETHOD_(LONGLONG, GetCorrelatedTime) (THIS_ - PLONGLONG SystemTime - ) PURE; - STDMETHOD_(LONGLONG, GetCorrelatedPhysicalTime) (THIS_ - PLONGLONG SystemTime - ) PURE; - STDMETHOD_(NTSTATUS, GetResolution) (THIS_ - PKSRESOLUTION Resolution - ) PURE; - STDMETHOD_(NTSTATUS, GetState) (THIS_ - PKSSTATE State - ) PURE; -}; - # undef INTERFACE - - # define INTERFACE IKsDeviceFunctions -DECLARE_INTERFACE_(IKsDeviceFunctions, IUnknown) -{ - DEFINE_ABSTRACT_UNKNOWN() - STDMETHOD_(NTSTATUS, RegisterAdapterObjectEx) (THIS_ - PADAPTER_OBJECT AdapterObject, - PDEVICE_DESCRIPTION DeviceDescription, - ULONG NumberOfMapRegisters, - ULONG MaxMappingsByteCount, - ULONG MappingTableStride - ) PURE; -}; - - # undef INTERFACE - # define STATIC_IID_IKsControl \ - 0x28F54685L, 0x06FD, 0x11D2, 0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUID(IID_IKsControl, - 0x28F54685L, 0x06FD, 0x11D2, 0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96); - # define STATIC_IID_IKsFastClock \ - 0xc9902485, 0xc180, 0x11d2, 0x84, 0x73, 0xd4, 0x23, 0x94, 0x45, 0x9e, 0x5e -DEFINE_GUID(IID_IKsFastClock, - 0xc9902485, 0xc180, 0x11d2, 0x84, 0x73, 0xd4, 0x23, 0x94, 0x45, 0x9e, 0x5e); - # define STATIC_IID_IKsDeviceFunctions \ - 0xe234f2e2, 0xbd69, 0x4f8c, 0xb3, 0xf2, 0x7c, 0xd7, 0x9e, 0xd4, 0x66, 0xbd -DEFINE_GUID(IID_IKsDeviceFunctions, - 0xe234f2e2, 0xbd69, 0x4f8c, 0xb3, 0xf2, 0x7c, 0xd7, 0x9e, 0xd4, 0x66, 0xbd); - # endif /* _IKsControl_ */ - # endif /* defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__) */ - -#endif /* _NTDDK_ */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _KSDDK_ - # define KSDDKAPI -#else - # define KSDDKAPI DECLSPEC_IMPORT -#endif - -#if defined(_NTDDK_) - -KSDDKAPI NTSTATUS NTAPI KsEnableEvent(PIRP Irp, ULONG EventSetsCount, const KSEVENT_SET* EventSet, PLIST_ENTRY EventsList, KSEVENTS_LOCKTYPE EventsFlags, PVOID EventsLock); - -KSDDKAPI NTSTATUS NTAPI KsEnableEventWithAllocator(PIRP Irp, ULONG EventSetsCount, const KSEVENT_SET* EventSet, PLIST_ENTRY EventsList, KSEVENTS_LOCKTYPE EventsFlags, PVOID EventsLock, PFNKSALLOCATOR Allocator, ULONG EventItemSize); - -KSDDKAPI NTSTATUS NTAPI KsDisableEvent(PIRP Irp, PLIST_ENTRY EventsList, KSEVENTS_LOCKTYPE EventsFlags, PVOID EventsLock); - -KSDDKAPI VOID NTAPI KsDiscardEvent(PKSEVENT_ENTRY EventEntry); - -KSDDKAPI VOID NTAPI KsFreeEventList(PFILE_OBJECT FileObject, PLIST_ENTRY EventsList, KSEVENTS_LOCKTYPE EventsFlags, PVOID EventsLock); - -KSDDKAPI NTSTATUS NTAPI KsGenerateEvent(PKSEVENT_ENTRY EventEntry); - -KSDDKAPI NTSTATUS NTAPI KsGenerateDataEvent(PKSEVENT_ENTRY EventEntry, ULONG DataSize, PVOID Data); - -KSDDKAPI VOID NTAPI KsGenerateEventList(GUID* Set, ULONG EventId, PLIST_ENTRY EventsList, KSEVENTS_LOCKTYPE EventsFlags, PVOID EventsLock); - -KSDDKAPI NTSTATUS NTAPI KsPropertyHandler(PIRP Irp, ULONG PropertySetsCount, const KSPROPERTY_SET* PropertySet); - -KSDDKAPI NTSTATUS NTAPI KsPropertyHandlerWithAllocator(PIRP Irp, ULONG PropertySetsCount, const KSPROPERTY_SET* PropertySet, PFNKSALLOCATOR Allocator, ULONG PropertyItemSize); - -KSDDKAPI BOOLEAN NTAPI KsFastPropertyHandler(PFILE_OBJECT FileObject, PKSPROPERTY Property, ULONG PropertyLength, PVOID Data, ULONG DataLength, PIO_STATUS_BLOCK IoStatus, ULONG PropertySetsCount, const KSPROPERTY_SET* PropertySet); - -KSDDKAPI NTSTATUS NTAPI KsMethodHandler(PIRP Irp, ULONG MethodSetsCount, const KSMETHOD_SET* MethodSet); - -KSDDKAPI NTSTATUS NTAPI KsMethodHandlerWithAllocator(PIRP Irp, ULONG MethodSetsCount, const KSMETHOD_SET* MethodSet, PFNKSALLOCATOR Allocator, ULONG MethodItemSize); - -KSDDKAPI BOOLEAN NTAPI KsFastMethodHandler(PFILE_OBJECT FileObject, PKSMETHOD Method, ULONG MethodLength, PVOID Data, ULONG DataLength, PIO_STATUS_BLOCK IoStatus, ULONG MethodSetsCount, const KSMETHOD_SET* MethodSet); - -KSDDKAPI NTSTATUS NTAPI KsCreateDefaultAllocator(PIRP Irp); - -KSDDKAPI NTSTATUS NTAPI KsCreateDefaultAllocatorEx(PIRP Irp, PVOID InitializeContext, PFNKSDEFAULTALLOCATE DefaultAllocate, PFNKSDEFAULTFREE DefaultFree, PFNKSINITIALIZEALLOCATOR InitializeAllocator, PFNKSDELETEALLOCATOR DeleteAllocator); - -KSDDKAPI NTSTATUS NTAPI KsCreateAllocator(HANDLE ConnectionHandle, PKSALLOCATOR_FRAMING AllocatorFraming, PHANDLE AllocatorHandle); - -KSDDKAPI NTSTATUS NTAPI KsValidateAllocatorCreateRequest(PIRP Irp, PKSALLOCATOR_FRAMING* AllocatorFraming); - -KSDDKAPI NTSTATUS NTAPI KsValidateAllocatorFramingEx(PKSALLOCATOR_FRAMING_EX Framing, ULONG BufferSize, const KSALLOCATOR_FRAMING_EX* PinFraming); - -KSDDKAPI NTSTATUS NTAPI KsAllocateDefaultClock(PKSDEFAULTCLOCK* DefaultClock); - -KSDDKAPI NTSTATUS NTAPI KsAllocateDefaultClockEx(PKSDEFAULTCLOCK* DefaultClock, PVOID Context, PFNKSSETTIMER SetTimer, PFNKSCANCELTIMER CancelTimer, PFNKSCORRELATEDTIME CorrelatedTime, const KSRESOLUTION* Resolution, ULONG Flags); - -KSDDKAPI VOID NTAPI KsFreeDefaultClock(PKSDEFAULTCLOCK DefaultClock); -KSDDKAPI NTSTATUS NTAPI KsCreateDefaultClock(PIRP Irp, PKSDEFAULTCLOCK DefaultClock); - -KSDDKAPI NTSTATUS NTAPI KsCreateClock(HANDLE ConnectionHandle, PKSCLOCK_CREATE ClockCreate, PHANDLE ClockHandle); - -KSDDKAPI NTSTATUS NTAPI KsValidateClockCreateRequest(PIRP Irp, PKSCLOCK_CREATE* ClockCreate); - -KSDDKAPI KSSTATE NTAPI KsGetDefaultClockState(PKSDEFAULTCLOCK DefaultClock); -KSDDKAPI VOID NTAPI KsSetDefaultClockState(PKSDEFAULTCLOCK DefaultClock, KSSTATE State); -KSDDKAPI LONGLONG NTAPI KsGetDefaultClockTime(PKSDEFAULTCLOCK DefaultClock); -KSDDKAPI VOID NTAPI KsSetDefaultClockTime(PKSDEFAULTCLOCK DefaultClock, LONGLONG Time); - -KSDDKAPI NTSTATUS NTAPI KsCreatePin(HANDLE FilterHandle, PKSPIN_CONNECT Connect, ACCESS_MASK DesiredAccess, PHANDLE ConnectionHandle); - -KSDDKAPI NTSTATUS NTAPI KsValidateConnectRequest(PIRP Irp, ULONG DescriptorsCount, const KSPIN_DESCRIPTOR* Descriptor, PKSPIN_CONNECT* Connect); - -KSDDKAPI NTSTATUS NTAPI KsPinPropertyHandler(PIRP Irp, PKSPROPERTY Property, PVOID Data, ULONG DescriptorsCount, const KSPIN_DESCRIPTOR* Descriptor); - -KSDDKAPI NTSTATUS NTAPI KsPinDataIntersection(PIRP Irp, PKSP_PIN Pin, PVOID Data, ULONG DescriptorsCount, const KSPIN_DESCRIPTOR* Descriptor, PFNKSINTERSECTHANDLER IntersectHandler); - -KSDDKAPI NTSTATUS NTAPI KsPinDataIntersectionEx(PIRP Irp, PKSP_PIN Pin, PVOID Data, ULONG DescriptorsCount, const KSPIN_DESCRIPTOR* Descriptor, ULONG DescriptorSize, PFNKSINTERSECTHANDLEREX IntersectHandler, PVOID HandlerContext); - -KSDDKAPI NTSTATUS NTAPI KsHandleSizedListQuery(PIRP Irp, ULONG DataItemsCount, ULONG DataItemSize, const VOID* DataItems); - - # ifndef MAKEINTRESOURCE - # define MAKEINTRESOURCE(r) ((ULONG_PTR)(USHORT)r) - # endif - # ifndef RT_STRING - # define RT_STRING MAKEINTRESOURCE(6) - # define RT_RCDATA MAKEINTRESOURCE(10) - # endif - -KSDDKAPI NTSTATUS NTAPI KsLoadResource(PVOID ImageBase, POOL_TYPE PoolType, ULONG_PTR ResourceName, ULONG ResourceType, PVOID* Resource, PULONG ResourceSize); - -KSDDKAPI NTSTATUS NTAPI KsGetImageNameAndResourceId(HANDLE RegKey, PUNICODE_STRING ImageName, PULONG_PTR ResourceId, PULONG ValueType); - -KSDDKAPI NTSTATUS NTAPI KsMapModuleName(PDEVICE_OBJECT PhysicalDeviceObject, PUNICODE_STRING ModuleName, PUNICODE_STRING ImageName, PULONG_PTR ResourceId, PULONG ValueType); - -KSDDKAPI NTSTATUS NTAPI KsReferenceBusObject(KSDEVICE_HEADER Header); -KSDDKAPI VOID NTAPI KsDereferenceBusObject(KSDEVICE_HEADER Header); -KSDDKAPI NTSTATUS NTAPI KsDispatchQuerySecurity(PDEVICE_OBJECT DeviceObject, PIRP Irp); -KSDDKAPI NTSTATUS NTAPI KsDispatchSetSecurity(PDEVICE_OBJECT DeviceObject, PIRP Irp); -KSDDKAPI NTSTATUS NTAPI KsDispatchSpecificProperty(PIRP Irp, PFNKSHANDLER Handler); -KSDDKAPI NTSTATUS NTAPI KsDispatchSpecificMethod(PIRP Irp, PFNKSHANDLER Handler); - -KSDDKAPI NTSTATUS NTAPI KsReadFile(PFILE_OBJECT FileObject, PKEVENT Event, PVOID PortContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, ULONG Key, KPROCESSOR_MODE RequestorMode); - -KSDDKAPI NTSTATUS NTAPI KsWriteFile(PFILE_OBJECT FileObject, PKEVENT Event, PVOID PortContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, ULONG Key, KPROCESSOR_MODE RequestorMode); - -KSDDKAPI NTSTATUS NTAPI KsQueryInformationFile(PFILE_OBJECT FileObject, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass); - -KSDDKAPI NTSTATUS NTAPI KsSetInformationFile(PFILE_OBJECT FileObject, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass); - -KSDDKAPI NTSTATUS NTAPI KsStreamIo(PFILE_OBJECT FileObject, PKEVENT Event, PVOID PortContext, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext, KSCOMPLETION_INVOCATION CompletionInvocationFlags, PIO_STATUS_BLOCK IoStatusBlock, PVOID StreamHeaders, ULONG Length, ULONG Flags, KPROCESSOR_MODE RequestorMode); - -KSDDKAPI NTSTATUS NTAPI KsProbeStreamIrp(PIRP Irp, ULONG ProbeFlags, ULONG HeaderSize); -KSDDKAPI NTSTATUS NTAPI KsAllocateExtraData(PIRP Irp, ULONG ExtraSize, PVOID* ExtraBuffer); -KSDDKAPI VOID NTAPI KsNullDriverUnload(PDRIVER_OBJECT DriverObject); - -KSDDKAPI NTSTATUS NTAPI KsSetMajorFunctionHandler(PDRIVER_OBJECT DriverObject, ULONG MajorFunction); - -KSDDKAPI NTSTATUS NTAPI KsDispatchInvalidDeviceRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -KSDDKAPI NTSTATUS NTAPI KsDefaultDeviceIoCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -KSDDKAPI NTSTATUS NTAPI KsDispatchIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -KSDDKAPI BOOLEAN NTAPI KsDispatchFastIoDeviceControlFailure(PFILE_OBJECT FileObject, BOOLEAN Wait, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength, ULONG IoControlCode, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject); - -KSDDKAPI BOOLEAN NTAPI KsDispatchFastReadFailure(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject); - - # define KsDispatchFastWriteFailure KsDispatchFastReadFailure - -KSDDKAPI VOID NTAPI KsCancelRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp); -KSDDKAPI VOID NTAPI KsCancelIo(PLIST_ENTRY QueueHead, PKSPIN_LOCK SpinLock); -KSDDKAPI VOID NTAPI KsReleaseIrpOnCancelableQueue(PIRP Irp, PDRIVER_CANCEL DriverCancel); - -KSDDKAPI PIRP NTAPI KsRemoveIrpFromCancelableQueue(PLIST_ENTRY QueueHead, PKSPIN_LOCK SpinLock, KSLIST_ENTRY_LOCATION ListLocation, KSIRP_REMOVAL_OPERATION RemovalOperation); - -KSDDKAPI NTSTATUS NTAPI KsMoveIrpsOnCancelableQueue(PLIST_ENTRY SourceList, PKSPIN_LOCK SourceLock, PLIST_ENTRY DestinationList, PKSPIN_LOCK DestinationLock, KSLIST_ENTRY_LOCATION ListLocation, PFNKSIRPLISTCALLBACK ListCallback, PVOID Context); - -KSDDKAPI VOID NTAPI KsRemoveSpecificIrpFromCancelableQueue(PIRP Irp); - -KSDDKAPI VOID NTAPI KsAddIrpToCancelableQueue(PLIST_ENTRY QueueHead, PKSPIN_LOCK SpinLock, PIRP Irp, KSLIST_ENTRY_LOCATION ListLocation, PDRIVER_CANCEL DriverCancel); - -KSDDKAPI NTSTATUS NTAPI KsAcquireResetValue(PIRP Irp, KSRESET* ResetValue); - -KSDDKAPI NTSTATUS NTAPI KsTopologyPropertyHandler(PIRP Irp, PKSPROPERTY Property, PVOID Data, const KSTOPOLOGY* Topology); - -KSDDKAPI VOID NTAPI KsAcquireDeviceSecurityLock(KSDEVICE_HEADER Header, BOOLEAN Exclusive); -KSDDKAPI VOID NTAPI KsReleaseDeviceSecurityLock(KSDEVICE_HEADER Header); -KSDDKAPI NTSTATUS NTAPI KsDefaultDispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp); -KSDDKAPI NTSTATUS NTAPI KsDefaultDispatchPower(PDEVICE_OBJECT DeviceObject, PIRP Irp); -KSDDKAPI NTSTATUS NTAPI KsDefaultForwardIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -KSDDKAPI VOID NTAPI KsSetDevicePnpAndBaseObject(KSDEVICE_HEADER Header, PDEVICE_OBJECT PnpDeviceObject, PDEVICE_OBJECT BaseObject); - -KSDDKAPI PDEVICE_OBJECT NTAPI KsQueryDevicePnpObject(KSDEVICE_HEADER Header); -KSDDKAPI ACCESS_MASK NTAPI KsQueryObjectAccessMask(KSOBJECT_HEADER Header); - -KSDDKAPI VOID NTAPI KsRecalculateStackDepth(KSDEVICE_HEADER Header, BOOLEAN ReuseStackLocation); - -KSDDKAPI VOID NTAPI KsSetTargetState(KSOBJECT_HEADER Header, KSTARGET_STATE TargetState); - -KSDDKAPI VOID NTAPI KsSetTargetDeviceObject(KSOBJECT_HEADER Header, PDEVICE_OBJECT TargetDevice); - -KSDDKAPI VOID NTAPI KsSetPowerDispatch(KSOBJECT_HEADER Header, PFNKSCONTEXT_DISPATCH PowerDispatch, PVOID PowerContext); - -KSDDKAPI PKSOBJECT_CREATE_ITEM NTAPI KsQueryObjectCreateItem(KSOBJECT_HEADER Header); - -KSDDKAPI NTSTATUS NTAPI KsAllocateDeviceHeader(KSDEVICE_HEADER* Header, ULONG ItemsCount, PKSOBJECT_CREATE_ITEM ItemsList); - -KSDDKAPI VOID NTAPI KsFreeDeviceHeader(KSDEVICE_HEADER Header); - -KSDDKAPI NTSTATUS NTAPI KsAllocateObjectHeader(KSOBJECT_HEADER* Header, ULONG ItemsCount, PKSOBJECT_CREATE_ITEM ItemsList, PIRP Irp, const KSDISPATCH_TABLE* Table); - -KSDDKAPI VOID NTAPI KsFreeObjectHeader(KSOBJECT_HEADER Header); - -KSDDKAPI NTSTATUS NTAPI KsAddObjectCreateItemToDeviceHeader(KSDEVICE_HEADER Header, PDRIVER_DISPATCH Create, PVOID Context, PWSTR ObjectClass, PSECURITY_DESCRIPTOR SecurityDescriptor); - -KSDDKAPI NTSTATUS NTAPI KsAddObjectCreateItemToObjectHeader(KSOBJECT_HEADER Header, PDRIVER_DISPATCH Create, PVOID Context, PWSTR ObjectClass, PSECURITY_DESCRIPTOR SecurityDescriptor); - -KSDDKAPI NTSTATUS NTAPI KsAllocateObjectCreateItem(KSDEVICE_HEADER Header, PKSOBJECT_CREATE_ITEM CreateItem, BOOLEAN AllocateEntry, PFNKSITEMFREECALLBACK ItemFreeCallback); - -KSDDKAPI NTSTATUS NTAPI KsFreeObjectCreateItem(KSDEVICE_HEADER Header, PUNICODE_STRING CreateItem); - -KSDDKAPI NTSTATUS NTAPI KsFreeObjectCreateItemsByContext(KSDEVICE_HEADER Header, PVOID Context); - -KSDDKAPI NTSTATUS NTAPI KsCreateDefaultSecurity(PSECURITY_DESCRIPTOR ParentSecurity, PSECURITY_DESCRIPTOR* DefaultSecurity); - -KSDDKAPI NTSTATUS NTAPI KsForwardIrp(PIRP Irp, PFILE_OBJECT FileObject, BOOLEAN ReuseStackLocation); - -KSDDKAPI NTSTATUS NTAPI KsForwardAndCatchIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp, PFILE_OBJECT FileObject, KSSTACK_USE StackUse); - -KSDDKAPI NTSTATUS NTAPI KsSynchronousIoControlDevice(PFILE_OBJECT FileObject, KPROCESSOR_MODE RequestorMode, ULONG IoControl, PVOID InBuffer, ULONG InSize, PVOID OutBuffer, ULONG OutSize, PULONG BytesReturned); - -KSDDKAPI NTSTATUS NTAPI KsUnserializeObjectPropertiesFromRegistry(PFILE_OBJECT FileObject, HANDLE ParentKey, PUNICODE_STRING RegistryPath); - -KSDDKAPI NTSTATUS NTAPI KsCacheMedium(PUNICODE_STRING SymbolicLink, PKSPIN_MEDIUM Medium, ULONG PinDirection); - -KSDDKAPI NTSTATUS NTAPI KsRegisterWorker(WORK_QUEUE_TYPE WorkQueueType, PKSWORKER* Worker); - -KSDDKAPI NTSTATUS NTAPI KsRegisterCountedWorker(WORK_QUEUE_TYPE WorkQueueType, PWORK_QUEUE_ITEM CountedWorkItem, PKSWORKER* Worker); - -KSDDKAPI VOID NTAPI KsUnregisterWorker(PKSWORKER Worker); -KSDDKAPI NTSTATUS NTAPI KsQueueWorkItem(PKSWORKER Worker, PWORK_QUEUE_ITEM WorkItem); -KSDDKAPI ULONG NTAPI KsIncrementCountedWorker(PKSWORKER Worker); -KSDDKAPI ULONG NTAPI KsDecrementCountedWorker(PKSWORKER Worker); - -KSDDKAPI NTSTATUS NTAPI KsCreateTopologyNode(HANDLE ParentHandle, PKSNODE_CREATE NodeCreate, ACCESS_MASK DesiredAccess, PHANDLE NodeHandle); - -KSDDKAPI NTSTATUS NTAPI KsValidateTopologyNodeCreateRequest(PIRP Irp, PKSTOPOLOGY Topology, PKSNODE_CREATE* NodeCreate); - -KSDDKAPI NTSTATUS NTAPI KsMergeAutomationTables(PKSAUTOMATION_TABLE* AutomationTableAB, PKSAUTOMATION_TABLE AutomationTableA, PKSAUTOMATION_TABLE AutomationTableB, KSOBJECT_BAG Bag); - -KSDDKAPI NTSTATUS NTAPI KsInitializeDriver(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPathName, const KSDEVICE_DESCRIPTOR* Descriptor); - -KSDDKAPI NTSTATUS NTAPI KsAddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject); - -KSDDKAPI NTSTATUS NTAPI KsCreateDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject, const KSDEVICE_DESCRIPTOR* Descriptor, ULONG ExtensionSize, PKSDEVICE* Device); - -KSDDKAPI NTSTATUS NTAPI KsInitializeDevice(PDEVICE_OBJECT FunctionalDeviceObject, PDEVICE_OBJECT PhysicalDeviceObject, PDEVICE_OBJECT NextDeviceObject, const KSDEVICE_DESCRIPTOR* Descriptor); - -KSDDKAPI void NTAPI KsTerminateDevice(PDEVICE_OBJECT DeviceObject); -KSDDKAPI PKSDEVICE NTAPI KsGetDeviceForDeviceObject(PDEVICE_OBJECT FunctionalDeviceObject); -KSDDKAPI void NTAPI KsAcquireDevice(PKSDEVICE Device); -KSDDKAPI void NTAPI KsReleaseDevice(PKSDEVICE Device); - -KSDDKAPI void NTAPI KsDeviceRegisterAdapterObject(PKSDEVICE Device, PADAPTER_OBJECT AdapterObject, ULONG MaxMappingsByteCount, ULONG MappingTableStride); - -KSDDKAPI ULONG NTAPI KsDeviceGetBusData(PKSDEVICE Device, ULONG DataType, PVOID Buffer, ULONG Offset, ULONG Length); - -KSDDKAPI ULONG NTAPI KsDeviceSetBusData(PKSDEVICE Device, ULONG DataType, PVOID Buffer, ULONG Offset, ULONG Length); - -KSDDKAPI NTSTATUS NTAPI KsCreateFilterFactory(PDEVICE_OBJECT DeviceObject, const KSFILTER_DESCRIPTOR* Descriptor, PWSTR RefString, PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG CreateItemFlags, PFNKSFILTERFACTORYPOWER SleepCallback, PFNKSFILTERFACTORYPOWER WakeCallback, PKSFILTERFACTORY* FilterFactory); - - # define KsDeleteFilterFactory(FilterFactory) \ - KsFreeObjectCreateItemsByContext(*(KSDEVICE_HEADER*)( \ - KsFilterFactoryGetParentDevice(FilterFactory)->FunctionalDeviceObject->DeviceExtension), \ - FilterFactory) - -KSDDKAPI NTSTATUS NTAPI KsFilterFactoryUpdateCacheData(PKSFILTERFACTORY FilterFactory, const KSFILTER_DESCRIPTOR* FilterDescriptor); - -KSDDKAPI NTSTATUS NTAPI KsFilterFactoryAddCreateItem(PKSFILTERFACTORY FilterFactory, PWSTR RefString, PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG CreateItemFlags); - -KSDDKAPI NTSTATUS NTAPI KsFilterFactorySetDeviceClassesState(PKSFILTERFACTORY FilterFactory, BOOLEAN NewState); - -KSDDKAPI PUNICODE_STRING NTAPI KsFilterFactoryGetSymbolicLink(PKSFILTERFACTORY FilterFactory); - -KSDDKAPI void NTAPI KsAddEvent(PVOID Object, PKSEVENT_ENTRY EventEntry); - -void __forceinline KsFilterAddEvent(PKSFILTER Filter, PKSEVENT_ENTRY EventEntry) -{ - KsAddEvent(Filter, EventEntry); -} - -void __forceinline KsPinAddEvent(PKSPIN Pin, PKSEVENT_ENTRY EventEntry) -{ - KsAddEvent(Pin, EventEntry); -} - -KSDDKAPI NTSTATUS NTAPI KsDefaultAddEventHandler(PIRP Irp, PKSEVENTDATA EventData, PKSEVENT_ENTRY EventEntry); - -KSDDKAPI void NTAPI KsGenerateEvents(PVOID Object, const GUID* EventSet, ULONG EventId, ULONG DataSize, PVOID Data, PFNKSGENERATEEVENTCALLBACK CallBack, PVOID CallBackContext); - -void __forceinline KsFilterGenerateEvents(PKSFILTER Filter, const GUID* EventSet, ULONG EventId, ULONG DataSize, PVOID Data, PFNKSGENERATEEVENTCALLBACK CallBack, PVOID CallBackContext) -{ - KsGenerateEvents(Filter, EventSet, EventId, DataSize, Data, CallBack, - CallBackContext); -} - -void __forceinline KsPinGenerateEvents(PKSPIN Pin, const GUID* EventSet, ULONG EventId, ULONG DataSize, PVOID Data, PFNKSGENERATEEVENTCALLBACK CallBack, PVOID CallBackContext) -{ - KsGenerateEvents(Pin, EventSet, EventId, DataSize, Data, CallBack, - CallBackContext); -} - -typedef enum -{ - KSSTREAM_POINTER_STATE_UNLOCKED = 0, - KSSTREAM_POINTER_STATE_LOCKED -}KSSTREAM_POINTER_STATE; - -KSDDKAPI NTSTATUS NTAPI KsPinGetAvailableByteCount(PKSPIN Pin, PLONG InputDataBytes, PLONG OutputBufferBytes); - -KSDDKAPI PKSSTREAM_POINTER NTAPI KsPinGetLeadingEdgeStreamPointer(PKSPIN Pin, KSSTREAM_POINTER_STATE State); - -KSDDKAPI PKSSTREAM_POINTER NTAPI KsPinGetTrailingEdgeStreamPointer(PKSPIN Pin, KSSTREAM_POINTER_STATE State); - -KSDDKAPI NTSTATUS NTAPI KsStreamPointerSetStatusCode(PKSSTREAM_POINTER StreamPointer, NTSTATUS Status); - -KSDDKAPI NTSTATUS NTAPI KsStreamPointerLock(PKSSTREAM_POINTER StreamPointer); -KSDDKAPI void NTAPI KsStreamPointerUnlock(PKSSTREAM_POINTER StreamPointer, BOOLEAN Eject); - -KSDDKAPI void NTAPI KsStreamPointerAdvanceOffsetsAndUnlock(PKSSTREAM_POINTER StreamPointer, ULONG InUsed, ULONG OutUsed, BOOLEAN Eject); - -KSDDKAPI void NTAPI KsStreamPointerDelete(PKSSTREAM_POINTER StreamPointer); - -KSDDKAPI NTSTATUS NTAPI KsStreamPointerClone(PKSSTREAM_POINTER StreamPointer, PFNKSSTREAMPOINTER CancelCallback, ULONG ContextSize, PKSSTREAM_POINTER* CloneStreamPointer); - -KSDDKAPI NTSTATUS NTAPI KsStreamPointerAdvanceOffsets(PKSSTREAM_POINTER StreamPointer, ULONG InUsed, ULONG OutUsed, BOOLEAN Eject); - -KSDDKAPI NTSTATUS NTAPI KsStreamPointerAdvance(PKSSTREAM_POINTER StreamPointer); -KSDDKAPI PMDL NTAPI KsStreamPointerGetMdl(PKSSTREAM_POINTER StreamPointer); - -KSDDKAPI PIRP NTAPI KsStreamPointerGetIrp(PKSSTREAM_POINTER StreamPointer, PBOOLEAN FirstFrameInIrp, PBOOLEAN LastFrameInIrp); - -KSDDKAPI void NTAPI KsStreamPointerScheduleTimeout(PKSSTREAM_POINTER StreamPointer, PFNKSSTREAMPOINTER Callback, ULONGLONG Interval); - -KSDDKAPI void NTAPI KsStreamPointerCancelTimeout(PKSSTREAM_POINTER StreamPointer); -KSDDKAPI PKSSTREAM_POINTER NTAPI KsPinGetFirstCloneStreamPointer(PKSPIN Pin); - -KSDDKAPI PKSSTREAM_POINTER NTAPI KsStreamPointerGetNextClone(PKSSTREAM_POINTER StreamPointer); - -KSDDKAPI NTSTATUS NTAPI KsPinHandshake(PKSPIN Pin, PKSHANDSHAKE In, PKSHANDSHAKE Out); -KSDDKAPI void NTAPI KsCompletePendingRequest(PIRP Irp); -KSDDKAPI KSOBJECTTYPE NTAPI KsGetObjectTypeFromIrp(PIRP Irp); -KSDDKAPI PVOID NTAPI KsGetObjectFromFileObject(PFILE_OBJECT FileObject); -KSDDKAPI KSOBJECTTYPE NTAPI KsGetObjectTypeFromFileObject(PFILE_OBJECT FileObject); - -PKSFILTER __forceinline KsGetFilterFromFileObject(PFILE_OBJECT FileObject) -{ - return (PKSFILTER)KsGetObjectFromFileObject(FileObject); -} - -PKSPIN __forceinline KsGetPinFromFileObject(PFILE_OBJECT FileObject) -{ - return (PKSPIN)KsGetObjectFromFileObject(FileObject); -} - -KSDDKAPI PKSGATE NTAPI KsFilterGetAndGate(PKSFILTER Filter); -KSDDKAPI void NTAPI KsFilterAcquireProcessingMutex(PKSFILTER Filter); -KSDDKAPI void NTAPI KsFilterReleaseProcessingMutex(PKSFILTER Filter); -KSDDKAPI void NTAPI KsFilterAttemptProcessing(PKSFILTER Filter, BOOLEAN Asynchronous); -KSDDKAPI PKSGATE NTAPI KsPinGetAndGate(PKSPIN Pin); -KSDDKAPI void NTAPI KsPinAttachAndGate(PKSPIN Pin, PKSGATE AndGate); -KSDDKAPI void NTAPI KsPinAttachOrGate(PKSPIN Pin, PKSGATE OrGate); -KSDDKAPI void NTAPI KsPinAcquireProcessingMutex(PKSPIN Pin); -KSDDKAPI void NTAPI KsPinReleaseProcessingMutex(PKSPIN Pin); -KSDDKAPI BOOLEAN NTAPI KsProcessPinUpdate(PKSPROCESSPIN ProcessPin); - -KSDDKAPI void NTAPI KsPinGetCopyRelationships(PKSPIN Pin, PKSPIN* CopySource, PKSPIN* DelegateBranch); - -KSDDKAPI void NTAPI KsPinAttemptProcessing(PKSPIN Pin, BOOLEAN Asynchronous); -KSDDKAPI PVOID NTAPI KsGetParent(PVOID Object); - -PKSDEVICE __forceinline KsFilterFactoryGetParentDevice(PKSFILTERFACTORY FilterFactory) -{ - return (PKSDEVICE)KsGetParent((PVOID)FilterFactory); -} - -PKSFILTERFACTORY __forceinline KsFilterGetParentFilterFactory(PKSFILTER Filter) -{ - return (PKSFILTERFACTORY)KsGetParent((PVOID)Filter); -} - -KSDDKAPI PKSFILTER NTAPI KsPinGetParentFilter(PKSPIN Pin); -KSDDKAPI PVOID NTAPI KsGetFirstChild(PVOID Object); - -PKSFILTERFACTORY __forceinline KsDeviceGetFirstChildFilterFactory(PKSDEVICE Device) -{ - return (PKSFILTERFACTORY)KsGetFirstChild((PVOID)Device); -} - -PKSFILTER __forceinline KsFilterFactoryGetFirstChildFilter(PKSFILTERFACTORY FilterFactory) -{ - return (PKSFILTER)KsGetFirstChild((PVOID)FilterFactory); -} - -KSDDKAPI ULONG NTAPI KsFilterGetChildPinCount(PKSFILTER Filter, ULONG PinId); -KSDDKAPI PKSPIN NTAPI KsFilterGetFirstChildPin(PKSFILTER Filter, ULONG PinId); -KSDDKAPI PVOID NTAPI KsGetNextSibling(PVOID Object); -KSDDKAPI PKSPIN NTAPI KsPinGetNextSiblingPin(PKSPIN Pin); - -PKSFILTERFACTORY __forceinline KsFilterFactoryGetNextSiblingFilterFactory(PKSFILTERFACTORY FilterFactory) -{ - return (PKSFILTERFACTORY)KsGetNextSibling((PVOID)FilterFactory); -} - -PKSFILTER __forceinline KsFilterGetNextSiblingFilter(PKSFILTER Filter) -{ - return (PKSFILTER)KsGetNextSibling((PVOID)Filter); -} - -KSDDKAPI PKSDEVICE NTAPI KsGetDevice(PVOID Object); - -PKSDEVICE __forceinline KsFilterFactoryGetDevice(PKSFILTERFACTORY FilterFactory) -{ - return KsGetDevice((PVOID)FilterFactory); -} - -PKSDEVICE __forceinline KsFilterGetDevice(PKSFILTER Filter) -{ - return KsGetDevice((PVOID)Filter); -} - -PKSDEVICE __forceinline KsPinGetDevice(PKSPIN Pin) -{ - return KsGetDevice((PVOID)Pin); -} - -KSDDKAPI PKSFILTER NTAPI KsGetFilterFromIrp(PIRP Irp); -KSDDKAPI PKSPIN NTAPI KsGetPinFromIrp(PIRP Irp); -KSDDKAPI ULONG NTAPI KsGetNodeIdFromIrp(PIRP Irp); -KSDDKAPI void NTAPI KsAcquireControl(PVOID Object); -KSDDKAPI void NTAPI KsReleaseControl(PVOID Object); - -void __forceinline KsFilterAcquireControl(PKSFILTER Filter) -{ - KsAcquireControl((PVOID)Filter); -} - -void __forceinline KsFilterReleaseControl(PKSFILTER Filter) -{ - KsReleaseControl((PVOID)Filter); -} - -void __forceinline KsPinAcquireControl(PKSPIN Pin) -{ - KsAcquireControl((PVOID)Pin); -} - -void __forceinline KsPinReleaseControl(PKSPIN Pin) -{ - KsReleaseControl((PVOID)Pin); -} - -KSDDKAPI NTSTATUS NTAPI KsAddItemToObjectBag(KSOBJECT_BAG ObjectBag, PVOID Item, PFNKSFREE Free); - -KSDDKAPI ULONG NTAPI KsRemoveItemFromObjectBag(KSOBJECT_BAG ObjectBag, PVOID Item, BOOLEAN Free); - - # define KsDiscard(Object, Pointer) \ - KsRemoveItemFromObjectBag((Object)->Bag, (PVOID)(Pointer), TRUE) - -KSDDKAPI NTSTATUS NTAPI KsAllocateObjectBag(PKSDEVICE Device, KSOBJECT_BAG* ObjectBag); -KSDDKAPI void NTAPI KsFreeObjectBag(KSOBJECT_BAG ObjectBag); - -KSDDKAPI NTSTATUS NTAPI KsCopyObjectBagItems(KSOBJECT_BAG ObjectBagDestination, KSOBJECT_BAG ObjectBagSource); - -KSDDKAPI NTSTATUS NTAPI _KsEdit(KSOBJECT_BAG ObjectBag, PVOID* PointerToPointerToItem, ULONG NewSize, ULONG OldSize, ULONG Tag); - - # define KsEdit(Object, PointerToPointer, Tag) \ - _KsEdit((Object)->Bag, (PVOID*)(PointerToPointer), \ - sizeof(**(PointerToPointer)), sizeof(**(PointerToPointer)), (Tag)) - - # define KsEditSized(Object, PointerToPointer, NewSize, OldSize, Tag) \ - _KsEdit((Object)->Bag, (PVOID*)(PointerToPointer), (NewSize), (OldSize), (Tag)) - -KSDDKAPI NTSTATUS NTAPI KsRegisterFilterWithNoKSPins(PDEVICE_OBJECT DeviceObject, const GUID* InterfaceClassGUID, ULONG PinCount, WINBOOL* PinDirection, KSPIN_MEDIUM* MediumList, GUID* CategoryList); - -KSDDKAPI NTSTATUS NTAPI KsFilterCreatePinFactory(PKSFILTER Filter, const KSPIN_DESCRIPTOR_EX* const PinDescriptor, PULONG PinID); - -KSDDKAPI NTSTATUS NTAPI KsFilterCreateNode(PKSFILTER Filter, const KSNODE_DESCRIPTOR* const NodeDescriptor, PULONG NodeID); - -KSDDKAPI NTSTATUS NTAPI KsFilterAddTopologyConnections(PKSFILTER Filter, ULONG NewConnectionsCount, const KSTOPOLOGY_CONNECTION* const NewTopologyConnections); - -KSDDKAPI NTSTATUS NTAPI KsPinGetConnectedPinInterface(PKSPIN Pin, const GUID* InterfaceId, PVOID* Interface); - -KSDDKAPI PFILE_OBJECT NTAPI KsPinGetConnectedPinFileObject(PKSPIN Pin); -KSDDKAPI PDEVICE_OBJECT NTAPI KsPinGetConnectedPinDeviceObject(PKSPIN Pin); - -KSDDKAPI NTSTATUS NTAPI KsPinGetConnectedFilterInterface(PKSPIN Pin, const GUID* InterfaceId, PVOID* Interface); - - # if defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__) -KSDDKAPI NTSTATUS NTAPI KsPinGetReferenceClockInterface(PKSPIN Pin, PIKSREFERENCECLOCK* Interface); - # endif /* defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__) */ - -KSDDKAPI VOID NTAPI KsPinSetPinClockTime(PKSPIN Pin, LONGLONG Time); - -KSDDKAPI NTSTATUS NTAPI KsPinSubmitFrame(PKSPIN Pin, PVOID Data, ULONG Size, PKSSTREAM_HEADER StreamHeader, PVOID Context); - -KSDDKAPI NTSTATUS NTAPI KsPinSubmitFrameMdl(PKSPIN Pin, PMDL Mdl, PKSSTREAM_HEADER StreamHeader, PVOID Context); - -KSDDKAPI void NTAPI KsPinRegisterFrameReturnCallback(PKSPIN Pin, PFNKSPINFRAMERETURN FrameReturn); - -KSDDKAPI void NTAPI KsPinRegisterIrpCompletionCallback(PKSPIN Pin, PFNKSPINIRPCOMPLETION IrpCompletion); - -KSDDKAPI void NTAPI KsPinRegisterHandshakeCallback(PKSPIN Pin, PFNKSPINHANDSHAKE Handshake); - -KSDDKAPI void NTAPI KsFilterRegisterPowerCallbacks(PKSFILTER Filter, PFNKSFILTERPOWER Sleep, PFNKSFILTERPOWER Wake); - -KSDDKAPI void NTAPI KsPinRegisterPowerCallbacks(PKSPIN Pin, PFNKSPINPOWER Sleep, PFNKSPINPOWER Wake); - - # if defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__) -KSDDKAPI PUNKNOWN NTAPI KsRegisterAggregatedClientUnknown(PVOID Object, PUNKNOWN ClientUnknown); - -KSDDKAPI PUNKNOWN NTAPI KsGetOuterUnknown(PVOID Object); - -PUNKNOWN __forceinline KsDeviceRegisterAggregatedClientUnknown(PKSDEVICE Device, PUNKNOWN ClientUnknown) -{ - return KsRegisterAggregatedClientUnknown((PVOID)Device, ClientUnknown); -} - -PUNKNOWN __forceinline KsDeviceGetOuterUnknown(PKSDEVICE Device) -{ - return KsGetOuterUnknown((PVOID)Device); -} - -PUNKNOWN __forceinline KsFilterFactoryRegisterAggregatedClientUnknown(PKSFILTERFACTORY FilterFactory, PUNKNOWN ClientUnknown) -{ - return KsRegisterAggregatedClientUnknown((PVOID)FilterFactory, ClientUnknown); -} - -PUNKNOWN __forceinline KsFilterFactoryGetOuterUnknown(PKSFILTERFACTORY FilterFactory) -{ - return KsGetOuterUnknown((PVOID)FilterFactory); -} - -PUNKNOWN __forceinline KsFilterRegisterAggregatedClientUnknown(PKSFILTER Filter, PUNKNOWN ClientUnknown) -{ - return KsRegisterAggregatedClientUnknown((PVOID)Filter, ClientUnknown); -} - -PUNKNOWN __forceinline KsFilterGetOuterUnknown(PKSFILTER Filter) -{ - return KsGetOuterUnknown((PVOID)Filter); -} - -PUNKNOWN __forceinline KsPinRegisterAggregatedClientUnknown(PKSPIN Pin, PUNKNOWN ClientUnknown) -{ - return KsRegisterAggregatedClientUnknown((PVOID)Pin, ClientUnknown); -} - -PUNKNOWN __forceinline KsPinGetOuterUnknown(PKSPIN Pin) -{ - return KsGetOuterUnknown((PVOID)Pin); -} - - # endif /* defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__) */ - -#else /* _NTDDK_ */ - - # ifndef KS_NO_CREATE_FUNCTIONS -KSDDKAPI DWORD WINAPI KsCreateAllocator(HANDLE ConnectionHandle, PKSALLOCATOR_FRAMING AllocatorFraming, PHANDLE AllocatorHandle); -KSDDKAPI DWORD NTAPI KsCreateClock(HANDLE ConnectionHandle, PKSCLOCK_CREATE ClockCreate, PHANDLE ClockHandle); -KSDDKAPI DWORD WINAPI KsCreatePin(HANDLE FilterHandle, PKSPIN_CONNECT Connect, ACCESS_MASK DesiredAccess, PHANDLE ConnectionHandle); -KSDDKAPI DWORD WINAPI KsCreateTopologyNode(HANDLE ParentHandle, PKSNODE_CREATE NodeCreate, ACCESS_MASK DesiredAccess, PHANDLE NodeHandle); - # endif - -#endif /* _NTDDK_ */ - -#ifdef __cplusplus -} -#endif - -#define DENY_USERMODE_ACCESS(pIrp, CompleteRequest) \ - if(pIrp->RequestorMode != KernelMode){ \ - pIrp->IoStatus.Information = 0; \ - pIrp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; \ - if(CompleteRequest){ \ - IoCompleteRequest(pIrp, IO_NO_INCREMENT); } \ - return STATUS_INVALID_DEVICE_REQUEST; \ - } - -#endif /* _KS_ */ - diff --git a/include/ksmedia.h b/include/ksmedia.h deleted file mode 100644 index a01823b9..00000000 --- a/include/ksmedia.h +++ /dev/null @@ -1,4824 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the w64 mingw-runtime package. - */ -#if !defined(_KS_) - # warning ks.h must be included before ksmedia.h - # include "ks.h" -#endif - -#if __GNUC__ >= 3 - # pragma GCC system_header -#endif - -#if !defined(_KSMEDIA_) - # define _KSMEDIA_ - -typedef struct -{ - KSPROPERTY Property; - KSMULTIPLE_ITEM MultipleItem; -}KSMULTIPLE_DATA_PROP, * PKSMULTIPLE_DATA_PROP; - - # define STATIC_KSMEDIUMSETID_MidiBus \ - 0x05908040L, 0x3246, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("05908040-3246-11D0-A5D6-28DB04C10000", KSMEDIUMSETID_MidiBus); - # define KSMEDIUMSETID_MidiBus DEFINE_GUIDNAMED(KSMEDIUMSETID_MidiBus) - - # define STATIC_KSMEDIUMSETID_VPBus \ - 0xA18C15ECL, 0xCE43, 0x11D0, 0xAB, 0xE7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("A18C15EC-CE43-11D0-ABE7-00A0C9223196", KSMEDIUMSETID_VPBus); - # define KSMEDIUMSETID_VPBus DEFINE_GUIDNAMED(KSMEDIUMSETID_VPBus) - - # define STATIC_KSINTERFACESETID_Media \ - 0x3A13EB40L, 0x30A7, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("3A13EB40-30A7-11D0-A5D6-28DB04C10000", KSINTERFACESETID_Media); - # define KSINTERFACESETID_Media DEFINE_GUIDNAMED(KSINTERFACESETID_Media) - -typedef enum -{ - KSINTERFACE_MEDIA_MUSIC, - KSINTERFACE_MEDIA_WAVE_BUFFERED, - KSINTERFACE_MEDIA_WAVE_QUEUED -}KSINTERFACE_MEDIA; - - # ifndef INIT_USBAUDIO_MID - # define INIT_USBAUDIO_MID(guid, id) \ - { \ - (guid)->Data1 = 0x4e1cecd2 + (USHORT)(id); \ - (guid)->Data2 = 0x1679; \ - (guid)->Data3 = 0x463b; \ - (guid)->Data4[0] = 0xa7; \ - (guid)->Data4[1] = 0x2f; \ - (guid)->Data4[2] = 0xa5; \ - (guid)->Data4[3] = 0xbf; \ - (guid)->Data4[4] = 0x64; \ - (guid)->Data4[5] = 0xc8; \ - (guid)->Data4[6] = 0x6e; \ - (guid)->Data4[7] = 0xba; \ - } - # define EXTRACT_USBAUDIO_MID(guid) \ - (USHORT)((guid)->Data1 - 0x4e1cecd2) - # define DEFINE_USBAUDIO_MID_GUID(id) \ - 0x4e1cecd2 + (USHORT)(id), 0x1679, 0x463b, 0xa7, 0x2f, 0xa5, 0xbf, 0x64, 0xc8, 0x6e, 0xba - # define IS_COMPATIBLE_USBAUDIO_MID(guid) \ - (((guid)->Data1 >= 0x4e1cecd2) && \ - ((guid)->Data1 < 0x4e1cecd2 + 0xffff) && \ - ((guid)->Data2 == 0x1679) && \ - ((guid)->Data3 == 0x463b) && \ - ((guid)->Data4[0] == 0xa7) && \ - ((guid)->Data4[1] == 0x2f) && \ - ((guid)->Data4[2] == 0xa5) && \ - ((guid)->Data4[3] == 0xbf) && \ - ((guid)->Data4[4] == 0x64) && \ - ((guid)->Data4[5] == 0xc8) && \ - ((guid)->Data4[6] == 0x6e) && \ - ((guid)->Data4[7] == 0xba)) - # endif /* INIT_USBAUDIO_MID */ - - # ifndef INIT_USBAUDIO_PID - # define INIT_USBAUDIO_PID(guid, id) \ - { \ - (guid)->Data1 = 0xabcc5a5e + (USHORT)(id); \ - (guid)->Data2 = 0xc263; \ - (guid)->Data3 = 0x463b; \ - (guid)->Data4[0] = 0xa7; \ - (guid)->Data4[1] = 0x2f; \ - (guid)->Data4[2] = 0xa5; \ - (guid)->Data4[3] = 0xbf; \ - (guid)->Data4[4] = 0x64; \ - (guid)->Data4[5] = 0xc8; \ - (guid)->Data4[6] = 0x6e; \ - (guid)->Data4[7] = 0xba; \ - } - # define EXTRACT_USBAUDIO_PID(guid) \ - (USHORT)((guid)->Data1 - 0xabcc5a5e) - # define DEFINE_USBAUDIO_PID_GUID(id) \ - 0xabcc5a5e + (USHORT)(id), 0xc263, 0x463b, 0xa7, 0x2f, 0xa5, 0xbf, 0x64, 0xc8, 0x6e, 0xba - # define IS_COMPATIBLE_USBAUDIO_PID(guid) \ - (((guid)->Data1 >= 0xabcc5a5e) && \ - ((guid)->Data1 < 0xabcc5a5e + 0xffff) && \ - ((guid)->Data2 == 0xc263) && \ - ((guid)->Data3 == 0x463b) && \ - ((guid)->Data4[0] == 0xa7) && \ - ((guid)->Data4[1] == 0x2f) && \ - ((guid)->Data4[2] == 0xa5) && \ - ((guid)->Data4[3] == 0xbf) && \ - ((guid)->Data4[4] == 0x64) && \ - ((guid)->Data4[5] == 0xc8) && \ - ((guid)->Data4[6] == 0x6e) && \ - ((guid)->Data4[7] == 0xba)) - # endif /* INIT_USBAUDIO_PID */ - - # ifndef INIT_USBAUDIO_PRODUCT_NAME - # define INIT_USBAUDIO_PRODUCT_NAME(guid, vid, pid, strIndex) \ - { \ - (guid)->Data1 = 0XFC575048 + (USHORT)(vid); \ - (guid)->Data2 = 0x2E08 + (USHORT)(pid); \ - (guid)->Data3 = 0x463B + (USHORT)(strIndex); \ - (guid)->Data4[0] = 0xA7; \ - (guid)->Data4[1] = 0x2F; \ - (guid)->Data4[2] = 0xA5; \ - (guid)->Data4[3] = 0xBF; \ - (guid)->Data4[4] = 0x64; \ - (guid)->Data4[5] = 0xC8; \ - (guid)->Data4[6] = 0x6E; \ - (guid)->Data4[7] = 0xBA; \ - } - # define DEFINE_USBAUDIO_PRODUCT_NAME(vid, pid, strIndex) \ - 0xFC575048 + (USHORT)(vid), 0x2E08 + (USHORT)(pid), 0x463B + (USHORT)(strIndex), 0xA7, 0x2F, 0xA5, 0xBF, 0x64, 0xC8, 0x6E, 0xBA - # endif /* INIT_USBAUDIO_PRODUCT_NAME */ - - # define STATIC_KSCOMPONENTID_USBAUDIO \ - 0x8F1275F0, 0x26E9, 0x4264, 0xBA, 0x4D, 0x39, 0xFF, 0xF0, 0x1D, 0x94, 0xAA -DEFINE_GUIDSTRUCT("8F1275F0-26E9-4264-BA4D-39FFF01D94AA", KSCOMPONENTID_USBAUDIO); - # define KSCOMPONENTID_USBAUDIO DEFINE_GUIDNAMED(KSCOMPONENTID_USBAUDIO) - - # define INIT_USB_TERMINAL(guid, id) \ - { \ - (guid)->Data1 = 0xDFF219E0 + (USHORT)(id); \ - (guid)->Data2 = 0xF70F; \ - (guid)->Data3 = 0x11D0; \ - (guid)->Data4[0] = 0xb9; \ - (guid)->Data4[1] = 0x17; \ - (guid)->Data4[2] = 0x00; \ - (guid)->Data4[3] = 0xa0; \ - (guid)->Data4[4] = 0xc9; \ - (guid)->Data4[5] = 0x22; \ - (guid)->Data4[6] = 0x31; \ - (guid)->Data4[7] = 0x96; \ - } - # define EXTRACT_USB_TERMINAL(guid) \ - (USHORT)((guid)->Data1 - 0xDFF219E0) - # define DEFINE_USB_TERMINAL_GUID(id) \ - 0xDFF219E0 + (USHORT)(id), 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 - - # define STATIC_KSNODETYPE_MICROPHONE \ - DEFINE_USB_TERMINAL_GUID(0x0201) -DEFINE_GUIDSTRUCT("DFF21BE1-F70F-11D0-B917-00A0C9223196", KSNODETYPE_MICROPHONE); - # define KSNODETYPE_MICROPHONE DEFINE_GUIDNAMED(KSNODETYPE_MICROPHONE) - - # define STATIC_KSNODETYPE_DESKTOP_MICROPHONE \ - DEFINE_USB_TERMINAL_GUID(0x0202) -DEFINE_GUIDSTRUCT("DFF21BE2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DESKTOP_MICROPHONE); - # define KSNODETYPE_DESKTOP_MICROPHONE DEFINE_GUIDNAMED(KSNODETYPE_DESKTOP_MICROPHONE) - - # define STATIC_KSNODETYPE_PERSONAL_MICROPHONE \ - DEFINE_USB_TERMINAL_GUID(0x0203) -DEFINE_GUIDSTRUCT("DFF21BE3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_PERSONAL_MICROPHONE); - # define KSNODETYPE_PERSONAL_MICROPHONE DEFINE_GUIDNAMED(KSNODETYPE_PERSONAL_MICROPHONE) - - # define STATIC_KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE \ - DEFINE_USB_TERMINAL_GUID(0x0204) -DEFINE_GUIDSTRUCT("DFF21BE4-F70F-11D0-B917-00A0C9223196", KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE); - # define KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE DEFINE_GUIDNAMED(KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE) - - # define STATIC_KSNODETYPE_MICROPHONE_ARRAY \ - DEFINE_USB_TERMINAL_GUID(0x0205) -DEFINE_GUIDSTRUCT("DFF21BE5-F70F-11D0-B917-00A0C9223196", KSNODETYPE_MICROPHONE_ARRAY); - # define KSNODETYPE_MICROPHONE_ARRAY DEFINE_GUIDNAMED(KSNODETYPE_MICROPHONE_ARRAY) - - # define STATIC_KSNODETYPE_PROCESSING_MICROPHONE_ARRAY \ - DEFINE_USB_TERMINAL_GUID(0x0206) -DEFINE_GUIDSTRUCT("DFF21BE6-F70F-11D0-B917-00A0C9223196", KSNODETYPE_PROCESSING_MICROPHONE_ARRAY); - # define KSNODETYPE_PROCESSING_MICROPHONE_ARRAY DEFINE_GUIDNAMED(KSNODETYPE_PROCESSING_MICROPHONE_ARRAY) - - # define STATIC_KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR \ - 0x830a44f2, 0xa32d, 0x476b, 0xbe, 0x97, 0x42, 0x84, 0x56, 0x73, 0xb3, 0x5a -DEFINE_GUIDSTRUCT("830a44f2-a32d-476b-be97-42845673b35a", KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR); - # define KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR DEFINE_GUIDNAMED(KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR) - - # define STATIC_KSNODETYPE_SPEAKER \ - DEFINE_USB_TERMINAL_GUID(0x0301) -DEFINE_GUIDSTRUCT("DFF21CE1-F70F-11D0-B917-00A0C9223196", KSNODETYPE_SPEAKER); - # define KSNODETYPE_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_SPEAKER) - - # define STATIC_KSNODETYPE_HEADPHONES \ - DEFINE_USB_TERMINAL_GUID(0x0302) -DEFINE_GUIDSTRUCT("DFF21CE2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_HEADPHONES); - # define KSNODETYPE_HEADPHONES DEFINE_GUIDNAMED(KSNODETYPE_HEADPHONES) - - # define STATIC_KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO \ - DEFINE_USB_TERMINAL_GUID(0x0303) -DEFINE_GUIDSTRUCT("DFF21CE3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO); - # define KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO) - - # define STATIC_KSNODETYPE_DESKTOP_SPEAKER \ - DEFINE_USB_TERMINAL_GUID(0x0304) -DEFINE_GUIDSTRUCT("DFF21CE4-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DESKTOP_SPEAKER); - # define KSNODETYPE_DESKTOP_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_DESKTOP_SPEAKER) - - # define STATIC_KSNODETYPE_ROOM_SPEAKER \ - DEFINE_USB_TERMINAL_GUID(0x0305) -DEFINE_GUIDSTRUCT("DFF21CE5-F70F-11D0-B917-00A0C9223196", KSNODETYPE_ROOM_SPEAKER); - # define KSNODETYPE_ROOM_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_ROOM_SPEAKER) - - # define STATIC_KSNODETYPE_COMMUNICATION_SPEAKER \ - DEFINE_USB_TERMINAL_GUID(0x0306) -DEFINE_GUIDSTRUCT("DFF21CE6-F70F-11D0-B917-00A0C9223196", KSNODETYPE_COMMUNICATION_SPEAKER); - # define KSNODETYPE_COMMUNICATION_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_COMMUNICATION_SPEAKER) - - # define STATIC_KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER \ - DEFINE_USB_TERMINAL_GUID(0x0307) -DEFINE_GUIDSTRUCT("DFF21CE7-F70F-11D0-B917-00A0C9223196", KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER); - # define KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER) - - # define STATIC_KSNODETYPE_HANDSET \ - DEFINE_USB_TERMINAL_GUID(0x0401) -DEFINE_GUIDSTRUCT("DFF21DE1-F70F-11D0-B917-00A0C9223196", KSNODETYPE_HANDSET); - # define KSNODETYPE_HANDSET DEFINE_GUIDNAMED(KSNODETYPE_HANDSET) - - # define STATIC_KSNODETYPE_HEADSET \ - DEFINE_USB_TERMINAL_GUID(0x0402) -DEFINE_GUIDSTRUCT("DFF21DE2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_HEADSET); - # define KSNODETYPE_HEADSET DEFINE_GUIDNAMED(KSNODETYPE_HEADSET) - - # define STATIC_KSNODETYPE_SPEAKERPHONE_NO_ECHO_REDUCTION \ - DEFINE_USB_TERMINAL_GUID(0x0403) -DEFINE_GUIDSTRUCT("DFF21DE3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_SPEAKERPHONE_NO_ECHO_REDUCTION); - # define KSNODETYPE_SPEAKERPHONE_NO_ECHO_REDUCTION DEFINE_GUIDNAMED(KSNODETYPE_SPEAKERPHONE_NO_ECHO_REDUCTION) - - # define STATIC_KSNODETYPE_ECHO_SUPPRESSING_SPEAKERPHONE \ - DEFINE_USB_TERMINAL_GUID(0x0404) -DEFINE_GUIDSTRUCT("DFF21DE4-F70F-11D0-B917-00A0C9223196", KSNODETYPE_ECHO_SUPPRESSING_SPEAKERPHONE); - # define KSNODETYPE_ECHO_SUPPRESSING_SPEAKERPHONE DEFINE_GUIDNAMED(KSNODETYPE_ECHO_SUPPRESSING_SPEAKERPHONE) - - # define STATIC_KSNODETYPE_ECHO_CANCELING_SPEAKERPHONE \ - DEFINE_USB_TERMINAL_GUID(0x0405) -DEFINE_GUIDSTRUCT("DFF21DE5-F70F-11D0-B917-00A0C9223196", KSNODETYPE_ECHO_CANCELING_SPEAKERPHONE); - # define KSNODETYPE_ECHO_CANCELING_SPEAKERPHONE DEFINE_GUIDNAMED(KSNODETYPE_ECHO_CANCELING_SPEAKERPHONE) - - # define STATIC_KSNODETYPE_PHONE_LINE \ - DEFINE_USB_TERMINAL_GUID(0x0501) -DEFINE_GUIDSTRUCT("DFF21EE1-F70F-11D0-B917-00A0C9223196", KSNODETYPE_PHONE_LINE); - # define KSNODETYPE_PHONE_LINE DEFINE_GUIDNAMED(KSNODETYPE_PHONE_LINE) - - # define STATIC_KSNODETYPE_TELEPHONE \ - DEFINE_USB_TERMINAL_GUID(0x0502) -DEFINE_GUIDSTRUCT("DFF21EE2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_TELEPHONE); - # define KSNODETYPE_TELEPHONE DEFINE_GUIDNAMED(KSNODETYPE_TELEPHONE) - - # define STATIC_KSNODETYPE_DOWN_LINE_PHONE \ - DEFINE_USB_TERMINAL_GUID(0x0503) -DEFINE_GUIDSTRUCT("DFF21EE3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DOWN_LINE_PHONE); - # define KSNODETYPE_DOWN_LINE_PHONE DEFINE_GUIDNAMED(KSNODETYPE_DOWN_LINE_PHONE) - - # define STATIC_KSNODETYPE_ANALOG_CONNECTOR \ - DEFINE_USB_TERMINAL_GUID(0x601) -DEFINE_GUIDSTRUCT("DFF21FE1-F70F-11D0-B917-00A0C9223196", KSNODETYPE_ANALOG_CONNECTOR); - # define KSNODETYPE_ANALOG_CONNECTOR DEFINE_GUIDNAMED(KSNODETYPE_ANALOG_CONNECTOR) - - # define STATIC_KSNODETYPE_DIGITAL_AUDIO_INTERFACE \ - DEFINE_USB_TERMINAL_GUID(0x0602) -DEFINE_GUIDSTRUCT("DFF21FE2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DIGITAL_AUDIO_INTERFACE); - # define KSNODETYPE_DIGITAL_AUDIO_INTERFACE DEFINE_GUIDNAMED(KSNODETYPE_DIGITAL_AUDIO_INTERFACE) - - # define STATIC_KSNODETYPE_LINE_CONNECTOR \ - DEFINE_USB_TERMINAL_GUID(0x0603) -DEFINE_GUIDSTRUCT("DFF21FE3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_LINE_CONNECTOR); - # define KSNODETYPE_LINE_CONNECTOR DEFINE_GUIDNAMED(KSNODETYPE_LINE_CONNECTOR) - - # define STATIC_KSNODETYPE_LEGACY_AUDIO_CONNECTOR \ - DEFINE_USB_TERMINAL_GUID(0x0604) -DEFINE_GUIDSTRUCT("DFF21FE4-F70F-11D0-B917-00A0C9223196", KSNODETYPE_LEGACY_AUDIO_CONNECTOR); - # define KSNODETYPE_LEGACY_AUDIO_CONNECTOR DEFINE_GUIDNAMED(KSNODETYPE_LEGACY_AUDIO_CONNECTOR) - - # define STATIC_KSNODETYPE_SPDIF_INTERFACE \ - DEFINE_USB_TERMINAL_GUID(0x0605) -DEFINE_GUIDSTRUCT("DFF21FE5-F70F-11D0-B917-00A0C9223196", KSNODETYPE_SPDIF_INTERFACE); - # define KSNODETYPE_SPDIF_INTERFACE DEFINE_GUIDNAMED(KSNODETYPE_SPDIF_INTERFACE) - - # define STATIC_KSNODETYPE_1394_DA_STREAM \ - DEFINE_USB_TERMINAL_GUID(0x0606) -DEFINE_GUIDSTRUCT("DFF21FE6-F70F-11D0-B917-00A0C9223196", KSNODETYPE_1394_DA_STREAM); - # define KSNODETYPE_1394_DA_STREAM DEFINE_GUIDNAMED(KSNODETYPE_1394_DA_STREAM) - - # define STATIC_KSNODETYPE_1394_DV_STREAM_SOUNDTRACK \ - DEFINE_USB_TERMINAL_GUID(0x0607) -DEFINE_GUIDSTRUCT("DFF21FE7-F70F-11D0-B917-00A0C9223196", KSNODETYPE_1394_DV_STREAM_SOUNDTRACK); - # define KSNODETYPE_1394_DV_STREAM_SOUNDTRACK DEFINE_GUIDNAMED(KSNODETYPE_1394_DV_STREAM_SOUNDTRACK) - - # define STATIC_KSNODETYPE_LEVEL_CALIBRATION_NOISE_SOURCE \ - DEFINE_USB_TERMINAL_GUID(0x0701) -DEFINE_GUIDSTRUCT("DFF220E1-F70F-11D0-B917-00A0C9223196", KSNODETYPE_LEVEL_CALIBRATION_NOISE_SOURCE); - # define KSNODETYPE_LEVEL_CALIBRATION_NOISE_SOURCE DEFINE_GUIDNAMED(KSNODETYPE_LEVEL_CALIBRATION_NOISE_SOURCE) - - # define STATIC_KSNODETYPE_EQUALIZATION_NOISE \ - DEFINE_USB_TERMINAL_GUID(0x0702) -DEFINE_GUIDSTRUCT("DFF220E2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_EQUALIZATION_NOISE); - # define KSNODETYPE_EQUALIZATION_NOISE DEFINE_GUIDNAMED(KSNODETYPE_EQUALIZATION_NOISE) - - # define STATIC_KSNODETYPE_CD_PLAYER \ - DEFINE_USB_TERMINAL_GUID(0x0703) -DEFINE_GUIDSTRUCT("DFF220E3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_CD_PLAYER); - # define KSNODETYPE_CD_PLAYER DEFINE_GUIDNAMED(KSNODETYPE_CD_PLAYER) - - # define STATIC_KSNODETYPE_DAT_IO_DIGITAL_AUDIO_TAPE \ - DEFINE_USB_TERMINAL_GUID(0x0704) -DEFINE_GUIDSTRUCT("DFF220E4-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DAT_IO_DIGITAL_AUDIO_TAPE); - # define KSNODETYPE_DAT_IO_DIGITAL_AUDIO_TAPE DEFINE_GUIDNAMED(KSNODETYPE_DAT_IO_DIGITAL_AUDIO_TAPE) - - # define STATIC_KSNODETYPE_DCC_IO_DIGITAL_COMPACT_CASSETTE \ - DEFINE_USB_TERMINAL_GUID(0x0705) -DEFINE_GUIDSTRUCT("DFF220E5-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DCC_IO_DIGITAL_COMPACT_CASSETTE); - # define KSNODETYPE_DCC_IO_DIGITAL_COMPACT_CASSETTE DEFINE_GUIDNAMED(KSNODETYPE_DCC_IO_DIGITAL_COMPACT_CASSETTE) - - # define STATIC_KSNODETYPE_MINIDISK \ - DEFINE_USB_TERMINAL_GUID(0x0706) -DEFINE_GUIDSTRUCT("DFF220E6-F70F-11D0-B917-00A0C9223196", KSNODETYPE_MINIDISK); - # define KSNODETYPE_MINIDISK DEFINE_GUIDNAMED(KSNODETYPE_MINIDISK) - - # define STATIC_KSNODETYPE_ANALOG_TAPE \ - DEFINE_USB_TERMINAL_GUID(0x0707) -DEFINE_GUIDSTRUCT("DFF220E7-F70F-11D0-B917-00A0C9223196", KSNODETYPE_ANALOG_TAPE); - # define KSNODETYPE_ANALOG_TAPE DEFINE_GUIDNAMED(KSNODETYPE_ANALOG_TAPE) - - # define STATIC_KSNODETYPE_PHONOGRAPH \ - DEFINE_USB_TERMINAL_GUID(0x0708) -DEFINE_GUIDSTRUCT("DFF220E8-F70F-11D0-B917-00A0C9223196", KSNODETYPE_PHONOGRAPH); - # define KSNODETYPE_PHONOGRAPH DEFINE_GUIDNAMED(KSNODETYPE_PHONOGRAPH) - - # define STATIC_KSNODETYPE_VCR_AUDIO \ - DEFINE_USB_TERMINAL_GUID(0x0708) -DEFINE_GUIDSTRUCT("DFF220E9-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VCR_AUDIO); - # define KSNODETYPE_VCR_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_VCR_AUDIO) - - # define STATIC_KSNODETYPE_VIDEO_DISC_AUDIO \ - DEFINE_USB_TERMINAL_GUID(0x070A) -DEFINE_GUIDSTRUCT("DFF220EA-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_DISC_AUDIO); - # define KSNODETYPE_VIDEO_DISC_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_DISC_AUDIO) - - # define STATIC_KSNODETYPE_DVD_AUDIO \ - DEFINE_USB_TERMINAL_GUID(0x070B) -DEFINE_GUIDSTRUCT("DFF220EB-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DVD_AUDIO); - # define KSNODETYPE_DVD_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_DVD_AUDIO) - - # define STATIC_KSNODETYPE_TV_TUNER_AUDIO \ - DEFINE_USB_TERMINAL_GUID(0x070C) -DEFINE_GUIDSTRUCT("DFF220EC-F70F-11D0-B917-00A0C9223196", KSNODETYPE_TV_TUNER_AUDIO); - # define KSNODETYPE_TV_TUNER_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_TV_TUNER_AUDIO) - - # define STATIC_KSNODETYPE_SATELLITE_RECEIVER_AUDIO \ - DEFINE_USB_TERMINAL_GUID(0x070D) -DEFINE_GUIDSTRUCT("DFF220ED-F70F-11D0-B917-00A0C9223196", KSNODETYPE_SATELLITE_RECEIVER_AUDIO); - # define KSNODETYPE_SATELLITE_RECEIVER_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_SATELLITE_RECEIVER_AUDIO) - - # define STATIC_KSNODETYPE_CABLE_TUNER_AUDIO \ - DEFINE_USB_TERMINAL_GUID(0x070E) -DEFINE_GUIDSTRUCT("DFF220EE-F70F-11D0-B917-00A0C9223196", KSNODETYPE_CABLE_TUNER_AUDIO); - # define KSNODETYPE_CABLE_TUNER_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_CABLE_TUNER_AUDIO) - - # define STATIC_KSNODETYPE_DSS_AUDIO \ - DEFINE_USB_TERMINAL_GUID(0x070F) -DEFINE_GUIDSTRUCT("DFF220EF-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DSS_AUDIO); - # define KSNODETYPE_DSS_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_DSS_AUDIO) - - # define STATIC_KSNODETYPE_RADIO_RECEIVER \ - DEFINE_USB_TERMINAL_GUID(0x0710) -DEFINE_GUIDSTRUCT("DFF220F0-F70F-11D0-B917-00A0C9223196", KSNODETYPE_RADIO_RECEIVER); - # define KSNODETYPE_RADIO_RECEIVER DEFINE_GUIDNAMED(KSNODETYPE_RADIO_RECEIVER) - - # define STATIC_KSNODETYPE_RADIO_TRANSMITTER \ - DEFINE_USB_TERMINAL_GUID(0x0711) -DEFINE_GUIDSTRUCT("DFF220F1-F70F-11D0-B917-00A0C9223196", KSNODETYPE_RADIO_TRANSMITTER); - # define KSNODETYPE_RADIO_TRANSMITTER DEFINE_GUIDNAMED(KSNODETYPE_RADIO_TRANSMITTER) - - # define STATIC_KSNODETYPE_MULTITRACK_RECORDER \ - DEFINE_USB_TERMINAL_GUID(0x0712) -DEFINE_GUIDSTRUCT("DFF220F2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_MULTITRACK_RECORDER); - # define KSNODETYPE_MULTITRACK_RECORDER DEFINE_GUIDNAMED(KSNODETYPE_MULTITRACK_RECORDER) - - # define STATIC_KSNODETYPE_SYNTHESIZER \ - DEFINE_USB_TERMINAL_GUID(0x0713) -DEFINE_GUIDSTRUCT("DFF220F3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_SYNTHESIZER); - # define KSNODETYPE_SYNTHESIZER DEFINE_GUIDNAMED(KSNODETYPE_SYNTHESIZER) - - # define STATIC_KSNODETYPE_SWSYNTH \ - 0x423274A0L, 0x8B81, 0x11D1, 0xA0, 0x50, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88 -DEFINE_GUIDSTRUCT("423274A0-8B81-11D1-A050-0000F8004788", KSNODETYPE_SWSYNTH); - # define KSNODETYPE_SWSYNTH DEFINE_GUIDNAMED(KSNODETYPE_SWSYNTH) - - # define STATIC_KSNODETYPE_SWMIDI \ - 0xCB9BEFA0L, 0xA251, 0x11D1, 0xA0, 0x50, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88 -DEFINE_GUIDSTRUCT("CB9BEFA0-A251-11D1-A050-0000F8004788", KSNODETYPE_SWMIDI); - # define KSNODETYPE_SWMIDI DEFINE_GUIDNAMED(KSNODETYPE_SWMIDI) - - # define STATIC_KSNODETYPE_DRM_DESCRAMBLE \ - 0xFFBB6E3FL, 0xCCFE, 0x4D84, 0x90, 0xD9, 0x42, 0x14, 0x18, 0xB0, 0x3A, 0x8E -DEFINE_GUIDSTRUCT("FFBB6E3F-CCFE-4D84-90D9-421418B03A8E", KSNODETYPE_DRM_DESCRAMBLE); - # define KSNODETYPE_DRM_DESCRAMBLE DEFINE_GUIDNAMED(KSNODETYPE_DRM_DESCRAMBLE) - - # define STATIC_KSCATEGORY_AUDIO \ - 0x6994AD04L, 0x93EF, 0x11D0, { 0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 } -DEFINE_GUIDSTRUCT("6994AD04-93EF-11D0-A3CC-00A0C9223196", KSCATEGORY_AUDIO); - # define KSCATEGORY_AUDIO DEFINE_GUIDNAMED(KSCATEGORY_AUDIO) - - # define STATIC_KSCATEGORY_VIDEO \ - 0x6994AD05L, 0x93EF, 0x11D0, 0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("6994AD05-93EF-11D0-A3CC-00A0C9223196", KSCATEGORY_VIDEO); - # define KSCATEGORY_VIDEO DEFINE_GUIDNAMED(KSCATEGORY_VIDEO) - - # define STATIC_KSCATEGORY_TEXT \ - 0x6994AD06L, 0x93EF, 0x11D0, 0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("6994AD06-93EF-11D0-A3CC-00A0C9223196", KSCATEGORY_TEXT); - # define KSCATEGORY_TEXT DEFINE_GUIDNAMED(KSCATEGORY_TEXT) - - # define STATIC_KSCATEGORY_NETWORK \ - 0x67C9CC3CL, 0x69C4, 0x11D2, 0x87, 0x59, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("67C9CC3C-69C4-11D2-8759-00A0C9223196", KSCATEGORY_NETWORK); - # define KSCATEGORY_NETWORK DEFINE_GUIDNAMED(KSCATEGORY_NETWORK) - - # define STATIC_KSCATEGORY_TOPOLOGY \ - 0xDDA54A40L, 0x1E4C, 0x11D1, 0xA0, 0x50, 0x40, 0x57, 0x05, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("DDA54A40-1E4C-11D1-A050-405705C10000", KSCATEGORY_TOPOLOGY); - # define KSCATEGORY_TOPOLOGY DEFINE_GUIDNAMED(KSCATEGORY_TOPOLOGY) - - # define STATIC_KSCATEGORY_VIRTUAL \ - 0x3503EAC4L, 0x1F26, 0x11D1, 0x8A, 0xB0, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("3503EAC4-1F26-11D1-8AB0-00A0C9223196", KSCATEGORY_VIRTUAL); - # define KSCATEGORY_VIRTUAL DEFINE_GUIDNAMED(KSCATEGORY_VIRTUAL) - - # define STATIC_KSCATEGORY_ACOUSTIC_ECHO_CANCEL \ - 0xBF963D80L, 0xC559, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("BF963D80-C559-11D0-8A2B-00A0C9255AC1", KSCATEGORY_ACOUSTIC_ECHO_CANCEL); - # define KSCATEGORY_ACOUSTIC_ECHO_CANCEL DEFINE_GUIDNAMED(KSCATEGORY_ACOUSTIC_ECHO_CANCEL) - - # define STATIC_KSCATEGORY_SYSAUDIO \ - 0xA7C7A5B1L, 0x5AF3, 0x11D1, 0x9C, 0xED, 0x00, 0xA0, 0x24, 0xBF, 0x04, 0x07 -DEFINE_GUIDSTRUCT("A7C7A5B1-5AF3-11D1-9CED-00A024BF0407", KSCATEGORY_SYSAUDIO); - # define KSCATEGORY_SYSAUDIO DEFINE_GUIDNAMED(KSCATEGORY_SYSAUDIO) - - # define STATIC_KSCATEGORY_WDMAUD \ - 0x3E227E76L, 0x690D, 0x11D2, 0x81, 0x61, 0x00, 0x00, 0xF8, 0x77, 0x5B, 0xF1 -DEFINE_GUIDSTRUCT("3E227E76-690D-11D2-8161-0000F8775BF1", KSCATEGORY_WDMAUD); - # define KSCATEGORY_WDMAUD DEFINE_GUIDNAMED(KSCATEGORY_WDMAUD) - - # define STATIC_KSCATEGORY_AUDIO_GFX \ - 0x9BAF9572L, 0x340C, 0x11D3, 0xAB, 0xDC, 0x00, 0xA0, 0xC9, 0x0A, 0xB1, 0x6F -DEFINE_GUIDSTRUCT("9BAF9572-340C-11D3-ABDC-00A0C90AB16F", KSCATEGORY_AUDIO_GFX); - # define KSCATEGORY_AUDIO_GFX DEFINE_GUIDNAMED(KSCATEGORY_AUDIO_GFX) - - # define STATIC_KSCATEGORY_AUDIO_SPLITTER \ - 0x9EA331FAL, 0xB91B, 0x45F8, 0x92, 0x85, 0xBD, 0x2B, 0xC7, 0x7A, 0xFC, 0xDE -DEFINE_GUIDSTRUCT("9EA331FA-B91B-45F8-9285-BD2BC77AFCDE", KSCATEGORY_AUDIO_SPLITTER); - # define KSCATEGORY_AUDIO_SPLITTER DEFINE_GUIDNAMED(KSCATEGORY_AUDIO_SPLITTER) - - # define STATIC_KSCATEGORY_SYNTHESIZER STATIC_KSNODETYPE_SYNTHESIZER - # define KSCATEGORY_SYNTHESIZER KSNODETYPE_SYNTHESIZER - - # define STATIC_KSCATEGORY_DRM_DESCRAMBLE STATIC_KSNODETYPE_DRM_DESCRAMBLE - # define KSCATEGORY_DRM_DESCRAMBLE KSNODETYPE_DRM_DESCRAMBLE - - # define STATIC_KSCATEGORY_AUDIO_DEVICE \ - 0xFBF6F530L, 0x07B9, 0x11D2, 0xA7, 0x1E, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88 -DEFINE_GUIDSTRUCT("FBF6F530-07B9-11D2-A71E-0000F8004788", KSCATEGORY_AUDIO_DEVICE); - # define KSCATEGORY_AUDIO_DEVICE DEFINE_GUIDNAMED(KSCATEGORY_AUDIO_DEVICE) - - # define STATIC_KSCATEGORY_PREFERRED_WAVEOUT_DEVICE \ - 0xD6C5066EL, 0x72C1, 0x11D2, 0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88 -DEFINE_GUIDSTRUCT("D6C5066E-72C1-11D2-9755-0000F8004788", KSCATEGORY_PREFERRED_WAVEOUT_DEVICE); - # define KSCATEGORY_PREFERRED_WAVEOUT_DEVICE DEFINE_GUIDNAMED(KSCATEGORY_PREFERRED_WAVEOUT_DEVICE) - - # define STATIC_KSCATEGORY_PREFERRED_WAVEIN_DEVICE \ - 0xD6C50671L, 0x72C1, 0x11D2, 0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88 -DEFINE_GUIDSTRUCT("D6C50671-72C1-11D2-9755-0000F8004788", KSCATEGORY_PREFERRED_WAVEIN_DEVICE); - # define KSCATEGORY_PREFERRED_WAVEIN_DEVICE DEFINE_GUIDNAMED(KSCATEGORY_PREFERRED_WAVEIN_DEVICE) - - # define STATIC_KSCATEGORY_PREFERRED_MIDIOUT_DEVICE \ - 0xD6C50674L, 0x72C1, 0x11D2, 0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88 -DEFINE_GUIDSTRUCT("D6C50674-72C1-11D2-9755-0000F8004788", KSCATEGORY_PREFERRED_MIDIOUT_DEVICE); - # define KSCATEGORY_PREFERRED_MIDIOUT_DEVICE DEFINE_GUIDNAMED(KSCATEGORY_PREFERRED_MIDIOUT_DEVICE) - - # define STATIC_KSCATEGORY_WDMAUD_USE_PIN_NAME \ - 0x47A4FA20L, 0xA251, 0x11D1, 0xA0, 0x50, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88 -DEFINE_GUIDSTRUCT("47A4FA20-A251-11D1-A050-0000F8004788", KSCATEGORY_WDMAUD_USE_PIN_NAME); - # define KSCATEGORY_WDMAUD_USE_PIN_NAME DEFINE_GUIDNAMED(KSCATEGORY_WDMAUD_USE_PIN_NAME) - - # define STATIC_KSCATEGORY_ESCALANTE_PLATFORM_DRIVER \ - 0x74f3aea8L, 0x9768, 0x11d1, 0x8e, 0x07, 0x00, 0xa0, 0xc9, 0x5e, 0xc2, 0x2e -DEFINE_GUIDSTRUCT("74f3aea8-9768-11d1-8e07-00a0c95ec22e", KSCATEGORY_ESCALANTE_PLATFORM_DRIVER); - # define KSCATEGORY_ESCALANTE_PLATFORM_DRIVER DEFINE_GUIDNAMED(KSCATEGORY_ESCALANTE_PLATFORM_DRIVER) - - # define STATIC_KSDATAFORMAT_TYPE_VIDEO \ - 0x73646976L, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 -DEFINE_GUIDSTRUCT("73646976-0000-0010-8000-00aa00389b71", KSDATAFORMAT_TYPE_VIDEO); - # define KSDATAFORMAT_TYPE_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_VIDEO) - - # define STATIC_KSDATAFORMAT_TYPE_AUDIO \ - 0x73647561L, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 -DEFINE_GUIDSTRUCT("73647561-0000-0010-8000-00aa00389b71", KSDATAFORMAT_TYPE_AUDIO); - # define KSDATAFORMAT_TYPE_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_AUDIO) - - # define STATIC_KSDATAFORMAT_TYPE_TEXT \ - 0x73747874L, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 -DEFINE_GUIDSTRUCT("73747874-0000-0010-8000-00aa00389b71", KSDATAFORMAT_TYPE_TEXT); - # define KSDATAFORMAT_TYPE_TEXT DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_TEXT) - - # if !defined(DEFINE_WAVEFORMATEX_GUID) - # define DEFINE_WAVEFORMATEX_GUID(x) \ - (USHORT)(x), 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } - # endif - - # define STATIC_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX \ - 0x00000000L, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 -DEFINE_GUIDSTRUCT("00000000-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_WAVEFORMATEX); - # define KSDATAFORMAT_SUBTYPE_WAVEFORMATEX DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_WAVEFORMATEX) - - # define INIT_WAVEFORMATEX_GUID(Guid, x) \ - { \ - *(Guid) = KSDATAFORMAT_SUBTYPE_WAVEFORMATEX; \ - (Guid)->Data1 = (USHORT)(x); \ - } - - # define EXTRACT_WAVEFORMATEX_ID(Guid) \ - (USHORT)((Guid)->Data1) - - # define IS_VALID_WAVEFORMATEX_GUID(Guid) \ - (!memcmp(((PUSHORT)&KSDATAFORMAT_SUBTYPE_WAVEFORMATEX) + 1, ((PUSHORT)(Guid)) + 1, sizeof(GUID) - sizeof(USHORT))) - - # ifndef INIT_MMREG_MID - # define INIT_MMREG_MID(guid, id) \ - { \ - (guid)->Data1 = 0xd5a47fa7 + (USHORT)(id); \ - (guid)->Data2 = 0x6d98; \ - (guid)->Data3 = 0x11d1; \ - (guid)->Data4[0] = 0xa2; \ - (guid)->Data4[1] = 0x1a; \ - (guid)->Data4[2] = 0x00; \ - (guid)->Data4[3] = 0xa0; \ - (guid)->Data4[4] = 0xc9; \ - (guid)->Data4[5] = 0x22; \ - (guid)->Data4[6] = 0x31; \ - (guid)->Data4[7] = 0x96; \ - } - # define EXTRACT_MMREG_MID(guid) \ - (USHORT)((guid)->Data1 - 0xd5a47fa7) - # define DEFINE_MMREG_MID_GUID(id) \ - 0xd5a47fa7 + (USHORT)(id), 0x6d98, 0x11d1, 0xa2, 0x1a, 0x00, 0xa0, 0xc9, 0x22, 0x31, 0x96 - - # define IS_COMPATIBLE_MMREG_MID(guid) \ - (((guid)->Data1 >= 0xd5a47fa7) && \ - ((guid)->Data1 < 0xd5a47fa7 + 0xffff) && \ - ((guid)->Data2 == 0x6d98) && \ - ((guid)->Data3 == 0x11d1) && \ - ((guid)->Data4[0] == 0xa2) && \ - ((guid)->Data4[1] == 0x1a) && \ - ((guid)->Data4[2] == 0x00) && \ - ((guid)->Data4[3] == 0xa0) && \ - ((guid)->Data4[4] == 0xc9) && \ - ((guid)->Data4[5] == 0x22) && \ - ((guid)->Data4[6] == 0x31) && \ - ((guid)->Data4[7] == 0x96)) - # endif /* INIT_MMREG_MID */ - - # ifndef INIT_MMREG_PID - # define INIT_MMREG_PID(guid, id) \ - { \ - (guid)->Data1 = 0xe36dc2ac + (USHORT)(id); \ - (guid)->Data2 = 0x6d9a; \ - (guid)->Data3 = 0x11d1; \ - (guid)->Data4[0] = 0xa2; \ - (guid)->Data4[1] = 0x1a; \ - (guid)->Data4[2] = 0x00; \ - (guid)->Data4[3] = 0xa0; \ - (guid)->Data4[4] = 0xc9; \ - (guid)->Data4[5] = 0x22; \ - (guid)->Data4[6] = 0x31; \ - (guid)->Data4[7] = 0x96; \ - } - # define EXTRACT_MMREG_PID(guid) \ - (USHORT)((guid)->Data1 - 0xe36dc2ac) - # define DEFINE_MMREG_PID_GUID(id) \ - 0xe36dc2ac + (USHORT)(id), 0x6d9a, 0x11d1, 0xa2, 0x1a, 0x00, 0xa0, 0xc9, 0x22, 0x31, 0x96 - - # define IS_COMPATIBLE_MMREG_PID(guid) \ - (((guid)->Data1 >= 0xe36dc2ac) && \ - ((guid)->Data1 < 0xe36dc2ac + 0xffff) && \ - ((guid)->Data2 == 0x6d9a) && \ - ((guid)->Data3 == 0x11d1) && \ - ((guid)->Data4[0] == 0xa2) && \ - ((guid)->Data4[1] == 0x1a) && \ - ((guid)->Data4[2] == 0x00) && \ - ((guid)->Data4[3] == 0xa0) && \ - ((guid)->Data4[4] == 0xc9) && \ - ((guid)->Data4[5] == 0x22) && \ - ((guid)->Data4[6] == 0x31) && \ - ((guid)->Data4[7] == 0x96)) - # endif /* INIT_MMREG_PID */ - - # define STATIC_KSDATAFORMAT_SUBTYPE_ANALOG \ - 0x6dba3190L, 0x67bd, 0x11cf, 0xa0, 0xf7, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4 -DEFINE_GUIDSTRUCT("6dba3190-67bd-11cf-a0f7-0020afd156e4", KSDATAFORMAT_SUBTYPE_ANALOG); - # define KSDATAFORMAT_SUBTYPE_ANALOG DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_ANALOG) - - # define STATIC_KSDATAFORMAT_SUBTYPE_PCM \ - DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_PCM) -DEFINE_GUIDSTRUCT("00000001-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_PCM); - # define KSDATAFORMAT_SUBTYPE_PCM DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_PCM) - - # ifdef _INC_MMREG - # define STATIC_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT \ - DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_IEEE_FLOAT) -DEFINE_GUIDSTRUCT("00000003-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_IEEE_FLOAT); - # define KSDATAFORMAT_SUBTYPE_IEEE_FLOAT DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) - - # define STATIC_KSDATAFORMAT_SUBTYPE_DRM \ - DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_DRM) -DEFINE_GUIDSTRUCT("00000009-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_DRM); - # define KSDATAFORMAT_SUBTYPE_DRM DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DRM) - - # define STATIC_KSDATAFORMAT_SUBTYPE_ALAW \ - DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_ALAW) -DEFINE_GUIDSTRUCT("00000006-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_ALAW); - # define KSDATAFORMAT_SUBTYPE_ALAW DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_ALAW) - - # define STATIC_KSDATAFORMAT_SUBTYPE_MULAW \ - DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_MULAW) -DEFINE_GUIDSTRUCT("00000007-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_MULAW); - # define KSDATAFORMAT_SUBTYPE_MULAW DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MULAW) - - # define STATIC_KSDATAFORMAT_SUBTYPE_ADPCM \ - DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_ADPCM) -DEFINE_GUIDSTRUCT("00000002-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_ADPCM); - # define KSDATAFORMAT_SUBTYPE_ADPCM DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_ADPCM) - - # define STATIC_KSDATAFORMAT_SUBTYPE_MPEG \ - DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_MPEG) -DEFINE_GUIDSTRUCT("00000050-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_MPEG); - # define KSDATAFORMAT_SUBTYPE_MPEG DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG) - # endif /* _INC_MMREG */ - - # define STATIC_KSDATAFORMAT_SPECIFIER_VC_ID \ - 0xAD98D184L, 0xAAC3, 0x11D0, 0xA4, 0x1C, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("AD98D184-AAC3-11D0-A41C-00A0C9223196", KSDATAFORMAT_SPECIFIER_VC_ID); - # define KSDATAFORMAT_SPECIFIER_VC_ID DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_VC_ID) - - # define STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX \ - 0x05589f81L, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a -DEFINE_GUIDSTRUCT("05589f81-c356-11ce-bf01-00aa0055595a", KSDATAFORMAT_SPECIFIER_WAVEFORMATEX); - # define KSDATAFORMAT_SPECIFIER_WAVEFORMATEX DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) - - # define STATIC_KSDATAFORMAT_SPECIFIER_DSOUND \ - 0x518590a2L, 0xa184, 0x11d0, 0x85, 0x22, 0x00, 0xc0, 0x4f, 0xd9, 0xba, 0xf3 -DEFINE_GUIDSTRUCT("518590a2-a184-11d0-8522-00c04fd9baf3", KSDATAFORMAT_SPECIFIER_DSOUND); - # define KSDATAFORMAT_SPECIFIER_DSOUND DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DSOUND) - - # if defined(_INC_MMSYSTEM) || defined(_INC_MMREG) || 1 - # if !defined(PACK_PRAGMAS_NOT_SUPPORTED) - # include - # endif -typedef struct -{ - KSDATAFORMAT DataFormat; - WAVEFORMATEX WaveFormatEx; -}KSDATAFORMAT_WAVEFORMATEX, * PKSDATAFORMAT_WAVEFORMATEX; - - # ifndef _WAVEFORMATEXTENSIBLE_ - # define _WAVEFORMATEXTENSIBLE_ -typedef struct -{ - WAVEFORMATEX Format; - union - { - WORD wValidBitsPerSample; - WORD wSamplesPerBlock; - WORD wReserved; - }Samples; - DWORD dwChannelMask; - - GUID SubFormat; -}WAVEFORMATEXTENSIBLE, * PWAVEFORMATEXTENSIBLE; - # endif /* _WAVEFORMATEXTENSIBLE_ */ - - # if !defined(WAVE_FORMAT_EXTENSIBLE) - # define WAVE_FORMAT_EXTENSIBLE 0xFFFE - # endif - -typedef struct -{ - ULONG Flags; - ULONG Control; - WAVEFORMATEX WaveFormatEx; -}KSDSOUND_BUFFERDESC, * PKSDSOUND_BUFFERDESC; - -typedef struct -{ - KSDATAFORMAT DataFormat; - KSDSOUND_BUFFERDESC BufferDesc; -}KSDATAFORMAT_DSOUND, * PKSDATAFORMAT_DSOUND; - - # if !defined(PACK_PRAGMAS_NOT_SUPPORTED) - # include - # endif - # endif /* defined(_INC_MMSYSTEM) || defined(_INC_MMREG) */ - - # define KSDSOUND_BUFFER_PRIMARY 0x00000001 - # define KSDSOUND_BUFFER_STATIC 0x00000002 - # define KSDSOUND_BUFFER_LOCHARDWARE 0x00000004 - # define KSDSOUND_BUFFER_LOCSOFTWARE 0x00000008 - - # define KSDSOUND_BUFFER_CTRL_3D 0x00000001 - # define KSDSOUND_BUFFER_CTRL_FREQUENCY 0x00000002 - # define KSDSOUND_BUFFER_CTRL_PAN 0x00000004 - # define KSDSOUND_BUFFER_CTRL_VOLUME 0x00000008 - # define KSDSOUND_BUFFER_CTRL_POSITIONNOTIFY 0x00000010 - -typedef struct -{ - DWORDLONG PlayOffset; - DWORDLONG WriteOffset; -}KSAUDIO_POSITION, * PKSAUDIO_POSITION; - -typedef struct _DS3DVECTOR -{ - __MINGW_EXTENSION union - { - FLOAT x; - FLOAT dvX; - }; - __MINGW_EXTENSION union - { - FLOAT y; - FLOAT dvY; - }; - __MINGW_EXTENSION union - { - FLOAT z; - FLOAT dvZ; - }; -}DS3DVECTOR, * PDS3DVECTOR; - - # define STATIC_KSPROPSETID_DirectSound3DListener \ - 0x437b3414L, 0xd060, 0x11d0, 0x85, 0x83, 0x00, 0xc0, 0x4f, 0xd9, 0xba, 0xf3 -DEFINE_GUIDSTRUCT("437b3414-d060-11d0-8583-00c04fd9baf3", KSPROPSETID_DirectSound3DListener); - # define KSPROPSETID_DirectSound3DListener DEFINE_GUIDNAMED(KSPROPSETID_DirectSound3DListener) - -typedef enum -{ - KSPROPERTY_DIRECTSOUND3DLISTENER_ALL, - KSPROPERTY_DIRECTSOUND3DLISTENER_POSITION, - KSPROPERTY_DIRECTSOUND3DLISTENER_VELOCITY, - KSPROPERTY_DIRECTSOUND3DLISTENER_ORIENTATION, - KSPROPERTY_DIRECTSOUND3DLISTENER_DISTANCEFACTOR, - KSPROPERTY_DIRECTSOUND3DLISTENER_ROLLOFFFACTOR, - KSPROPERTY_DIRECTSOUND3DLISTENER_DOPPLERFACTOR, - KSPROPERTY_DIRECTSOUND3DLISTENER_BATCH, - KSPROPERTY_DIRECTSOUND3DLISTENER_ALLOCATION -}KSPROPERTY_DIRECTSOUND3DLISTENER; - -typedef struct -{ - DS3DVECTOR Position; - DS3DVECTOR Velocity; - DS3DVECTOR OrientFront; - DS3DVECTOR OrientTop; - FLOAT DistanceFactor; - FLOAT RolloffFactor; - FLOAT DopplerFactor; -}KSDS3D_LISTENER_ALL, * PKSDS3D_LISTENER_ALL; - -typedef struct -{ - DS3DVECTOR Front; - DS3DVECTOR Top; -}KSDS3D_LISTENER_ORIENTATION, * PKSDS3D_LISTENER_ORIENTATION; - - # define STATIC_KSPROPSETID_DirectSound3DBuffer \ - 0x437b3411L, 0xd060, 0x11d0, 0x85, 0x83, 0x00, 0xc0, 0x4f, 0xd9, 0xba, 0xf3 -DEFINE_GUIDSTRUCT("437b3411-d060-11d0-8583-00c04fd9baf3", KSPROPSETID_DirectSound3DBuffer); - # define KSPROPSETID_DirectSound3DBuffer DEFINE_GUIDNAMED(KSPROPSETID_DirectSound3DBuffer) - -typedef enum -{ - KSPROPERTY_DIRECTSOUND3DBUFFER_ALL, - KSPROPERTY_DIRECTSOUND3DBUFFER_POSITION, - KSPROPERTY_DIRECTSOUND3DBUFFER_VELOCITY, - KSPROPERTY_DIRECTSOUND3DBUFFER_CONEANGLES, - KSPROPERTY_DIRECTSOUND3DBUFFER_CONEORIENTATION, - KSPROPERTY_DIRECTSOUND3DBUFFER_CONEOUTSIDEVOLUME, - KSPROPERTY_DIRECTSOUND3DBUFFER_MINDISTANCE, - KSPROPERTY_DIRECTSOUND3DBUFFER_MAXDISTANCE, - KSPROPERTY_DIRECTSOUND3DBUFFER_MODE -}KSPROPERTY_DIRECTSOUND3DBUFFER; - -typedef struct -{ - DS3DVECTOR Position; - DS3DVECTOR Velocity; - ULONG InsideConeAngle; - ULONG OutsideConeAngle; - DS3DVECTOR ConeOrientation; - LONG ConeOutsideVolume; - FLOAT MinDistance; - FLOAT MaxDistance; - ULONG Mode; -}KSDS3D_BUFFER_ALL, * PKSDS3D_BUFFER_ALL; - -typedef struct -{ - ULONG InsideConeAngle; - ULONG OutsideConeAngle; -}KSDS3D_BUFFER_CONE_ANGLES, * PKSDS3D_BUFFER_CONE_ANGLES; - - # define KSAUDIO_STEREO_SPEAKER_GEOMETRY_HEADPHONE (-1) - # define KSAUDIO_STEREO_SPEAKER_GEOMETRY_MIN 5 - # define KSAUDIO_STEREO_SPEAKER_GEOMETRY_NARROW 10 - # define KSAUDIO_STEREO_SPEAKER_GEOMETRY_WIDE 20 - # define KSAUDIO_STEREO_SPEAKER_GEOMETRY_MAX 180 - - # define KSDSOUND_3D_MODE_NORMAL 0x00000000 - # define KSDSOUND_3D_MODE_HEADRELATIVE 0x00000001 - # define KSDSOUND_3D_MODE_DISABLE 0x00000002 - - # define KSDSOUND_BUFFER_CTRL_HRTF_3D 0x40000000 - -typedef struct -{ - ULONG Size; - ULONG Enabled; - WINBOOL SwapChannels; - WINBOOL ZeroAzimuth; - WINBOOL CrossFadeOutput; - ULONG FilterSize; -}KSDS3D_HRTF_PARAMS_MSG, * PKSDS3D_HRTF_PARAMS_MSG; - -typedef enum -{ - FULL_FILTER, - LIGHT_FILTER, - KSDS3D_FILTER_QUALITY_COUNT -}KSDS3D_HRTF_FILTER_QUALITY; - -typedef struct -{ - ULONG Size; - KSDS3D_HRTF_FILTER_QUALITY Quality; - FLOAT SampleRate; - ULONG MaxFilterSize; - ULONG FilterTransientMuteLength; - ULONG FilterOverlapBufferLength; - ULONG OutputOverlapBufferLength; - ULONG Reserved; -}KSDS3D_HRTF_INIT_MSG, * PKSDS3D_HRTF_INIT_MSG; - -typedef enum -{ - FLOAT_COEFF, - SHORT_COEFF, - KSDS3D_COEFF_COUNT -}KSDS3D_HRTF_COEFF_FORMAT; - -typedef enum -{ - DIRECT_FORM, - CASCADE_FORM, - KSDS3D_FILTER_METHOD_COUNT -}KSDS3D_HRTF_FILTER_METHOD; - -typedef enum -{ - DS3D_HRTF_VERSION_1 -}KSDS3D_HRTF_FILTER_VERSION; - -typedef struct -{ - KSDS3D_HRTF_FILTER_METHOD FilterMethod; - KSDS3D_HRTF_COEFF_FORMAT CoeffFormat; - KSDS3D_HRTF_FILTER_VERSION Version; - ULONG Reserved; -}KSDS3D_HRTF_FILTER_FORMAT_MSG, * PKSDS3D_HRTF_FILTER_FORMAT_MSG; - - # define STATIC_KSPROPSETID_Hrtf3d \ - 0xb66decb0L, 0xa083, 0x11d0, 0x85, 0x1e, 0x00, 0xc0, 0x4f, 0xd9, 0xba, 0xf3 -DEFINE_GUIDSTRUCT("b66decb0-a083-11d0-851e-00c04fd9baf3", KSPROPSETID_Hrtf3d); - # define KSPROPSETID_Hrtf3d DEFINE_GUIDNAMED(KSPROPSETID_Hrtf3d) - -typedef enum -{ - KSPROPERTY_HRTF3D_PARAMS = 0, - KSPROPERTY_HRTF3D_INITIALIZE, - KSPROPERTY_HRTF3D_FILTER_FORMAT -}KSPROPERTY_HRTF3D; - -typedef struct -{ - LONG Channel; - FLOAT VolSmoothScale; - FLOAT TotalDryAttenuation; - FLOAT TotalWetAttenuation; - LONG SmoothFrequency; - LONG Delay; -}KSDS3D_ITD_PARAMS, * PKSDS3D_ITD_PARAMS; - -typedef struct -{ - ULONG Enabled; - KSDS3D_ITD_PARAMS LeftParams; - KSDS3D_ITD_PARAMS RightParams; - ULONG Reserved; -}KSDS3D_ITD_PARAMS_MSG, * PKSDS3D_ITD_PARAMS_MSG; - - # define STATIC_KSPROPSETID_Itd3d \ - 0x6429f090L, 0x9fd9, 0x11d0, 0xa7, 0x5b, 0x00, 0xa0, 0xc9, 0x03, 0x65, 0xe3 -DEFINE_GUIDSTRUCT("6429f090-9fd9-11d0-a75b-00a0c90365e3", KSPROPSETID_Itd3d); - # define KSPROPSETID_Itd3d DEFINE_GUIDNAMED(KSPROPSETID_Itd3d) - -typedef enum -{ - KSPROPERTY_ITD3D_PARAMS = 0 -}KSPROPERTY_ITD3D; - -typedef struct -{ - KSDATARANGE DataRange; - ULONG MaximumChannels; - ULONG MinimumBitsPerSample; - ULONG MaximumBitsPerSample; - ULONG MinimumSampleFrequency; - ULONG MaximumSampleFrequency; -}KSDATARANGE_AUDIO, * PKSDATARANGE_AUDIO; - - # define STATIC_KSDATAFORMAT_SUBTYPE_RIFF \ - 0x4995DAEEL, 0x9EE6, 0x11D0, 0xA4, 0x0E, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("4995DAEE-9EE6-11D0-A40E-00A0C9223196", KSDATAFORMAT_SUBTYPE_RIFF); - # define KSDATAFORMAT_SUBTYPE_RIFF DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_RIFF) - - # define STATIC_KSDATAFORMAT_SUBTYPE_RIFFWAVE \ - 0xe436eb8bL, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 -DEFINE_GUIDSTRUCT("e436eb8b-524f-11ce-9f53-0020af0ba770", KSDATAFORMAT_SUBTYPE_RIFFWAVE); - # define KSDATAFORMAT_SUBTYPE_RIFFWAVE DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_RIFFWAVE) - - # define STATIC_KSPROPSETID_Bibliographic \ - 0x07BA150EL, 0xE2B1, 0x11D0, 0xAC, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("07BA150E-E2B1-11D0-AC17-00A0C9223196", KSPROPSETID_Bibliographic); - # define KSPROPSETID_Bibliographic DEFINE_GUIDNAMED(KSPROPSETID_Bibliographic) - - # define SEB_MK_FOURCC(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | (d << 0)) - -typedef enum -{ - KSPROPERTY_BIBLIOGRAPHIC_LEADER = SEB_MK_FOURCC('R', 'D', 'L', ' '), - KSPROPERTY_BIBLIOGRAPHIC_LCCN = SEB_MK_FOURCC('0', '1', '0', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ISBN = SEB_MK_FOURCC('0', '2', '0', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ISSN = SEB_MK_FOURCC('2', '2', '0', ' '), - KSPROPERTY_BIBLIOGRAPHIC_CATALOGINGSOURCE = SEB_MK_FOURCC('0', '4', '0', ' '), - KSPROPERTY_BIBLIOGRAPHIC_MAINPERSONALNAME = SEB_MK_FOURCC('0', '0', '1', ' '), - KSPROPERTY_BIBLIOGRAPHIC_MAINCORPORATEBODY = SEB_MK_FOURCC('0', '1', '1', ' '), - KSPROPERTY_BIBLIOGRAPHIC_MAINMEETINGNAME = SEB_MK_FOURCC('1', '1', '1', ' '), - KSPROPERTY_BIBLIOGRAPHIC_MAINUNIFORMTITLE = SEB_MK_FOURCC('0', '3', '1', ' '), - KSPROPERTY_BIBLIOGRAPHIC_UNIFORMTITLE = SEB_MK_FOURCC('0', '4', '2', ' '), - KSPROPERTY_BIBLIOGRAPHIC_TITLESTATEMENT = SEB_MK_FOURCC('5', '4', '2', ' '), - KSPROPERTY_BIBLIOGRAPHIC_VARYINGFORMTITLE = SEB_MK_FOURCC('6', '4', '2', ' '), - KSPROPERTY_BIBLIOGRAPHIC_PUBLICATION = SEB_MK_FOURCC('0', '6', '2', ' '), - KSPROPERTY_BIBLIOGRAPHIC_PHYSICALDESCRIPTION = SEB_MK_FOURCC('0', '0', '3', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYTITLE = SEB_MK_FOURCC('0', '4', '4', ' '), - KSPROPERTY_BIBLIOGRAPHIC_SERIESSTATEMENT = SEB_MK_FOURCC('0', '9', '4', ' '), - KSPROPERTY_BIBLIOGRAPHIC_GENERALNOTE = SEB_MK_FOURCC('0', '0', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_BIBLIOGRAPHYNOTE = SEB_MK_FOURCC('4', '0', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_CONTENTSNOTE = SEB_MK_FOURCC('5', '0', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_CREATIONCREDIT = SEB_MK_FOURCC('8', '0', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_CITATION = SEB_MK_FOURCC('0', '1', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_PARTICIPANT = SEB_MK_FOURCC('1', '1', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_SUMMARY = SEB_MK_FOURCC('0', '2', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_TARGETAUDIENCE = SEB_MK_FOURCC('1', '2', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ADDEDFORMAVAILABLE = SEB_MK_FOURCC('0', '3', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_SYSTEMDETAILS = SEB_MK_FOURCC('8', '3', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_AWARDS = SEB_MK_FOURCC('6', '8', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYPERSONALNAME = SEB_MK_FOURCC('0', '0', '6', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYTOPICALTERM = SEB_MK_FOURCC('0', '5', '6', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYGEOGRAPHIC = SEB_MK_FOURCC('1', '5', '6', ' '), - KSPROPERTY_BIBLIOGRAPHIC_INDEXTERMGENRE = SEB_MK_FOURCC('5', '5', '6', ' '), - KSPROPERTY_BIBLIOGRAPHIC_INDEXTERMCURRICULUM = SEB_MK_FOURCC('8', '5', '6', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYUNIFORMTITLE = SEB_MK_FOURCC('0', '3', '7', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYRELATED = SEB_MK_FOURCC('0', '4', '7', ' '), - KSPROPERTY_BIBLIOGRAPHIC_SERIESSTATEMENTPERSONALNAME = SEB_MK_FOURCC('0', '0', '8', ' '), - KSPROPERTY_BIBLIOGRAPHIC_SERIESSTATEMENTUNIFORMTITLE = SEB_MK_FOURCC('0', '3', '8', ' ') -}KSPROPERTY_BIBLIOGRAPHIC; - - # undef SEB_MK_FOURCC - - # define STATIC_KSPROPSETID_TopologyNode \ - 0x45FFAAA1L, 0x6E1B, 0x11D0, 0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 -DEFINE_GUIDSTRUCT("45FFAAA1-6E1B-11D0-BCF2-444553540000", KSPROPSETID_TopologyNode); - # define KSPROPSETID_TopologyNode DEFINE_GUIDNAMED(KSPROPSETID_TopologyNode) - -typedef enum -{ - KSPROPERTY_TOPOLOGYNODE_ENABLE = 1, - KSPROPERTY_TOPOLOGYNODE_RESET -}KSPROPERTY_TOPOLOGYNODE; - - # define STATIC_KSPROPSETID_RtAudio \ - 0xa855a48c, 0x2f78, 0x4729, 0x90, 0x51, 0x19, 0x68, 0x74, 0x6b, 0x9e, 0xef -DEFINE_GUIDSTRUCT("A855A48C-2F78-4729-9051-1968746B9EEF", KSPROPSETID_RtAudio); - # define KSPROPSETID_RtAudio DEFINE_GUIDNAMED(KSPROPSETID_RtAudio) - -typedef enum -{ - KSPROPERTY_RTAUDIO_GETPOSITIONFUNCTION -}KSPROPERTY_RTAUDIO; - - # define STATIC_KSPROPSETID_DrmAudioStream \ - 0x2f2c8ddd, 0x4198, 0x4fac, 0xba, 0x29, 0x61, 0xbb, 0x5, 0xb7, 0xde, 0x6 -DEFINE_GUIDSTRUCT("2F2C8DDD-4198-4fac-BA29-61BB05B7DE06", KSPROPSETID_DrmAudioStream); - # define KSPROPSETID_DrmAudioStream DEFINE_GUIDNAMED(KSPROPSETID_DrmAudioStream) - -typedef enum -{ - KSPROPERTY_DRMAUDIOSTREAM_CONTENTID -}KSPROPERTY_DRMAUDIOSTREAM; - - # define STATIC_KSPROPSETID_Audio \ - 0x45FFAAA0L, 0x6E1B, 0x11D0, 0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 -DEFINE_GUIDSTRUCT("45FFAAA0-6E1B-11D0-BCF2-444553540000", KSPROPSETID_Audio); - # define KSPROPSETID_Audio DEFINE_GUIDNAMED(KSPROPSETID_Audio) - -typedef enum -{ - KSPROPERTY_AUDIO_LATENCY = 1, - KSPROPERTY_AUDIO_COPY_PROTECTION, - KSPROPERTY_AUDIO_CHANNEL_CONFIG, - KSPROPERTY_AUDIO_VOLUMELEVEL, - KSPROPERTY_AUDIO_POSITION, - KSPROPERTY_AUDIO_DYNAMIC_RANGE, - KSPROPERTY_AUDIO_QUALITY, - KSPROPERTY_AUDIO_SAMPLING_RATE, - KSPROPERTY_AUDIO_DYNAMIC_SAMPLING_RATE, - KSPROPERTY_AUDIO_MIX_LEVEL_TABLE, - KSPROPERTY_AUDIO_MIX_LEVEL_CAPS, - KSPROPERTY_AUDIO_MUX_SOURCE, - KSPROPERTY_AUDIO_MUTE, - KSPROPERTY_AUDIO_BASS, - KSPROPERTY_AUDIO_MID, - KSPROPERTY_AUDIO_TREBLE, - KSPROPERTY_AUDIO_BASS_BOOST, - KSPROPERTY_AUDIO_EQ_LEVEL, - KSPROPERTY_AUDIO_NUM_EQ_BANDS, - KSPROPERTY_AUDIO_EQ_BANDS, - KSPROPERTY_AUDIO_AGC, - KSPROPERTY_AUDIO_DELAY, - KSPROPERTY_AUDIO_LOUDNESS, - KSPROPERTY_AUDIO_WIDE_MODE, - KSPROPERTY_AUDIO_WIDENESS, - KSPROPERTY_AUDIO_REVERB_LEVEL, - KSPROPERTY_AUDIO_CHORUS_LEVEL, - KSPROPERTY_AUDIO_DEV_SPECIFIC, - KSPROPERTY_AUDIO_DEMUX_DEST, - KSPROPERTY_AUDIO_STEREO_ENHANCE, - KSPROPERTY_AUDIO_MANUFACTURE_GUID, - KSPROPERTY_AUDIO_PRODUCT_GUID, - KSPROPERTY_AUDIO_CPU_RESOURCES, - KSPROPERTY_AUDIO_STEREO_SPEAKER_GEOMETRY, - KSPROPERTY_AUDIO_SURROUND_ENCODE, - KSPROPERTY_AUDIO_3D_INTERFACE, - KSPROPERTY_AUDIO_PEAKMETER, - KSPROPERTY_AUDIO_ALGORITHM_INSTANCE, - KSPROPERTY_AUDIO_FILTER_STATE, - KSPROPERTY_AUDIO_PREFERRED_STATUS -}KSPROPERTY_AUDIO; - - # define KSAUDIO_QUALITY_WORST 0x0 - # define KSAUDIO_QUALITY_PC 0x1 - # define KSAUDIO_QUALITY_BASIC 0x2 - # define KSAUDIO_QUALITY_ADVANCED 0x3 - - # define KSAUDIO_CPU_RESOURCES_NOT_HOST_CPU 0x00000000 - # define KSAUDIO_CPU_RESOURCES_HOST_CPU 0x7FFFFFFF - -typedef struct -{ - WINBOOL fCopyrighted; - WINBOOL fOriginal; -}KSAUDIO_COPY_PROTECTION, * PKSAUDIO_COPY_PROTECTION; - -typedef struct -{ - LONG ActiveSpeakerPositions; -}KSAUDIO_CHANNEL_CONFIG, * PKSAUDIO_CHANNEL_CONFIG; - - # define SPEAKER_FRONT_LEFT 0x1 - # define SPEAKER_FRONT_RIGHT 0x2 - # define SPEAKER_FRONT_CENTER 0x4 - # define SPEAKER_LOW_FREQUENCY 0x8 - # define SPEAKER_BACK_LEFT 0x10 - # define SPEAKER_BACK_RIGHT 0x20 - # define SPEAKER_FRONT_LEFT_OF_CENTER 0x40 - # define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80 - # define SPEAKER_BACK_CENTER 0x100 - # define SPEAKER_SIDE_LEFT 0x200 - # define SPEAKER_SIDE_RIGHT 0x400 - # define SPEAKER_TOP_CENTER 0x800 - # define SPEAKER_TOP_FRONT_LEFT 0x1000 - # define SPEAKER_TOP_FRONT_CENTER 0x2000 - # define SPEAKER_TOP_FRONT_RIGHT 0x4000 - # define SPEAKER_TOP_BACK_LEFT 0x8000 - # define SPEAKER_TOP_BACK_CENTER 0x10000 - # define SPEAKER_TOP_BACK_RIGHT 0x20000 - - # define SPEAKER_RESERVED 0x7FFC0000 - - # define SPEAKER_ALL 0x80000000 - - # define KSAUDIO_SPEAKER_DIRECTOUT 0 - # define KSAUDIO_SPEAKER_MONO (SPEAKER_FRONT_CENTER) - # define KSAUDIO_SPEAKER_STEREO (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT) - # define KSAUDIO_SPEAKER_QUAD (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \ - SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT) - # define KSAUDIO_SPEAKER_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \ - SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER) - # define KSAUDIO_SPEAKER_5POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \ - SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | \ - SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT) - # define KSAUDIO_SPEAKER_7POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \ - SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | \ - SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | \ - SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER) - # define KSAUDIO_SPEAKER_5POINT1_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \ - SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | \ - SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT) - # define KSAUDIO_SPEAKER_7POINT1_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \ - SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | \ - SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | \ - SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT) - - # define KSAUDIO_SPEAKER_5POINT1_BACK KSAUDIO_SPEAKER_5POINT1 - # define KSAUDIO_SPEAKER_7POINT1_WIDE KSAUDIO_SPEAKER_7POINT1 - - # define KSAUDIO_SPEAKER_GROUND_FRONT_LEFT SPEAKER_FRONT_LEFT - # define KSAUDIO_SPEAKER_GROUND_FRONT_CENTER SPEAKER_FRONT_CENTER - # define KSAUDIO_SPEAKER_GROUND_FRONT_RIGHT SPEAKER_FRONT_RIGHT - # define KSAUDIO_SPEAKER_GROUND_REAR_LEFT SPEAKER_BACK_LEFT - # define KSAUDIO_SPEAKER_GROUND_REAR_RIGHT SPEAKER_BACK_RIGHT - # define KSAUDIO_SPEAKER_TOP_MIDDLE SPEAKER_TOP_CENTER - # define KSAUDIO_SPEAKER_SUPER_WOOFER SPEAKER_LOW_FREQUENCY - -typedef struct -{ - ULONG QuietCompression; - ULONG LoudCompression; -}KSAUDIO_DYNAMIC_RANGE, * PKSAUDIO_DYNAMIC_RANGE; - -typedef struct -{ - WINBOOL Mute; - LONG Level; -}KSAUDIO_MIXLEVEL, * PKSAUDIO_MIXLEVEL; - -typedef struct -{ - WINBOOL Mute; - LONG Minimum; - LONG Maximum; - LONG Reset; -}KSAUDIO_MIX_CAPS, * PKSAUDIO_MIX_CAPS; - -typedef struct -{ - ULONG InputChannels; - ULONG OutputChannels; - KSAUDIO_MIX_CAPS Capabilities[1]; -}KSAUDIO_MIXCAP_TABLE, * PKSAUDIO_MIXCAP_TABLE; - -typedef enum -{ - SE_TECH_NONE, - SE_TECH_ANALOG_DEVICES_PHAT, - SE_TECH_CREATIVE, - SE_TECH_NATIONAL_SEMI, - SE_TECH_YAMAHA_YMERSION, - SE_TECH_BBE, - SE_TECH_CRYSTAL_SEMI, - SE_TECH_QSOUND_QXPANDER, - SE_TECH_SPATIALIZER, - SE_TECH_SRS, - SE_TECH_PLATFORM_TECH, - SE_TECH_AKM, - SE_TECH_AUREAL, - SE_TECH_AZTECH, - SE_TECH_BINAURA, - SE_TECH_ESS_TECH, - SE_TECH_HARMAN_VMAX, - SE_TECH_NVIDEA, - SE_TECH_PHILIPS_INCREDIBLE, - SE_TECH_TEXAS_INST, - SE_TECH_VLSI_TECH -}SE_TECHNIQUE; - -typedef struct -{ - SE_TECHNIQUE Technique; - ULONG Center; - ULONG Depth; - ULONG Reserved; -}KSAUDIO_STEREO_ENHANCE, * PKSAUDIO_STEREO_ENHANCE; - -typedef enum -{ - KSPROPERTY_SYSAUDIO_NORMAL_DEFAULT = 0, - KSPROPERTY_SYSAUDIO_PLAYBACK_DEFAULT, - KSPROPERTY_SYSAUDIO_RECORD_DEFAULT, - KSPROPERTY_SYSAUDIO_MIDI_DEFAULT, - KSPROPERTY_SYSAUDIO_MIXER_DEFAULT -}KSPROPERTY_SYSAUDIO_DEFAULT_TYPE; - -typedef struct -{ - WINBOOL Enable; - KSPROPERTY_SYSAUDIO_DEFAULT_TYPE DeviceType; - ULONG Flags; - ULONG Reserved; -}KSAUDIO_PREFERRED_STATUS, * PKSAUDIO_PREFERRED_STATUS; - - # define STATIC_KSNODETYPE_DAC \ - 0x507AE360L, 0xC554, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("507AE360-C554-11D0-8A2B-00A0C9255AC1", KSNODETYPE_DAC); - # define KSNODETYPE_DAC DEFINE_GUIDNAMED(KSNODETYPE_DAC) - - # define STATIC_KSNODETYPE_ADC \ - 0x4D837FE0L, 0xC555, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("4D837FE0-C555-11D0-8A2B-00A0C9255AC1", KSNODETYPE_ADC); - # define KSNODETYPE_ADC DEFINE_GUIDNAMED(KSNODETYPE_ADC) - - # define STATIC_KSNODETYPE_SRC \ - 0x9DB7B9E0L, 0xC555, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("9DB7B9E0-C555-11D0-8A2B-00A0C9255AC1", KSNODETYPE_SRC); - # define KSNODETYPE_SRC DEFINE_GUIDNAMED(KSNODETYPE_SRC) - - # define STATIC_KSNODETYPE_SUPERMIX \ - 0xE573ADC0L, 0xC555, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("E573ADC0-C555-11D0-8A2B-00A0C9255AC1", KSNODETYPE_SUPERMIX); - # define KSNODETYPE_SUPERMIX DEFINE_GUIDNAMED(KSNODETYPE_SUPERMIX) - - # define STATIC_KSNODETYPE_MUX \ - 0x2CEAF780L, 0xC556, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("2CEAF780-C556-11D0-8A2B-00A0C9255AC1", KSNODETYPE_MUX); - # define KSNODETYPE_MUX DEFINE_GUIDNAMED(KSNODETYPE_MUX) - - # define STATIC_KSNODETYPE_DEMUX \ - 0xC0EB67D4L, 0xE807, 0x11D0, 0x95, 0x8A, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("C0EB67D4-E807-11D0-958A-00C04FB925D3", KSNODETYPE_DEMUX); - # define KSNODETYPE_DEMUX DEFINE_GUIDNAMED(KSNODETYPE_DEMUX) - - # define STATIC_KSNODETYPE_SUM \ - 0xDA441A60L, 0xC556, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("DA441A60-C556-11D0-8A2B-00A0C9255AC1", KSNODETYPE_SUM); - # define KSNODETYPE_SUM DEFINE_GUIDNAMED(KSNODETYPE_SUM) - - # define STATIC_KSNODETYPE_MUTE \ - 0x02B223C0L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("02B223C0-C557-11D0-8A2B-00A0C9255AC1", KSNODETYPE_MUTE); - # define KSNODETYPE_MUTE DEFINE_GUIDNAMED(KSNODETYPE_MUTE) - - # define STATIC_KSNODETYPE_VOLUME \ - 0x3A5ACC00L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("3A5ACC00-C557-11D0-8A2B-00A0C9255AC1", KSNODETYPE_VOLUME); - # define KSNODETYPE_VOLUME DEFINE_GUIDNAMED(KSNODETYPE_VOLUME) - - # define STATIC_KSNODETYPE_TONE \ - 0x7607E580L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("7607E580-C557-11D0-8A2B-00A0C9255AC1", KSNODETYPE_TONE); - # define KSNODETYPE_TONE DEFINE_GUIDNAMED(KSNODETYPE_TONE) - - # define STATIC_KSNODETYPE_EQUALIZER \ - 0x9D41B4A0L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("9D41B4A0-C557-11D0-8A2B-00A0C9255AC1", KSNODETYPE_EQUALIZER); - # define KSNODETYPE_EQUALIZER DEFINE_GUIDNAMED(KSNODETYPE_EQUALIZER) - - # define STATIC_KSNODETYPE_AGC \ - 0xE88C9BA0L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("E88C9BA0-C557-11D0-8A2B-00A0C9255AC1", KSNODETYPE_AGC); - # define KSNODETYPE_AGC DEFINE_GUIDNAMED(KSNODETYPE_AGC) - - # define STATIC_KSNODETYPE_NOISE_SUPPRESS \ - 0xe07f903f, 0x62fd, 0x4e60, 0x8c, 0xdd, 0xde, 0xa7, 0x23, 0x66, 0x65, 0xb5 -DEFINE_GUIDSTRUCT("E07F903F-62FD-4e60-8CDD-DEA7236665B5", KSNODETYPE_NOISE_SUPPRESS); - # define KSNODETYPE_NOISE_SUPPRESS DEFINE_GUIDNAMED(KSNODETYPE_NOISE_SUPPRESS) - - # define STATIC_KSNODETYPE_DELAY \ - 0x144981E0L, 0xC558, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("144981E0-C558-11D0-8A2B-00A0C9255AC1", KSNODETYPE_DELAY); - # define KSNODETYPE_DELAY DEFINE_GUIDNAMED(KSNODETYPE_DELAY) - - # define STATIC_KSNODETYPE_LOUDNESS \ - 0x41887440L, 0xC558, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("41887440-C558-11D0-8A2B-00A0C9255AC1", KSNODETYPE_LOUDNESS); - # define KSNODETYPE_LOUDNESS DEFINE_GUIDNAMED(KSNODETYPE_LOUDNESS) - - # define STATIC_KSNODETYPE_PROLOGIC_DECODER \ - 0x831C2C80L, 0xC558, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("831C2C80-C558-11D0-8A2B-00A0C9255AC1", KSNODETYPE_PROLOGIC_DECODER); - # define KSNODETYPE_PROLOGIC_DECODER DEFINE_GUIDNAMED(KSNODETYPE_PROLOGIC_DECODER) - - # define STATIC_KSNODETYPE_STEREO_WIDE \ - 0xA9E69800L, 0xC558, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("A9E69800-C558-11D0-8A2B-00A0C9255AC1", KSNODETYPE_STEREO_WIDE); - # define KSNODETYPE_STEREO_WIDE DEFINE_GUIDNAMED(KSNODETYPE_STEREO_WIDE) - - # define STATIC_KSNODETYPE_STEREO_ENHANCE \ - 0xAF6878ACL, 0xE83F, 0x11D0, 0x95, 0x8A, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("AF6878AC-E83F-11D0-958A-00C04FB925D3", KSNODETYPE_STEREO_ENHANCE); - # define KSNODETYPE_STEREO_ENHANCE DEFINE_GUIDNAMED(KSNODETYPE_STEREO_ENHANCE) - - # define STATIC_KSNODETYPE_REVERB \ - 0xEF0328E0L, 0xC558, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("EF0328E0-C558-11D0-8A2B-00A0C9255AC1", KSNODETYPE_REVERB); - # define KSNODETYPE_REVERB DEFINE_GUIDNAMED(KSNODETYPE_REVERB) - - # define STATIC_KSNODETYPE_CHORUS \ - 0x20173F20L, 0xC559, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("20173F20-C559-11D0-8A2B-00A0C9255AC1", KSNODETYPE_CHORUS); - # define KSNODETYPE_CHORUS DEFINE_GUIDNAMED(KSNODETYPE_CHORUS) - - # define STATIC_KSNODETYPE_3D_EFFECTS \ - 0x55515860L, 0xC559, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("55515860-C559-11D0-8A2B-00A0C9255AC1", KSNODETYPE_3D_EFFECTS); - # define KSNODETYPE_3D_EFFECTS DEFINE_GUIDNAMED(KSNODETYPE_3D_EFFECTS) - - # define STATIC_KSNODETYPE_ACOUSTIC_ECHO_CANCEL STATIC_KSCATEGORY_ACOUSTIC_ECHO_CANCEL - # define KSNODETYPE_ACOUSTIC_ECHO_CANCEL KSCATEGORY_ACOUSTIC_ECHO_CANCEL - - # define STATIC_KSALGORITHMINSTANCE_SYSTEM_ACOUSTIC_ECHO_CANCEL \ - 0x1c22c56dL, 0x9879, 0x4f5b, 0xa3, 0x89, 0x27, 0x99, 0x6d, 0xdc, 0x28, 0x10 -DEFINE_GUIDSTRUCT("1C22C56D-9879-4f5b-A389-27996DDC2810", KSALGORITHMINSTANCE_SYSTEM_ACOUSTIC_ECHO_CANCEL); - # define KSALGORITHMINSTANCE_SYSTEM_ACOUSTIC_ECHO_CANCEL DEFINE_GUIDNAMED(KSALGORITHMINSTANCE_SYSTEM_ACOUSTIC_ECHO_CANCEL) - - # define STATIC_KSALGORITHMINSTANCE_SYSTEM_NOISE_SUPPRESS \ - 0x5ab0882eL, 0x7274, 0x4516, 0x87, 0x7d, 0x4e, 0xee, 0x99, 0xba, 0x4f, 0xd0 -DEFINE_GUIDSTRUCT("5AB0882E-7274-4516-877D-4EEE99BA4FD0", KSALGORITHMINSTANCE_SYSTEM_NOISE_SUPPRESS); - # define KSALGORITHMINSTANCE_SYSTEM_NOISE_SUPPRESS DEFINE_GUIDNAMED(KSALGORITHMINSTANCE_SYSTEM_NOISE_SUPPRESS) - - # define STATIC_KSALGORITHMINSTANCE_SYSTEM_AGC \ - 0x950e55b9L, 0x877c, 0x4c67, 0xbe, 0x8, 0xe4, 0x7b, 0x56, 0x11, 0x13, 0xa -DEFINE_GUIDSTRUCT("950E55B9-877C-4c67-BE08-E47B5611130A", KSALGORITHMINSTANCE_SYSTEM_AGC); - # define KSALGORITHMINSTANCE_SYSTEM_AGC DEFINE_GUIDNAMED(KSALGORITHMINSTANCE_SYSTEM_AGC) - - # define STATIC_KSALGORITHMINSTANCE_SYSTEM_MICROPHONE_ARRAY_PROCESSOR \ - 0xB6F5A0A0L, 0x9E61, 0x4F8C, 0x91, 0xE3, 0x76, 0xCF, 0xF, 0x3C, 0x47, 0x1F -DEFINE_GUIDSTRUCT("B6F5A0A0-9E61-4f8c-91E3-76CF0F3C471F", KSALGORITHMINSTANCE_SYSTEM_MICROPHONE_ARRAY_PROCESSOR); - # define KSALGORITHMINSTANCE_SYSTEM_MICROPHONE_ARRAY_PROCESSOR DEFINE_GUIDNAMED(KSALGORITHMINSTANCE_SYSTEM_MICROPHONE_ARRAY_PROCESSOR) - - # define STATIC_KSNODETYPE_MICROPHONE_ARRAY_PROCESSOR STATIC_KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR - # define KSNODETYPE_MICROPHONE_ARRAY_PROCESSOR KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR - - # define STATIC_KSNODETYPE_DEV_SPECIFIC \ - 0x941C7AC0L, 0xC559, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("941C7AC0-C559-11D0-8A2B-00A0C9255AC1", KSNODETYPE_DEV_SPECIFIC); - # define KSNODETYPE_DEV_SPECIFIC DEFINE_GUIDNAMED(KSNODETYPE_DEV_SPECIFIC) - - # define STATIC_KSNODETYPE_PROLOGIC_ENCODER \ - 0x8074C5B2L, 0x3C66, 0x11D2, 0xB4, 0x5A, 0x30, 0x78, 0x30, 0x2C, 0x20, 0x30 -DEFINE_GUIDSTRUCT("8074C5B2-3C66-11D2-B45A-3078302C2030", KSNODETYPE_PROLOGIC_ENCODER); - # define KSNODETYPE_PROLOGIC_ENCODER DEFINE_GUIDNAMED(KSNODETYPE_PROLOGIC_ENCODER) - # define KSNODETYPE_SURROUND_ENCODER KSNODETYPE_PROLOGIC_ENCODER - - # define STATIC_KSNODETYPE_PEAKMETER \ - 0xa085651eL, 0x5f0d, 0x4b36, 0xa8, 0x69, 0xd1, 0x95, 0xd6, 0xab, 0x4b, 0x9e -DEFINE_GUIDSTRUCT("A085651E-5F0D-4b36-A869-D195D6AB4B9E", KSNODETYPE_PEAKMETER); - # define KSNODETYPE_PEAKMETER DEFINE_GUIDNAMED(KSNODETYPE_PEAKMETER) - - # define STATIC_KSAUDFNAME_BASS \ - 0x185FEDE0L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE0-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_BASS); - # define KSAUDFNAME_BASS DEFINE_GUIDNAMED(KSAUDFNAME_BASS) - - # define STATIC_KSAUDFNAME_TREBLE \ - 0x185FEDE1L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE1-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_TREBLE); - # define KSAUDFNAME_TREBLE DEFINE_GUIDNAMED(KSAUDFNAME_TREBLE) - - # define STATIC_KSAUDFNAME_3D_STEREO \ - 0x185FEDE2L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE2-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_3D_STEREO); - # define KSAUDFNAME_3D_STEREO DEFINE_GUIDNAMED(KSAUDFNAME_3D_STEREO) - - # define STATIC_KSAUDFNAME_MASTER_VOLUME \ - 0x185FEDE3L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE3-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MASTER_VOLUME); - # define KSAUDFNAME_MASTER_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MASTER_VOLUME) - - # define STATIC_KSAUDFNAME_MASTER_MUTE \ - 0x185FEDE4L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE4-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MASTER_MUTE); - # define KSAUDFNAME_MASTER_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_MASTER_MUTE) - - # define STATIC_KSAUDFNAME_WAVE_VOLUME \ - 0x185FEDE5L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE5-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_WAVE_VOLUME); - # define KSAUDFNAME_WAVE_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_WAVE_VOLUME) - - # define STATIC_KSAUDFNAME_WAVE_MUTE \ - 0x185FEDE6L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE6-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_WAVE_MUTE); - # define KSAUDFNAME_WAVE_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_WAVE_MUTE) - - # define STATIC_KSAUDFNAME_MIDI_VOLUME \ - 0x185FEDE7L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE7-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MIDI_VOLUME); - # define KSAUDFNAME_MIDI_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MIDI_VOLUME) - - # define STATIC_KSAUDFNAME_MIDI_MUTE \ - 0x185FEDE8L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE8-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MIDI_MUTE); - # define KSAUDFNAME_MIDI_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_MIDI_MUTE) - - # define STATIC_KSAUDFNAME_CD_VOLUME \ - 0x185FEDE9L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE9-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_CD_VOLUME); - # define KSAUDFNAME_CD_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_CD_VOLUME) - - # define STATIC_KSAUDFNAME_CD_MUTE \ - 0x185FEDEAL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDEA-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_CD_MUTE); - # define KSAUDFNAME_CD_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_CD_MUTE) - - # define STATIC_KSAUDFNAME_LINE_VOLUME \ - 0x185FEDEBL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDEB-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_LINE_VOLUME); - # define KSAUDFNAME_LINE_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_LINE_VOLUME) - - # define STATIC_KSAUDFNAME_LINE_MUTE \ - 0x185FEDECL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDEC-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_LINE_MUTE); - # define KSAUDFNAME_LINE_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_LINE_MUTE) - - # define STATIC_KSAUDFNAME_MIC_VOLUME \ - 0x185FEDEDL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDED-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MIC_VOLUME); - # define KSAUDFNAME_MIC_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MIC_VOLUME) - - # define STATIC_KSAUDFNAME_MIC_MUTE \ - 0x185FEDEEL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDEE-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MIC_MUTE); - # define KSAUDFNAME_MIC_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_MIC_MUTE) - - # define STATIC_KSAUDFNAME_RECORDING_SOURCE \ - 0x185FEDEFL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDEF-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_RECORDING_SOURCE); - # define KSAUDFNAME_RECORDING_SOURCE DEFINE_GUIDNAMED(KSAUDFNAME_RECORDING_SOURCE) - - # define STATIC_KSAUDFNAME_PC_SPEAKER_VOLUME \ - 0x185FEDF0L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF0-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_PC_SPEAKER_VOLUME); - # define KSAUDFNAME_PC_SPEAKER_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_PC_SPEAKER_VOLUME) - - # define STATIC_KSAUDFNAME_PC_SPEAKER_MUTE \ - 0x185FEDF1L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF1-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_PC_SPEAKER_MUTE); - # define KSAUDFNAME_PC_SPEAKER_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_PC_SPEAKER_MUTE) - - # define STATIC_KSAUDFNAME_MIDI_IN_VOLUME \ - 0x185FEDF2L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF2-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MIDI_IN_VOLUME); - # define KSAUDFNAME_MIDI_IN_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MIDI_IN_VOLUME) - - # define STATIC_KSAUDFNAME_CD_IN_VOLUME \ - 0x185FEDF3L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF3-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_CD_IN_VOLUME); - # define KSAUDFNAME_CD_IN_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_CD_IN_VOLUME) - - # define STATIC_KSAUDFNAME_LINE_IN_VOLUME \ - 0x185FEDF4L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF4-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_LINE_IN_VOLUME); - # define KSAUDFNAME_LINE_IN_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_LINE_IN_VOLUME) - - # define STATIC_KSAUDFNAME_MIC_IN_VOLUME \ - 0x185FEDF5L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF5-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MIC_IN_VOLUME); - # define KSAUDFNAME_MIC_IN_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MIC_IN_VOLUME) - - # define STATIC_KSAUDFNAME_WAVE_IN_VOLUME \ - 0x185FEDF6L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF6-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_WAVE_IN_VOLUME); - # define KSAUDFNAME_WAVE_IN_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_WAVE_IN_VOLUME) - - # define STATIC_KSAUDFNAME_VOLUME_CONTROL \ - 0x185FEDF7L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF7-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_VOLUME_CONTROL); - # define KSAUDFNAME_VOLUME_CONTROL DEFINE_GUIDNAMED(KSAUDFNAME_VOLUME_CONTROL) - - # define STATIC_KSAUDFNAME_MIDI \ - 0x185FEDF8L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF8-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MIDI); - # define KSAUDFNAME_MIDI DEFINE_GUIDNAMED(KSAUDFNAME_MIDI) - - # define STATIC_KSAUDFNAME_LINE_IN \ - 0x185FEDF9L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF9-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_LINE_IN); - # define KSAUDFNAME_LINE_IN DEFINE_GUIDNAMED(KSAUDFNAME_LINE_IN) - - # define STATIC_KSAUDFNAME_RECORDING_CONTROL \ - 0x185FEDFAL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDFA-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_RECORDING_CONTROL); - # define KSAUDFNAME_RECORDING_CONTROL DEFINE_GUIDNAMED(KSAUDFNAME_RECORDING_CONTROL) - - # define STATIC_KSAUDFNAME_CD_AUDIO \ - 0x185FEDFBL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDFB-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_CD_AUDIO); - # define KSAUDFNAME_CD_AUDIO DEFINE_GUIDNAMED(KSAUDFNAME_CD_AUDIO) - - # define STATIC_KSAUDFNAME_AUX_VOLUME \ - 0x185FEDFCL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDFC-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_AUX_VOLUME); - # define KSAUDFNAME_AUX_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_AUX_VOLUME) - - # define STATIC_KSAUDFNAME_AUX_MUTE \ - 0x185FEDFDL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDFD-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_AUX_MUTE); - # define KSAUDFNAME_AUX_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_AUX_MUTE) - - # define STATIC_KSAUDFNAME_AUX \ - 0x185FEDFEL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDFE-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_AUX); - # define KSAUDFNAME_AUX DEFINE_GUIDNAMED(KSAUDFNAME_AUX) - - # define STATIC_KSAUDFNAME_PC_SPEAKER \ - 0x185FEDFFL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDFF-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_PC_SPEAKER); - # define KSAUDFNAME_PC_SPEAKER DEFINE_GUIDNAMED(KSAUDFNAME_PC_SPEAKER) - - # define STATIC_KSAUDFNAME_WAVE_OUT_MIX \ - 0x185FEE00L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEE00-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_WAVE_OUT_MIX); - # define KSAUDFNAME_WAVE_OUT_MIX DEFINE_GUIDNAMED(KSAUDFNAME_WAVE_OUT_MIX) - - # define STATIC_KSAUDFNAME_MONO_OUT \ - 0xf9b41dc3L, 0x96e2, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("F9B41DC3-96E2-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_MONO_OUT); - # define KSAUDFNAME_MONO_OUT DEFINE_GUIDNAMED(KSAUDFNAME_MONO_OUT) - - # define STATIC_KSAUDFNAME_STEREO_MIX \ - 0xdff077L, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("00DFF077-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_STEREO_MIX); - # define KSAUDFNAME_STEREO_MIX DEFINE_GUIDNAMED(KSAUDFNAME_STEREO_MIX) - - # define STATIC_KSAUDFNAME_MONO_MIX \ - 0xdff078L, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("00DFF078-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_MONO_MIX); - # define KSAUDFNAME_MONO_MIX DEFINE_GUIDNAMED(KSAUDFNAME_MONO_MIX) - - # define STATIC_KSAUDFNAME_MONO_OUT_VOLUME \ - 0x1ad247ebL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("1AD247EB-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_MONO_OUT_VOLUME); - # define KSAUDFNAME_MONO_OUT_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MONO_OUT_VOLUME) - - # define STATIC_KSAUDFNAME_MONO_OUT_MUTE \ - 0x1ad247ecL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("1AD247EC-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_MONO_OUT_MUTE); - # define KSAUDFNAME_MONO_OUT_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_MONO_OUT_MUTE) - - # define STATIC_KSAUDFNAME_STEREO_MIX_VOLUME \ - 0x1ad247edL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("1AD247ED-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_STEREO_MIX_VOLUME); - # define KSAUDFNAME_STEREO_MIX_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_STEREO_MIX_VOLUME) - - # define STATIC_KSAUDFNAME_STEREO_MIX_MUTE \ - 0x22b0eafdL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("22B0EAFD-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_STEREO_MIX_MUTE); - # define KSAUDFNAME_STEREO_MIX_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_STEREO_MIX_MUTE) - - # define STATIC_KSAUDFNAME_MONO_MIX_VOLUME \ - 0x22b0eafeL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("22B0EAFE-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_MONO_MIX_VOLUME); - # define KSAUDFNAME_MONO_MIX_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MONO_MIX_VOLUME) - - # define STATIC_KSAUDFNAME_MONO_MIX_MUTE \ - 0x2bc31d69L, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("2BC31D69-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_MONO_MIX_MUTE); - # define KSAUDFNAME_MONO_MIX_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_MONO_MIX_MUTE) - - # define STATIC_KSAUDFNAME_MICROPHONE_BOOST \ - 0x2bc31d6aL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("2BC31D6A-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_MICROPHONE_BOOST); - # define KSAUDFNAME_MICROPHONE_BOOST DEFINE_GUIDNAMED(KSAUDFNAME_MICROPHONE_BOOST) - - # define STATIC_KSAUDFNAME_ALTERNATE_MICROPHONE \ - 0x2bc31d6bL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("2BC31D6B-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_ALTERNATE_MICROPHONE); - # define KSAUDFNAME_ALTERNATE_MICROPHONE DEFINE_GUIDNAMED(KSAUDFNAME_ALTERNATE_MICROPHONE) - - # define STATIC_KSAUDFNAME_3D_DEPTH \ - 0x63ff5747L, 0x991f, 0x11d2, 0xac, 0x4d, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("63FF5747-991F-11d2-AC4D-00C04F8EFB68", KSAUDFNAME_3D_DEPTH); - # define KSAUDFNAME_3D_DEPTH DEFINE_GUIDNAMED(KSAUDFNAME_3D_DEPTH) - - # define STATIC_KSAUDFNAME_3D_CENTER \ - 0x9f0670b4L, 0x991f, 0x11d2, 0xac, 0x4d, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("9F0670B4-991F-11d2-AC4D-00C04F8EFB68", KSAUDFNAME_3D_CENTER); - # define KSAUDFNAME_3D_CENTER DEFINE_GUIDNAMED(KSAUDFNAME_3D_CENTER) - - # define STATIC_KSAUDFNAME_VIDEO_VOLUME \ - 0x9b46e708L, 0x992a, 0x11d2, 0xac, 0x4d, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("9B46E708-992A-11d2-AC4D-00C04F8EFB68", KSAUDFNAME_VIDEO_VOLUME); - # define KSAUDFNAME_VIDEO_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_VIDEO_VOLUME) - - # define STATIC_KSAUDFNAME_VIDEO_MUTE \ - 0x9b46e709L, 0x992a, 0x11d2, 0xac, 0x4d, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("9B46E709-992A-11d2-AC4D-00C04F8EFB68", KSAUDFNAME_VIDEO_MUTE); - # define KSAUDFNAME_VIDEO_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_VIDEO_MUTE) - - # define STATIC_KSAUDFNAME_VIDEO \ - 0x915daec4L, 0xa434, 0x11d2, 0xac, 0x52, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("915DAEC4-A434-11d2-AC52-00C04F8EFB68", KSAUDFNAME_VIDEO); - # define KSAUDFNAME_VIDEO DEFINE_GUIDNAMED(KSAUDFNAME_VIDEO) - - # define STATIC_KSAUDFNAME_PEAKMETER \ - 0x57e24340L, 0xfc5b, 0x4612, 0xa5, 0x62, 0x72, 0xb1, 0x1a, 0x29, 0xdf, 0xae -DEFINE_GUIDSTRUCT("57E24340-FC5B-4612-A562-72B11A29DFAE", KSAUDFNAME_PEAKMETER); - # define KSAUDFNAME_PEAKMETER DEFINE_GUIDNAMED(KSAUDFNAME_PEAKMETER) - - # define KSNODEPIN_STANDARD_IN 1 - # define KSNODEPIN_STANDARD_OUT 0 - - # define KSNODEPIN_SUM_MUX_IN 1 - # define KSNODEPIN_SUM_MUX_OUT 0 - - # define KSNODEPIN_DEMUX_IN 0 - # define KSNODEPIN_DEMUX_OUT 1 - - # define KSNODEPIN_AEC_RENDER_IN 1 - # define KSNODEPIN_AEC_RENDER_OUT 0 - # define KSNODEPIN_AEC_CAPTURE_IN 2 - # define KSNODEPIN_AEC_CAPTURE_OUT 3 - - # define STATIC_KSMETHODSETID_Wavetable \ - 0xDCEF31EBL, 0xD907, 0x11D0, 0x95, 0x83, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("DCEF31EB-D907-11D0-9583-00C04FB925D3", KSMETHODSETID_Wavetable); - # define KSMETHODSETID_Wavetable DEFINE_GUIDNAMED(KSMETHODSETID_Wavetable) - -typedef enum -{ - KSMETHOD_WAVETABLE_WAVE_ALLOC, - KSMETHOD_WAVETABLE_WAVE_FREE, - KSMETHOD_WAVETABLE_WAVE_FIND, - KSMETHOD_WAVETABLE_WAVE_WRITE -}KSMETHOD_WAVETABLE; - -typedef struct -{ - KSIDENTIFIER Identifier; - ULONG Size; - WINBOOL Looped; - ULONG LoopPoint; - WINBOOL InROM; - KSDATAFORMAT Format; -}KSWAVETABLE_WAVE_DESC, * PKSWAVETABLE_WAVE_DESC; - - # define STATIC_KSPROPSETID_Acoustic_Echo_Cancel \ - 0xd7a4af8bL, 0x3dc1, 0x4902, 0x91, 0xea, 0x8a, 0x15, 0xc9, 0x0e, 0x05, 0xb2 -DEFINE_GUIDSTRUCT("D7A4AF8B-3DC1-4902-91EA-8A15C90E05B2", KSPROPSETID_Acoustic_Echo_Cancel); - # define KSPROPSETID_Acoustic_Echo_Cancel DEFINE_GUIDNAMED(KSPROPSETID_Acoustic_Echo_Cancel) - -typedef enum -{ - KSPROPERTY_AEC_NOISE_FILL_ENABLE = 0, - KSPROPERTY_AEC_STATUS, - KSPROPERTY_AEC_MODE -}KSPROPERTY_AEC; - - # define AEC_STATUS_FD_HISTORY_UNINITIALIZED 0x0 - # define AEC_STATUS_FD_HISTORY_CONTINUOUSLY_CONVERGED 0x1 - # define AEC_STATUS_FD_HISTORY_PREVIOUSLY_DIVERGED 0x2 - # define AEC_STATUS_FD_CURRENTLY_CONVERGED 0x8 - - # define AEC_MODE_PASS_THROUGH 0x0 - # define AEC_MODE_HALF_DUPLEX 0x1 - # define AEC_MODE_FULL_DUPLEX 0x2 - - # define STATIC_KSPROPSETID_Wave \ - 0x924e54b0L, 0x630f, 0x11cf, 0xad, 0xa7, 0x08, 0x00, 0x3e, 0x30, 0x49, 0x4a -DEFINE_GUIDSTRUCT("924e54b0-630f-11cf-ada7-08003e30494a", KSPROPSETID_Wave); - # define KSPROPSETID_Wave DEFINE_GUIDNAMED(KSPROPSETID_Wave) - -typedef enum -{ - KSPROPERTY_WAVE_COMPATIBLE_CAPABILITIES, - KSPROPERTY_WAVE_INPUT_CAPABILITIES, - KSPROPERTY_WAVE_OUTPUT_CAPABILITIES, - KSPROPERTY_WAVE_BUFFER, - KSPROPERTY_WAVE_FREQUENCY, - KSPROPERTY_WAVE_VOLUME, - KSPROPERTY_WAVE_PAN -}KSPROPERTY_WAVE; - -typedef struct -{ - ULONG ulDeviceType; -}KSWAVE_COMPATCAPS, * PKSWAVE_COMPATCAPS; - - # define KSWAVE_COMPATCAPS_INPUT 0x00000000 - # define KSWAVE_COMPATCAPS_OUTPUT 0x00000001 - -typedef struct -{ - ULONG MaximumChannelsPerConnection; - ULONG MinimumBitsPerSample; - ULONG MaximumBitsPerSample; - ULONG MinimumSampleFrequency; - ULONG MaximumSampleFrequency; - ULONG TotalConnections; - ULONG ActiveConnections; -}KSWAVE_INPUT_CAPABILITIES, * PKSWAVE_INPUT_CAPABILITIES; - -typedef struct -{ - ULONG MaximumChannelsPerConnection; - ULONG MinimumBitsPerSample; - ULONG MaximumBitsPerSample; - ULONG MinimumSampleFrequency; - ULONG MaximumSampleFrequency; - ULONG TotalConnections; - ULONG StaticConnections; - ULONG StreamingConnections; - ULONG ActiveConnections; - ULONG ActiveStaticConnections; - ULONG ActiveStreamingConnections; - ULONG Total3DConnections; - ULONG Static3DConnections; - ULONG Streaming3DConnections; - ULONG Active3DConnections; - ULONG ActiveStatic3DConnections; - ULONG ActiveStreaming3DConnections; - ULONG TotalSampleMemory; - ULONG FreeSampleMemory; - ULONG LargestFreeContiguousSampleMemory; -}KSWAVE_OUTPUT_CAPABILITIES, * PKSWAVE_OUTPUT_CAPABILITIES; - -typedef struct -{ - LONG LeftAttenuation; - LONG RightAttenuation; -}KSWAVE_VOLUME, * PKSWAVE_VOLUME; - - # define KSWAVE_BUFFER_ATTRIBUTEF_LOOPING 0x00000001 - # define KSWAVE_BUFFER_ATTRIBUTEF_STATIC 0x00000002 - -typedef struct -{ - ULONG Attributes; - ULONG BufferSize; - PVOID BufferAddress; -}KSWAVE_BUFFER, * PKSWAVE_BUFFER; - - # define STATIC_KSMUSIC_TECHNOLOGY_PORT \ - 0x86C92E60L, 0x62E8, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("86C92E60-62E8-11CF-A5D6-28DB04C10000", KSMUSIC_TECHNOLOGY_PORT); - # define KSMUSIC_TECHNOLOGY_PORT DEFINE_GUIDNAMED(KSMUSIC_TECHNOLOGY_PORT) - - # define STATIC_KSMUSIC_TECHNOLOGY_SQSYNTH \ - 0x0ECF4380L, 0x62E9, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("0ECF4380-62E9-11CF-A5D6-28DB04C10000", KSMUSIC_TECHNOLOGY_SQSYNTH); - # define KSMUSIC_TECHNOLOGY_SQSYNTH DEFINE_GUIDNAMED(KSMUSIC_TECHNOLOGY_SQSYNTH) - - # define STATIC_KSMUSIC_TECHNOLOGY_FMSYNTH \ - 0x252C5C80L, 0x62E9, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("252C5C80-62E9-11CF-A5D6-28DB04C10000", KSMUSIC_TECHNOLOGY_FMSYNTH); - # define KSMUSIC_TECHNOLOGY_FMSYNTH DEFINE_GUIDNAMED(KSMUSIC_TECHNOLOGY_FMSYNTH) - - # define STATIC_KSMUSIC_TECHNOLOGY_WAVETABLE \ - 0x394EC7C0L, 0x62E9, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("394EC7C0-62E9-11CF-A5D6-28DB04C10000", KSMUSIC_TECHNOLOGY_WAVETABLE); - # define KSMUSIC_TECHNOLOGY_WAVETABLE DEFINE_GUIDNAMED(KSMUSIC_TECHNOLOGY_WAVETABLE) - - # define STATIC_KSMUSIC_TECHNOLOGY_SWSYNTH \ - 0x37407736L, 0x3620, 0x11D1, 0x85, 0xD3, 0x00, 0x00, 0xF8, 0x75, 0x43, 0x80 -DEFINE_GUIDSTRUCT("37407736-3620-11D1-85D3-0000F8754380", KSMUSIC_TECHNOLOGY_SWSYNTH); - # define KSMUSIC_TECHNOLOGY_SWSYNTH DEFINE_GUIDNAMED(KSMUSIC_TECHNOLOGY_SWSYNTH) - - # define STATIC_KSPROPSETID_WaveTable \ - 0x8539E660L, 0x62E9, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("8539E660-62E9-11CF-A5D6-28DB04C10000", KSPROPSETID_WaveTable); - # define KSPROPSETID_WaveTable DEFINE_GUIDNAMED(KSPROPSETID_WaveTable) - -typedef enum -{ - KSPROPERTY_WAVETABLE_LOAD_SAMPLE, - KSPROPERTY_WAVETABLE_UNLOAD_SAMPLE, - KSPROPERTY_WAVETABLE_MEMORY, - KSPROPERTY_WAVETABLE_VERSION -}KSPROPERTY_WAVETABLE; - -typedef struct -{ - KSDATARANGE DataRange; - GUID Technology; - ULONG Channels; - ULONG Notes; - ULONG ChannelMask; -}KSDATARANGE_MUSIC, * PKSDATARANGE_MUSIC; - - # define STATIC_KSEVENTSETID_Cyclic \ - 0x142C1AC0L, 0x072A, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("142C1AC0-072A-11D0-A5D6-28DB04C10000", KSEVENTSETID_Cyclic); - # define KSEVENTSETID_Cyclic DEFINE_GUIDNAMED(KSEVENTSETID_Cyclic) - -typedef enum -{ - KSEVENT_CYCLIC_TIME_INTERVAL -}KSEVENT_CYCLIC_TIME; - - # define STATIC_KSPROPSETID_Cyclic \ - 0x3FFEAEA0L, 0x2BEE, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("3FFEAEA0-2BEE-11CF-A5D6-28DB04C10000", KSPROPSETID_Cyclic); - # define KSPROPSETID_Cyclic DEFINE_GUIDNAMED(KSPROPSETID_Cyclic) - -typedef enum -{ - KSPROPERTY_CYCLIC_POSITION -}KSPROPERTY_CYCLIC; - - # define STATIC_KSEVENTSETID_AudioControlChange \ - 0xE85E9698L, 0xFA2F, 0x11D1, 0x95, 0xBD, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("E85E9698-FA2F-11D1-95BD-00C04FB925D3", KSEVENTSETID_AudioControlChange); - # define KSEVENTSETID_AudioControlChange DEFINE_GUIDNAMED(KSEVENTSETID_AudioControlChange) - -typedef enum -{ - KSEVENT_CONTROL_CHANGE -}KSEVENT_AUDIO_CONTROL_CHANGE; - - # define STATIC_KSEVENTSETID_LoopedStreaming \ - 0x4682B940L, 0xC6EF, 0x11D0, 0x96, 0xD8, 0x00, 0xAA, 0x00, 0x51, 0xE5, 0x1D -DEFINE_GUIDSTRUCT("4682B940-C6EF-11D0-96D8-00AA0051E51D", KSEVENTSETID_LoopedStreaming); - # define KSEVENTSETID_LoopedStreaming DEFINE_GUIDNAMED(KSEVENTSETID_LoopedStreaming) - -typedef enum -{ - KSEVENT_LOOPEDSTREAMING_POSITION -}KSEVENT_LOOPEDSTREAMING; - -typedef struct -{ - KSEVENTDATA KsEventData; - DWORDLONG Position; -}LOOPEDSTREAMING_POSITION_EVENT_DATA, * PLOOPEDSTREAMING_POSITION_EVENT_DATA; - - # define STATIC_KSPROPSETID_Sysaudio \ - 0xCBE3FAA0L, 0xCC75, 0x11D0, 0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6 -DEFINE_GUIDSTRUCT("CBE3FAA0-CC75-11D0-B465-00001A1818E6", KSPROPSETID_Sysaudio); - # define KSPROPSETID_Sysaudio DEFINE_GUIDNAMED(KSPROPSETID_Sysaudio) - -typedef enum -{ - KSPROPERTY_SYSAUDIO_DEVICE_COUNT = 1, - KSPROPERTY_SYSAUDIO_DEVICE_FRIENDLY_NAME = 2, - KSPROPERTY_SYSAUDIO_DEVICE_INSTANCE = 3, - KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME = 4, - KSPROPERTY_SYSAUDIO_SELECT_GRAPH = 5, - KSPROPERTY_SYSAUDIO_CREATE_VIRTUAL_SOURCE = 6, - KSPROPERTY_SYSAUDIO_DEVICE_DEFAULT = 7, - KSPROPERTY_SYSAUDIO_INSTANCE_INFO = 14, - KSPROPERTY_SYSAUDIO_COMPONENT_ID = 16 -}KSPROPERTY_SYSAUDIO; - -typedef struct -{ - KSPROPERTY Property; - GUID PinCategory; - GUID PinName; -}SYSAUDIO_CREATE_VIRTUAL_SOURCE, * PSYSAUDIO_CREATE_VIRTUAL_SOURCE; - -typedef struct -{ - KSPROPERTY Property; - ULONG PinId; - ULONG NodeId; - ULONG Flags; - ULONG Reserved; -}SYSAUDIO_SELECT_GRAPH, * PSYSAUDIO_SELECT_GRAPH; - -typedef struct -{ - KSPROPERTY Property; - ULONG Flags; - ULONG DeviceNumber; -}SYSAUDIO_INSTANCE_INFO, * PSYSAUDIO_INSTANCE_INFO; - - # define SYSAUDIO_FLAGS_DONT_COMBINE_PINS 0x00000001 - - # define STATIC_KSPROPSETID_Sysaudio_Pin \ - 0xA3A53220L, 0xC6E4, 0x11D0, 0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6 -DEFINE_GUIDSTRUCT("A3A53220-C6E4-11D0-B465-00001A1818E6", KSPROPSETID_Sysaudio_Pin); - # define KSPROPSETID_Sysaudio_Pin DEFINE_GUIDNAMED(KSPROPSETID_Sysaudio_Pin) - -typedef enum -{ - KSPROPERTY_SYSAUDIO_ATTACH_VIRTUAL_SOURCE = 1 -}KSPROPERTY_SYSAUDIO_PIN; - -typedef struct -{ - KSPROPERTY Property; - ULONG MixerPinId; - ULONG Reserved; -}SYSAUDIO_ATTACH_VIRTUAL_SOURCE, * PSYSAUDIO_ATTACH_VIRTUAL_SOURCE; - -typedef struct -{ - KSPROPERTY Property; - ULONG NodeId; - ULONG Reserved; -}KSNODEPROPERTY, * PKSNODEPROPERTY; - -typedef struct -{ - KSNODEPROPERTY NodeProperty; - LONG Channel; - ULONG Reserved; -}KSNODEPROPERTY_AUDIO_CHANNEL, * PKSNODEPROPERTY_AUDIO_CHANNEL; - -typedef struct -{ - KSNODEPROPERTY NodeProperty; - ULONG DevSpecificId; - ULONG DeviceInfo; - ULONG Length; -}KSNODEPROPERTY_AUDIO_DEV_SPECIFIC, * PKSNODEPROPERTY_AUDIO_DEV_SPECIFIC; - -typedef struct -{ - KSNODEPROPERTY NodeProperty; - PVOID ListenerId; - # ifndef _WIN64 - ULONG Reserved; - # endif -}KSNODEPROPERTY_AUDIO_3D_LISTENER, * PKSNODEPROPERTY_AUDIO_3D_LISTENER; - -typedef struct -{ - KSNODEPROPERTY NodeProperty; - PVOID AppContext; - ULONG Length; - # ifndef _WIN64 - ULONG Reserved; - # endif -}KSNODEPROPERTY_AUDIO_PROPERTY, * PKSNODEPROPERTY_AUDIO_PROPERTY; - - # define STATIC_KSPROPSETID_AudioGfx \ - 0x79a9312eL, 0x59ae, 0x43b0, 0xa3, 0x50, 0x8b, 0x5, 0x28, 0x4c, 0xab, 0x24 -DEFINE_GUIDSTRUCT("79A9312E-59AE-43b0-A350-8B05284CAB24", KSPROPSETID_AudioGfx); - # define KSPROPSETID_AudioGfx DEFINE_GUIDNAMED(KSPROPSETID_AudioGfx) - -typedef enum -{ - KSPROPERTY_AUDIOGFX_RENDERTARGETDEVICEID, - KSPROPERTY_AUDIOGFX_CAPTURETARGETDEVICEID -}KSPROPERTY_AUDIOGFX; - - # define STATIC_KSPROPSETID_Linear \ - 0x5A2FFE80L, 0x16B9, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("5A2FFE80-16B9-11D0-A5D6-28DB04C10000", KSPROPSETID_Linear); - # define KSPROPSETID_Linear DEFINE_GUIDNAMED(KSPROPSETID_Linear) - -typedef enum -{ - KSPROPERTY_LINEAR_POSITION -}KSPROPERTY_LINEAR; - - # define STATIC_KSDATAFORMAT_TYPE_MUSIC \ - 0xE725D360L, 0x62CC, 0x11CF, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 } -DEFINE_GUIDSTRUCT("E725D360-62CC-11CF-A5D6-28DB04C10000", KSDATAFORMAT_TYPE_MUSIC); - # define KSDATAFORMAT_TYPE_MUSIC DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_MUSIC) - - # define STATIC_KSDATAFORMAT_TYPE_MIDI \ - 0x7364696DL, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 -DEFINE_GUIDSTRUCT("7364696D-0000-0010-8000-00aa00389b71", KSDATAFORMAT_TYPE_MIDI); - # define KSDATAFORMAT_TYPE_MIDI DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_MIDI) - - # define STATIC_KSDATAFORMAT_SUBTYPE_MIDI \ - 0x1D262760L, 0xE957, 0x11CF, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 } -DEFINE_GUIDSTRUCT("1D262760-E957-11CF-A5D6-28DB04C10000", KSDATAFORMAT_SUBTYPE_MIDI); - # define KSDATAFORMAT_SUBTYPE_MIDI DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MIDI) - - # define STATIC_KSDATAFORMAT_SUBTYPE_MIDI_BUS \ - 0x2CA15FA0L, 0x6CFE, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("2CA15FA0-6CFE-11CF-A5D6-28DB04C10000", KSDATAFORMAT_SUBTYPE_MIDI_BUS); - # define KSDATAFORMAT_SUBTYPE_MIDI_BUS DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MIDI_BUS) - - # define STATIC_KSDATAFORMAT_SUBTYPE_RIFFMIDI \ - 0x4995DAF0L, 0x9EE6, 0x11D0, 0xA4, 0x0E, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("4995DAF0-9EE6-11D0-A40E-00A0C9223196", KSDATAFORMAT_SUBTYPE_RIFFMIDI); - # define KSDATAFORMAT_SUBTYPE_RIFFMIDI DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_RIFFMIDI) - -typedef struct -{ - ULONG TimeDeltaMs; - - ULONG ByteCount; -}KSMUSICFORMAT, * PKSMUSICFORMAT; - - # define STATIC_KSDATAFORMAT_TYPE_STANDARD_ELEMENTARY_STREAM \ - 0x36523b11L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B11-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_TYPE_STANDARD_ELEMENTARY_STREAM); - # define KSDATAFORMAT_TYPE_STANDARD_ELEMENTARY_STREAM DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_STANDARD_ELEMENTARY_STREAM) - - # define STATIC_KSDATAFORMAT_TYPE_STANDARD_PES_PACKET \ - 0x36523b12L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B12-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_TYPE_STANDARD_PES_PACKET); - # define KSDATAFORMAT_TYPE_STANDARD_PES_PACKET DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_STANDARD_PES_PACKET) - - # define STATIC_KSDATAFORMAT_TYPE_STANDARD_PACK_HEADER \ - 0x36523b13L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B13-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_TYPE_STANDARD_PACK_HEADER); - # define KSDATAFORMAT_TYPE_STANDARD_PACK_HEADER DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_STANDARD_PACK_HEADER) - - # define STATIC_KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_VIDEO \ - 0x36523b21L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B21-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_VIDEO); - # define KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_VIDEO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_AUDIO \ - 0x36523b22L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B22-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_AUDIO); - # define KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_AUDIO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_VIDEO \ - 0x36523b23L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B23-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_VIDEO); - # define KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_VIDEO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_AUDIO \ - 0x36523b24L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B24-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_AUDIO); - # define KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_AUDIO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_STANDARD_AC3_AUDIO \ - 0x36523b25L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B25-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SUBTYPE_STANDARD_AC3_AUDIO); - # define KSDATAFORMAT_SUBTYPE_STANDARD_AC3_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_STANDARD_AC3_AUDIO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_VIDEO \ - 0x36523b31L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B31-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_VIDEO); - # define KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_VIDEO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_AUDIO \ - 0x36523b32L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B32-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_AUDIO); - # define KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_AUDIO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_VIDEO \ - 0x36523b33L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B33-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_VIDEO); - # define KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_VIDEO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_AUDIO \ - 0x36523b34L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B34-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_AUDIO); - # define KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_AUDIO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_DIALECT_AC3_AUDIO \ - 0x36523b35L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B35-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SPECIFIER_DIALECT_AC3_AUDIO); - # define KSDATAFORMAT_SPECIFIER_DIALECT_AC3_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DIALECT_AC3_AUDIO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_DSS_VIDEO \ - 0xa0af4f81L, 0xe163, 0x11d0, 0xba, 0xd9, 0x00, 0x60, 0x97, 0x44, 0x11, 0x1a -DEFINE_GUIDSTRUCT("a0af4f81-e163-11d0-bad9-00609744111a", KSDATAFORMAT_SUBTYPE_DSS_VIDEO); - # define KSDATAFORMAT_SUBTYPE_DSS_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DSS_VIDEO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_DSS_AUDIO \ - 0xa0af4f82L, 0xe163, 0x11d0, 0xba, 0xd9, 0x00, 0x60, 0x97, 0x44, 0x11, 0x1a -DEFINE_GUIDSTRUCT("a0af4f82-e163-11d0-bad9-00609744111a", KSDATAFORMAT_SUBTYPE_DSS_AUDIO); - # define KSDATAFORMAT_SUBTYPE_DSS_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DSS_AUDIO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_MPEG1Packet \ - 0xe436eb80, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 -DEFINE_GUIDSTRUCT("e436eb80-524f-11ce-9F53-0020af0ba770", KSDATAFORMAT_SUBTYPE_MPEG1Packet); - # define KSDATAFORMAT_SUBTYPE_MPEG1Packet DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG1Packet) - - # define STATIC_KSDATAFORMAT_SUBTYPE_MPEG1Payload \ - 0xe436eb81, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 -DEFINE_GUIDSTRUCT("e436eb81-524f-11ce-9F53-0020af0ba770", KSDATAFORMAT_SUBTYPE_MPEG1Payload); - # define KSDATAFORMAT_SUBTYPE_MPEG1Payload DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG1Payload) - - # define STATIC_KSDATAFORMAT_SUBTYPE_MPEG1Video \ - 0xe436eb86, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 -DEFINE_GUIDSTRUCT("e436eb86-524f-11ce-9f53-0020af0ba770", KSDATAFORMAT_SUBTYPE_MPEG1Video); - # define KSDATAFORMAT_SUBTYPE_MPEG1Video DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG1Video) - - # define STATIC_KSDATAFORMAT_SPECIFIER_MPEG1_VIDEO \ - 0x05589f82L, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a -DEFINE_GUIDSTRUCT("05589f82-c356-11ce-bf01-00aa0055595a", KSDATAFORMAT_SPECIFIER_MPEG1_VIDEO); - # define KSDATAFORMAT_SPECIFIER_MPEG1_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_MPEG1_VIDEO) - - # define STATIC_KSDATAFORMAT_TYPE_MPEG2_PES \ - 0xe06d8020L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d8020-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_TYPE_MPEG2_PES); - # define KSDATAFORMAT_TYPE_MPEG2_PES DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_MPEG2_PES) - - # define STATIC_KSDATAFORMAT_TYPE_MPEG2_PROGRAM \ - 0xe06d8022L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d8022-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_TYPE_MPEG2_PROGRAM); - # define KSDATAFORMAT_TYPE_MPEG2_PROGRAM DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_MPEG2_PROGRAM) - - # define STATIC_KSDATAFORMAT_TYPE_MPEG2_TRANSPORT \ - 0xe06d8023L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d8023-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_TYPE_MPEG2_TRANSPORT); - # define KSDATAFORMAT_TYPE_MPEG2_TRANSPORT DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_MPEG2_TRANSPORT) - - # define STATIC_KSDATAFORMAT_SUBTYPE_MPEG2_VIDEO \ - 0xe06d8026L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d8026-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SUBTYPE_MPEG2_VIDEO); - # define KSDATAFORMAT_SUBTYPE_MPEG2_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG2_VIDEO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_MPEG2_VIDEO \ - 0xe06d80e3L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d80e3-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SPECIFIER_MPEG2_VIDEO); - # define KSDATAFORMAT_SPECIFIER_MPEG2_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_MPEG2_VIDEO) - - # define STATIC_KSPROPSETID_Mpeg2Vid \ - 0xC8E11B60L, 0x0CC9, 0x11D0, 0xBD, 0x69, 0x00, 0x35, 0x05, 0xC1, 0x03, 0xA9 -DEFINE_GUIDSTRUCT("C8E11B60-0CC9-11D0-BD69-003505C103A9", KSPROPSETID_Mpeg2Vid); - # define KSPROPSETID_Mpeg2Vid DEFINE_GUIDNAMED(KSPROPSETID_Mpeg2Vid) - -typedef enum -{ - KSPROPERTY_MPEG2VID_MODES, - KSPROPERTY_MPEG2VID_CUR_MODE, - KSPROPERTY_MPEG2VID_4_3_RECT, - KSPROPERTY_MPEG2VID_16_9_RECT, - KSPROPERTY_MPEG2VID_16_9_PANSCAN -}KSPROPERTY_MPEG2VID; - - # define KSMPEGVIDMODE_PANSCAN 0x0001 - # define KSMPEGVIDMODE_LTRBOX 0x0002 - # define KSMPEGVIDMODE_SCALE 0x0004 - -typedef struct _KSMPEGVID_RECT -{ - ULONG StartX; - ULONG StartY; - ULONG EndX; - ULONG EndY; -}KSMPEGVID_RECT, * PKSMPEGVID_RECT; - - # define STATIC_KSDATAFORMAT_SUBTYPE_MPEG2_AUDIO \ - 0xe06d802bL, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d802b-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SUBTYPE_MPEG2_AUDIO); - # define KSDATAFORMAT_SUBTYPE_MPEG2_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG2_AUDIO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_MPEG2_AUDIO \ - 0xe06d80e5L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d80e5-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SPECIFIER_MPEG2_AUDIO); - # define KSDATAFORMAT_SPECIFIER_MPEG2_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_MPEG2_AUDIO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_LPCM_AUDIO \ - 0xe06d8032L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d8032-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SUBTYPE_LPCM_AUDIO); - # define KSDATAFORMAT_SUBTYPE_LPCM_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_LPCM_AUDIO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_LPCM_AUDIO \ - 0xe06d80e6L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d80e6-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SPECIFIER_LPCM_AUDIO); - # define KSDATAFORMAT_SPECIFIER_LPCM_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_LPCM_AUDIO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_AC3_AUDIO \ - 0xe06d802cL, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d802c-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SUBTYPE_AC3_AUDIO); - # define KSDATAFORMAT_SUBTYPE_AC3_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_AC3_AUDIO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_AC3_AUDIO \ - 0xe06d80e4L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d80e4-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SPECIFIER_AC3_AUDIO); - # define KSDATAFORMAT_SPECIFIER_AC3_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_AC3_AUDIO) - - # define STATIC_KSPROPSETID_AC3 \ - 0xBFABE720L, 0x6E1F, 0x11D0, 0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 -DEFINE_GUIDSTRUCT("BFABE720-6E1F-11D0-BCF2-444553540000", KSPROPSETID_AC3); - # define KSPROPSETID_AC3 DEFINE_GUIDNAMED(KSPROPSETID_AC3) - -typedef enum -{ - KSPROPERTY_AC3_ERROR_CONCEALMENT = 1, - KSPROPERTY_AC3_ALTERNATE_AUDIO, - KSPROPERTY_AC3_DOWNMIX, - KSPROPERTY_AC3_BIT_STREAM_MODE, - KSPROPERTY_AC3_DIALOGUE_LEVEL, - KSPROPERTY_AC3_LANGUAGE_CODE, - KSPROPERTY_AC3_ROOM_TYPE -}KSPROPERTY_AC3; - -typedef struct -{ - WINBOOL fRepeatPreviousBlock; - WINBOOL fErrorInCurrentBlock; -}KSAC3_ERROR_CONCEALMENT, * PKSAC3_ERROR_CONCEALMENT; - -typedef struct -{ - WINBOOL fStereo; - ULONG DualMode; -}KSAC3_ALTERNATE_AUDIO, * PKSAC3_ALTERNATE_AUDIO; - - # define KSAC3_ALTERNATE_AUDIO_1 1 - # define KSAC3_ALTERNATE_AUDIO_2 2 - # define KSAC3_ALTERNATE_AUDIO_BOTH 3 - -typedef struct -{ - WINBOOL fDownMix; - WINBOOL fDolbySurround; -}KSAC3_DOWNMIX, * PKSAC3_DOWNMIX; - -typedef struct -{ - LONG BitStreamMode; -}KSAC3_BIT_STREAM_MODE, * PKSAC3_BIT_STREAM_MODE; - - # define KSAC3_SERVICE_MAIN_AUDIO 0 - # define KSAC3_SERVICE_NO_DIALOG 1 - # define KSAC3_SERVICE_VISUALLY_IMPAIRED 2 - # define KSAC3_SERVICE_HEARING_IMPAIRED 3 - # define KSAC3_SERVICE_DIALOG_ONLY 4 - # define KSAC3_SERVICE_COMMENTARY 5 - # define KSAC3_SERVICE_EMERGENCY_FLASH 6 - # define KSAC3_SERVICE_VOICE_OVER 7 - -typedef struct -{ - ULONG DialogueLevel; -}KSAC3_DIALOGUE_LEVEL, * PKSAC3_DIALOGUE_LEVEL; - -typedef struct -{ - WINBOOL fLargeRoom; -}KSAC3_ROOM_TYPE, * PKSAC3_ROOM_TYPE; - - # define STATIC_KSDATAFORMAT_SUBTYPE_DTS_AUDIO \ - 0xe06d8033L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d8033-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SUBTYPE_DTS_AUDIO); - # define KSDATAFORMAT_SUBTYPE_DTS_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DTS_AUDIO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_SDDS_AUDIO \ - 0xe06d8034L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d8034-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SUBTYPE_SDDS_AUDIO); - # define KSDATAFORMAT_SUBTYPE_SDDS_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_SDDS_AUDIO) - - # define STATIC_KSPROPSETID_AudioDecoderOut \ - 0x6ca6e020L, 0x43bd, 0x11d0, 0xbd, 0x6a, 0x00, 0x35, 0x05, 0xc1, 0x03, 0xa9 -DEFINE_GUIDSTRUCT("6ca6e020-43bd-11d0-bd6a-003505c103a9", KSPROPSETID_AudioDecoderOut); - # define KSPROPSETID_AudioDecoderOut DEFINE_GUIDNAMED(KSPROPSETID_AudioDecoderOut) - -typedef enum -{ - KSPROPERTY_AUDDECOUT_MODES, - KSPROPERTY_AUDDECOUT_CUR_MODE -}KSPROPERTY_AUDDECOUT; - - # define KSAUDDECOUTMODE_STEREO_ANALOG 0x0001 - # define KSAUDDECOUTMODE_PCM_51 0x0002 - # define KSAUDDECOUTMODE_SPDIFF 0x0004 - - # define STATIC_KSDATAFORMAT_SUBTYPE_SUBPICTURE \ - 0xe06d802dL, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d802d-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SUBTYPE_SUBPICTURE); - # define KSDATAFORMAT_SUBTYPE_SUBPICTURE DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_SUBPICTURE) - - # define STATIC_KSPROPSETID_DvdSubPic \ - 0xac390460L, 0x43af, 0x11d0, 0xbd, 0x6a, 0x00, 0x35, 0x05, 0xc1, 0x03, 0xa9 -DEFINE_GUIDSTRUCT("ac390460-43af-11d0-bd6a-003505c103a9", KSPROPSETID_DvdSubPic); - # define KSPROPSETID_DvdSubPic DEFINE_GUIDNAMED(KSPROPSETID_DvdSubPic) - -typedef enum -{ - KSPROPERTY_DVDSUBPIC_PALETTE, - KSPROPERTY_DVDSUBPIC_HLI, - KSPROPERTY_DVDSUBPIC_COMPOSIT_ON -}KSPROPERTY_DVDSUBPIC; - -typedef struct _KS_DVD_YCrCb -{ - UCHAR Reserved; - UCHAR Y; - UCHAR Cr; - UCHAR Cb; -}KS_DVD_YCrCb, * PKS_DVD_YCrCb; - -typedef struct _KS_DVD_YUV -{ - UCHAR Reserved; - UCHAR Y; - UCHAR V; - UCHAR U; -}KS_DVD_YUV, * PKS_DVD_YUV; - -typedef struct _KSPROPERTY_SPPAL -{ - KS_DVD_YUV sppal[16]; -}KSPROPERTY_SPPAL, * PKSPROPERTY_SPPAL; - -typedef struct _KS_COLCON -{ - UCHAR emph1col : 4; - UCHAR emph2col : 4; - UCHAR backcol : 4; - UCHAR patcol : 4; - UCHAR emph1con : 4; - UCHAR emph2con : 4; - UCHAR backcon : 4; - UCHAR patcon : 4; -}KS_COLCON, * PKS_COLCON; - -typedef struct _KSPROPERTY_SPHLI -{ - USHORT HLISS; - USHORT Reserved; - ULONG StartPTM; - ULONG EndPTM; - USHORT StartX; - USHORT StartY; - USHORT StopX; - USHORT StopY; - KS_COLCON ColCon; -}KSPROPERTY_SPHLI, * PKSPROPERTY_SPHLI; - -typedef WINBOOL KSPROPERTY_COMPOSIT_ON, * PKSPROPERTY_COMPOSIT_ON; - - # define STATIC_KSPROPSETID_CopyProt \ - 0x0E8A0A40L, 0x6AEF, 0x11D0, 0x9E, 0xD0, 0x00, 0xA0, 0x24, 0xCA, 0x19, 0xB3 -DEFINE_GUIDSTRUCT("0E8A0A40-6AEF-11D0-9ED0-00A024CA19B3", KSPROPSETID_CopyProt); - # define KSPROPSETID_CopyProt DEFINE_GUIDNAMED(KSPROPSETID_CopyProt) - -typedef enum -{ - KSPROPERTY_DVDCOPY_CHLG_KEY = 0x01, - KSPROPERTY_DVDCOPY_DVD_KEY1, - KSPROPERTY_DVDCOPY_DEC_KEY2, - KSPROPERTY_DVDCOPY_TITLE_KEY, - KSPROPERTY_COPY_MACROVISION, - KSPROPERTY_DVDCOPY_REGION, - KSPROPERTY_DVDCOPY_SET_COPY_STATE, - KSPROPERTY_DVDCOPY_DISC_KEY = 0x80 -}KSPROPERTY_COPYPROT; - -typedef struct _KS_DVDCOPY_CHLGKEY -{ - BYTE ChlgKey[10]; - BYTE Reserved[2]; -}KS_DVDCOPY_CHLGKEY, * PKS_DVDCOPY_CHLGKEY; - -typedef struct _KS_DVDCOPY_BUSKEY -{ - BYTE BusKey[5]; - BYTE Reserved[1]; -}KS_DVDCOPY_BUSKEY, * PKS_DVDCOPY_BUSKEY; - -typedef struct _KS_DVDCOPY_DISCKEY -{ - BYTE DiscKey[2048]; -}KS_DVDCOPY_DISCKEY, * PKS_DVDCOPY_DISCKEY; - -typedef struct _KS_DVDCOPY_REGION -{ - UCHAR Reserved; - UCHAR RegionData; - UCHAR Reserved2[2]; -}KS_DVDCOPY_REGION, * PKS_DVDCOPY_REGION; - -typedef struct _KS_DVDCOPY_TITLEKEY -{ - ULONG KeyFlags; - ULONG ReservedNT[2]; - UCHAR TitleKey[6]; - UCHAR Reserved[2]; -}KS_DVDCOPY_TITLEKEY, * PKS_DVDCOPY_TITLEKEY; - -typedef struct _KS_COPY_MACROVISION -{ - ULONG MACROVISIONLevel; -}KS_COPY_MACROVISION, * PKS_COPY_MACROVISION; - -typedef struct _KS_DVDCOPY_SET_COPY_STATE -{ - ULONG DVDCopyState; -}KS_DVDCOPY_SET_COPY_STATE, * PKS_DVDCOPY_SET_COPY_STATE; - -typedef enum -{ - KS_DVDCOPYSTATE_INITIALIZE, - KS_DVDCOPYSTATE_INITIALIZE_TITLE, - KS_DVDCOPYSTATE_AUTHENTICATION_NOT_REQUIRED, - KS_DVDCOPYSTATE_AUTHENTICATION_REQUIRED, - KS_DVDCOPYSTATE_DONE -}KS_DVDCOPYSTATE; - -typedef enum -{ - KS_MACROVISION_DISABLED, - KS_MACROVISION_LEVEL1, - KS_MACROVISION_LEVEL2, - KS_MACROVISION_LEVEL3 -}KS_COPY_MACROVISION_LEVEL, * PKS_COPY_MACROVISION_LEVEL; - - # define KS_DVD_CGMS_RESERVED_MASK 0x00000078 - - # define KS_DVD_CGMS_COPY_PROTECT_MASK 0x00000018 - # define KS_DVD_CGMS_COPY_PERMITTED 0x00000000 - # define KS_DVD_CGMS_COPY_ONCE 0x00000010 - # define KS_DVD_CGMS_NO_COPY 0x00000018 - - # define KS_DVD_COPYRIGHT_MASK 0x00000040 - # define KS_DVD_NOT_COPYRIGHTED 0x00000000 - # define KS_DVD_COPYRIGHTED 0x00000040 - - # define KS_DVD_SECTOR_PROTECT_MASK 0x00000020 - # define KS_DVD_SECTOR_NOT_PROTECTED 0x00000000 - # define KS_DVD_SECTOR_PROTECTED 0x00000020 - - # define STATIC_KSCATEGORY_TVTUNER \ - 0xa799a800L, 0xa46d, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0x24, 0x01, 0xdc, 0xd4 -DEFINE_GUIDSTRUCT("a799a800-a46d-11d0-a18c-00a02401dcd4", KSCATEGORY_TVTUNER); - # define KSCATEGORY_TVTUNER DEFINE_GUIDNAMED(KSCATEGORY_TVTUNER) - - # define STATIC_KSCATEGORY_CROSSBAR \ - 0xa799a801L, 0xa46d, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0x24, 0x01, 0xdc, 0xd4 -DEFINE_GUIDSTRUCT("a799a801-a46d-11d0-a18c-00a02401dcd4", KSCATEGORY_CROSSBAR); - # define KSCATEGORY_CROSSBAR DEFINE_GUIDNAMED(KSCATEGORY_CROSSBAR) - - # define STATIC_KSCATEGORY_TVAUDIO \ - 0xa799a802L, 0xa46d, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0x24, 0x01, 0xdc, 0xd4 -DEFINE_GUIDSTRUCT("a799a802-a46d-11d0-a18c-00a02401dcd4", KSCATEGORY_TVAUDIO); - # define KSCATEGORY_TVAUDIO DEFINE_GUIDNAMED(KSCATEGORY_TVAUDIO) - - # define STATIC_KSCATEGORY_VPMUX \ - 0xa799a803L, 0xa46d, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0x24, 0x01, 0xdc, 0xd4 -DEFINE_GUIDSTRUCT("a799a803-a46d-11d0-a18c-00a02401dcd4", KSCATEGORY_VPMUX); - # define KSCATEGORY_VPMUX DEFINE_GUIDNAMED(KSCATEGORY_VPMUX) - - # define STATIC_KSCATEGORY_VBICODEC \ - 0x07dad660L, 0x22f1, 0x11d1, 0xa9, 0xf4, 0x00, 0xc0, 0x4f, 0xbb, 0xde, 0x8f -DEFINE_GUIDSTRUCT("07dad660-22f1-11d1-a9f4-00c04fbbde8f", KSCATEGORY_VBICODEC); - # define KSCATEGORY_VBICODEC DEFINE_GUIDNAMED(KSCATEGORY_VBICODEC) - - # define STATIC_KSDATAFORMAT_SUBTYPE_VPVideo \ - 0x5a9b6a40L, 0x1a22, 0x11d1, 0xba, 0xd9, 0x0, 0x60, 0x97, 0x44, 0x11, 0x1a -DEFINE_GUIDSTRUCT("5a9b6a40-1a22-11d1-bad9-00609744111a", KSDATAFORMAT_SUBTYPE_VPVideo); - # define KSDATAFORMAT_SUBTYPE_VPVideo DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_VPVideo) - - # define STATIC_KSDATAFORMAT_SUBTYPE_VPVBI \ - 0x5a9b6a41L, 0x1a22, 0x11d1, 0xba, 0xd9, 0x0, 0x60, 0x97, 0x44, 0x11, 0x1a -DEFINE_GUIDSTRUCT("5a9b6a41-1a22-11d1-bad9-00609744111a", KSDATAFORMAT_SUBTYPE_VPVBI); - # define KSDATAFORMAT_SUBTYPE_VPVBI DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_VPVBI) - - # define STATIC_KSDATAFORMAT_SPECIFIER_VIDEOINFO \ - 0x05589f80L, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a -DEFINE_GUIDSTRUCT("05589f80-c356-11ce-bf01-00aa0055595a", KSDATAFORMAT_SPECIFIER_VIDEOINFO); - # define KSDATAFORMAT_SPECIFIER_VIDEOINFO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_VIDEOINFO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_VIDEOINFO2 \ - 0xf72a76A0L, 0xeb0a, 0x11d0, 0xac, 0xe4, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("f72a76A0-eb0a-11d0-ace4-0000c0cc16ba", KSDATAFORMAT_SPECIFIER_VIDEOINFO2); - # define KSDATAFORMAT_SPECIFIER_VIDEOINFO2 DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_VIDEOINFO2) - - # define STATIC_KSDATAFORMAT_TYPE_ANALOGVIDEO \ - 0x0482dde1L, 0x7817, 0x11cf, 0x8a, 0x03, 0x00, 0xaa, 0x00, 0x6e, 0xcb, 0x65 -DEFINE_GUIDSTRUCT("0482dde1-7817-11cf-8a03-00aa006ecb65", KSDATAFORMAT_TYPE_ANALOGVIDEO); - # define KSDATAFORMAT_TYPE_ANALOGVIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_ANALOGVIDEO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_ANALOGVIDEO \ - 0x0482dde0L, 0x7817, 0x11cf, 0x8a, 0x03, 0x00, 0xaa, 0x00, 0x6e, 0xcb, 0x65 -DEFINE_GUIDSTRUCT("0482dde0-7817-11cf-8a03-00aa006ecb65", KSDATAFORMAT_SPECIFIER_ANALOGVIDEO); - # define KSDATAFORMAT_SPECIFIER_ANALOGVIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_ANALOGVIDEO) - - # define STATIC_KSDATAFORMAT_TYPE_ANALOGAUDIO \ - 0x0482dee1L, 0x7817, 0x11cf, 0x8a, 0x03, 0x00, 0xaa, 0x00, 0x6e, 0xcb, 0x65 -DEFINE_GUIDSTRUCT("0482DEE1-7817-11cf-8a03-00aa006ecb65", KSDATAFORMAT_TYPE_ANALOGAUDIO); - # define KSDATAFORMAT_TYPE_ANALOGAUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_ANALOGAUDIO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_VBI \ - 0xf72a76e0L, 0xeb0a, 0x11d0, 0xac, 0xe4, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("f72a76e0-eb0a-11d0-ace4-0000c0cc16ba", KSDATAFORMAT_SPECIFIER_VBI); - # define KSDATAFORMAT_SPECIFIER_VBI DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_VBI) - - # define STATIC_KSDATAFORMAT_TYPE_VBI \ - 0xf72a76e1L, 0xeb0a, 0x11d0, 0xac, 0xe4, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("f72a76e1-eb0a-11d0-ace4-0000c0cc16ba", KSDATAFORMAT_TYPE_VBI); - # define KSDATAFORMAT_TYPE_VBI DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_VBI) - - # define STATIC_KSDATAFORMAT_SUBTYPE_RAW8 \ - 0xca20d9a0, 0x3e3e, 0x11d1, 0x9b, 0xf9, 0x0, 0xc0, 0x4f, 0xbb, 0xde, 0xbf -DEFINE_GUIDSTRUCT("ca20d9a0-3e3e-11d1-9bf9-00c04fbbdebf", KSDATAFORMAT_SUBTYPE_RAW8); - # define KSDATAFORMAT_SUBTYPE_RAW8 DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_RAW8) - - # define STATIC_KSDATAFORMAT_SUBTYPE_CC \ - 0x33214cc1, 0x11f, 0x11d2, 0xb4, 0xb1, 0x0, 0xa0, 0xd1, 0x2, 0xcf, 0xbe -DEFINE_GUIDSTRUCT("33214CC1-011F-11D2-B4B1-00A0D102CFBE", KSDATAFORMAT_SUBTYPE_CC); - # define KSDATAFORMAT_SUBTYPE_CC DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_CC) - - # define STATIC_KSDATAFORMAT_SUBTYPE_NABTS \ - 0xf72a76e2L, 0xeb0a, 0x11d0, 0xac, 0xe4, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("f72a76e2-eb0a-11d0-ace4-0000c0cc16ba", KSDATAFORMAT_SUBTYPE_NABTS); - # define KSDATAFORMAT_SUBTYPE_NABTS DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_NABTS) - - # define STATIC_KSDATAFORMAT_SUBTYPE_TELETEXT \ - 0xf72a76e3L, 0xeb0a, 0x11d0, 0xac, 0xe4, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("f72a76e3-eb0a-11d0-ace4-0000c0cc16ba", KSDATAFORMAT_SUBTYPE_TELETEXT); - # define KSDATAFORMAT_SUBTYPE_TELETEXT DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_TELETEXT) - - # define KS_BI_RGB 0L - # define KS_BI_RLE8 1L - # define KS_BI_RLE4 2L - # define KS_BI_BITFIELDS 3L - -typedef struct tagKS_RGBQUAD -{ - BYTE rgbBlue; - BYTE rgbGreen; - BYTE rgbRed; - BYTE rgbReserved; -}KS_RGBQUAD, * PKS_RGBQUAD; - - # define KS_iPALETTE_COLORS 256 - # define KS_iEGA_COLORS 16 - # define KS_iMASK_COLORS 3 - # define KS_iTRUECOLOR 16 - # define KS_iRED 0 - # define KS_iGREEN 1 - # define KS_iBLUE 2 - # define KS_iPALETTE 8 - # define KS_iMAXBITS 8 - # define KS_SIZE_EGA_PALETTE (KS_iEGA_COLORS * sizeof(KS_RGBQUAD)) - # define KS_SIZE_PALETTE (KS_iPALETTE_COLORS * sizeof(KS_RGBQUAD)) - -typedef struct tagKS_BITMAPINFOHEADER -{ - DWORD biSize; - LONG biWidth; - LONG biHeight; - WORD biPlanes; - WORD biBitCount; - DWORD biCompression; - DWORD biSizeImage; - LONG biXPelsPerMeter; - LONG biYPelsPerMeter; - DWORD biClrUsed; - DWORD biClrImportant; -}KS_BITMAPINFOHEADER, * PKS_BITMAPINFOHEADER; - -typedef struct tag_KS_TRUECOLORINFO -{ - DWORD dwBitMasks[KS_iMASK_COLORS]; - KS_RGBQUAD bmiColors[KS_iPALETTE_COLORS]; -}KS_TRUECOLORINFO, * PKS_TRUECOLORINFO; - - # define KS_WIDTHBYTES(bits) ((DWORD)(((bits) + 31) & (~31)) / 8) - # define KS_DIBWIDTHBYTES(bi) (DWORD)KS_WIDTHBYTES((DWORD)(bi).biWidth * (DWORD)(bi).biBitCount) - # define KS__DIBSIZE(bi) (KS_DIBWIDTHBYTES(bi) * (DWORD)(bi).biHeight) - # define KS_DIBSIZE(bi) ((bi).biHeight < 0 ? (-1) * (KS__DIBSIZE(bi)) : KS__DIBSIZE(bi)) - -typedef LONGLONG REFERENCE_TIME; - -typedef struct tagKS_VIDEOINFOHEADER -{ - RECT rcSource; - RECT rcTarget; - DWORD dwBitRate; - DWORD dwBitErrorRate; - REFERENCE_TIME AvgTimePerFrame; - KS_BITMAPINFOHEADER bmiHeader; -}KS_VIDEOINFOHEADER, * PKS_VIDEOINFOHEADER; - -typedef struct tagKS_VIDEOINFO -{ - RECT rcSource; - RECT rcTarget; - DWORD dwBitRate; - DWORD dwBitErrorRate; - REFERENCE_TIME AvgTimePerFrame; - KS_BITMAPINFOHEADER bmiHeader; - __MINGW_EXTENSION union - { - KS_RGBQUAD bmiColors[KS_iPALETTE_COLORS]; - DWORD dwBitMasks[KS_iMASK_COLORS]; - KS_TRUECOLORINFO TrueColorInfo; - }; -}KS_VIDEOINFO, * PKS_VIDEOINFO; - - # define KS_SIZE_MASKS (KS_iMASK_COLORS * sizeof(DWORD)) - # define KS_SIZE_PREHEADER (FIELD_OFFSET(KS_VIDEOINFOHEADER, bmiHeader)) - - # define KS_SIZE_VIDEOHEADER(pbmi) ((pbmi)->bmiHeader.biSize + KS_SIZE_PREHEADER) - -typedef struct tagKS_VBIINFOHEADER -{ - ULONG StartLine; - ULONG EndLine; - ULONG SamplingFrequency; - ULONG MinLineStartTime; - ULONG MaxLineStartTime; - ULONG ActualLineStartTime; - ULONG ActualLineEndTime; - ULONG VideoStandard; - ULONG SamplesPerLine; - ULONG StrideInBytes; - ULONG BufferSize; -}KS_VBIINFOHEADER, * PKS_VBIINFOHEADER; - - # define KS_VBIDATARATE_NABTS (5727272L) - # define KS_VBIDATARATE_CC (503493L) - # define KS_VBISAMPLINGRATE_4X_NABTS ((long)(4 * KS_VBIDATARATE_NABTS)) - # define KS_VBISAMPLINGRATE_47X_NABTS ((long)(27000000)) - # define KS_VBISAMPLINGRATE_5X_NABTS ((long)(5 * KS_VBIDATARATE_NABTS)) - - # define KS_47NABTS_SCALER (KS_VBISAMPLINGRATE_47X_NABTS / (double)KS_VBIDATARATE_NABTS) - -typedef struct tagKS_AnalogVideoInfo -{ - RECT rcSource; - RECT rcTarget; - DWORD dwActiveWidth; - DWORD dwActiveHeight; - REFERENCE_TIME AvgTimePerFrame; -}KS_ANALOGVIDEOINFO, * PKS_ANALOGVIDEOINFO; - - # define KS_TVTUNER_CHANGE_BEGIN_TUNE 0x0001L - # define KS_TVTUNER_CHANGE_END_TUNE 0x0002L - -typedef struct tagKS_TVTUNER_CHANGE_INFO -{ - DWORD dwFlags; - DWORD dwCountryCode; - DWORD dwAnalogVideoStandard; - DWORD dwChannel; -}KS_TVTUNER_CHANGE_INFO, * PKS_TVTUNER_CHANGE_INFO; - -typedef enum -{ - KS_MPEG2Level_Low, - KS_MPEG2Level_Main, - KS_MPEG2Level_High1440, - KS_MPEG2Level_High -}KS_MPEG2Level; - -typedef enum -{ - KS_MPEG2Profile_Simple, - KS_MPEG2Profile_Main, - KS_MPEG2Profile_SNRScalable, - KS_MPEG2Profile_SpatiallyScalable, - KS_MPEG2Profile_High -}KS_MPEG2Profile; - - # define KS_INTERLACE_IsInterlaced 0x00000001 - # define KS_INTERLACE_1FieldPerSample 0x00000002 - # define KS_INTERLACE_Field1First 0x00000004 - # define KS_INTERLACE_UNUSED 0x00000008 - # define KS_INTERLACE_FieldPatternMask 0x00000030 - # define KS_INTERLACE_FieldPatField1Only 0x00000000 - # define KS_INTERLACE_FieldPatField2Only 0x00000010 - # define KS_INTERLACE_FieldPatBothRegular 0x00000020 - # define KS_INTERLACE_FieldPatBothIrregular 0x00000030 - # define KS_INTERLACE_DisplayModeMask 0x000000c0 - # define KS_INTERLACE_DisplayModeBobOnly 0x00000000 - # define KS_INTERLACE_DisplayModeWeaveOnly 0x00000040 - # define KS_INTERLACE_DisplayModeBobOrWeave 0x00000080 - - # define KS_MPEG2_DoPanScan 0x00000001 - # define KS_MPEG2_DVDLine21Field1 0x00000002 - # define KS_MPEG2_DVDLine21Field2 0x00000004 - # define KS_MPEG2_SourceIsLetterboxed 0x00000008 - # define KS_MPEG2_FilmCameraMode 0x00000010 - # define KS_MPEG2_LetterboxAnalogOut 0x00000020 - # define KS_MPEG2_DSS_UserData 0x00000040 - # define KS_MPEG2_DVB_UserData 0x00000080 - # define KS_MPEG2_27MhzTimebase 0x00000100 - -typedef struct tagKS_VIDEOINFOHEADER2 -{ - RECT rcSource; - RECT rcTarget; - DWORD dwBitRate; - DWORD dwBitErrorRate; - REFERENCE_TIME AvgTimePerFrame; - DWORD dwInterlaceFlags; - DWORD dwCopyProtectFlags; - DWORD dwPictAspectRatioX; - DWORD dwPictAspectRatioY; - DWORD dwReserved1; - DWORD dwReserved2; - KS_BITMAPINFOHEADER bmiHeader; -}KS_VIDEOINFOHEADER2, * PKS_VIDEOINFOHEADER2; - -typedef struct tagKS_MPEG1VIDEOINFO -{ - KS_VIDEOINFOHEADER hdr; - DWORD dwStartTimeCode; - DWORD cbSequenceHeader; - BYTE bSequenceHeader[1]; -}KS_MPEG1VIDEOINFO, * PKS_MPEG1VIDEOINFO; - - # define KS_MAX_SIZE_MPEG1_SEQUENCE_INFO 140 - # define KS_SIZE_MPEG1VIDEOINFO(pv) (FIELD_OFFSET(KS_MPEG1VIDEOINFO, bSequenceHeader[0]) + (pv)->cbSequenceHeader) - # define KS_MPEG1_SEQUENCE_INFO(pv) ((const BYTE*)(pv)->bSequenceHeader) - -typedef struct tagKS_MPEGVIDEOINFO2 -{ - KS_VIDEOINFOHEADER2 hdr; - DWORD dwStartTimeCode; - DWORD cbSequenceHeader; - DWORD dwProfile; - DWORD dwLevel; - DWORD dwFlags; - DWORD bSequenceHeader[1]; -}KS_MPEGVIDEOINFO2, * PKS_MPEGVIDEOINFO2; - - # define KS_SIZE_MPEGVIDEOINFO2(pv) (FIELD_OFFSET(KS_MPEGVIDEOINFO2, bSequenceHeader[0]) + (pv)->cbSequenceHeader) - # define KS_MPEG1_SEQUENCE_INFO(pv) ((const BYTE*)(pv)->bSequenceHeader) - - # define KS_MPEGAUDIOINFO_27MhzTimebase 0x00000001 - -typedef struct tagKS_MPEAUDIOINFO -{ - DWORD dwFlags; - DWORD dwReserved1; - DWORD dwReserved2; - DWORD dwReserved3; -}KS_MPEGAUDIOINFO, * PKS_MPEGAUDIOINFO; - -typedef struct tagKS_DATAFORMAT_VIDEOINFOHEADER -{ - KSDATAFORMAT DataFormat; - KS_VIDEOINFOHEADER VideoInfoHeader; -}KS_DATAFORMAT_VIDEOINFOHEADER, * PKS_DATAFORMAT_VIDEOINFOHEADER; - -typedef struct tagKS_DATAFORMAT_VIDEOINFOHEADER2 -{ - KSDATAFORMAT DataFormat; - KS_VIDEOINFOHEADER2 VideoInfoHeader2; -}KS_DATAFORMAT_VIDEOINFOHEADER2, * PKS_DATAFORMAT_VIDEOINFOHEADER2; - -typedef struct tagKS_DATAFORMAT_VIDEOINFO_PALETTE -{ - KSDATAFORMAT DataFormat; - KS_VIDEOINFO VideoInfo; -}KS_DATAFORMAT_VIDEOINFO_PALETTE, * PKS_DATAFORMAT_VIDEOINFO_PALETTE; - -typedef struct tagKS_DATAFORMAT_VBIINFOHEADER -{ - KSDATAFORMAT DataFormat; - KS_VBIINFOHEADER VBIInfoHeader; -}KS_DATAFORMAT_VBIINFOHEADER, * PKS_DATAFORMAT_VBIINFOHEADER; - -typedef struct _KS_VIDEO_STREAM_CONFIG_CAPS -{ - GUID guid; - ULONG VideoStandard; - SIZE InputSize; - SIZE MinCroppingSize; - SIZE MaxCroppingSize; - int CropGranularityX; - int CropGranularityY; - int CropAlignX; - int CropAlignY; - SIZE MinOutputSize; - SIZE MaxOutputSize; - int OutputGranularityX; - int OutputGranularityY; - int StretchTapsX; - int StretchTapsY; - int ShrinkTapsX; - int ShrinkTapsY; - LONGLONG MinFrameInterval; - LONGLONG MaxFrameInterval; - LONG MinBitsPerSecond; - LONG MaxBitsPerSecond; -}KS_VIDEO_STREAM_CONFIG_CAPS, * PKS_VIDEO_STREAM_CONFIG_CAPS; - -typedef struct tagKS_DATARANGE_VIDEO -{ - KSDATARANGE DataRange; - WINBOOL bFixedSizeSamples; - WINBOOL bTemporalCompression; - DWORD StreamDescriptionFlags; - DWORD MemoryAllocationFlags; - KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps; - KS_VIDEOINFOHEADER VideoInfoHeader; -}KS_DATARANGE_VIDEO, * PKS_DATARANGE_VIDEO; - -typedef struct tagKS_DATARANGE_VIDEO2 -{ - KSDATARANGE DataRange; - WINBOOL bFixedSizeSamples; - WINBOOL bTemporalCompression; - DWORD StreamDescriptionFlags; - DWORD MemoryAllocationFlags; - KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps; - KS_VIDEOINFOHEADER2 VideoInfoHeader; -}KS_DATARANGE_VIDEO2, * PKS_DATARANGE_VIDEO2; - -typedef struct tagKS_DATARANGE_MPEG1_VIDEO -{ - KSDATARANGE DataRange; - WINBOOL bFixedSizeSamples; - WINBOOL bTemporalCompression; - DWORD StreamDescriptionFlags; - DWORD MemoryAllocationFlags; - KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps; - KS_MPEG1VIDEOINFO VideoInfoHeader; -}KS_DATARANGE_MPEG1_VIDEO, * PKS_DATARANGE_MPEG1_VIDEO; - -typedef struct tagKS_DATARANGE_MPEG2_VIDEO -{ - KSDATARANGE DataRange; - WINBOOL bFixedSizeSamples; - WINBOOL bTemporalCompression; - DWORD StreamDescriptionFlags; - DWORD MemoryAllocationFlags; - KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps; - KS_MPEGVIDEOINFO2 VideoInfoHeader; -}KS_DATARANGE_MPEG2_VIDEO, * PKS_DATARANGE_MPEG2_VIDEO; - -typedef struct tagKS_DATARANGE_VIDEO_PALETTE -{ - KSDATARANGE DataRange; - WINBOOL bFixedSizeSamples; - WINBOOL bTemporalCompression; - DWORD StreamDescriptionFlags; - DWORD MemoryAllocationFlags; - KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps; - KS_VIDEOINFO VideoInfo; -}KS_DATARANGE_VIDEO_PALETTE, * PKS_DATARANGE_VIDEO_PALETTE; - -typedef struct tagKS_DATARANGE_VIDEO_VBI -{ - KSDATARANGE DataRange; - WINBOOL bFixedSizeSamples; - WINBOOL bTemporalCompression; - DWORD StreamDescriptionFlags; - DWORD MemoryAllocationFlags; - KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps; - KS_VBIINFOHEADER VBIInfoHeader; -}KS_DATARANGE_VIDEO_VBI, * PKS_DATARANGE_VIDEO_VBI; - -typedef struct tagKS_DATARANGE_ANALOGVIDEO -{ - KSDATARANGE DataRange; - KS_ANALOGVIDEOINFO AnalogVideoInfo; -}KS_DATARANGE_ANALOGVIDEO, * PKS_DATARANGE_ANALOGVIDEO; - - # define KS_VIDEOSTREAM_PREVIEW 0x0001 - # define KS_VIDEOSTREAM_CAPTURE 0x0002 - # define KS_VIDEOSTREAM_VBI 0x0010 - # define KS_VIDEOSTREAM_NABTS 0x0020 - # define KS_VIDEOSTREAM_CC 0x0100 - # define KS_VIDEOSTREAM_EDS 0x0200 - # define KS_VIDEOSTREAM_TELETEXT 0x0400 - # define KS_VIDEOSTREAM_STILL 0x1000 - # define KS_VIDEOSTREAM_IS_VPE 0x8000 - - # define KS_VIDEO_ALLOC_VPE_SYSTEM 0x0001 - # define KS_VIDEO_ALLOC_VPE_DISPLAY 0x0002 - # define KS_VIDEO_ALLOC_VPE_AGP 0x0004 - - # define STATIC_KSPROPSETID_VBICAP_PROPERTIES \ - 0xf162c607, 0x7b35, 0x496f, 0xad, 0x7f, 0x2d, 0xca, 0x3b, 0x46, 0xb7, 0x18 -DEFINE_GUIDSTRUCT("F162C607-7B35-496f-AD7F-2DCA3B46B718", KSPROPSETID_VBICAP_PROPERTIES); - # define KSPROPSETID_VBICAP_PROPERTIES DEFINE_GUIDNAMED(KSPROPSETID_VBICAP_PROPERTIES) - -typedef enum -{ - KSPROPERTY_VBICAP_PROPERTIES_PROTECTION = 0x01 -}KSPROPERTY_VBICAP; - -typedef struct _VBICAP_PROPERTIES_PROTECTION_S -{ - KSPROPERTY Property; - ULONG StreamIndex; - ULONG Status; -}VBICAP_PROPERTIES_PROTECTION_S, * PVBICAP_PROPERTIES_PROTECTION_S; - - # define KS_VBICAP_PROTECTION_MV_PRESENT 0x0001L - # define KS_VBICAP_PROTECTION_MV_HARDWARE 0x0002L - # define KS_VBICAP_PROTECTION_MV_DETECTED 0x0004L - - # define KS_NABTS_GROUPID_ORIGINAL_CONTENT_BASE 0x800 - # define KS_NABTS_GROUPID_ORIGINAL_CONTENT_ADVERTISER_BASE 0x810 - - # define KS_NABTS_GROUPID_PRODUCTION_COMPANY_CONTENT_BASE 0x820 - # define KS_NABTS_GROUPID_PRODUCTION_COMPANY_ADVERTISER_BASE 0x830 - - # define KS_NABTS_GROUPID_SYNDICATED_SHOW_CONTENT_BASE 0x840 - # define KS_NABTS_GROUPID_SYNDICATED_SHOW_ADVERTISER_BASE 0x850 - - # define KS_NABTS_GROUPID_NETWORK_WIDE_CONTENT_BASE 0x860 - # define KS_NABTS_GROUPID_NETWORK_WIDE_ADVERTISER_BASE 0x870 - - # define KS_NABTS_GROUPID_TELEVISION_STATION_CONTENT_BASE 0x880 - # define KS_NABTS_GROUPID_TELEVISION_STATION_ADVERTISER_BASE 0x890 - - # define KS_NABTS_GROUPID_LOCAL_CABLE_SYSTEM_CONTENT_BASE 0x8A0 - # define KS_NABTS_GROUPID_LOCAL_CABLE_SYSTEM_ADVERTISER_BASE 0x8B0 - - # define KS_NABTS_GROUPID_MICROSOFT_RESERVED_TEST_DATA_BASE 0x8F0 - - # define STATIC_KSDATAFORMAT_TYPE_NABTS \ - 0xe757bca0, 0x39ac, 0x11d1, 0xa9, 0xf5, 0x0, 0xc0, 0x4f, 0xbb, 0xde, 0x8f -DEFINE_GUIDSTRUCT("E757BCA0-39AC-11d1-A9F5-00C04FBBDE8F", KSDATAFORMAT_TYPE_NABTS); - # define KSDATAFORMAT_TYPE_NABTS DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_NABTS) - - # define STATIC_KSDATAFORMAT_SUBTYPE_NABTS_FEC \ - 0xe757bca1, 0x39ac, 0x11d1, 0xa9, 0xf5, 0x0, 0xc0, 0x4f, 0xbb, 0xde, 0x8f -DEFINE_GUIDSTRUCT("E757BCA1-39AC-11d1-A9F5-00C04FBBDE8F", KSDATAFORMAT_SUBTYPE_NABTS_FEC); - # define KSDATAFORMAT_SUBTYPE_NABTS_FEC DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_NABTS_FEC) - - # define MAX_NABTS_VBI_LINES_PER_FIELD 11 - # define NABTS_LINES_PER_BUNDLE 16 - # define NABTS_PAYLOAD_PER_LINE 28 - # define NABTS_BYTES_PER_LINE 36 - -typedef struct _NABTSFEC_BUFFER -{ - ULONG dataSize; - USHORT groupID; - USHORT Reserved; - UCHAR data[NABTS_LINES_PER_BUNDLE * NABTS_PAYLOAD_PER_LINE]; -}NABTSFEC_BUFFER, * PNABTSFEC_BUFFER; - - # define STATIC_KSPROPSETID_VBICodecFiltering \ - 0xcafeb0caL, 0x8715, 0x11d0, 0xbd, 0x6a, 0x00, 0x35, 0xc0, 0xed, 0xba, 0xbe -DEFINE_GUIDSTRUCT("cafeb0ca-8715-11d0-bd6a-0035c0edbabe", KSPROPSETID_VBICodecFiltering); - # define KSPROPSETID_VBICodecFiltering DEFINE_GUIDNAMED(KSPROPSETID_VBICodecFiltering) - -typedef enum -{ - KSPROPERTY_VBICODECFILTERING_SCANLINES_REQUESTED_BIT_ARRAY = 0x01, - KSPROPERTY_VBICODECFILTERING_SCANLINES_DISCOVERED_BIT_ARRAY, - KSPROPERTY_VBICODECFILTERING_SUBSTREAMS_REQUESTED_BIT_ARRAY, - KSPROPERTY_VBICODECFILTERING_SUBSTREAMS_DISCOVERED_BIT_ARRAY, - KSPROPERTY_VBICODECFILTERING_STATISTICS -}KSPROPERTY_VBICODECFILTERING; - -typedef struct _VBICODECFILTERING_SCANLINES -{ - DWORD DwordBitArray[32]; -}VBICODECFILTERING_SCANLINES, * PVBICODECFILTERING_SCANLINES; - -typedef struct _VBICODECFILTERING_NABTS_SUBSTREAMS -{ - DWORD SubstreamMask[128]; -}VBICODECFILTERING_NABTS_SUBSTREAMS, * PVBICODECFILTERING_NABTS_SUBSTREAMS; - -typedef struct _VBICODECFILTERING_CC_SUBSTREAMS -{ - DWORD SubstreamMask; -}VBICODECFILTERING_CC_SUBSTREAMS, * PVBICODECFILTERING_CC_SUBSTREAMS; - - # define KS_CC_SUBSTREAM_ODD 0x0001L - # define KS_CC_SUBSTREAM_EVEN 0x0002L - - # define KS_CC_SUBSTREAM_FIELD1_MASK 0x00F0L - # define KS_CC_SUBSTREAM_SERVICE_CC1 0x0010L - # define KS_CC_SUBSTREAM_SERVICE_CC2 0x0020L - # define KS_CC_SUBSTREAM_SERVICE_T1 0x0040L - # define KS_CC_SUBSTREAM_SERVICE_T2 0x0080L - - # define KS_CC_SUBSTREAM_FIELD2_MASK 0x1F00L - # define KS_CC_SUBSTREAM_SERVICE_CC3 0x0100L - # define KS_CC_SUBSTREAM_SERVICE_CC4 0x0200L - # define KS_CC_SUBSTREAM_SERVICE_T3 0x0400L - # define KS_CC_SUBSTREAM_SERVICE_T4 0x0800L - # define KS_CC_SUBSTREAM_SERVICE_XDS 0x1000L - - # define CC_MAX_HW_DECODE_LINES 12 -typedef struct _CC_BYTE_PAIR -{ - BYTE Decoded[2]; - USHORT Reserved; -}CC_BYTE_PAIR, * PCC_BYTE_PAIR; - -typedef struct _CC_HW_FIELD -{ - VBICODECFILTERING_SCANLINES ScanlinesRequested; - ULONG fieldFlags; - LONGLONG PictureNumber; - CC_BYTE_PAIR Lines[CC_MAX_HW_DECODE_LINES]; -}CC_HW_FIELD, * PCC_HW_FIELD; - - # ifndef PACK_PRAGMAS_NOT_SUPPORTED - # include - # endif -typedef struct _NABTS_BUFFER_LINE -{ - BYTE Confidence; - BYTE Bytes[NABTS_BYTES_PER_LINE]; -}NABTS_BUFFER_LINE, * PNABTS_BUFFER_LINE; - - # define NABTS_BUFFER_PICTURENUMBER_SUPPORT 1 -typedef struct _NABTS_BUFFER -{ - VBICODECFILTERING_SCANLINES ScanlinesRequested; - LONGLONG PictureNumber; - NABTS_BUFFER_LINE NabtsLines[MAX_NABTS_VBI_LINES_PER_FIELD]; -}NABTS_BUFFER, * PNABTS_BUFFER; - # ifndef PACK_PRAGMAS_NOT_SUPPORTED - # include - # endif - - # define WST_TVTUNER_CHANGE_BEGIN_TUNE 0x1000L - # define WST_TVTUNER_CHANGE_END_TUNE 0x2000L - - # define MAX_WST_VBI_LINES_PER_FIELD 17 - # define WST_BYTES_PER_LINE 42 - -typedef struct _WST_BUFFER_LINE -{ - BYTE Confidence; - BYTE Bytes[WST_BYTES_PER_LINE]; -}WST_BUFFER_LINE, * PWST_BUFFER_LINE; - -typedef struct _WST_BUFFER -{ - VBICODECFILTERING_SCANLINES ScanlinesRequested; - WST_BUFFER_LINE WstLines[MAX_WST_VBI_LINES_PER_FIELD]; -}WST_BUFFER, * PWST_BUFFER; - -typedef struct _VBICODECFILTERING_STATISTICS_COMMON -{ - DWORD InputSRBsProcessed; - DWORD OutputSRBsProcessed; - DWORD SRBsIgnored; - DWORD InputSRBsMissing; - DWORD OutputSRBsMissing; - DWORD OutputFailures; - DWORD InternalErrors; - DWORD ExternalErrors; - DWORD InputDiscontinuities; - DWORD DSPFailures; - DWORD TvTunerChanges; - DWORD VBIHeaderChanges; - DWORD LineConfidenceAvg; - DWORD BytesOutput; -}VBICODECFILTERING_STATISTICS_COMMON, * PVBICODECFILTERING_STATISTICS_COMMON; - -typedef struct _VBICODECFILTERING_STATISTICS_COMMON_PIN -{ - DWORD SRBsProcessed; - DWORD SRBsIgnored; - DWORD SRBsMissing; - DWORD InternalErrors; - DWORD ExternalErrors; - DWORD Discontinuities; - DWORD LineConfidenceAvg; - DWORD BytesOutput; -}VBICODECFILTERING_STATISTICS_COMMON_PIN, * PVBICODECFILTERING_STATISTICS_COMMON_PIN; - -typedef struct _VBICODECFILTERING_STATISTICS_NABTS -{ - VBICODECFILTERING_STATISTICS_COMMON Common; - DWORD FECBundleBadLines; - DWORD FECQueueOverflows; - DWORD FECCorrectedLines; - DWORD FECUncorrectableLines; - DWORD BundlesProcessed; - DWORD BundlesSent2IP; - DWORD FilteredLines; -}VBICODECFILTERING_STATISTICS_NABTS, * PVBICODECFILTERING_STATISTICS_NABTS; - -typedef struct _VBICODECFILTERING_STATISTICS_NABTS_PIN -{ - VBICODECFILTERING_STATISTICS_COMMON_PIN Common; -}VBICODECFILTERING_STATISTICS_NABTS_PIN, * PVBICODECFILTERING_STATISTICS_NABTS_PIN; - -typedef struct _VBICODECFILTERING_STATISTICS_CC -{ - VBICODECFILTERING_STATISTICS_COMMON Common; -}VBICODECFILTERING_STATISTICS_CC, * PVBICODECFILTERING_STATISTICS_CC; - -typedef struct _VBICODECFILTERING_STATISTICS_CC_PIN -{ - VBICODECFILTERING_STATISTICS_COMMON_PIN Common; -}VBICODECFILTERING_STATISTICS_CC_PIN, * PVBICODECFILTERING_STATISTICS_CC_PIN; - -typedef struct _VBICODECFILTERING_STATISTICS_TELETEXT -{ - VBICODECFILTERING_STATISTICS_COMMON Common; -}VBICODECFILTERING_STATISTICS_TELETEXT, * PVBICODECFILTERING_STATISTICS_TELETEXT; - -typedef struct _VBICODECFILTERING_STATISTICS_TELETEXT_PIN -{ - VBICODECFILTERING_STATISTICS_COMMON_PIN Common; -}VBICODECFILTERING_STATISTICS_TELETEXT_PIN, * PVBICODECFILTERING_STATISTICS_TELETEXT_PIN; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_SCANLINES Scanlines; -}KSPROPERTY_VBICODECFILTERING_SCANLINES_S, * PKSPROPERTY_VBICODECFILTERING_SCANLINES_S; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_NABTS_SUBSTREAMS Substreams; -}KSPROPERTY_VBICODECFILTERING_NABTS_SUBSTREAMS_S, * PKSPROPERTY_VBICODECFILTERING_NABTS_SUBSTREAMS_S; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_CC_SUBSTREAMS Substreams; -}KSPROPERTY_VBICODECFILTERING_CC_SUBSTREAMS_S, * PKSPROPERTY_VBICODECFILTERING_CC_SUBSTREAMS_S; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_STATISTICS_COMMON Statistics; -}KSPROPERTY_VBICODECFILTERING_STATISTICS_COMMON_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_COMMON_S; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_STATISTICS_COMMON_PIN Statistics; -}KSPROPERTY_VBICODECFILTERING_STATISTICS_COMMON_PIN_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_COMMON_PIN_S; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_STATISTICS_NABTS Statistics; -}KSPROPERTY_VBICODECFILTERING_STATISTICS_NABTS_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_NABTS_S; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_STATISTICS_NABTS_PIN Statistics; -}KSPROPERTY_VBICODECFILTERING_STATISTICS_NABTS_PIN_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_NABTS_PIN_S; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_STATISTICS_CC Statistics; -}KSPROPERTY_VBICODECFILTERING_STATISTICS_CC_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_CC_S; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_STATISTICS_CC_PIN Statistics; -}KSPROPERTY_VBICODECFILTERING_STATISTICS_CC_PIN_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_CC_PIN_S; - - # define STATIC_PINNAME_VIDEO_CAPTURE \ - 0xfb6c4281, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba - # define STATIC_PINNAME_CAPTURE STATIC_PINNAME_VIDEO_CAPTURE -DEFINE_GUIDSTRUCT("FB6C4281-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_CAPTURE); - # define PINNAME_VIDEO_CAPTURE DEFINE_GUIDNAMED(PINNAME_VIDEO_CAPTURE) - # define PINNAME_CAPTURE PINNAME_VIDEO_CAPTURE - - # define STATIC_PINNAME_VIDEO_CC_CAPTURE \ - 0x1aad8061, 0x12d, 0x11d2, 0xb4, 0xb1, 0x0, 0xa0, 0xd1, 0x2, 0xcf, 0xbe - # define STATIC_PINNAME_CC_CAPTURE STATIC_PINNAME_VIDEO_CC_CAPTURE -DEFINE_GUIDSTRUCT("1AAD8061-012D-11d2-B4B1-00A0D102CFBE", PINNAME_VIDEO_CC_CAPTURE); - # define PINNAME_VIDEO_CC_CAPTURE DEFINE_GUIDNAMED(PINNAME_VIDEO_CC_CAPTURE) - - # define STATIC_PINNAME_VIDEO_NABTS_CAPTURE \ - 0x29703660, 0x498a, 0x11d2, 0xb4, 0xb1, 0x0, 0xa0, 0xd1, 0x2, 0xcf, 0xbe - # define STATIC_PINNAME_NABTS_CAPTURE STATIC_PINNAME_VIDEO_NABTS_CAPTURE -DEFINE_GUIDSTRUCT("29703660-498A-11d2-B4B1-00A0D102CFBE", PINNAME_VIDEO_NABTS_CAPTURE); - # define PINNAME_VIDEO_NABTS_CAPTURE DEFINE_GUIDNAMED(PINNAME_VIDEO_NABTS_CAPTURE) - - # define STATIC_PINNAME_VIDEO_PREVIEW \ - 0xfb6c4282, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba - # define STATIC_PINNAME_PREVIEW STATIC_PINNAME_VIDEO_PREVIEW -DEFINE_GUIDSTRUCT("FB6C4282-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_PREVIEW); - # define PINNAME_VIDEO_PREVIEW DEFINE_GUIDNAMED(PINNAME_VIDEO_PREVIEW) - # define PINNAME_PREVIEW PINNAME_VIDEO_PREVIEW - - # define STATIC_PINNAME_VIDEO_ANALOGVIDEOIN \ - 0xfb6c4283, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C4283-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_ANALOGVIDEOIN); - # define PINNAME_VIDEO_ANALOGVIDEOIN DEFINE_GUIDNAMED(PINNAME_VIDEO_ANALOGVIDEOIN) - - # define STATIC_PINNAME_VIDEO_VBI \ - 0xfb6c4284, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C4284-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_VBI); - # define PINNAME_VIDEO_VBI DEFINE_GUIDNAMED(PINNAME_VIDEO_VBI) - - # define STATIC_PINNAME_VIDEO_VIDEOPORT \ - 0xfb6c4285, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C4285-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_VIDEOPORT); - # define PINNAME_VIDEO_VIDEOPORT DEFINE_GUIDNAMED(PINNAME_VIDEO_VIDEOPORT) - - # define STATIC_PINNAME_VIDEO_NABTS \ - 0xfb6c4286, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C4286-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_NABTS); - # define PINNAME_VIDEO_NABTS DEFINE_GUIDNAMED(PINNAME_VIDEO_NABTS) - - # define STATIC_PINNAME_VIDEO_EDS \ - 0xfb6c4287, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C4287-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_EDS); - # define PINNAME_VIDEO_EDS DEFINE_GUIDNAMED(PINNAME_VIDEO_EDS) - - # define STATIC_PINNAME_VIDEO_TELETEXT \ - 0xfb6c4288, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C4288-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_TELETEXT); - # define PINNAME_VIDEO_TELETEXT DEFINE_GUIDNAMED(PINNAME_VIDEO_TELETEXT) - - # define STATIC_PINNAME_VIDEO_CC \ - 0xfb6c4289, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C4289-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_CC); - # define PINNAME_VIDEO_CC DEFINE_GUIDNAMED(PINNAME_VIDEO_CC) - - # define STATIC_PINNAME_VIDEO_STILL \ - 0xfb6c428A, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C428A-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_STILL); - # define PINNAME_VIDEO_STILL DEFINE_GUIDNAMED(PINNAME_VIDEO_STILL) - - # define STATIC_PINNAME_VIDEO_TIMECODE \ - 0xfb6c428B, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C428B-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_TIMECODE); - # define PINNAME_VIDEO_TIMECODE DEFINE_GUIDNAMED(PINNAME_VIDEO_TIMECODE) - - # define STATIC_PINNAME_VIDEO_VIDEOPORT_VBI \ - 0xfb6c428C, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C428C-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_VIDEOPORT_VBI); - # define PINNAME_VIDEO_VIDEOPORT_VBI DEFINE_GUIDNAMED(PINNAME_VIDEO_VIDEOPORT_VBI) - - # define KS_VIDEO_FLAG_FRAME 0x0000L - # define KS_VIDEO_FLAG_FIELD1 0x0001L - # define KS_VIDEO_FLAG_FIELD2 0x0002L - - # define KS_VIDEO_FLAG_I_FRAME 0x0000L - # define KS_VIDEO_FLAG_P_FRAME 0x0010L - # define KS_VIDEO_FLAG_B_FRAME 0x0020L - -typedef struct tagKS_FRAME_INFO -{ - ULONG ExtendedHeaderSize; - DWORD dwFrameFlags; - LONGLONG PictureNumber; - LONGLONG DropCount; - HANDLE hDirectDraw; - HANDLE hSurfaceHandle; - RECT DirectDrawRect; - - DWORD Reserved1; - DWORD Reserved2; - DWORD Reserved3; - DWORD Reserved4; -}KS_FRAME_INFO, * PKS_FRAME_INFO; - - # define KS_VBI_FLAG_FIELD1 0x0001L - # define KS_VBI_FLAG_FIELD2 0x0002L - - # define KS_VBI_FLAG_MV_PRESENT 0x0100L - # define KS_VBI_FLAG_MV_HARDWARE 0x0200L - # define KS_VBI_FLAG_MV_DETECTED 0x0400L - - # define KS_VBI_FLAG_TVTUNER_CHANGE 0x0010L - # define KS_VBI_FLAG_VBIINFOHEADER_CHANGE 0x0020L - -typedef struct tagKS_VBI_FRAME_INFO -{ - ULONG ExtendedHeaderSize; - DWORD dwFrameFlags; - LONGLONG PictureNumber; - LONGLONG DropCount; - DWORD dwSamplingFrequency; - KS_TVTUNER_CHANGE_INFO TvTunerChangeInfo; - KS_VBIINFOHEADER VBIInfoHeader; -}KS_VBI_FRAME_INFO, * PKS_VBI_FRAME_INFO; - -typedef enum -{ - KS_AnalogVideo_None = 0x00000000, - KS_AnalogVideo_NTSC_M = 0x00000001, - KS_AnalogVideo_NTSC_M_J = 0x00000002, - KS_AnalogVideo_NTSC_433 = 0x00000004, - KS_AnalogVideo_PAL_B = 0x00000010, - KS_AnalogVideo_PAL_D = 0x00000020, - KS_AnalogVideo_PAL_G = 0x00000040, - KS_AnalogVideo_PAL_H = 0x00000080, - KS_AnalogVideo_PAL_I = 0x00000100, - KS_AnalogVideo_PAL_M = 0x00000200, - KS_AnalogVideo_PAL_N = 0x00000400, - KS_AnalogVideo_PAL_60 = 0x00000800, - KS_AnalogVideo_SECAM_B = 0x00001000, - KS_AnalogVideo_SECAM_D = 0x00002000, - KS_AnalogVideo_SECAM_G = 0x00004000, - KS_AnalogVideo_SECAM_H = 0x00008000, - KS_AnalogVideo_SECAM_K = 0x00010000, - KS_AnalogVideo_SECAM_K1 = 0x00020000, - KS_AnalogVideo_SECAM_L = 0x00040000, - KS_AnalogVideo_SECAM_L1 = 0x00080000, - KS_AnalogVideo_PAL_N_COMBO = 0x00100000 -}KS_AnalogVideoStandard; - - # define KS_AnalogVideo_NTSC_Mask 0x00000007 - # define KS_AnalogVideo_PAL_Mask 0x00100FF0 - # define KS_AnalogVideo_SECAM_Mask 0x000FF000 - - # define STATIC_PROPSETID_ALLOCATOR_CONTROL \ - 0x53171960, 0x148e, 0x11d2, 0x99, 0x79, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("53171960-148E-11d2-9979-0000C0CC16BA", PROPSETID_ALLOCATOR_CONTROL); - # define PROPSETID_ALLOCATOR_CONTROL DEFINE_GUIDNAMED(PROPSETID_ALLOCATOR_CONTROL) - -typedef enum -{ - KSPROPERTY_ALLOCATOR_CONTROL_HONOR_COUNT, - KSPROPERTY_ALLOCATOR_CONTROL_SURFACE_SIZE, - KSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_CAPS, - KSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_INTERLEAVE -}KSPROPERTY_ALLOCATOR_CONTROL; - -typedef struct -{ - ULONG CX; - ULONG CY; -}KSPROPERTY_ALLOCATOR_CONTROL_SURFACE_SIZE_S, * PKSPROPERTY_ALLOCATOR_CONTROL_SURFACE_SIZE_S; - -typedef struct -{ - ULONG InterleavedCapSupported; -}KSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_CAPS_S, * PKSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_CAPS_S; - -typedef struct -{ - ULONG InterleavedCapPossible; -}KSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_INTERLEAVE_S, * PKSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_INTERLEAVE_S; - - # define STATIC_PROPSETID_VIDCAP_VIDEOPROCAMP \ - 0xC6E13360L, 0x30AC, 0x11d0, 0xa1, 0x8c, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("C6E13360-30AC-11d0-A18C-00A0C9118956", PROPSETID_VIDCAP_VIDEOPROCAMP); - # define PROPSETID_VIDCAP_VIDEOPROCAMP DEFINE_GUIDNAMED(PROPSETID_VIDCAP_VIDEOPROCAMP) - -typedef enum -{ - KSPROPERTY_VIDEOPROCAMP_BRIGHTNESS, - KSPROPERTY_VIDEOPROCAMP_CONTRAST, - KSPROPERTY_VIDEOPROCAMP_HUE, - KSPROPERTY_VIDEOPROCAMP_SATURATION, - KSPROPERTY_VIDEOPROCAMP_SHARPNESS, - KSPROPERTY_VIDEOPROCAMP_GAMMA, - KSPROPERTY_VIDEOPROCAMP_COLORENABLE, - KSPROPERTY_VIDEOPROCAMP_WHITEBALANCE, - KSPROPERTY_VIDEOPROCAMP_BACKLIGHT_COMPENSATION, - KSPROPERTY_VIDEOPROCAMP_GAIN, - KSPROPERTY_VIDEOPROCAMP_DIGITAL_MULTIPLIER, - KSPROPERTY_VIDEOPROCAMP_DIGITAL_MULTIPLIER_LIMIT, - KSPROPERTY_VIDEOPROCAMP_WHITEBALANCE_COMPONENT, - KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY -}KSPROPERTY_VIDCAP_VIDEOPROCAMP; - -typedef struct -{ - KSPROPERTY Property; - LONG Value; - ULONG Flags; - ULONG Capabilities; -}KSPROPERTY_VIDEOPROCAMP_S, * PKSPROPERTY_VIDEOPROCAMP_S; - -typedef struct -{ - KSP_NODE NodeProperty; - LONG Value; - ULONG Flags; - ULONG Capabilities; -}KSPROPERTY_VIDEOPROCAMP_NODE_S, * PKSPROPERTY_VIDEOPROCAMP_NODE_S; - -typedef struct -{ - KSPROPERTY Property; - LONG Value1; - ULONG Flags; - ULONG Capabilities; - LONG Value2; -}KSPROPERTY_VIDEOPROCAMP_S2, * PKSPROPERTY_VIDEOPROCAMP_S2; - -typedef struct -{ - KSP_NODE NodeProperty; - LONG Value1; - ULONG Flags; - ULONG Capabilities; - LONG Value2; -}KSPROPERTY_VIDEOPROCAMP_NODE_S2, * PKSPROPERTY_VIDEOPROCAMP_NODE_S2; - - # define KSPROPERTY_VIDEOPROCAMP_FLAGS_AUTO 0X0001L - # define KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL 0X0002L - - # define STATIC_PROPSETID_VIDCAP_SELECTOR \ - 0x1ABDAECA, 0x68B6, 0x4F83, 0x93, 0x71, 0xB4, 0x13, 0x90, 0x7C, 0x7B, 0x9F -DEFINE_GUIDSTRUCT("1ABDAECA-68B6-4F83-9371-B413907C7B9F", PROPSETID_VIDCAP_SELECTOR); - # define PROPSETID_VIDCAP_SELECTOR DEFINE_GUIDNAMED(PROPSETID_VIDCAP_SELECTOR) - -typedef enum -{ - KSPROPERTY_SELECTOR_SOURCE_NODE_ID, - KSPROPERTY_SELECTOR_NUM_SOURCES -}KSPROPERTY_VIDCAP_SELECTOR, * PKSPROPERTY_VIDCAP_SELECTOR; - -typedef struct -{ - KSPROPERTY Property; - LONG Value; - ULONG Flags; - ULONG Capabilities; -}KSPROPERTY_SELECTOR_S, * PKSPROPERTY_SELECTOR_S; - -typedef struct -{ - KSP_NODE NodeProperty; - LONG Value; - ULONG Flags; - ULONG Capabilities; -}KSPROPERTY_SELECTOR_NODE_S, * PKSPROPERTY_SELECTOR_NODE_S; - - # define STATIC_PROPSETID_TUNER \ - 0x6a2e0605L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0605-28e4-11d0-a18c-00a0c9118956", PROPSETID_TUNER); - # define PROPSETID_TUNER DEFINE_GUIDNAMED(PROPSETID_TUNER) - -typedef enum -{ - KSPROPERTY_TUNER_CAPS, - KSPROPERTY_TUNER_MODE_CAPS, - KSPROPERTY_TUNER_MODE, - KSPROPERTY_TUNER_STANDARD, - KSPROPERTY_TUNER_FREQUENCY, - KSPROPERTY_TUNER_INPUT, - KSPROPERTY_TUNER_STATUS, - KSPROPERTY_TUNER_IF_MEDIUM -}KSPROPERTY_TUNER; - -typedef enum -{ - KSPROPERTY_TUNER_MODE_TV = 0X0001, - KSPROPERTY_TUNER_MODE_FM_RADIO = 0X0002, - KSPROPERTY_TUNER_MODE_AM_RADIO = 0X0004, - KSPROPERTY_TUNER_MODE_DSS = 0X0008, - KSPROPERTY_TUNER_MODE_ATSC = 0X0010 -}KSPROPERTY_TUNER_MODES; - -typedef enum -{ - KS_TUNER_TUNING_EXACT = 1, - KS_TUNER_TUNING_FINE, - KS_TUNER_TUNING_COARSE -}KS_TUNER_TUNING_FLAGS; - -typedef enum -{ - KS_TUNER_STRATEGY_PLL = 0X01, - KS_TUNER_STRATEGY_SIGNAL_STRENGTH = 0X02, - KS_TUNER_STRATEGY_DRIVER_TUNES = 0X04 -}KS_TUNER_STRATEGY; - -typedef struct -{ - KSPROPERTY Property; - ULONG ModesSupported; - KSPIN_MEDIUM VideoMedium; - KSPIN_MEDIUM TVAudioMedium; - KSPIN_MEDIUM RadioAudioMedium; -}KSPROPERTY_TUNER_CAPS_S, * PKSPROPERTY_TUNER_CAPS_S; - -typedef struct -{ - KSPROPERTY Property; - KSPIN_MEDIUM IFMedium; -}KSPROPERTY_TUNER_IF_MEDIUM_S, * PKSPROPERTY_TUNER_IF_MEDIUM_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG Mode; - ULONG StandardsSupported; - ULONG MinFrequency; - ULONG MaxFrequency; - ULONG TuningGranularity; - ULONG NumberOfInputs; - ULONG SettlingTime; - ULONG Strategy; -}KSPROPERTY_TUNER_MODE_CAPS_S, * PKSPROPERTY_TUNER_MODE_CAPS_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG Mode; -}KSPROPERTY_TUNER_MODE_S, * PKSPROPERTY_TUNER_MODE_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG Frequency; - ULONG LastFrequency; - ULONG TuningFlags; - ULONG VideoSubChannel; - ULONG AudioSubChannel; - ULONG Channel; - ULONG Country; -}KSPROPERTY_TUNER_FREQUENCY_S, * PKSPROPERTY_TUNER_FREQUENCY_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG Standard; -}KSPROPERTY_TUNER_STANDARD_S, * PKSPROPERTY_TUNER_STANDARD_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG InputIndex; -}KSPROPERTY_TUNER_INPUT_S, * PKSPROPERTY_TUNER_INPUT_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG CurrentFrequency; - ULONG PLLOffset; - ULONG SignalStrength; - ULONG Busy; -}KSPROPERTY_TUNER_STATUS_S, * PKSPROPERTY_TUNER_STATUS_S; - - # define STATIC_EVENTSETID_TUNER \ - 0x6a2e0606L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0606-28e4-11d0-a18c-00a0c9118956", EVENTSETID_TUNER); - # define EVENTSETID_TUNER DEFINE_GUIDNAMED(EVENTSETID_TUNER) - -typedef enum -{ - KSEVENT_TUNER_CHANGED -}KSEVENT_TUNER; - - # define STATIC_KSNODETYPE_VIDEO_STREAMING \ - 0xDFF229E1L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("DFF229E1-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_STREAMING); - # define KSNODETYPE_VIDEO_STREAMING DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_STREAMING) - - # define STATIC_KSNODETYPE_VIDEO_INPUT_TERMINAL \ - 0xDFF229E2L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("DFF229E2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_INPUT_TERMINAL); - # define KSNODETYPE_VIDEO_INPUT_TERMINAL DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_INPUT_TERMINAL) - - # define STATIC_KSNODETYPE_VIDEO_OUTPUT_TERMINAL \ - 0xDFF229E3L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("DFF229E3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_OUTPUT_TERMINAL); - # define KSNODETYPE_VIDEO_OUTPUT_TERMINAL DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_OUTPUT_TERMINAL) - - # define STATIC_KSNODETYPE_VIDEO_SELECTOR \ - 0xDFF229E4L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("DFF229E4-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_SELECTOR); - # define KSNODETYPE_VIDEO_SELECTOR DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_SELECTOR) - - # define STATIC_KSNODETYPE_VIDEO_PROCESSING \ - 0xDFF229E5L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("DFF229E5-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_PROCESSING); - # define KSNODETYPE_VIDEO_PROCESSING DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_PROCESSING) - - # define STATIC_KSNODETYPE_VIDEO_CAMERA_TERMINAL \ - 0xDFF229E6L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("DFF229E6-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_CAMERA_TERMINAL); - # define KSNODETYPE_VIDEO_CAMERA_TERMINAL DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_CAMERA_TERMINAL) - - # define STATIC_KSNODETYPE_VIDEO_INPUT_MTT \ - 0xDFF229E7L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("DFF229E7-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_INPUT_MTT); - # define KSNODETYPE_VIDEO_INPUT_MTT DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_INPUT_MTT) - - # define STATIC_KSNODETYPE_VIDEO_OUTPUT_MTT \ - 0xDFF229E8L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("DFF229E8-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_OUTPUT_MTT); - # define KSNODETYPE_VIDEO_OUTPUT_MTT DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_OUTPUT_MTT) - - # define STATIC_PROPSETID_VIDCAP_VIDEOENCODER \ - 0x6a2e0610L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0610-28e4-11d0-a18c-00a0c9118956", PROPSETID_VIDCAP_VIDEOENCODER); - # define PROPSETID_VIDCAP_VIDEOENCODER DEFINE_GUIDNAMED(PROPSETID_VIDCAP_VIDEOENCODER) - -typedef enum -{ - KSPROPERTY_VIDEOENCODER_CAPS, - KSPROPERTY_VIDEOENCODER_STANDARD, - KSPROPERTY_VIDEOENCODER_COPYPROTECTION, - KSPROPERTY_VIDEOENCODER_CC_ENABLE -}KSPROPERTY_VIDCAP_VIDEOENCODER; - -typedef struct -{ - KSPROPERTY Property; - LONG Value; - ULONG Flags; - ULONG Capabilities; -}KSPROPERTY_VIDEOENCODER_S, * PKSPROPERTY_VIDEOENCODER_S; - - # define STATIC_PROPSETID_VIDCAP_VIDEODECODER \ - 0xC6E13350L, 0x30AC, 0x11d0, 0xA1, 0x8C, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("C6E13350-30AC-11d0-A18C-00A0C9118956", PROPSETID_VIDCAP_VIDEODECODER); - # define PROPSETID_VIDCAP_VIDEODECODER DEFINE_GUIDNAMED(PROPSETID_VIDCAP_VIDEODECODER) - -typedef enum -{ - KSPROPERTY_VIDEODECODER_CAPS, - KSPROPERTY_VIDEODECODER_STANDARD, - KSPROPERTY_VIDEODECODER_STATUS, - KSPROPERTY_VIDEODECODER_OUTPUT_ENABLE, - KSPROPERTY_VIDEODECODER_VCR_TIMING -}KSPROPERTY_VIDCAP_VIDEODECODER; - -typedef enum -{ - KS_VIDEODECODER_FLAGS_CAN_DISABLE_OUTPUT = 0X0001, - KS_VIDEODECODER_FLAGS_CAN_USE_VCR_LOCKING = 0X0002, - KS_VIDEODECODER_FLAGS_CAN_INDICATE_LOCKED = 0X0004 -}KS_VIDEODECODER_FLAGS; - -typedef struct -{ - KSPROPERTY Property; - ULONG StandardsSupported; - ULONG Capabilities; - ULONG SettlingTime; - ULONG HSyncPerVSync; -}KSPROPERTY_VIDEODECODER_CAPS_S, * PKSPROPERTY_VIDEODECODER_CAPS_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG NumberOfLines; - ULONG SignalLocked; -}KSPROPERTY_VIDEODECODER_STATUS_S, * PKSPROPERTY_VIDEODECODER_STATUS_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG Value; -}KSPROPERTY_VIDEODECODER_S, * PKSPROPERTY_VIDEODECODER_S; - - # define STATIC_EVENTSETID_VIDEODECODER \ - 0x6a2e0621L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0621-28e4-11d0-a18c-00a0c9118956", EVENTSETID_VIDEODECODER); - # define EVENTSETID_VIDEODECODER DEFINE_GUIDNAMED(EVENTSETID_VIDEODECODER) - -typedef enum -{ - KSEVENT_VIDEODECODER_CHANGED -}KSEVENT_VIDEODECODER; - - # define STATIC_PROPSETID_VIDCAP_CAMERACONTROL \ - 0xC6E13370L, 0x30AC, 0x11d0, 0xa1, 0x8C, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("C6E13370-30AC-11d0-A18C-00A0C9118956", PROPSETID_VIDCAP_CAMERACONTROL); - # define PROPSETID_VIDCAP_CAMERACONTROL DEFINE_GUIDNAMED(PROPSETID_VIDCAP_CAMERACONTROL) - -typedef enum -{ - KSPROPERTY_CAMERACONTROL_PAN, - KSPROPERTY_CAMERACONTROL_TILT, - KSPROPERTY_CAMERACONTROL_ROLL, - KSPROPERTY_CAMERACONTROL_ZOOM, - KSPROPERTY_CAMERACONTROL_EXPOSURE, - KSPROPERTY_CAMERACONTROL_IRIS, - KSPROPERTY_CAMERACONTROL_FOCUS, - KSPROPERTY_CAMERACONTROL_SCANMODE, - KSPROPERTY_CAMERACONTROL_PRIVACY, - KSPROPERTY_CAMERACONTROL_PANTILT, - KSPROPERTY_CAMERACONTROL_PAN_RELATIVE, - KSPROPERTY_CAMERACONTROL_TILT_RELATIVE, - KSPROPERTY_CAMERACONTROL_ROLL_RELATIVE, - KSPROPERTY_CAMERACONTROL_ZOOM_RELATIVE, - KSPROPERTY_CAMERACONTROL_EXPOSURE_RELATIVE, - KSPROPERTY_CAMERACONTROL_IRIS_RELATIVE, - KSPROPERTY_CAMERACONTROL_FOCUS_RELATIVE, - KSPROPERTY_CAMERACONTROL_PANTILT_RELATIVE, - KSPROPERTY_CAMERACONTROL_FOCAL_LENGTH -}KSPROPERTY_VIDCAP_CAMERACONTROL; - -typedef struct -{ - KSPROPERTY Property; - LONG Value; - ULONG Flags; - ULONG Capabilities; -}KSPROPERTY_CAMERACONTROL_S, * PKSPROPERTY_CAMERACONTROL_S; - -typedef struct -{ - KSP_NODE NodeProperty; - LONG Value; - ULONG Flags; - ULONG Capabilities; -}KSPROPERTY_CAMERACONTROL_NODE_S, PKSPROPERTY_CAMERACONTROL_NODE_S; - -typedef struct -{ - KSPROPERTY Property; - LONG Value1; - ULONG Flags; - ULONG Capabilities; - LONG Value2; -}KSPROPERTY_CAMERACONTROL_S2, * PKSPROPERTY_CAMERACONTROL_S2; - -typedef struct -{ - KSP_NODE NodeProperty; - LONG Value1; - ULONG Flags; - ULONG Capabilities; - LONG Value2; -}KSPROPERTY_CAMERACONTROL_NODE_S2, * PKSPROPERTY_CAMERACONTROL_NODE_S2; - -typedef struct -{ - KSPROPERTY Property; - LONG lOcularFocalLength; - LONG lObjectiveFocalLengthMin; - LONG lObjectiveFocalLengthMax; -}KSPROPERTY_CAMERACONTROL_FOCAL_LENGTH_S, * PKSPROPERTY_CAMERACONTROL_FOCAL_LENGTH_S; - -typedef struct -{ - KSNODEPROPERTY NodeProperty; - LONG lOcularFocalLength; - LONG lObjectiveFocalLengthMin; - LONG lObjectiveFocalLengthMax; -}KSPROPERTY_CAMERACONTROL_NODE_FOCAL_LENGTH_S, * PKSPROPERTY_CAMERACONTROL_NODE_FOCAL_LENGTH_S; - - # define KSPROPERTY_CAMERACONTROL_FLAGS_AUTO 0X0001L - # define KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL 0X0002L - - # define KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE 0X0000L - # define KSPROPERTY_CAMERACONTROL_FLAGS_RELATIVE 0X0010L - - # ifndef __EDevCtrl__ - # define __EDevCtrl__ - - # define STATIC_PROPSETID_EXT_DEVICE \ - 0xB5730A90L, 0x1A2C, 0x11cf, 0x8c, 0x23, 0x00, 0xAA, 0x00, 0x6B, 0x68, 0x14 -DEFINE_GUIDSTRUCT("B5730A90-1A2C-11cf-8C23-00AA006B6814", PROPSETID_EXT_DEVICE); - # define PROPSETID_EXT_DEVICE DEFINE_GUIDNAMED(PROPSETID_EXT_DEVICE) - -typedef enum -{ - KSPROPERTY_EXTDEVICE_ID, - KSPROPERTY_EXTDEVICE_VERSION, - KSPROPERTY_EXTDEVICE_POWER_STATE, - KSPROPERTY_EXTDEVICE_PORT, - KSPROPERTY_EXTDEVICE_CAPABILITIES -}KSPROPERTY_EXTDEVICE; - -typedef struct tagDEVCAPS -{ - LONG CanRecord; - LONG CanRecordStrobe; - LONG HasAudio; - LONG HasVideo; - LONG UsesFiles; - LONG CanSave; - LONG DeviceType; - LONG TCRead; - LONG TCWrite; - LONG CTLRead; - LONG IndexRead; - LONG Preroll; - LONG Postroll; - LONG SyncAcc; - LONG NormRate; - LONG CanPreview; - LONG CanMonitorSrc; - LONG CanTest; - LONG VideoIn; - LONG AudioIn; - LONG Calibrate; - LONG SeekType; - LONG SimulatedHardware; -}DEVCAPS, * PDEVCAPS; - -typedef struct -{ - KSPROPERTY Property; - union - { - DEVCAPS Capabilities; - ULONG DevPort; - ULONG PowerState; - WCHAR pawchString[MAX_PATH]; - DWORD NodeUniqueID[2]; - }u; -}KSPROPERTY_EXTDEVICE_S, * PKSPROPERTY_EXTDEVICE_S; - - # define STATIC_PROPSETID_EXT_TRANSPORT \ - 0xA03CD5F0L, 0x3045, 0x11cf, 0x8c, 0x44, 0x00, 0xAA, 0x00, 0x6B, 0x68, 0x14 -DEFINE_GUIDSTRUCT("A03CD5F0-3045-11cf-8C44-00AA006B6814", PROPSETID_EXT_TRANSPORT); - # define PROPSETID_EXT_TRANSPORT DEFINE_GUIDNAMED(PROPSETID_EXT_TRANSPORT) - -typedef enum -{ - KSPROPERTY_EXTXPORT_CAPABILITIES, - KSPROPERTY_EXTXPORT_INPUT_SIGNAL_MODE, - KSPROPERTY_EXTXPORT_OUTPUT_SIGNAL_MODE, - KSPROPERTY_EXTXPORT_LOAD_MEDIUM, - KSPROPERTY_EXTXPORT_MEDIUM_INFO, - KSPROPERTY_EXTXPORT_STATE, - KSPROPERTY_EXTXPORT_STATE_NOTIFY, - KSPROPERTY_EXTXPORT_TIMECODE_SEARCH, - KSPROPERTY_EXTXPORT_ATN_SEARCH, - KSPROPERTY_EXTXPORT_RTC_SEARCH, - KSPROPERTY_RAW_AVC_CMD -}KSPROPERTY_EXTXPORT; - -typedef struct tagTRANSPORTSTATUS -{ - LONG Mode; - LONG LastError; - LONG RecordInhibit; - LONG ServoLock; - LONG MediaPresent; - LONG MediaLength; - LONG MediaSize; - LONG MediaTrackCount; - LONG MediaTrackLength; - LONG MediaTrackSide; - LONG MediaType; - LONG LinkMode; - LONG NotifyOn; -}TRANSPORTSTATUS, * PTRANSPORTSTATUS; - -typedef struct tagTRANSPORTBASICPARMS -{ - LONG TimeFormat; - LONG TimeReference; - LONG Superimpose; - LONG EndStopAction; - LONG RecordFormat; - LONG StepFrames; - LONG SetpField; - LONG Preroll; - LONG RecPreroll; - LONG Postroll; - LONG EditDelay; - LONG PlayTCDelay; - LONG RecTCDelay; - LONG EditField; - LONG FrameServo; - LONG ColorFrameServo; - LONG ServoRef; - LONG WarnGenlock; - LONG SetTracking; - TCHAR VolumeName[40]; - LONG Ballistic[20]; - LONG Speed; - LONG CounterFormat; - LONG TunerChannel; - LONG TunerNumber; - LONG TimerEvent; - LONG TimerStartDay; - LONG TimerStartTime; - LONG TimerStopDay; - LONG TimerStopTime; -}TRANSPORTBASICPARMS, * PTRANSPORTBASICPARMS; - -typedef struct tagTRANSPORTVIDEOPARMS -{ - LONG OutputMode; - LONG Input; -}TRANSPORTVIDEOPARMS, * PTRANSPORTVIDEOPARMS; - -typedef struct tagTRANSPORTAUDIOPARMS -{ - LONG EnableOutput; - LONG EnableRecord; - LONG EnableSelsync; - LONG Input; - LONG MonitorSource; -}TRANSPORTAUDIOPARMS, * PTRANSPORTAUDIOPARMS; - -typedef struct -{ - WINBOOL MediaPresent; - ULONG MediaType; - WINBOOL RecordInhibit; -}MEDIUM_INFO, * PMEDIUM_INFO; - -typedef struct -{ - ULONG Mode; - ULONG State; -}TRANSPORT_STATE, * PTRANSPORT_STATE; - -typedef struct -{ - KSPROPERTY Property; - union - { - ULONG Capabilities; - ULONG SignalMode; - ULONG LoadMedium; - MEDIUM_INFO MediumInfo; - TRANSPORT_STATE XPrtState; - struct - { - BYTE frame; - BYTE second; - BYTE minute; - BYTE hour; - }Timecode; - DWORD dwTimecode; - DWORD dwAbsTrackNumber; - struct - { - ULONG PayloadSize; - BYTE Payload[512]; - }RawAVC; - }u; -}KSPROPERTY_EXTXPORT_S, * PKSPROPERTY_EXTXPORT_S; - -typedef struct -{ - KSP_NODE NodeProperty; - union - { - ULONG Capabilities; - ULONG SignalMode; - ULONG LoadMedium; - MEDIUM_INFO MediumInfo; - TRANSPORT_STATE XPrtState; - struct - { - BYTE frame; - BYTE second; - BYTE minute; - BYTE hour; - }Timecode; - DWORD dwTimecode; - DWORD dwAbsTrackNumber; - struct - { - ULONG PayloadSize; - BYTE Payload[512]; - }RawAVC; - }u; -}KSPROPERTY_EXTXPORT_NODE_S, * PKSPROPERTY_EXTXPORT_NODE_S; - - # define STATIC_PROPSETID_TIMECODE_READER \ - 0x9B496CE1L, 0x811B, 0x11cf, 0x8C, 0x77, 0x00, 0xAA, 0x00, 0x6B, 0x68, 0x14 -DEFINE_GUIDSTRUCT("9B496CE1-811B-11cf-8C77-00AA006B6814", PROPSETID_TIMECODE_READER); - # define PROPSETID_TIMECODE_READER DEFINE_GUIDNAMED(PROPSETID_TIMECODE_READER) - -typedef enum -{ - KSPROPERTY_TIMECODE_READER, - KSPROPERTY_ATN_READER, - KSPROPERTY_RTC_READER -}KSPROPERTY_TIMECODE; - - # ifndef TIMECODE_DEFINED - # define TIMECODE_DEFINED -typedef union _timecode -{ - struct - { - WORD wFrameRate; - WORD wFrameFract; - DWORD dwFrames; - }; - DWORDLONG qw; -}TIMECODE; -typedef TIMECODE* PTIMECODE; - -typedef struct tagTIMECODE_SAMPLE -{ - LONGLONG qwTick; - TIMECODE timecode; - DWORD dwUser; - DWORD dwFlags; -}TIMECODE_SAMPLE; - -typedef TIMECODE_SAMPLE* PTIMECODE_SAMPLE; - # endif /* TIMECODE_DEFINED */ - -typedef struct -{ - KSPROPERTY Property; - TIMECODE_SAMPLE TimecodeSamp; -}KSPROPERTY_TIMECODE_S, * PKSPROPERTY_TIMECODE_S; - -typedef struct -{ - KSP_NODE NodeProperty; - TIMECODE_SAMPLE TimecodeSamp; -}KSPROPERTY_TIMECODE_NODE_S, * PKSPROPERTY_TIMECODE_NODE_S; - - # define STATIC_KSEVENTSETID_EXTDEV_Command \ - 0x109c7988L, 0xb3cb, 0x11d2, 0xb4, 0x8e, 0x00, 0x60, 0x97, 0xb3, 0x39, 0x1b -DEFINE_GUIDSTRUCT("109c7988-b3cb-11d2-b48e-006097b3391b", KSEVENTSETID_EXTDEV_Command); - # define KSEVENTSETID_EXTDEV_Command DEFINE_GUIDNAMED(KSEVENTSETID_EXTDEV_Command) - -typedef enum -{ - KSEVENT_EXTDEV_COMMAND_NOTIFY_INTERIM_READY, - KSEVENT_EXTDEV_COMMAND_CONTROL_INTERIM_READY, - KSEVENT_EXTDEV_COMMAND_BUSRESET, - KSEVENT_EXTDEV_TIMECODE_UPDATE, - KSEVENT_EXTDEV_OPERATION_MODE_UPDATE, - KSEVENT_EXTDEV_TRANSPORT_STATE_UPDATE, - KSEVENT_EXTDEV_NOTIFY_REMOVAL, - KSEVENT_EXTDEV_NOTIFY_MEDIUM_CHANGE -}KSEVENT_DEVCMD; - # endif /* __EDevCtrl__ */ - - # define STATIC_PROPSETID_VIDCAP_CROSSBAR \ - 0x6a2e0640L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0640-28e4-11d0-a18c-00a0c9118956", PROPSETID_VIDCAP_CROSSBAR); - # define PROPSETID_VIDCAP_CROSSBAR DEFINE_GUIDNAMED(PROPSETID_VIDCAP_CROSSBAR) - -typedef enum -{ - KSPROPERTY_CROSSBAR_CAPS, - KSPROPERTY_CROSSBAR_PININFO, - KSPROPERTY_CROSSBAR_CAN_ROUTE, - KSPROPERTY_CROSSBAR_ROUTE -}KSPROPERTY_VIDCAP_CROSSBAR; - -typedef struct -{ - KSPROPERTY Property; - ULONG NumberOfInputs; - ULONG NumberOfOutputs; -}KSPROPERTY_CROSSBAR_CAPS_S, * PKSPROPERTY_CROSSBAR_CAPS_S; - -typedef struct -{ - KSPROPERTY Property; - KSPIN_DATAFLOW Direction; - ULONG Index; - ULONG PinType; - ULONG RelatedPinIndex; - KSPIN_MEDIUM Medium; -}KSPROPERTY_CROSSBAR_PININFO_S, * PKSPROPERTY_CROSSBAR_PININFO_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG IndexInputPin; - ULONG IndexOutputPin; - ULONG CanRoute; -}KSPROPERTY_CROSSBAR_ROUTE_S, * PKSPROPERTY_CROSSBAR_ROUTE_S; - - # define STATIC_EVENTSETID_CROSSBAR \ - 0x6a2e0641L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0641-28e4-11d0-a18c-00a0c9118956", EVENTSETID_CROSSBAR); - # define EVENTSETID_CROSSBAR DEFINE_GUIDNAMED(EVENTSETID_CROSSBAR) - -typedef enum -{ - KSEVENT_CROSSBAR_CHANGED -}KSEVENT_CROSSBAR; - -typedef enum -{ - KS_PhysConn_Video_Tuner = 1, - KS_PhysConn_Video_Composite, - KS_PhysConn_Video_SVideo, - KS_PhysConn_Video_RGB, - KS_PhysConn_Video_YRYBY, - KS_PhysConn_Video_SerialDigital, - KS_PhysConn_Video_ParallelDigital, - KS_PhysConn_Video_SCSI, - KS_PhysConn_Video_AUX, - KS_PhysConn_Video_1394, - KS_PhysConn_Video_USB, - KS_PhysConn_Video_VideoDecoder, - KS_PhysConn_Video_VideoEncoder, - KS_PhysConn_Video_SCART, - KS_PhysConn_Audio_Tuner = 4096, - KS_PhysConn_Audio_Line, - KS_PhysConn_Audio_Mic, - KS_PhysConn_Audio_AESDigital, - KS_PhysConn_Audio_SPDIFDigital, - KS_PhysConn_Audio_SCSI, - KS_PhysConn_Audio_AUX, - KS_PhysConn_Audio_1394, - KS_PhysConn_Audio_USB, - KS_PhysConn_Audio_AudioDecoder -}KS_PhysicalConnectorType; - - # define STATIC_PROPSETID_VIDCAP_TVAUDIO \ - 0x6a2e0650L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0650-28e4-11d0-a18c-00a0c9118956", PROPSETID_VIDCAP_TVAUDIO); - # define PROPSETID_VIDCAP_TVAUDIO DEFINE_GUIDNAMED(PROPSETID_VIDCAP_TVAUDIO) - -typedef enum -{ - KSPROPERTY_TVAUDIO_CAPS, - KSPROPERTY_TVAUDIO_MODE, - KSPROPERTY_TVAUDIO_CURRENTLY_AVAILABLE_MODES -}KSPROPERTY_VIDCAP_TVAUDIO; - - # define KS_TVAUDIO_MODE_MONO 0x0001 - # define KS_TVAUDIO_MODE_STEREO 0x0002 - # define KS_TVAUDIO_MODE_LANG_A 0x0010 - # define KS_TVAUDIO_MODE_LANG_B 0x0020 - # define KS_TVAUDIO_MODE_LANG_C 0x0040 - -typedef struct -{ - KSPROPERTY Property; - ULONG Capabilities; - KSPIN_MEDIUM InputMedium; - KSPIN_MEDIUM OutputMedium; -}KSPROPERTY_TVAUDIO_CAPS_S, * PKSPROPERTY_TVAUDIO_CAPS_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG Mode; -}KSPROPERTY_TVAUDIO_S, * PKSPROPERTY_TVAUDIO_S; - - # define STATIC_KSEVENTSETID_VIDCAP_TVAUDIO \ - 0x6a2e0651L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0651-28e4-11d0-a18c-00a0c9118956", KSEVENTSETID_VIDCAP_TVAUDIO); - # define KSEVENTSETID_VIDCAP_TVAUDIO DEFINE_GUIDNAMED(KSEVENTSETID_VIDCAP_TVAUDIO) - -typedef enum -{ - KSEVENT_TVAUDIO_CHANGED -}KSEVENT_TVAUDIO; - - # define STATIC_PROPSETID_VIDCAP_VIDEOCOMPRESSION \ - 0xC6E13343L, 0x30AC, 0x11d0, 0xA1, 0x8C, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("C6E13343-30AC-11d0-A18C-00A0C9118956", PROPSETID_VIDCAP_VIDEOCOMPRESSION); - # define PROPSETID_VIDCAP_VIDEOCOMPRESSION DEFINE_GUIDNAMED(PROPSETID_VIDCAP_VIDEOCOMPRESSION) - -typedef enum -{ - KSPROPERTY_VIDEOCOMPRESSION_GETINFO, - KSPROPERTY_VIDEOCOMPRESSION_KEYFRAME_RATE, - KSPROPERTY_VIDEOCOMPRESSION_PFRAMES_PER_KEYFRAME, - KSPROPERTY_VIDEOCOMPRESSION_QUALITY, - KSPROPERTY_VIDEOCOMPRESSION_OVERRIDE_KEYFRAME, - KSPROPERTY_VIDEOCOMPRESSION_OVERRIDE_FRAME_SIZE, - KSPROPERTY_VIDEOCOMPRESSION_WINDOWSIZE -}KSPROPERTY_VIDCAP_VIDEOCOMPRESSION; - -typedef enum -{ - KS_CompressionCaps_CanQuality = 1, - KS_CompressionCaps_CanCrunch = 2, - KS_CompressionCaps_CanKeyFrame = 4, - KS_CompressionCaps_CanBFrame = 8, - KS_CompressionCaps_CanWindow = 0x10 -}KS_CompressionCaps; - -typedef enum -{ - KS_StreamingHint_FrameInterval = 0x0100, - KS_StreamingHint_KeyFrameRate = 0x0200, - KS_StreamingHint_PFrameRate = 0x0400, - KS_StreamingHint_CompQuality = 0x0800, - KS_StreamingHint_CompWindowSize = 0x1000 -}KS_VideoStreamingHints; - -typedef struct -{ - KSPROPERTY Property; - ULONG StreamIndex; - LONG DefaultKeyFrameRate; - LONG DefaultPFrameRate; - LONG DefaultQuality; - LONG NumberOfQualitySettings; - LONG Capabilities; -}KSPROPERTY_VIDEOCOMPRESSION_GETINFO_S, * PKSPROPERTY_VIDEOCOMPRESSION_GETINFO_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG StreamIndex; - LONG Value; -}KSPROPERTY_VIDEOCOMPRESSION_S, * PKSPROPERTY_VIDEOCOMPRESSION_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG StreamIndex; - LONG Value; - ULONG Flags; -}KSPROPERTY_VIDEOCOMPRESSION_S1, * PKSPROPERTY_VIDEOCOMPRESSION_S1; - - # define STATIC_KSDATAFORMAT_SUBTYPE_OVERLAY \ - 0xe436eb7fL, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 -DEFINE_GUIDSTRUCT("e436eb7f-524f-11ce-9f53-0020af0ba770", KSDATAFORMAT_SUBTYPE_OVERLAY); - # define KSDATAFORMAT_SUBTYPE_OVERLAY DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_OVERLAY) - - # define STATIC_KSPROPSETID_OverlayUpdate \ - 0x490EA5CFL, 0x7681, 0x11D1, 0xA2, 0x1C, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("490EA5CF-7681-11D1-A21C-00A0C9223196", KSPROPSETID_OverlayUpdate); - # define KSPROPSETID_OverlayUpdate DEFINE_GUIDNAMED(KSPROPSETID_OverlayUpdate) - -typedef enum -{ - KSPROPERTY_OVERLAYUPDATE_INTERESTS, - KSPROPERTY_OVERLAYUPDATE_CLIPLIST = 0x1, - KSPROPERTY_OVERLAYUPDATE_PALETTE = 0x2, - KSPROPERTY_OVERLAYUPDATE_COLORKEY = 0x4, - KSPROPERTY_OVERLAYUPDATE_VIDEOPOSITION = 0x8, - KSPROPERTY_OVERLAYUPDATE_DISPLAYCHANGE = 0x10, - KSPROPERTY_OVERLAYUPDATE_COLORREF = 0x10000000 -}KSPROPERTY_OVERLAYUPDATE; - -typedef struct -{ - ULONG PelsWidth; - ULONG PelsHeight; - ULONG BitsPerPel; - WCHAR DeviceID[1]; -}KSDISPLAYCHANGE, * PKSDISPLAYCHANGE; - - # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_INTERESTS(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_OVERLAYUPDATE_INTERESTS, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(ULONG), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_PALETTE(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_OVERLAYUPDATE_PALETTE, \ - NULL, \ - sizeof(KSPROPERTY), \ - 0, \ - (Handler), \ - NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_COLORKEY(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_OVERLAYUPDATE_COLORKEY, \ - NULL, \ - sizeof(KSPROPERTY), \ - sizeof(COLORKEY), \ - (Handler), \ - NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_CLIPLIST(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_OVERLAYUPDATE_CLIPLIST, \ - NULL, \ - sizeof(KSPROPERTY), \ - 2 * sizeof(RECT) + sizeof(RGNDATAHEADER), \ - (Handler), \ - NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_VIDEOPOSITION(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_OVERLAYUPDATE_VIDEOPOSITION, \ - NULL, \ - sizeof(KSPROPERTY), \ - 2 * sizeof(RECT), \ - (Handler), \ - NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_DISPLAYCHANGE(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_OVERLAYUPDATE_DISPLAYCHANGE, \ - NULL, \ - sizeof(KSPROPERTY), \ - sizeof(KSDISPLAYCHANGE), \ - (Handler), \ - NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_COLORREF(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_OVERLAYUPDATE_COLORREF, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(COLORREF), \ - NULL, \ - NULL, 0, NULL, NULL, 0) - - # define STATIC_PROPSETID_VIDCAP_VIDEOCONTROL \ - 0x6a2e0670L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0670-28e4-11d0-a18c-00a0c9118956", PROPSETID_VIDCAP_VIDEOCONTROL); - # define PROPSETID_VIDCAP_VIDEOCONTROL DEFINE_GUIDNAMED(PROPSETID_VIDCAP_VIDEOCONTROL) - -typedef enum -{ - KSPROPERTY_VIDEOCONTROL_CAPS, - KSPROPERTY_VIDEOCONTROL_ACTUAL_FRAME_RATE, - KSPROPERTY_VIDEOCONTROL_FRAME_RATES, - KSPROPERTY_VIDEOCONTROL_MODE -}KSPROPERTY_VIDCAP_VIDEOCONTROL; - -typedef enum -{ - KS_VideoControlFlag_FlipHorizontal = 0x0001, - KS_VideoControlFlag_FlipVertical = 0x0002, - KS_Obsolete_VideoControlFlag_ExternalTriggerEnable = 0x0010, - KS_Obsolete_VideoControlFlag_Trigger = 0x0020, - KS_VideoControlFlag_ExternalTriggerEnable = 0x0004, - KS_VideoControlFlag_Trigger = 0x0008 -}KS_VideoControlFlags; - -typedef struct -{ - KSPROPERTY Property; - ULONG StreamIndex; - ULONG VideoControlCaps; -}KSPROPERTY_VIDEOCONTROL_CAPS_S, * PKSPROPERTY_VIDEOCONTROL_CAPS_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG StreamIndex; - LONG Mode; -}KSPROPERTY_VIDEOCONTROL_MODE_S, * PKSPROPERTY_VIDEOCONTROL_MODE_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG StreamIndex; - ULONG RangeIndex; - SIZE Dimensions; - LONGLONG CurrentActualFrameRate; - LONGLONG CurrentMaxAvailableFrameRate; -}KSPROPERTY_VIDEOCONTROL_ACTUAL_FRAME_RATE_S, * PKSPROPERTY_VIDEOCONTROL_ACTUAL_FRAME_RATE_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG StreamIndex; - ULONG RangeIndex; - SIZE Dimensions; -}KSPROPERTY_VIDEOCONTROL_FRAME_RATES_S, * PKSPROPERTY_VIDEOCONTROL_FRAME_RATES_S; - - # define STATIC_PROPSETID_VIDCAP_DROPPEDFRAMES \ - 0xC6E13344L, 0x30AC, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("C6E13344-30AC-11d0-A18C-00A0C9118956", PROPSETID_VIDCAP_DROPPEDFRAMES); - # define PROPSETID_VIDCAP_DROPPEDFRAMES DEFINE_GUIDNAMED(PROPSETID_VIDCAP_DROPPEDFRAMES) - -typedef enum -{ - KSPROPERTY_DROPPEDFRAMES_CURRENT -}KSPROPERTY_VIDCAP_DROPPEDFRAMES; - -typedef struct -{ - KSPROPERTY Property; - LONGLONG PictureNumber; - LONGLONG DropCount; - ULONG AverageFrameSize; -}KSPROPERTY_DROPPEDFRAMES_CURRENT_S, * PKSPROPERTY_DROPPEDFRAMES_CURRENT_S; - - # define STATIC_KSPROPSETID_VPConfig \ - 0xbc29a660L, 0x30e3, 0x11d0, 0x9e, 0x69, 0x00, 0xc0, 0x4f, 0xd7, 0xc1, 0x5b -DEFINE_GUIDSTRUCT("bc29a660-30e3-11d0-9e69-00c04fd7c15b", KSPROPSETID_VPConfig); - # define KSPROPSETID_VPConfig DEFINE_GUIDNAMED(KSPROPSETID_VPConfig) - - # define STATIC_KSPROPSETID_VPVBIConfig \ - 0xec529b00L, 0x1a1f, 0x11d1, 0xba, 0xd9, 0x0, 0x60, 0x97, 0x44, 0x11, 0x1a -DEFINE_GUIDSTRUCT("ec529b00-1a1f-11d1-bad9-00609744111a", KSPROPSETID_VPVBIConfig); - # define KSPROPSETID_VPVBIConfig DEFINE_GUIDNAMED(KSPROPSETID_VPVBIConfig) - -typedef enum -{ - KSPROPERTY_VPCONFIG_NUMCONNECTINFO, - KSPROPERTY_VPCONFIG_GETCONNECTINFO, - KSPROPERTY_VPCONFIG_SETCONNECTINFO, - KSPROPERTY_VPCONFIG_VPDATAINFO, - KSPROPERTY_VPCONFIG_MAXPIXELRATE, - KSPROPERTY_VPCONFIG_INFORMVPINPUT, - KSPROPERTY_VPCONFIG_NUMVIDEOFORMAT, - KSPROPERTY_VPCONFIG_GETVIDEOFORMAT, - KSPROPERTY_VPCONFIG_SETVIDEOFORMAT, - KSPROPERTY_VPCONFIG_INVERTPOLARITY, - KSPROPERTY_VPCONFIG_DECIMATIONCAPABILITY, - KSPROPERTY_VPCONFIG_SCALEFACTOR, - KSPROPERTY_VPCONFIG_DDRAWHANDLE, - KSPROPERTY_VPCONFIG_VIDEOPORTID, - KSPROPERTY_VPCONFIG_DDRAWSURFACEHANDLE, - KSPROPERTY_VPCONFIG_SURFACEPARAMS -}KSPROPERTY_VPCONFIG; - - # define STATIC_CLSID_KsIBasicAudioInterfaceHandler \ - 0xb9f8ac3e, 0x0f71, 0x11d2, 0xb7, 0x2c, 0x00, 0xc0, 0x4f, 0xb6, 0xbd, 0x3d -DEFINE_GUIDSTRUCT("b9f8ac3e-0f71-11d2-b72c-00c04fb6bd3d", CLSID_KsIBasicAudioInterfaceHandler); - # define CLSID_KsIBasicAudioInterfaceHandler DEFINE_GUIDNAMED(CLSID_KsIBasicAudioInterfaceHandler) - - # ifdef __IVPType__ -typedef struct -{ - AMVPSIZE Size; - DWORD MaxPixelsPerSecond; - DWORD Reserved; -}KSVPMAXPIXELRATE, * PKSVPMAXPIXELRATE; - -typedef struct -{ - KSPROPERTY Property; - AMVPSIZE Size; -}KSVPSIZE_PROP, * PKSVPSIZE_PROP; - -typedef struct -{ - DWORD dwPitch; - DWORD dwXOrigin; - DWORD dwYOrigin; -}KSVPSURFACEPARAMS, * PKSVPSURFACEPARAMS; - # else /* __IVPType__ */ - - # ifndef __DDRAW_INCLUDED__ - # define DDPF_FOURCC 0x00000004l - -typedef struct _DDPIXELFORMAT -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwFourCC; - __MINGW_EXTENSION union - { - DWORD dwRGBBitCount; - DWORD dwYUVBitCount; - DWORD dwZBufferBitDepth; - DWORD dwAlphaBitDepth; - }; - __MINGW_EXTENSION union - { - DWORD dwRBitMask; - DWORD dwYBitMask; - }; - __MINGW_EXTENSION union - { - DWORD dwGBitMask; - DWORD dwUBitMask; - }; - __MINGW_EXTENSION union - { - DWORD dwBBitMask; - DWORD dwVBitMask; - }; - __MINGW_EXTENSION union - { - DWORD dwRGBAlphaBitMask; - DWORD dwYUVAlphaBitMask; - DWORD dwRGBZBitMask; - DWORD dwYUVZBitMask; - }; -}DDPIXELFORMAT, * LPDDPIXELFORMAT; - # endif /* __DDRAW_INCLUDED__ */ - - # ifndef __DVP_INCLUDED__ -typedef struct _DDVIDEOPORTCONNECT -{ - DWORD dwSize; - DWORD dwPortWidth; - GUID guidTypeID; - DWORD dwFlags; - ULONG_PTR dwReserved1; -}DDVIDEOPORTCONNECT, * LPDDVIDEOPORTCONNECT; - - # define DDVPTYPE_E_HREFH_VREFH \ - 0x54F39980L, 0xDA60, 0x11CF, 0x9B, 0x06, 0x00, 0xA0, 0xC9, 0x03, 0xA3, 0xB8 - - # define DDVPTYPE_E_HREFL_VREFL \ - 0xE09C77E0L, 0xDA60, 0x11CF, 0x9B, 0x06, 0x00, 0xA0, 0xC9, 0x03, 0xA3, 0xB8 - # endif /* __DVP_INCLUDED__ */ - -typedef enum -{ - KS_PixAspectRatio_NTSC4x3, - KS_PixAspectRatio_NTSC16x9, - KS_PixAspectRatio_PAL4x3, - KS_PixAspectRatio_PAL16x9 -}KS_AMPixAspectRatio; - -typedef enum -{ - KS_AMVP_DO_NOT_CARE, - KS_AMVP_BEST_BANDWIDTH, - KS_AMVP_INPUT_SAME_AS_OUTPUT -}KS_AMVP_SELECTFORMATBY; - -typedef enum -{ - KS_AMVP_MODE_WEAVE, - KS_AMVP_MODE_BOBINTERLEAVED, - KS_AMVP_MODE_BOBNONINTERLEAVED, - KS_AMVP_MODE_SKIPEVEN, - KS_AMVP_MODE_SKIPODD -}KS_AMVP_MODE; - -typedef struct tagKS_AMVPDIMINFO -{ - DWORD dwFieldWidth; - DWORD dwFieldHeight; - DWORD dwVBIWidth; - DWORD dwVBIHeight; - RECT rcValidRegion; -}KS_AMVPDIMINFO, * PKS_AMVPDIMINFO; - -typedef struct tagKS_AMVPDATAINFO -{ - DWORD dwSize; - DWORD dwMicrosecondsPerField; - KS_AMVPDIMINFO amvpDimInfo; - DWORD dwPictAspectRatioX; - DWORD dwPictAspectRatioY; - WINBOOL bEnableDoubleClock; - WINBOOL bEnableVACT; - WINBOOL bDataIsInterlaced; - LONG lHalfLinesOdd; - WINBOOL bFieldPolarityInverted; - DWORD dwNumLinesInVREF; - LONG lHalfLinesEven; - DWORD dwReserved1; -}KS_AMVPDATAINFO, * PKS_AMVPDATAINFO; - -typedef struct tagKS_AMVPSIZE -{ - DWORD dwWidth; - DWORD dwHeight; -}KS_AMVPSIZE, * PKS_AMVPSIZE; - -typedef struct -{ - KS_AMVPSIZE Size; - DWORD MaxPixelsPerSecond; - DWORD Reserved; -}KSVPMAXPIXELRATE, * PKSVPMAXPIXELRATE; - -typedef struct -{ - KSPROPERTY Property; - KS_AMVPSIZE Size; -}KSVPSIZE_PROP, * PKSVPSIZE_PROP; - -typedef struct -{ - DWORD dwPitch; - DWORD dwXOrigin; - DWORD dwYOrigin; -}KSVPSURFACEPARAMS, * PKSVPSURFACEPARAMS; - # endif /* __IVPType__ */ - - # define STATIC_KSEVENTSETID_VPNotify \ - 0x20c5598eL, 0xd3c8, 0x11d0, 0x8d, 0xfc, 0x00, 0xc0, 0x4f, 0xd7, 0xc0, 0x8b -DEFINE_GUIDSTRUCT("20c5598e-d3c8-11d0-8dfc-00c04fd7c08b", KSEVENTSETID_VPNotify); - # define KSEVENTSETID_VPNotify DEFINE_GUIDNAMED(KSEVENTSETID_VPNotify) - -typedef enum -{ - KSEVENT_VPNOTIFY_FORMATCHANGE -}KSEVENT_VPNOTIFY; - - # define STATIC_KSEVENTSETID_VIDCAPTOSTI \ - 0xdb47de20, 0xf628, 0x11d1, 0xba, 0x41, 0x0, 0xa0, 0xc9, 0xd, 0x2b, 0x5 -DEFINE_GUIDSTRUCT("DB47DE20-F628-11d1-BA41-00A0C90D2B05", KSEVENTSETID_VIDCAPTOSTI); - # define KSEVENTSETID_VIDCAPNotify DEFINE_GUIDNAMED(KSEVENTSETID_VIDCAPTOSTI) - -typedef enum -{ - KSEVENT_VIDCAPTOSTI_EXT_TRIGGER, - KSEVENT_VIDCAP_AUTO_UPDATE, - KSEVENT_VIDCAP_SEARCH -}KSEVENT_VIDCAPTOSTI; - -typedef enum -{ - KSPROPERTY_EXTENSION_UNIT_INFO, - KSPROPERTY_EXTENSION_UNIT_CONTROL, - KSPROPERTY_EXTENSION_UNIT_PASS_THROUGH = 0xffff -}KSPROPERTY_EXTENSION_UNIT, * PKSPROPERTY_EXTENSION_UNIT; - - # define STATIC_KSEVENTSETID_VPVBINotify \ - 0xec529b01L, 0x1a1f, 0x11d1, 0xba, 0xd9, 0x0, 0x60, 0x97, 0x44, 0x11, 0x1a -DEFINE_GUIDSTRUCT("ec529b01-1a1f-11d1-bad9-00609744111a", KSEVENTSETID_VPVBINotify); - # define KSEVENTSETID_VPVBINotify DEFINE_GUIDNAMED(KSEVENTSETID_VPVBINotify) - -typedef enum -{ - KSEVENT_VPVBINOTIFY_FORMATCHANGE -}KSEVENT_VPVBINOTIFY; - - # define STATIC_KSDATAFORMAT_TYPE_AUXLine21Data \ - 0x670aea80L, 0x3a82, 0x11d0, 0xb7, 0x9b, 0x00, 0xaa, 0x00, 0x37, 0x67, 0xa7 -DEFINE_GUIDSTRUCT("670aea80-3a82-11d0-b79b-00aa003767a7", KSDATAFORMAT_TYPE_AUXLine21Data); - # define KSDATAFORMAT_TYPE_AUXLine21Data DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_AUXLine21Data) - - # define STATIC_KSDATAFORMAT_SUBTYPE_Line21_BytePair \ - 0x6e8d4a22L, 0x310c, 0x11d0, 0xb7, 0x9a, 0x00, 0xaa, 0x00, 0x37, 0x67, 0xa7 -DEFINE_GUIDSTRUCT("6e8d4a22-310c-11d0-b79a-00aa003767a7", KSDATAFORMAT_SUBTYPE_Line21_BytePair); - # define KSDATAFORMAT_SUBTYPE_Line21_BytePair DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_Line21_BytePair) - - # define STATIC_KSDATAFORMAT_SUBTYPE_Line21_GOPPacket \ - 0x6e8d4a23L, 0x310c, 0x11d0, 0xb7, 0x9a, 0x00, 0xaa, 0x00, 0x37, 0x67, 0xa7 -DEFINE_GUIDSTRUCT("6e8d4a23-310c-11d0-b79a-00aa003767a7", KSDATAFORMAT_SUBTYPE_Line21_GOPPacket); - # define KSDATAFORMAT_SUBTYPE_Line21_GOPPacket DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_Line21_GOPPacket) - -typedef struct _KSGOP_USERDATA -{ - ULONG sc; - ULONG reserved1; - BYTE cFields; - CHAR l21Data[3]; -}KSGOP_USERDATA, * PKSGOP_USERDATA; - - # define STATIC_KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK \ - 0xed0b916a, 0x044d, 0x11d1, 0xaa, 0x78, 0x00, 0xc0, 0x4f, 0xc3, 0x1d, 0x60 -DEFINE_GUIDSTRUCT("ed0b916a-044d-11d1-aa78-00c04fc31d60", KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK); - # define KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK) - - # define KS_AM_UseNewCSSKey 0x1 - - # define STATIC_KSPROPSETID_TSRateChange \ - 0xa503c5c0, 0x1d1d, 0x11d1, 0xad, 0x80, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0 -DEFINE_GUIDSTRUCT("A503C5C0-1D1D-11D1-AD80-444553540000", KSPROPSETID_TSRateChange); - # define KSPROPSETID_TSRateChange DEFINE_GUIDNAMED(KSPROPSETID_TSRateChange) - -typedef enum -{ - KS_AM_RATE_SimpleRateChange = 1, - KS_AM_RATE_ExactRateChange = 2, - KS_AM_RATE_MaxFullDataRate = 3, - KS_AM_RATE_Step = 4 -}KS_AM_PROPERTY_TS_RATE_CHANGE; - -typedef struct -{ - REFERENCE_TIME StartTime; - LONG Rate; -}KS_AM_SimpleRateChange, * PKS_AM_SimpleRateChange; - -typedef struct -{ - REFERENCE_TIME OutputZeroTime; - LONG Rate; -}KS_AM_ExactRateChange, * PKS_AM_ExactRateChange; - -typedef LONG KS_AM_MaxFullDataRate; -typedef DWORD KS_AM_Step; - - # define STATIC_KSCATEGORY_ENCODER \ - 0x19689bf6, 0xc384, 0x48fd, 0xad, 0x51, 0x90, 0xe5, 0x8c, 0x79, 0xf7, 0xb -DEFINE_GUIDSTRUCT("19689BF6-C384-48fd-AD51-90E58C79F70B", KSCATEGORY_ENCODER); - # define KSCATEGORY_ENCODER DEFINE_GUIDNAMED(KSCATEGORY_ENCODER) - - # define STATIC_KSCATEGORY_MULTIPLEXER \ - 0x7a5de1d3, 0x1a1, 0x452c, 0xb4, 0x81, 0x4f, 0xa2, 0xb9, 0x62, 0x71, 0xe8 -DEFINE_GUIDSTRUCT("7A5DE1D3-01A1-452c-B481-4FA2B96271E8", KSCATEGORY_MULTIPLEXER); - # define KSCATEGORY_MULTIPLEXER DEFINE_GUIDNAMED(KSCATEGORY_MULTIPLEXER) - - # ifndef __ENCODER_API_GUIDS__ - # define __ENCODER_API_GUIDS__ - - # define STATIC_ENCAPIPARAM_BITRATE \ - 0x49cc4c43, 0xca83, 0x4ad4, 0xa9, 0xaf, 0xf3, 0x69, 0x6a, 0xf6, 0x66, 0xdf -DEFINE_GUIDSTRUCT("49CC4C43-CA83-4ad4-A9AF-F3696AF666DF", ENCAPIPARAM_BITRATE); - # define ENCAPIPARAM_BITRATE DEFINE_GUIDNAMED(ENCAPIPARAM_BITRATE) - - # define STATIC_ENCAPIPARAM_PEAK_BITRATE \ - 0x703f16a9, 0x3d48, 0x44a1, 0xb0, 0x77, 0x1, 0x8d, 0xff, 0x91, 0x5d, 0x19 -DEFINE_GUIDSTRUCT("703F16A9-3D48-44a1-B077-018DFF915D19", ENCAPIPARAM_PEAK_BITRATE); - # define ENCAPIPARAM_PEAK_BITRATE DEFINE_GUIDNAMED(ENCAPIPARAM_PEAK_BITRATE) - - # define STATIC_ENCAPIPARAM_BITRATE_MODE \ - 0xee5fb25c, 0xc713, 0x40d1, 0x9d, 0x58, 0xc0, 0xd7, 0x24, 0x1e, 0x25, 0xf -DEFINE_GUIDSTRUCT("EE5FB25C-C713-40d1-9D58-C0D7241E250F", ENCAPIPARAM_BITRATE_MODE); - # define ENCAPIPARAM_BITRATE_MODE DEFINE_GUIDNAMED(ENCAPIPARAM_BITRATE_MODE) - - # define STATIC_CODECAPI_CHANGELISTS \ - 0x62b12acf, 0xf6b0, 0x47d9, 0x94, 0x56, 0x96, 0xf2, 0x2c, 0x4e, 0x0b, 0x9d -DEFINE_GUIDSTRUCT("62B12ACF-F6B0-47D9-9456-96F22C4E0B9D", CODECAPI_CHANGELISTS); - # define CODECAPI_CHANGELISTS DEFINE_GUIDNAMED(CODECAPI_CHANGELISTS) - - # define STATIC_CODECAPI_VIDEO_ENCODER \ - 0x7112e8e1, 0x3d03, 0x47ef, 0x8e, 0x60, 0x03, 0xf1, 0xcf, 0x53, 0x73, 0x01 -DEFINE_GUIDSTRUCT("7112E8E1-3D03-47EF-8E60-03F1CF537301", CODECAPI_VIDEO_ENCODER); - # define CODECAPI_VIDEO_ENCODER DEFINE_GUIDNAMED(CODECAPI_VIDEO_ENCODER) - - # define STATIC_CODECAPI_AUDIO_ENCODER \ - 0xb9d19a3e, 0xf897, 0x429c, 0xbc, 0x46, 0x81, 0x38, 0xb7, 0x27, 0x2b, 0x2d -DEFINE_GUIDSTRUCT("B9D19A3E-F897-429C-BC46-8138B7272B2D", CODECAPI_AUDIO_ENCODER); - # define CODECAPI_AUDIO_ENCODER DEFINE_GUIDNAMED(CODECAPI_AUDIO_ENCODER) - - # define STATIC_CODECAPI_SETALLDEFAULTS \ - 0x6c5e6a7c, 0xacf8, 0x4f55, 0xa9, 0x99, 0x1a, 0x62, 0x81, 0x09, 0x05, 0x1b -DEFINE_GUIDSTRUCT("6C5E6A7C-ACF8-4F55-A999-1A628109051B", CODECAPI_SETALLDEFAULTS); - # define CODECAPI_SETALLDEFAULTS DEFINE_GUIDNAMED(CODECAPI_SETALLDEFAULTS) - - # define STATIC_CODECAPI_ALLSETTINGS \ - 0x6a577e92, 0x83e1, 0x4113, 0xad, 0xc2, 0x4f, 0xce, 0xc3, 0x2f, 0x83, 0xa1 -DEFINE_GUIDSTRUCT("6A577E92-83E1-4113-ADC2-4FCEC32F83A1", CODECAPI_ALLSETTINGS); - # define CODECAPI_ALLSETTINGS DEFINE_GUIDNAMED(CODECAPI_ALLSETTINGS) - - # define STATIC_CODECAPI_SUPPORTSEVENTS \ - 0x0581af97, 0x7693, 0x4dbd, 0x9d, 0xca, 0x3f, 0x9e, 0xbd, 0x65, 0x85, 0xa1 -DEFINE_GUIDSTRUCT("0581AF97-7693-4DBD-9DCA-3F9EBD6585A1", CODECAPI_SUPPORTSEVENTS); - # define CODECAPI_SUPPORTSEVENTS DEFINE_GUIDNAMED(CODECAPI_SUPPORTSEVENTS) - - # define STATIC_CODECAPI_CURRENTCHANGELIST \ - 0x1cb14e83, 0x7d72, 0x4657, 0x83, 0xfd, 0x47, 0xa2, 0xc5, 0xb9, 0xd1, 0x3d -DEFINE_GUIDSTRUCT("1CB14E83-7D72-4657-83FD-47A2C5B9D13D", CODECAPI_CURRENTCHANGELIST); - # define CODECAPI_CURRENTCHANGELIST DEFINE_GUIDNAMED(CODECAPI_CURRENTCHANGELIST) - # endif /* __ENCODER_API_GUIDS__ */ - - # ifndef __ENCODER_API_DEFINES__ - # define __ENCODER_API_DEFINES__ -typedef enum -{ - ConstantBitRate = 0, - VariableBitRateAverage, - VariableBitRatePeak -}VIDEOENCODER_BITRATE_MODE; - # endif /* __ENCODER_API_DEFINES__ */ - - # define STATIC_KSPROPSETID_Jack \ - 0x4509f757, 0x2d46, 0x4637, 0x8e, 0x62, 0xce, 0x7d, 0xb9, 0x44, 0xf5, 0x7b -DEFINE_GUIDSTRUCT("4509F757-2D46-4637-8E62-CE7DB944F57B", KSPROPSETID_Jack); - # define KSPROPSETID_Jack DEFINE_GUIDNAMED(KSPROPSETID_Jack) - -typedef enum -{ - KSPROPERTY_JACK_DESCRIPTION = 1, - KSPROPERTY_JACK_DESCRIPTION2, - KSPROPERTY_JACK_SINK_INFO -}KSPROPERTY_JACK; - -typedef enum -{ - eConnTypeUnknown, - eConnType3Point5mm, - eConnTypeQuarter, - eConnTypeAtapiInternal, - eConnTypeRCA, - eConnTypeOptical, - eConnTypeOtherDigital, - eConnTypeOtherAnalog, - eConnTypeMultichannelAnalogDIN, - eConnTypeXlrProfessional, - eConnTypeRJ11Modem, - eConnTypeCombination -}EPcxConnectionType; - -typedef enum -{ - eGeoLocRear = 0x1, - eGeoLocFront, - eGeoLocLeft, - eGeoLocRight, - eGeoLocTop, - eGeoLocBottom, - eGeoLocRearPanel, - eGeoLocRiser, - eGeoLocInsideMobileLid, - eGeoLocDrivebay, - eGeoLocHDMI, - eGeoLocOutsideMobileLid, - eGeoLocATAPI, - eGeoLocReserved5, - eGeoLocReserved6, - EPcxGeoLocation_enum_count -}EPcxGeoLocation; - -typedef enum -{ - eGenLocPrimaryBox = 0, - eGenLocInternal, - eGenLocSeparate, - eGenLocOther, - EPcxGenLocation_enum_count -}EPcxGenLocation; - -typedef enum -{ - ePortConnJack = 0, - ePortConnIntegratedDevice, - ePortConnBothIntegratedAndJack, - ePortConnUnknown -}EPxcPortConnection; - -typedef struct -{ - DWORD ChannelMapping; - COLORREF Color; - EPcxConnectionType ConnectionType; - EPcxGeoLocation GeoLocation; - EPcxGenLocation GenLocation; - EPxcPortConnection PortConnection; - BOOL IsConnected; -}KSJACK_DESCRIPTION, * PKSJACK_DESCRIPTION; - -typedef enum -{ - KSJACK_SINK_CONNECTIONTYPE_HDMI = 0, - KSJACK_SINK_CONNECTIONTYPE_DISPLAYPORT, -}KSJACK_SINK_CONNECTIONTYPE; - - # define MAX_SINK_DESCRIPTION_NAME_LENGTH 32 -typedef struct _tagKSJACK_SINK_INFORMATION -{ - KSJACK_SINK_CONNECTIONTYPE ConnType; - WORD ManufacturerId; - WORD ProductId; - WORD AudioLatency; - BOOL HDCPCapable; - BOOL AICapable; - UCHAR SinkDescriptionLength; - WCHAR SinkDescription[MAX_SINK_DESCRIPTION_NAME_LENGTH]; - LUID PortId; -}KSJACK_SINK_INFORMATION, * PKSJACK_SINK_INFORMATION; - - # define JACKDESC2_PRESENCE_DETECT_CAPABILITY 0x00000001 - # define JACKDESC2_DYNAMIC_FORMAT_CHANGE_CAPABILITY 0x00000002 - -typedef struct _tagKSJACK_DESCRIPTION2 -{ - DWORD DeviceStateInfo; - DWORD JackCapabilities; -}KSJACK_DESCRIPTION2, * PKSJACK_DESCRIPTION2; - -#endif /* _KSMEDIA_ */ - From 745fbe3fa6aa313b4e9d40cce465e57d07111afc Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Sun, 30 Mar 2014 13:04:40 -0400 Subject: [PATCH 003/388] Removed another reference to kernel streaming support in readme. --- readme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme b/readme index 4d56ed58..545ffc61 100644 --- a/readme +++ b/readme @@ -13,7 +13,7 @@ If you checked out the code from git, please run "autoconf" before "./configure" 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, Kernel Streming) 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 (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: - object oriented C++ design - simple, common API across all supported platforms From 774c66488cf9e2a1de119feb72529a0b144f4d08 Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Sun, 30 Mar 2014 13:09:19 -0400 Subject: [PATCH 004/388] Removed reference to WINKS in midiprobe.cpp --- tests/midiprobe.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/midiprobe.cpp b/tests/midiprobe.cpp index 6576e152..d9611edd 100644 --- a/tests/midiprobe.cpp +++ b/tests/midiprobe.cpp @@ -15,7 +15,6 @@ int main() 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"; From 7a3f04cd2c6461a9efc25dc064201806679d31a2 Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Mon, 31 Mar 2014 11:05:38 -0400 Subject: [PATCH 005/388] Corrected documentation regarding API default order in RtMidi.h --- RtMidi.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index 61418350..9a878884 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -219,8 +219,8 @@ class RtMidiIn : public RtMidi 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 JACK, - CORE (OS-X). + 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 @@ -354,8 +354,8 @@ class RtMidiOut : public RtMidi 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 JACK, - CORE (OS-X). + 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") ); From e746e6cb8ac81cf0a82daa5c33261e52b1964883 Mon Sep 17 00:00:00 2001 From: Sebastien Alaiwan Date: Sun, 6 Apr 2014 22:58:03 +0200 Subject: [PATCH 006/388] Allow out-of-tree builds. --- Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index 82ad7ad7..9eec40b6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -4,7 +4,7 @@ RM = /bin/rm LN = /bin/ln -OBJECTS = RtMidi.o +OBJECTS = @top_srcdir@/RtMidi.o LIBNAME = librtmidi STATIC = $(LIBNAME).a From 954986eb79f6aaac71ff67f3c1eb2dda66997822 Mon Sep 17 00:00:00 2001 From: Sebastien Alaiwan Date: Tue, 8 Apr 2014 20:40:27 +0200 Subject: [PATCH 007/388] Allow out-of-tree builds for 'tests' directory also --- tests/Makefile.in | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/Makefile.in b/tests/Makefile.in index 1826737e..42cb354e 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -4,11 +4,11 @@ PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest RM = /bin/rm SRC_PATH = .. -INCLUDE = .. +INCLUDE = @top_srcdir@ OBJECT_PATH = @object_path@ vpath %.o $(OBJECT_PATH) -OBJECTS = RtMidi.o +OBJECTS = @top_srcdir@/RtMidi.o CC = @CXX@ DEFS = @CPPFLAGS@ @@ -21,20 +21,20 @@ LIBRARY = @LIBS@ all : $(PROGRAMS) -midiprobe : midiprobe.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o midiprobe midiprobe.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) +midiprobe : @srcdir@/midiprobe.cpp $(OBJECTS) + $(CC) $(CFLAGS) $(DEFS) -o midiprobe $^ $(LIBRARY) -midiout : midiout.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o midiout midiout.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) +midiout : @srcdir@/midiout.cpp $(OBJECTS) + $(CC) $(CFLAGS) $(DEFS) -o midiout $^ $(LIBRARY) -qmidiin : qmidiin.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o qmidiin qmidiin.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) +qmidiin : @srcdir@/qmidiin.cpp $(OBJECTS) + $(CC) $(CFLAGS) $(DEFS) -o qmidiin $^ $(LIBRARY) -cmidiin : cmidiin.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o cmidiin cmidiin.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) +cmidiin : @srcdir@/cmidiin.cpp $(OBJECTS) + $(CC) $(CFLAGS) $(DEFS) -o cmidiin $^ $(LIBRARY) -sysextest : sysextest.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o sysextest sysextest.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) +sysextest : @srcdir@/sysextest.cpp $(OBJECTS) + $(CC) $(CFLAGS) $(DEFS) -o sysextest $^ $(LIBRARY) clean : $(RM) -f $(OBJECT_PATH)/*.o From c72f7fc50c59145a378412c592969845d02bc908 Mon Sep 17 00:00:00 2001 From: Sebastien Alaiwan Date: Fri, 11 Apr 2014 20:06:14 +0200 Subject: [PATCH 008/388] Add Makefile.am. Remove some generated files from repository --- .gitignore | 5 + Makefile.am | 3 + Makefile.in | 77 --- config/config.guess | 1371 ------------------------------------------- config/config.sub | 1362 ------------------------------------------ config/install.sh | 0 configure.ac | 2 + 7 files changed, 10 insertions(+), 2810 deletions(-) create mode 100644 .gitignore create mode 100644 Makefile.am delete mode 100644 Makefile.in delete mode 100755 config/config.guess delete mode 100755 config/config.sub delete mode 100755 config/install.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..80d8cedd --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/config +/Makefile.in +/aclocal.m4 +/autom4te.cache +/configure diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..299f0c09 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,3 @@ +noinst_LIBRARIES = %D%/librtmidi.a +librtmidi_a_SOURCES = %D%/RtMidi.cpp \ + %D%/RtMidi.h diff --git a/Makefile.in b/Makefile.in deleted file mode 100644 index 9eec40b6..00000000 --- a/Makefile.in +++ /dev/null @@ -1,77 +0,0 @@ -### Do not edit -- Generated by 'configure --with-whatever' from Makefile.in -### RtMidi library Makefile - -RM = /bin/rm -LN = /bin/ln - -OBJECTS = @top_srcdir@/RtMidi.o - -LIBNAME = librtmidi -STATIC = $(LIBNAME).a -SHARED = @sharedlib@ -RELEASE = 2.1.0 -MAJOR = 2 -LIBRARIES = $(STATIC) $(SHARED) - -CC = @CXX@ -AR = @AR@ -RANLIB = @RANLIB@ - -DEFS = @CPPFLAGS@ -CFLAGS = @CXXFLAGS@ -Iinclude -fPIC - -PREFIX = @prefix@ - -all : $(LIBRARIES) - -tests: - cd tests && $(MAKE) all - -$(LIBRARIES): $(OBJECTS) - $(AR) ruv $(STATIC) $(OBJECTS) - ranlib $(STATIC) - $(CC) -fPIC @libflags@ $(OBJECTS) @LIBS@ - $(LN) -sf @sharedname@ $(SHARED) - $(LN) -sf @sharedname@ $(SHARED).$(MAJOR) - -# $(CC) -shared $(OBJECTS) -o $(SHARED) @LIBS@ - -%.o : %.cpp - $(CC) $(CFLAGS) $(DEFS) -c $(<) -o $@ - -%.o : include/%.cpp - $(CC) $(CFLAGS) $(DEFS) -c $(<) -o $@ - -install: all - install --mode=755 $(STATIC) $(PREFIX)/lib/ - install --mode=755 @sharedname@ $(PREFIX)/lib/ - $(LN) -sf @sharedname@ $(PREFIX)/lib/$(SHARED) - $(LN) -sf @sharedname@ $(PREFIX)/lib/$(SHARED).$(MAJOR) - install --mode=644 $(LIBNAME).pc $(PREFIX)/lib/pkgconfig - install --mode=755 rtmidi-config $(PREFIX)/bin/ - install --mode=644 RtMidi.h RtError.h $(PREFIX)/include - -uninstall: - -@rm -vf $(patsubst %,$(PREFIX)/lib/%, $(LIBRARIES) $(SHARED).$(MAJOR) $(SHARED).$(RELEASE)) - -@rm -vf $(PREFIX)/lib/pkgconfig/$(LIBNAME).pc - -@rm -vf $(PREFIX)/bin/rtmidi-config - -clean : - $(RM) -f $(LIBRARIES) @sharedname@ $(SHARED)* - $(RM) -f $(OBJECTS) - $(RM) -f *~ - cd tests && $(MAKE) clean - -distclean: - $(RM) -f $(LIBRARIES) @sharedname@ $(SHARED)* - $(RM) -f $(OBJECTS) - $(RM) -f *~ - $(RM) -rf config.log config.status autom4te.cache Makefile rtmidi-config $(LIBNAME).pc - cd tests && $(MAKE) distclean - -strip : - strip $(LIBRARIES) - ranlib $(LIBRARIES) - cd tests && $(MAKE) strip - -.PHONY: strip distclean clean uninstall diff --git a/config/config.guess b/config/config.guess deleted file mode 100755 index 313be34b..00000000 --- a/config/config.guess +++ /dev/null @@ -1,1371 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. - -timestamp='2004-02-26' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Written by Per Bothner . -# Please send patches to . -# -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. -# -# The plan is that this can be called by configure scripts if you -# don't specify an explicit build system type. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 99, 2000 -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." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; - --version | -v ) - echo "$version" ; exit 0 ;; - --help | --h* | -h ) - echo "$usage"; exit 0 ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - - -dummy=dummy-$$ -trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int dummy(){}" > $dummy.c - for c in cc gcc c89 ; do - ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 - if test $? = 0 ; then - CC_FOR_BUILD="$c"; break - fi - done - rm -f $dummy.c $dummy.o $dummy.rel - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 8/24/94.) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # Netbsd (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # Determine the machine/vendor (is the vendor relevant). - case "${UNAME_MACHINE}" in - amiga) machine=m68k-unknown ;; - arm32) machine=arm-unknown ;; - atari*) machine=m68k-atari ;; - sun3*) machine=m68k-sun ;; - mac68k) machine=m68k-apple ;; - macppc) machine=powerpc-apple ;; - hp3[0-9][05]) machine=m68k-hp ;; - ibmrt|romp-ibm) machine=romp-ibm ;; - *) machine=${UNAME_MACHINE}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE}" in - i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k) - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit 0 ;; - alpha:OSF1:*:*) - if test $UNAME_RELEASE = "V4.0"; then - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - fi - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - cat <$dummy.s - .data -\$Lformat: - .byte 37,100,45,37,120,10,0 # "%d-%x\n" - - .text - .globl main - .align 4 - .ent main -main: - .frame \$30,16,\$26,0 - ldgp \$29,0(\$27) - .prologue 1 - .long 0x47e03d80 # implver \$0 - lda \$2,-1 - .long 0x47e20c21 # amask \$2,\$1 - lda \$16,\$Lformat - mov \$0,\$17 - not \$1,\$18 - jsr \$26,printf - ldgp \$29,0(\$26) - mov 0,\$16 - jsr \$26,exit - .end main -EOF - $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null - if test "$?" = 0 ; then - case `./$dummy` in - 0-0) - UNAME_MACHINE="alpha" - ;; - 1-0) - UNAME_MACHINE="alphaev5" - ;; - 1-1) - UNAME_MACHINE="alphaev56" - ;; - 1-101) - UNAME_MACHINE="alphapca56" - ;; - 2-303) - UNAME_MACHINE="alphaev6" - ;; - 2-307) - UNAME_MACHINE="alphaev67" - ;; - esac - fi - rm -f $dummy.s $dummy - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit 0 ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit 0 ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit 0 ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit 0;; - amiga:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit 0 ;; - arc64:OpenBSD:*:*) - echo mips64el-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - arc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - hkmips:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - pmax:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sgi:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - wgrisc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit 0 ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit 0;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit 0;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit 0 ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit 0 ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - i86pc:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit 0 ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit 0 ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit 0 ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit 0 ;; - atari*:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit 0 ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit 0 ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit 0 ;; - sun3*:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mac68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme88k:OpenBSD:*:*) - echo m88k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit 0 ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit 0 ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit 0 ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit 0 ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit 0 ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD $dummy.c -o $dummy \ - && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo mips-mips-riscos${UNAME_RELEASE} - exit 0 ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit 0 ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit 0 ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit 0 ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit 0 ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit 0 ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit 0 ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit 0 ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit 0 ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit 0 ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit 0 ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit 0 ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit 0 ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit 0 ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo rs6000-ibm-aix3.2.5 - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit 0 ;; - *:AIX:*:[45]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit 0 ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit 0 ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit 0 ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit 0 ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit 0 ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit 0 ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit 0 ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit 0 ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - case "${HPUX_REV}" in - 11.[0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - esac ;; - esac - fi ;; - esac - if [ "${HP_ARCH}" = "" ]; then - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` - if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi - rm -f $dummy.c $dummy - fi ;; - esac - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit 0 ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit 0 ;; - 3050*:HI-UX:*:*) - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo unknown-hitachi-hiuxwe2 - exit 0 ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit 0 ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit 0 ;; - *9??*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit 0 ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit 0 ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit 0 ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit 0 ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit 0 ;; - hppa*:OpenBSD:*:*) - echo hppa-unknown-openbsd - exit 0 ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit 0 ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit 0 ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit 0 ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit 0 ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit 0 ;; - CRAY*X-MP:*:*:*) - echo xmp-cray-unicos - exit 0 ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} - exit 0 ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ - exit 0 ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*T3D:*:*:*) - echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY-2:*:*:*) - echo cray2-cray-unicos - exit 0 ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit 0 ;; - hp300:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit 0 ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; - *:FreeBSD:*:*) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit 0 ;; - *:OpenBSD:*:*) - echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - exit 0 ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit 0 ;; - i*:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit 0 ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit 0 ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i386-pc-interix - exit 0 ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit 0 ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit 0 ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - *:GNU:*:*) - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit 0 ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit 0 ;; - arm*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux - exit 0 ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - mips:Linux:*:*) - cat >$dummy.c < /* for printf() prototype */ -int main (int argc, char *argv[]) { -#else -int main (argc, argv) int argc; char *argv[]; { -#endif -#ifdef __MIPSEB__ - printf ("%s-unknown-linux-gnu\n", argv[1]); -#endif -#ifdef __MIPSEL__ - printf ("%sel-unknown-linux-gnu\n", argv[1]); -#endif - return 0; -} -EOF - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - ;; - ppc:Linux:*:*) - # Determine Lib Version - cat >$dummy.c < -#if defined(__GLIBC__) -extern char __libc_version[]; -extern char __libc_release[]; -#endif -main(argc, argv) - int argc; - char *argv[]; -{ -#if defined(__GLIBC__) - printf("%s %s\n", __libc_version, __libc_release); -#else - printf("unknown\n"); -#endif - return 0; -} -EOF - LIBC="" - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null - if test "$?" = 0 ; then - ./$dummy | grep 1\.99 > /dev/null - if test "$?" = 0 ; then LIBC="libc1" ; fi - fi - rm -f $dummy.c $dummy - echo powerpc-unknown-linux-gnu${LIBC} - exit 0 ;; - alpha:Linux:*:*) - cat <$dummy.s - .data - \$Lformat: - .byte 37,100,45,37,120,10,0 # "%d-%x\n" - .text - .globl main - .align 4 - .ent main - main: - .frame \$30,16,\$26,0 - ldgp \$29,0(\$27) - .prologue 1 - .long 0x47e03d80 # implver \$0 - lda \$2,-1 - .long 0x47e20c21 # amask \$2,\$1 - lda \$16,\$Lformat - mov \$0,\$17 - not \$1,\$18 - jsr \$26,printf - ldgp \$29,0(\$26) - mov 0,\$16 - jsr \$26,exit - .end main -EOF - LIBC="" - $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null - if test "$?" = 0 ; then - case `./$dummy` in - 0-0) UNAME_MACHINE="alpha" ;; - 1-0) UNAME_MACHINE="alphaev5" ;; - 1-1) UNAME_MACHINE="alphaev56" ;; - 1-101) UNAME_MACHINE="alphapca56" ;; - 2-303) UNAME_MACHINE="alphaev6" ;; - 2-307) UNAME_MACHINE="alphaev67" ;; - esac - objdump --private-headers $dummy | \ - grep ld.so.1 > /dev/null - if test "$?" = 0 ; then - LIBC="libc1" - fi - fi - rm -f $dummy.s $dummy - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit 0 ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; - esac - exit 0 ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit 0 ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux - exit 0 ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu - exit 0 ;; - i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - ld_supported_emulations=`cd /; ld --help 2>&1 \ - | sed -ne '/supported emulations:/!d - s/[ ][ ]*/ /g - s/.*supported emulations: *// - s/ .*// - p'` - case "$ld_supported_emulations" in - i*86linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit 0 - ;; - elf_i*86) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - i*86coff) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit 0 - ;; - esac - # Either a pre-BFD a.out linker (linux-gnuoldld) - # or one that does not give us useful --help. - # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. - # If ld does not provide *any* "supported emulations:" - # that means it is gnuoldld. - test -z "$ld_supported_emulations" && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 - case "${UNAME_MACHINE}" in - i*86) - VENDOR=pc; - ;; - *) - VENDOR=unknown; - ;; - esac - # Determine whether the default compiler is a.out or elf - cat >$dummy.c < -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif -#ifdef __ELF__ -# ifdef __GLIBC__ -# if __GLIBC__ >= 2 - printf ("%s-${VENDOR}-linux-gnu\n", argv[1]); -# else - printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); -# endif -# else - printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); -# endif -#else - printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]); -#endif - return 0; -} -EOF - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 - ;; -# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions -# are messed up and put the nodename in both sysname and nodename. - i*86:DYNIX/ptx:4*:*) - echo i386-sequent-sysv4 - exit 0 ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit 0 ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit 0 ;; - i*86:*:5:7*) - # Fixed at (any) Pentium or better - UNAME_MACHINE=i586 - if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then - echo ${UNAME_MACHINE}-sco-sysv${UNAME_RELEASE}uw${UNAME_VERSION} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} - fi - exit 0 ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` - (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit 0 ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit 0 ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit 0 ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit 0 ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit 0 ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit 0 ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit 0 ;; - M68*:*:R3V[567]*:*) - test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; - 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4.3${OS_REL} && exit 0 - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4 && exit 0 ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit 0 ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit 0 ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit 0 ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit 0 ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit 0 ;; - PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit 0 ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit 0 ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit 0 ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit 0 ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit 0 ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit 0 ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit 0 ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit 0 ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit 0 ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit 0 ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit 0 ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; - *:Darwin:*:*) - echo `uname -p`-apple-darwin${UNAME_RELEASE} - exit 0 ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - if test "${UNAME_MACHINE}" = "x86pc"; then - UNAME_MACHINE=pc - fi - echo `uname -p`-${UNAME_MACHINE}-nto-qnx - exit 0 ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit 0 ;; - NSR-[KW]:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit 0 ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit 0 ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit 0 ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit 0 ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit 0 ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit 0 ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit 0 ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit 0 ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit 0 ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit 0 ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit 0 ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit 0 ;; -esac - -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 -rm -f $dummy.c $dummy - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit 0 ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit 0 ;; - c34*) - echo c34-convex-bsd - exit 0 ;; - c38*) - echo c38-convex-bsd - exit 0 ;; - c4*) - echo c4-convex-bsd - exit 0 ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/config/config.sub b/config/config.sub deleted file mode 100755 index 7d3f49f0..00000000 --- a/config/config.sub +++ /dev/null @@ -1,1362 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. - -timestamp='2004-02-26' - -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Please send patches to . -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -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." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; - --version | -v ) - echo "$version" ; exit 0 ;; - --help | --h* | -h ) - echo "$usage"; exit 0 ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit 0;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | storm-chaos* | os2-emx*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis) - os= - basic_machine=$1 - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc \ - | arm | arme[lb] | arm[bl]e | armv[2345] | armv[345][lb] | strongarm | xscale \ - | pyramid | mn10200 | mn10300 | tron | a29k \ - | 580 | i960 | h8300 \ - | x86 | ppcbe | mipsbe | mipsle | shbe | shle \ - | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \ - | hppa64 \ - | alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \ - | alphaev6[78] \ - | we32k | ns16k | clipper | i370 | sh | sh[34] \ - | powerpc | powerpcle \ - | 1750a | dsp16xx | pdp10 | pdp11 \ - | mips16 | mips64 | mipsel | mips64el \ - | mips64orion | mips64orionel | mipstx39 | mipstx39el \ - | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ - | mips64vr5000 | miprs64vr5000el | mcore | s390 | s390x \ - | sparc | sparclet | sparclite | sparc64 | sparcv9 | sparcv9b \ - | v850 | c4x \ - | thumb | d10v | d30v | fr30 | avr | openrisc | tic80 \ - | pj | pjl | h8500) - basic_machine=$basic_machine-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | w65) - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - # FIXME: clean up the formatting here. - vax-* | tahoe-* | i*86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \ - | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* \ - | arm-* | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \ - | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ - | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \ - | xmp-* | ymp-* \ - | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* \ - | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \ - | hppa2.0n-* | hppa64-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \ - | alphaev6[78]-* \ - | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ - | clipper-* | orion-* \ - | sparclite-* | pdp10-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ - | sparc64-* | sparcv9-* | sparcv9b-* | sparc86x-* \ - | mips16-* | mips64-* | mipsel-* \ - | mips64el-* | mips64orion-* | mips64orionel-* \ - | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \ - | mipstx39-* | mipstx39el-* | mcore-* \ - | f30[01]-* | f700-* | s390-* | s390x-* | sv1-* | t3e-* \ - | [cjt]90-* \ - | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ - | thumb-* | v850-* | d30v-* | tic30-* | tic80-* | c30-* | fr30-* \ - | bs2000-* | tic54x-* | c54x-* | x86_64-* | pj-* | pjl-*) - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | ymp) - basic_machine=ymp-cray - os=-unicos - ;; - cray2) - basic_machine=cray2-cray - os=-unicos - ;; - [cjt]90) - basic_machine=${basic_machine}-cray - os=-unicos - ;; - crds | unos) - basic_machine=m68k-crds - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mipsel*-linux*) - basic_machine=mipsel-unknown - os=-linux-gnu - ;; - mips*-linux*) - basic_machine=mips-unknown - os=-linux-gnu - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - mmix*) - basic_machine=mmix-knuth - os=-mmixware - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pentium | p5 | k5 | k6 | nexgen) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon) - basic_machine=i686-pc - ;; - pentiumii | pentium2) - basic_machine=i686-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc) basic_machine=powerpc-unknown - ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sparclite-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=t3e-cray - os=-unicos - ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xmp) - basic_machine=xmp-cray - os=-unicos - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - mips) - if [ x$os = x-linux-gnu ]; then - basic_machine=mips-unknown - else - basic_machine=mips-mips - fi - ;; - romp) - basic_machine=romp-ibm - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh3 | sh4) - basic_machine=sh-unknown - ;; - sparc | sparcv9 | sparcv9b) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - c4x*) - basic_machine=c4x-none - os=-coff - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ - | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto*) - os=-nto-qnx - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 - ;; - m68*-cisco) - os=-aout - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-ibm) - os=-aix - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -vxsim* | -vxworks*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit 0 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/config/install.sh b/config/install.sh deleted file mode 100755 index e69de29b..00000000 diff --git a/configure.ac b/configure.ac index f4f497aa..b5484136 100644 --- a/configure.ac +++ b/configure.ac @@ -3,12 +3,14 @@ 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]) +AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) # Fill GXX with something before test. AC_SUBST( GXX, ["no"] ) # Checks for programs. AC_PROG_CXX(g++ CC c++ cxx) +AM_PROG_AR AC_PROG_RANLIB AC_PATH_PROG(AR, ar, no) if [[ $AR = "no" ]] ; then From 8b5fe7703c9074ec3b957d6e32ad5267afe233e4 Mon Sep 17 00:00:00 2001 From: Sebastien Alaiwan Date: Fri, 11 Apr 2014 20:45:06 +0200 Subject: [PATCH 009/388] rtmidi can now easily be nested into another project --- Makefile.am | 7 ++++--- configure.ac | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 299f0c09..4fd5c9ac 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,4 @@ -noinst_LIBRARIES = %D%/librtmidi.a -librtmidi_a_SOURCES = %D%/RtMidi.cpp \ - %D%/RtMidi.h +noinst_LIBRARIES += %D%/librtmidi.a +%C%_librtmidi_a_SOURCES = \ + %D%/RtMidi.cpp \ + %D%/RtMidi.h diff --git a/configure.ac b/configure.ac index b5484136..413ed784 100644 --- a/configure.ac +++ b/configure.ac @@ -7,6 +7,7 @@ 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) From 98d6f925f907f8eb1d79a74a9fac297429f8a43f Mon Sep 17 00:00:00 2001 From: Sebastien Alaiwan Date: Wed, 16 Apr 2014 07:47:30 +0200 Subject: [PATCH 010/388] Add libtool support (allows ./configure --enable-shared and --enable-static) --- .gitignore | 2 ++ Makefile.am | 5 +++-- configure.ac | 4 +++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 80d8cedd..9f747efb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ /config +/configure /Makefile.in /aclocal.m4 /autom4te.cache /configure +/m4 diff --git a/Makefile.am b/Makefile.am index 4fd5c9ac..4851619d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,5 @@ -noinst_LIBRARIES += %D%/librtmidi.a -%C%_librtmidi_a_SOURCES = \ +lib_LTLIBRARIES = %D%/librtmidi.la +%C%_librtmidi_la_LDFLAGS = -no-undefined +%C%_librtmidi_la_SOURCES = \ %D%/RtMidi.cpp \ %D%/RtMidi.h diff --git a/configure.ac b/configure.ac index 413ed784..138a7fdc 100644 --- a/configure.ac +++ b/configure.ac @@ -12,12 +12,14 @@ AC_SUBST(noinst_LIBRARIES) # Checks for programs. AC_PROG_CXX(g++ CC c++ cxx) AM_PROG_AR -AC_PROG_RANLIB 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) From e8c88bc60b6223679fcc0a9a05094a7d809b5e1b Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 26 Mar 2014 20:30:35 +0100 Subject: [PATCH 011/388] 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 012/388] 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 013/388] 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 014/388] 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 015/388] 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 016/388] 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 017/388] 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 018/388] 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 2c7a6664d69ed39d9d1d4312231c064e9b1549dd Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Fri, 6 Jun 2014 15:57:16 -0400 Subject: [PATCH 019/388] Memory leak fix in CoreMidi and addition of UserData pointer to error callback. --- RtMidi.cpp | 15 ++++++++++----- RtMidi.h | 15 ++++++++------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 07e23168..a44e4b0c 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -224,7 +224,7 @@ RtMidiOut :: ~RtMidiOut() throw() //*********************************************************************// MidiApi :: MidiApi( void ) - : apiData_( 0 ), connected_( false ), errorCallback_(0) + : apiData_( 0 ), connected_( false ), errorCallback_(0), errorCallbackUserData_(0) { } @@ -232,9 +232,10 @@ MidiApi :: ~MidiApi( void ) { } -void MidiApi :: setErrorCallback( RtMidiErrorCallback errorCallback ) +void MidiApi :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData = 0 ) { errorCallback_ = errorCallback; + errorCallbackUserData_ = userData; } void MidiApi :: error( RtMidiError::Type type, std::string errorString ) @@ -248,7 +249,7 @@ void MidiApi :: error( RtMidiError::Type type, std::string errorString ) firstErrorOccured = true; const std::string errorMessage = errorString; - errorCallback_( type, errorMessage ); + errorCallback_( type, errorMessage, errorCallbackUserData_); firstErrorOccured = false; return; } @@ -567,7 +568,8 @@ 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 ); + CFStringRef name = CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ); + OSStatus result = MIDIClientCreate(name, NULL, NULL, &client ); if ( result != noErr ) { errorString_ = "MidiInCore::initialize: error creating OS-X MIDI client object."; error( RtMidiError::DRIVER_ERROR, errorString_ ); @@ -580,6 +582,7 @@ void MidiInCore :: initialize( const std::string& clientName ) data->endpoint = 0; apiData_ = (void *) data; inputData_.apiData = (void *) data; + CFRelease(name); } void MidiInCore :: openPort( unsigned int portNumber, const std::string portName ) @@ -852,7 +855,8 @@ 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 ); + CFStringRef name = CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ); + OSStatus result = MIDIClientCreate(name, NULL, NULL, &client ); if ( result != noErr ) { errorString_ = "MidiOutCore::initialize: error creating OS-X MIDI client object."; error( RtMidiError::DRIVER_ERROR, errorString_ ); @@ -864,6 +868,7 @@ void MidiOutCore :: initialize( const std::string& clientName ) data->client = client; data->endpoint = 0; apiData_ = (void *) data; + CFRelease( name ); } unsigned int MidiOutCore :: getPortCount() diff --git a/RtMidi.h b/RtMidi.h index 9a878884..622cf79b 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -109,7 +109,7 @@ class RtMidiError : public std::exception 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 ); +typedef void (*RtMidiErrorCallback)( RtMidiError::Type type, const std::string &errorText, void *userData ); class MidiApi; @@ -161,7 +161,7 @@ class RtMidi 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; + virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ) = 0; protected: @@ -322,7 +322,7 @@ class RtMidiIn : public RtMidi 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 ); + virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ); protected: void openMidiApi( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit ); @@ -413,7 +413,7 @@ class RtMidiOut : public RtMidi 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 ); + virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ); protected: void openMidiApi( RtMidi::Api api, const std::string clientName ); @@ -448,7 +448,7 @@ class MidiApi virtual std::string getPortName( unsigned int portNumber ) = 0; inline bool isPortOpen() const { return connected_; } - void setErrorCallback( RtMidiErrorCallback errorCallback ); + void setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ); //! A basic error reporting function for RtMidi classes. void error( RtMidiError::Type type, std::string errorString ); @@ -460,6 +460,7 @@ class MidiApi bool connected_; std::string errorString_; RtMidiErrorCallback errorCallback_; + void *errorCallbackUserData_; }; class MidiInApi : public MidiApi @@ -547,7 +548,7 @@ inline unsigned int RtMidiIn :: getPortCount( void ) { return rtapi_->getPortCou 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 void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); } 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 ); } @@ -557,7 +558,7 @@ 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 RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); } // **************************************************************** // // From ce21fe6205e42063f74443a12558f447ed0a5959 Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Tue, 15 Jul 2014 14:09:53 -0400 Subject: [PATCH 020/388] CoreMidi string release added to avoid memory leak. --- RtMidi.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RtMidi.cpp b/RtMidi.cpp index a44e4b0c..82a9daec 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -801,6 +801,8 @@ static CFStringRef ConnectedEndpointName( MIDIEndpointRef endpoint ) if ( anyStrings ) return result; + CFRelease( result ); + // Here, either the endpoint had no connections, or we failed to obtain names return EndpointName( endpoint, false ); } From 770b57260dc7607b75776e8bee7e059aa06435dc Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Tue, 15 Jul 2014 15:29:41 -0400 Subject: [PATCH 021/388] Reverted OS-X sendMessage function for sysex messages > 1024 bytes, as the MIDIReceived() function does not work for such. --- RtMidi.cpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 82a9daec..4dd9f02c 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -991,10 +991,10 @@ void MidiOutCore :: openVirtualPort( std::string portName ) // Not necessary if we don't treat sysex messages any differently than // normal messages ... see below. -//static void sysexCompletionProc( MIDISysexSendRequest *sreq ) -//{ -// free( sreq ); -//} +static void sysexCompletionProc( MIDISysexSendRequest *sreq ) +{ + free( sreq ); +} void MidiOutCore :: sendMessage( std::vector *message ) { @@ -1013,12 +1013,16 @@ void MidiOutCore :: sendMessage( std::vector *message ) 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. + ///* + // It would be nice if the following "special-case" code for sysex + // messages longer than 1024 bytes wasn't necessary. In fact, we + // can send sysex messages through the normal messaging mechanism. + // However, that does not work for messages greater than 1024 + // bytes. From a previous note, there may be a problem of virtual + // ports not receiving sysex messages when using this section of + // code. - if ( message->at(0) == 0xF0 ) { + if ( message->at(0) == 0xF0 && nBytes > 1022 ) { // Apple's fantastic API requires us to free the allocated data in // the completion callback but trashes the pointer and size before @@ -1049,12 +1053,12 @@ void MidiOutCore :: sendMessage( std::vector *message ) } return; } - else if ( nBytes > 3 ) { + else if ( message->at(0) != 0xF0 && nBytes > 3 ) { errorString_ = "MidiOutCore::sendMessage: message format problem ... not sysex but > 3 bytes?"; error( RtMidiError::WARNING, errorString_ ); return; } - */ + //*/ MIDIPacketList packetList; MIDIPacket *packet = MIDIPacketListInit( &packetList ); From 94a04ef1ee3fe9da283aebe35c94754d921837e3 Mon Sep 17 00:00:00 2001 From: Oli Larkin Date: Sun, 20 Jul 2014 00:21:04 +0100 Subject: [PATCH 022/388] fix MidiOutCore :: sendMessage() sysex sending, which was broken for sysex messages over 256 bytes, not 1024 rather than using MIDISendSysex, use MIDIPacketListAdd() and MIDISend(). --- RtMidi.cpp | 65 ++++++++++++++---------------------------------------- 1 file changed, 16 insertions(+), 49 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 4dd9f02c..36039985 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1007,62 +1007,29 @@ void MidiOutCore :: sendMessage( std::vector *message ) return; } - // unsigned int packetBytes, bytesLeft = nBytes; - // unsigned int messageIndex = 0; MIDITimeStamp timeStamp = AudioGetCurrentHostTime(); CoreMidiData *data = static_cast (apiData_); OSStatus result; - ///* - // It would be nice if the following "special-case" code for sysex - // messages longer than 1024 bytes wasn't necessary. In fact, we - // can send sysex messages through the normal messaging mechanism. - // However, that does not work for messages greater than 1024 - // bytes. From a previous note, there may be a problem of virtual - // ports not receiving sysex messages when using this section of - // code. - - if ( message->at(0) == 0xF0 && nBytes > 1022 ) { - - // 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 ( message->at(0) != 0xF0 && nBytes > 3 ) { + if ( message->at(0) != 0xF0 && 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 ) ); + Byte buffer[nBytes+(sizeof(MIDIPacketList))]; + ByteCount listSize = sizeof(buffer); + MIDIPacketList *packetList = (MIDIPacketList*)buffer; + MIDIPacket *packet = MIDIPacketListInit( packetList ); + + ByteCount remainingBytes = nBytes; + while (remainingBytes) { + ByteCount bytesForPacket = remainingBytes > 65535 ? 65535 : remainingBytes; // 65535 = maximum size of a MIDIPacket + const Byte* dataStartPtr = (const Byte *) &message->at( nBytes - remainingBytes ); + packet = MIDIPacketListAdd( packetList, listSize, packet, timeStamp, bytesForPacket, dataStartPtr); + remainingBytes -= bytesForPacket; + } + if ( !packet ) { errorString_ = "MidiOutCore::sendMessage: could not allocate packet list"; error( RtMidiError::DRIVER_ERROR, errorString_ ); @@ -1071,7 +1038,7 @@ void MidiOutCore :: sendMessage( std::vector *message ) // Send to any destinations that may have connected to us. if ( data->endpoint ) { - result = MIDIReceived( data->endpoint, &packetList ); + result = MIDIReceived( data->endpoint, packetList ); if ( result != noErr ) { errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; error( RtMidiError::WARNING, errorString_ ); @@ -1080,7 +1047,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->port, data->destinationId, packetList ); if ( result != noErr ) { errorString_ = "MidiOutCore::sendMessage: error sending MIDI message to port."; error( RtMidiError::WARNING, errorString_ ); From 4e5974b6e3c805183c2dc33ecab829ff9b89c406 Mon Sep 17 00:00:00 2001 From: Oli Larkin Date: Sun, 20 Jul 2014 00:28:26 +0100 Subject: [PATCH 023/388] add test for validity of packet pointer --- RtMidi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 36039985..27a47050 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1023,7 +1023,7 @@ void MidiOutCore :: sendMessage( std::vector *message ) MIDIPacket *packet = MIDIPacketListInit( packetList ); ByteCount remainingBytes = nBytes; - while (remainingBytes) { + while (remainingBytes && packet) { ByteCount bytesForPacket = remainingBytes > 65535 ? 65535 : remainingBytes; // 65535 = maximum size of a MIDIPacket const Byte* dataStartPtr = (const Byte *) &message->at( nBytes - remainingBytes ); packet = MIDIPacketListAdd( packetList, listSize, packet, timeStamp, bytesForPacket, dataStartPtr); From e52bfa207cec24fc0c1cc1cb017e8f63de4a5a11 Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Mon, 3 Nov 2014 14:14:13 -0500 Subject: [PATCH 024/388] Minor update to tutorial documentation to remove redundant info. --- doc/doxygen/tutorial.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/doxygen/tutorial.txt b/doc/doxygen/tutorial.txt index aba7f3bd..3b211ad1 100644 --- a/doc/doxygen/tutorial.txt +++ b/doc/doxygen/tutorial.txt @@ -412,8 +412,6 @@ The Windows Multimedia library MIDI calls used in RtMidi do not make use of stre RtMidi was originally developed with Visual C++ version 6.0 but has been tested with Virtual Studio 2010. -The \c configure script provides support for the MinGW compiler. - \section acknowledge Development & Acknowledgements RtMidi is on github (https://github.com/thestk/rtmidi). Many thanks to the developers that are helping to maintain and improve RtMidi. From c39bb17ab47499fc9827abc100b94fb8c71715ed Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Mon, 3 Nov 2014 15:59:42 -0500 Subject: [PATCH 025/388] Changed firstErrorOccurred to be class variable; Fix to ALSA input receiver id. --- RtMidi.cpp | 17 ++++++++++++----- RtMidi.h | 1 + 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 27a47050..94b61d6a 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -241,16 +241,15 @@ void MidiApi :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userD void MidiApi :: error( RtMidiError::Type type, std::string errorString ) { if ( errorCallback_ ) { - static bool firstErrorOccured = false; - if ( firstErrorOccured ) + if ( firstErrorOccured_ ) return; - firstErrorOccured = true; + firstErrorOccured_ = true; const std::string errorMessage = errorString; errorCallback_( type, errorMessage, errorCallbackUserData_); - firstErrorOccured = false; + firstErrorOccured_ = false; return; } @@ -1472,6 +1471,7 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName 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 ); + receiver.client = snd_seq_client_id( data->seq ); snd_seq_port_info_t *pinfo; snd_seq_port_info_alloca( &pinfo ); @@ -1501,7 +1501,6 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName 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 ) { @@ -2263,6 +2262,14 @@ std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) 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; } diff --git a/RtMidi.h b/RtMidi.h index 622cf79b..6fa519ef 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -460,6 +460,7 @@ class MidiApi bool connected_; std::string errorString_; RtMidiErrorCallback errorCallback_; + bool firstErrorOccurred_; void *errorCallbackUserData_; }; From 1690808587a5378004fd0562b0e36934ae46c5f3 Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Mon, 3 Nov 2014 22:49:20 -0500 Subject: [PATCH 026/388] Fixed typo with firstErrorOccurred_ variable. --- RtMidi.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 94b61d6a..cb3fa025 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -242,14 +242,14 @@ void MidiApi :: error( RtMidiError::Type type, std::string errorString ) { if ( errorCallback_ ) { - if ( firstErrorOccured_ ) + if ( firstErrorOccurred_ ) return; - firstErrorOccured_ = true; + firstErrorOccurred_ = true; const std::string errorMessage = errorString; errorCallback_( type, errorMessage, errorCallbackUserData_); - firstErrorOccured_ = false; + firstErrorOccurred_ = false; return; } @@ -988,13 +988,6 @@ void MidiOutCore :: openVirtualPort( std::string portName ) 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 From 28321c051ed849b0fbd1f7b1aaee19b8ca807390 Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Thu, 8 Jan 2015 11:49:37 -0500 Subject: [PATCH 027/388] Update to ALSA port type search. --- RtMidi.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index cb3fa025..ce6db637 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1385,7 +1385,8 @@ unsigned int portInfo( snd_seq_t *seq, snd_seq_port_info_t *pinfo, unsigned int 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; + if ( ( ( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) == 0 ) && + ( ( atyp & SND_SEQ_PORT_TYPE_SYNTH ) == 0 ) ) continue; unsigned int caps = snd_seq_port_info_get_capability( pinfo ); if ( ( caps & type ) != type ) continue; if ( count == portNumber ) return 1; From 6a06b40251823c27aa444979829621baef1ad433 Mon Sep 17 00:00:00 2001 From: Adam Avramov Date: Wed, 13 May 2015 21:21:55 +0300 Subject: [PATCH 028/388] Always allocate JACK ringbuffers. This makes sure a program using this library would not segfault while waiting for a stopped JACK server to autostart. --- RtMidi.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index ce6db637..1287afa7 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -2678,6 +2678,10 @@ void MidiOutJack :: connect() JackMidiData *data = static_cast (apiData_); if ( data->client ) return; + + // Initialize output ringbuffers + data->buffSize = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); + data->buffMessage = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); // Initialize JACK client if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { @@ -2687,8 +2691,6 @@ void MidiOutJack :: connect() } 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 ); } @@ -2696,12 +2698,12 @@ MidiOutJack :: ~MidiOutJack() { JackMidiData *data = static_cast (apiData_); closePort(); - + + // Cleanup + 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; From a5c375c7280e2134391a7d840f4fbda0a7f684bb Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Sat, 29 Aug 2015 20:44:00 +0800 Subject: [PATCH 029/388] Add C API. --- Makefile.am | 4 +- msw/rtmidilib.vcproj | 8 ++ rtmidi_c.cpp | 177 +++++++++++++++++++++++++++++++++++++++++++ rtmidi_c.h | 66 ++++++++++++++++ 4 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 rtmidi_c.cpp create mode 100644 rtmidi_c.h diff --git a/Makefile.am b/Makefile.am index 4851619d..706daf0c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,4 +2,6 @@ lib_LTLIBRARIES = %D%/librtmidi.la %C%_librtmidi_la_LDFLAGS = -no-undefined %C%_librtmidi_la_SOURCES = \ %D%/RtMidi.cpp \ - %D%/RtMidi.h + %D%/RtMidi.h \ + %D%/rtmidi_c.cpp \ + %D%/rtmidi_c.h diff --git a/msw/rtmidilib.vcproj b/msw/rtmidilib.vcproj index af1f75c2..20a458f0 100755 --- a/msw/rtmidilib.vcproj +++ b/msw/rtmidilib.vcproj @@ -151,6 +151,10 @@ RelativePath="..\RtMidi.cpp" > + + + + +#include +#include "rtmidi_c.h" +#include "RtMidi.h" + +/* misc */ +int rtmidi_sizeof_rtmidi_api () +{ + return sizeof (RtMidiApi); +} + +/* RtMidi API */ +int rtmidi_get_compiled_api (enum RtMidiApi **apis) // return length for NULL argument. +{ + if (!apis || !(*apis)) { + std::vector *v = new std::vector (); + try { + RtMidi::getCompiledApi (*v); + int size = v->size (); + delete v; + return size; + } catch (...) { + return -1; + } + } else { + try { + std::vector *v = new std::vector (); + RtMidi::getCompiledApi (*v); + for (unsigned int i = 0; i < v->size (); i++) + (*apis) [i] = (RtMidiApi) v->at (i); + delete v; + return 0; + } catch (...) { + return -1; + } + } +} + +void rtmidi_error (MidiApi *api, enum RtMidiErrorType type, const char* errorString) +{ + std::string msg = errorString; + api->error ((RtMidiError::Type) type, msg); +} + +void rtmidi_open_port (RtMidiPtr device, unsigned int portNumber, const char *portName) +{ + std::string name = portName; + ((RtMidi*) device)->openPort (portNumber, name); +} + +void rtmidi_open_virtual_port (RtMidiPtr device, const char *portName) +{ + std::string name = portName; + ((RtMidi*) device)->openVirtualPort (name); +} + +void rtmidi_close_port (RtMidiPtr device) +{ + ((RtMidi*) device)->closePort (); +} + +unsigned int rtmidi_get_port_count (RtMidiPtr device) +{ + return ((RtMidi*) device)->getPortCount (); +} + +const char* rtmidi_get_port_name (RtMidiPtr device, unsigned int portNumber) +{ + std::string name = ((RtMidi*) device)->getPortName (portNumber); + return name.c_str (); +} + +/* RtMidiIn API */ +RtMidiInPtr rtmidi_in_create_default () +{ + return new RtMidiIn (); +} + +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); +} + +void rtmidi_in_free (RtMidiInPtr device) +{ + delete (RtMidiIn*) device; +} + +enum RtMidiApi rtmidi_in_get_current_api (RtMidiPtr device) +{ + return (RtMidiApi) ((RtMidiIn*) device)->getCurrentApi (); +} + +class CallbackProxyUserData +{ + public: + CallbackProxyUserData (RtMidiCCallback cCallback, void *userData) + : c_callback (cCallback), user_data (userData) + { + } + RtMidiCCallback c_callback; + void *user_data; +}; + +void callback_proxy (double timeStamp, std::vector *message, void *userData) +{ + CallbackProxyUserData* data = reinterpret_cast (userData); + data->c_callback (timeStamp, message->data (), data->user_data); +} + +void rtmidi_in_set_callback (RtMidiInPtr device, RtMidiCCallback callback, void *userData) +{ + void *data = (void *) new CallbackProxyUserData (callback, userData); + ((RtMidiIn*) device)->setCallback (callback_proxy, data); +} + +void rtmidi_in_cancel_callback (RtMidiInPtr device) +{ + ((RtMidiIn*) device)->cancelCallback (); +} + +void rtmidi_in_ignore_types (RtMidiInPtr device, bool midiSysex, bool midiTime, bool midiSense) +{ + ((RtMidiIn*) device)->ignoreTypes (midiSysex, midiTime, midiSense); +} + +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); + *message = (unsigned char *) malloc ((int) ret); + memcpy (*message, v->data (), (int) ret); + delete v; + return ret; + } catch (...) { + return -1; + } +} + +/* RtMidiOut API */ +RtMidiOutPtr rtmidi_out_create_default () +{ + return new RtMidiOut (); +} + +RtMidiOutPtr rtmidi_out_create (enum RtMidiApi api, const char *clientName) +{ + std::string name = clientName; + return new RtMidiOut ((RtMidi::Api) api, name); +} + +void rtmidi_out_free (RtMidiOutPtr device) +{ + delete (RtMidiOut*) device; +} + +enum RtMidiApi rtmidi_out_get_current_api (RtMidiPtr device) +{ + return (RtMidiApi) ((RtMidiOut*) device)->getCurrentApi (); +} + +int rtmidi_out_send_message (RtMidiOutPtr device, const unsigned char *message, int length) +{ + try { + // FIXME: use allocator to achieve efficient buffering + std::vector *v = new std::vector (length); + memcpy (v->data (), message, length); + ((RtMidiOut*) device)->sendMessage (v); + delete v; + return 0; + } catch (...) { + return -1; + } +} diff --git a/rtmidi_c.h b/rtmidi_c.h new file mode 100644 index 00000000..6630c448 --- /dev/null +++ b/rtmidi_c.h @@ -0,0 +1,66 @@ + +#include + +#ifndef RTMIDI_C_H +#define RTMIDI_C_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void* RtMidiPtr; +typedef void* RtMidiInPtr; +typedef void* RtMidiOutPtr; + + enum RtMidiApi { + RT_MIDI_API_UNSPECIFIED, /*!< Search for a working compiled API. */ + RT_MIDI_API_MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ + RT_MIDI_API_LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ + 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. */ + }; + +enum RtMidiErrorType { + RT_ERROR_WARNING, RT_ERROR_DEBUG_WARNING, RT_ERROR_UNSPECIFIED, RT_ERROR_NO_DEVICES_FOUND, + RT_ERROR_INVALID_DEVICE, RT_ERROR_MEMORY_ERROR, RT_ERROR_INVALID_PARAMETER, RT_ERROR_INVALID_USE, + RT_ERROR_DRIVER_ERROR, RT_ERROR_SYSTEM_ERROR, RT_ERROR_THREAD_ERROR +}; + +typedef void(* RtMidiCCallback) (double timeStamp, const unsigned char* message, void *userData); + +int rtmidi_sizeof_rtmidi_api (); + +/* RtMidi API */ +int rtmidi_get_compiled_api (enum RtMidiApi **apis); // return length for NULL argument. +void rtmidi_error (enum RtMidiErrorType type, const char* errorString); + +void rtmidi_open_port (RtMidiPtr device, unsigned int portNumber, const char *portName); +void rtmidi_open_virtual_port (RtMidiPtr device, const char *portName); +void rtmidi_close_port (RtMidiPtr device); +unsigned int rtmidi_get_port_count (RtMidiPtr device); +const char* rtmidi_get_port_name (RtMidiPtr device, unsigned int portNumber); + +/* RtMidiIn API */ +RtMidiInPtr rtmidi_in_create_default (); +RtMidiInPtr rtmidi_in_create (enum RtMidiApi api, const char *clientName, unsigned int queueSizeLimit); +void rtmidi_in_free (RtMidiInPtr device); +enum RtMidiApi rtmidi_in_get_current_api (RtMidiPtr device); +void rtmidi_in_set_callback (RtMidiInPtr device, RtMidiCCallback callback, void *userData); +void rtmidi_in_cancel_callback (RtMidiInPtr device); +void rtmidi_in_ignore_types (RtMidiInPtr device, bool midiSysex, bool midiTime, bool midiSense); +double rtmidi_in_get_message (RtMidiInPtr device, unsigned char **message); + +/* RtMidiOut API */ +RtMidiOutPtr rtmidi_out_create_default (); +RtMidiOutPtr rtmidi_out_create (enum RtMidiApi api, const char *clientName); +void rtmidi_out_free (RtMidiOutPtr device); +enum RtMidiApi rtmidi_out_get_current_api (RtMidiPtr device); +int rtmidi_out_send_message (RtMidiOutPtr device, const unsigned char *message, int length); + + +#ifdef __cplusplus +} +#endif +#endif From 9db036c4496d28d847f5219cf5d05eda65a03f2c Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Sun, 6 Sep 2015 21:08:17 +0800 Subject: [PATCH 030/388] rtmidi_c.h: add declspec(dllexport) for dll builds. --- rtmidi_c.h | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/rtmidi_c.h b/rtmidi_c.h index 6630c448..c37b655c 100644 --- a/rtmidi_c.h +++ b/rtmidi_c.h @@ -4,6 +4,12 @@ #ifndef RTMIDI_C_H #define RTMIDI_C_H +#if defined(RTMIDI_EXPORT) +#define RTMIDIAPI __declspec(dllexport) +#else +#define RTMIDIAPI //__declspec(dllimport) +#endif + #ifdef __cplusplus extern "C" { #endif @@ -30,34 +36,34 @@ enum RtMidiErrorType { typedef void(* RtMidiCCallback) (double timeStamp, const unsigned char* message, void *userData); -int rtmidi_sizeof_rtmidi_api (); +RTMIDIAPI int rtmidi_sizeof_rtmidi_api (); /* RtMidi API */ -int rtmidi_get_compiled_api (enum RtMidiApi **apis); // return length for NULL argument. -void rtmidi_error (enum RtMidiErrorType type, const char* errorString); +RTMIDIAPI int rtmidi_get_compiled_api (enum RtMidiApi **apis); // return length for NULL argument. +RTMIDIAPI void rtmidi_error (enum RtMidiErrorType type, const char* errorString); -void rtmidi_open_port (RtMidiPtr device, unsigned int portNumber, const char *portName); -void rtmidi_open_virtual_port (RtMidiPtr device, const char *portName); -void rtmidi_close_port (RtMidiPtr device); -unsigned int rtmidi_get_port_count (RtMidiPtr device); -const char* rtmidi_get_port_name (RtMidiPtr device, unsigned int portNumber); +RTMIDIAPI void rtmidi_open_port (RtMidiPtr device, unsigned int portNumber, const char *portName); +RTMIDIAPI void rtmidi_open_virtual_port (RtMidiPtr device, const char *portName); +RTMIDIAPI void rtmidi_close_port (RtMidiPtr device); +RTMIDIAPI unsigned int rtmidi_get_port_count (RtMidiPtr device); +RTMIDIAPI const char* rtmidi_get_port_name (RtMidiPtr device, unsigned int portNumber); /* RtMidiIn API */ -RtMidiInPtr rtmidi_in_create_default (); -RtMidiInPtr rtmidi_in_create (enum RtMidiApi api, const char *clientName, unsigned int queueSizeLimit); -void rtmidi_in_free (RtMidiInPtr device); -enum RtMidiApi rtmidi_in_get_current_api (RtMidiPtr device); -void rtmidi_in_set_callback (RtMidiInPtr device, RtMidiCCallback callback, void *userData); -void rtmidi_in_cancel_callback (RtMidiInPtr device); -void rtmidi_in_ignore_types (RtMidiInPtr device, bool midiSysex, bool midiTime, bool midiSense); -double rtmidi_in_get_message (RtMidiInPtr device, unsigned char **message); +RTMIDIAPI RtMidiInPtr rtmidi_in_create_default (); +RTMIDIAPI RtMidiInPtr rtmidi_in_create (enum RtMidiApi api, const char *clientName, unsigned int queueSizeLimit); +RTMIDIAPI void rtmidi_in_free (RtMidiInPtr device); +RTMIDIAPI enum RtMidiApi rtmidi_in_get_current_api (RtMidiPtr device); +RTMIDIAPI void rtmidi_in_set_callback (RtMidiInPtr device, RtMidiCCallback callback, void *userData); +RTMIDIAPI void rtmidi_in_cancel_callback (RtMidiInPtr device); +RTMIDIAPI void rtmidi_in_ignore_types (RtMidiInPtr device, bool midiSysex, bool midiTime, bool midiSense); +RTMIDIAPI double rtmidi_in_get_message (RtMidiInPtr device, unsigned char **message); /* RtMidiOut API */ -RtMidiOutPtr rtmidi_out_create_default (); -RtMidiOutPtr rtmidi_out_create (enum RtMidiApi api, const char *clientName); -void rtmidi_out_free (RtMidiOutPtr device); -enum RtMidiApi rtmidi_out_get_current_api (RtMidiPtr device); -int rtmidi_out_send_message (RtMidiOutPtr device, const unsigned char *message, int length); +RTMIDIAPI RtMidiOutPtr rtmidi_out_create_default (); +RTMIDIAPI RtMidiOutPtr rtmidi_out_create (enum RtMidiApi api, const char *clientName); +RTMIDIAPI void rtmidi_out_free (RtMidiOutPtr device); +RTMIDIAPI enum RtMidiApi rtmidi_out_get_current_api (RtMidiPtr device); +RTMIDIAPI int rtmidi_out_send_message (RtMidiOutPtr device, const unsigned char *message, int length); #ifdef __cplusplus From 78799dad96e7741705d5aff82d68f58a9417b8ba Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Mon, 14 Sep 2015 23:30:57 +0800 Subject: [PATCH 031/388] return duplicated string for port name, to avoid unwanted freeing by bindings. --- rtmidi_c.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index 8c2e6762..b259e625 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -67,7 +67,7 @@ unsigned int rtmidi_get_port_count (RtMidiPtr device) const char* rtmidi_get_port_name (RtMidiPtr device, unsigned int portNumber) { std::string name = ((RtMidi*) device)->getPortName (portNumber); - return name.c_str (); + return strdup (name.c_str ()); } /* RtMidiIn API */ From 22f6344e3ed90619a639258157744b4ef7db5754 Mon Sep 17 00:00:00 2001 From: Szymon Kaliski Date: Fri, 4 Dec 2015 13:29:32 +0100 Subject: [PATCH 032/388] Fix for closing virtual ports on OSX --- RtMidi.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index ce6db637..4873d3db 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -956,11 +956,17 @@ void MidiOutCore :: openPort( unsigned int portNumber, const std::string portNam void MidiOutCore :: closePort( void ) { - if ( connected_ ) { - CoreMidiData *data = static_cast (apiData_); + CoreMidiData *data = static_cast (apiData_); + + if ( data->endpoint ) { + MIDIEndpointDispose( data->endpoint ); + } + + if ( data->port ) { MIDIPortDispose( data->port ); - connected_ = false; } + + connected_ = false; } void MidiOutCore :: openVirtualPort( std::string portName ) From 74c92f7c9b93415650d7d449c7d0a5de0e803b26 Mon Sep 17 00:00:00 2001 From: Szymon Kaliski Date: Tue, 19 Jan 2016 11:51:33 +0100 Subject: [PATCH 033/388] fix for closing virtual input --- RtMidi.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 4873d3db..4beaec9b 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -667,11 +667,17 @@ void MidiInCore :: openVirtualPort( const std::string portName ) void MidiInCore :: closePort( void ) { - if ( connected_ ) { - CoreMidiData *data = static_cast (apiData_); + CoreMidiData *data = static_cast (apiData_); + + if ( data->endpoint ) { + MIDIEndpointDispose( data->endpoint ); + } + + if ( data->port ) { MIDIPortDispose( data->port ); - connected_ = false; } + + connected_ = false; } unsigned int MidiInCore :: getPortCount() From 1240b7f7f921119a6612b633521f5128064aa6c8 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Sun, 24 Jan 2016 14:46:01 -0300 Subject: [PATCH 034/388] Add an autogen script to run autotools correctly. --- autogen.sh | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 autogen.sh diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 00000000..a8a30461 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,95 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +DIE=0 + +(test -f $srcdir/configure.ac) || { + echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" + echo " top-level package directory" + exit 1 +} + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`autoconf' installed." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +(grep "^LT_INIT" $srcdir/configure.ac >/dev/null) && { + (libtoolize --version) < /dev/null > /dev/null 2>&1 \ + && LIBTOOLIZE=libtoolize || { + (glibtoolize --version) < /dev/null > /dev/null 2>&1 \ + && LIBTOOLIZE=glibtoolize || { + echo + echo "**Error**: You must have \`libtool' installed." + echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" + DIE=1 + } + } +} + +(automake --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`automake' installed." + echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" + DIE=1 + NO_AUTOMAKE=yes +} + + +# if no automake, don't bother testing for aclocal +test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: Missing \`aclocal'. The version of \`automake'" + echo "installed doesn't appear recent enough." + echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +if test -z "$*"; then + echo "**Warning**: I am going to run \`configure' with no arguments." + echo "If you wish to pass any to it, please specify them on the" + echo \`$0\'" command line." + echo +fi + +# Make some directories required by automake, if they don't exist +if ! [ -d config ]; then mkdir -v config; fi +if ! [ -d m4 ]; then mkdir -v m4; fi + +case $CC in +xlc ) + am_opt=--include-deps;; +esac + +echo "Running aclocal $aclocalinclude ..." +aclocal $ACLOCAL_FLAGS || exit 1 +echo "Running $LIBTOOLIZE ..." +$LIBTOOLIZE || exit 1 +echo "Running automake --gnu $am_opt ..." +automake --add-missing --gnu $am_opt || exit 1 +echo "Running autoconf ..." +autoconf || exit 1 + +if ( echo "$@" | grep -q -e "--no-configure" ); then + NOCONFIGURE=1 +fi + +conf_flags="--enable-maintainer-mode --enable-debug --disable-silent-rules" + +if test x$NOCONFIGURE = x; then + echo Running $srcdir/configure $conf_flags "$@" ... + $srcdir/configure $conf_flags "$@" \ + && echo Now type \`make\' to compile. || exit 1 +else + echo Skipping configure process. +fi From aadd9737888eac663343519154bcf67e04518cd6 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Sun, 24 Jan 2016 14:46:58 -0300 Subject: [PATCH 035/388] Add some nice automake features if they are available. --- configure.ac | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure.ac b/configure.ac index 138a7fdc..a52ddb09 100644 --- a/configure.ac +++ b/configure.ac @@ -5,6 +5,10 @@ AC_CONFIG_SRCDIR(RtMidi.cpp) AC_CONFIG_FILES([rtmidi-config librtmidi.pc Makefile tests/Makefile]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) +# Enable some nice automake features if they are available +m4_ifdef([AM_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + # Fill GXX with something before test. AC_SUBST( GXX, ["no"] ) AC_SUBST(noinst_LIBRARIES) From b791569275369b20aee2ef28716153d6668cb162 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Sun, 24 Jan 2016 14:47:14 -0300 Subject: [PATCH 036/388] Use libtools version info. --- Makefile.am | 2 +- configure.ac | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 4851619d..90ad8395 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ lib_LTLIBRARIES = %D%/librtmidi.la -%C%_librtmidi_la_LDFLAGS = -no-undefined +%C%_librtmidi_la_LDFLAGS = -no-undefined -export-dynamic -version-info @SO_VERSION@ %C%_librtmidi_la_SOURCES = \ %D%/RtMidi.cpp \ %D%/RtMidi.h diff --git a/configure.ac b/configure.ac index a52ddb09..85e4f538 100644 --- a/configure.ac +++ b/configure.ac @@ -5,6 +5,29 @@ AC_CONFIG_SRCDIR(RtMidi.cpp) AC_CONFIG_FILES([rtmidi-config librtmidi.pc Makefile tests/Makefile]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) +# libtool version: current:revision:age +# +# If the library source code has changed at all since the last update, then +# increment revision (`c:r:a' becomes `c:r+1:a'). +# +# If any interfaces have been added, removed, or changed since the last update, +# increment current, and set revision to 0. +# +# If any interfaces have been added since the last public release, then +# increment age. +# +# If any interfaces have been removed since the last public release, then set +# age to 0. +m4_define([lt_current], 3) +m4_define([lt_revision], 0) +m4_define([lt_age], 0) + +m4_define([lt_version_info], [lt_current:lt_revision:lt_age]) +m4_define([lt_current_minus_age], [m4_eval(lt_current - lt_age)]) + +SO_VERSION=lt_version_info +AC_SUBST(SO_VERSION) + # Enable some nice automake features if they are available m4_ifdef([AM_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) From b9e4aa54ca55b7ee078f8a6159ed38079c8a0237 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Thu, 4 Feb 2016 14:35:33 -0300 Subject: [PATCH 037/388] Install the pkg-config (.pc) file. Renames it from librtmidi to just rtmidi. --- Makefile.am | 3 +++ configure.ac | 2 +- librtmidi.pc.in => rtmidi.pc.in | 0 3 files changed, 4 insertions(+), 1 deletion(-) rename librtmidi.pc.in => rtmidi.pc.in (100%) diff --git a/Makefile.am b/Makefile.am index 706daf0c..2ce8a899 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,3 +5,6 @@ lib_LTLIBRARIES = %D%/librtmidi.la %D%/RtMidi.h \ %D%/rtmidi_c.cpp \ %D%/rtmidi_c.h + +pkgconfigdatadir = $(libdir)/pkgconfig +pkgconfigdata_DATA = rtmidi.pc diff --git a/configure.ac b/configure.ac index a52ddb09..f789e5ea 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 rtmidi.pc Makefile tests/Makefile]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) # Enable some nice automake features if they are available diff --git a/librtmidi.pc.in b/rtmidi.pc.in similarity index 100% rename from librtmidi.pc.in rename to rtmidi.pc.in From e13f84bf098292c7423ee0343a48d8aa63a39128 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Thu, 4 Feb 2016 14:51:55 -0300 Subject: [PATCH 038/388] Install header files. --- Makefile.am | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 2ce8a899..970459dc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,8 +2,11 @@ lib_LTLIBRARIES = %D%/librtmidi.la %C%_librtmidi_la_LDFLAGS = -no-undefined %C%_librtmidi_la_SOURCES = \ %D%/RtMidi.cpp \ + %D%/rtmidi_c.cpp + +rtmidi_incdir = $(includedir) +rtmidi_inc_HEADERS = \ %D%/RtMidi.h \ - %D%/rtmidi_c.cpp \ %D%/rtmidi_c.h pkgconfigdatadir = $(libdir)/pkgconfig From 6621cfd22a53a84d1780bfb8543b7e4c81b8363b Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Thu, 4 Feb 2016 15:05:30 -0300 Subject: [PATCH 039/388] Move headers install path to ${prefix}/include/rtmidi --- Makefile.am | 2 +- configure.ac | 2 +- rtmidi.pc.in | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 970459dc..e71e3cd3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,7 +4,7 @@ lib_LTLIBRARIES = %D%/librtmidi.la %D%/RtMidi.cpp \ %D%/rtmidi_c.cpp -rtmidi_incdir = $(includedir) +rtmidi_incdir = $(includedir)/rtmidi rtmidi_inc_HEADERS = \ %D%/RtMidi.h \ %D%/rtmidi_c.h diff --git a/configure.ac b/configure.ac index f789e5ea..0dd978c7 100644 --- a/configure.ac +++ b/configure.ac @@ -38,7 +38,7 @@ AC_ARG_ENABLE(debug, # 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" + CPPFLAGS="$CPPFLAGS -I$prefix/include/rtmidi" fi # For -I and -D flags diff --git a/rtmidi.pc.in b/rtmidi.pc.in index d3099065..c94652ba 100644 --- a/rtmidi.pc.in +++ b/rtmidi.pc.in @@ -1,7 +1,7 @@ prefix=@prefix@ exec_prefix=${prefix} libdir=${exec_prefix}/lib -includedir=${prefix}/include +includedir=${prefix}/include/rtmidi Name: librtmidi Description: RtMidi - a set of C++ classes that provide a common API for realtime MIDI input/output From f8dac33707c68284be2e1750f08fb11f97e5c4af Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Thu, 4 Feb 2016 18:02:34 -0300 Subject: [PATCH 040/388] Build tests and docs via automake and add them to dist. --- Makefile.am | 10 ++++++++++ configure.ac | 6 +++++- doc/Makefile.am | 31 ++++++++++++++++++++++++++++++ tests/Makefile.am | 22 +++++++++++++++++++++ tests/Makefile.in | 49 ----------------------------------------------- 5 files changed, 68 insertions(+), 50 deletions(-) create mode 100644 doc/Makefile.am create mode 100644 tests/Makefile.am delete mode 100644 tests/Makefile.in diff --git a/Makefile.am b/Makefile.am index e71e3cd3..19fbacd8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,8 @@ +SUBDIRS = . tests +if MAKE_DOC +SUBDIRS += doc +endif + lib_LTLIBRARIES = %D%/librtmidi.la %C%_librtmidi_la_LDFLAGS = -no-undefined %C%_librtmidi_la_SOURCES = \ @@ -11,3 +16,8 @@ rtmidi_inc_HEADERS = \ pkgconfigdatadir = $(libdir)/pkgconfig pkgconfigdata_DATA = rtmidi.pc + +EXTRA_DIST = autogen.sh readme doc msw + +dist-hook: + $(MAKE) -C doc diff --git a/configure.ac b/configure.ac index 0dd978c7..bcaada8e 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 rtmidi.pc Makefile tests/Makefile]) +AC_CONFIG_FILES([rtmidi-config rtmidi.pc Makefile tests/Makefile doc/Makefile]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) # Enable some nice automake features if they are available @@ -55,6 +55,10 @@ fi CXXFLAGS="$CXXFLAGS $cxxflag" +# Checks for doxygen +AC_CHECK_PROG( DOXYGEN, [doxygen], [doxygen] ) +AM_CONDITIONAL( MAKE_DOC, [test "x${DOXYGEN}" != x] ) + # Checks for package options and external software AC_CANONICAL_HOST diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 00000000..6a52d94c --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,31 @@ + +MAINTAINERCLEANFILES=Makefile.in + +CLEANFILES=doxygen-build.stamp + +DOX=Doxyfile + +EXTRA_DIST=html + +INSTIMAGES=html/doxygen.png + +DOC_STAMPS=html-build.stamp + +DOC_DIR=$(HTML_DIR) + +all-local: doxygen-build.stamp + +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 + +clean-local: + rm -f *~ *.bak $(DOC_STAMPS) || true + if test -d html; then rm -fr html; fi + if test -d latex; then rm -fr latex; fi + if test -d man; then rm -fr man; fi + +distclean-local: clean + rm -f *.stamp || true + if test -d html; then rm -rf html; fi diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 00000000..b6bdcec6 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,22 @@ + +noinst_PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest + +midiprobe_CXXFLAGS = -Wall -I$(top_srcdir) +midiprobe_SOURCES = midiprobe.cpp +midiprobe_LDADD = $(top_builddir)/librtmidi.la + +midiout_CXXFLAGS = -Wall -I$(top_srcdir) +midiout_SOURCES = midiout.cpp +midiout_LDADD = $(top_builddir)/librtmidi.la + +qmidiin_CXXFLAGS = -Wall -I$(top_srcdir) +qmidiin_SOURCES = qmidiin.cpp +qmidiin_LDADD = $(top_builddir)/librtmidi.la + +cmidiin_CXXFLAGS = -Wall -I$(top_srcdir) +cmidiin_SOURCES = cmidiin.cpp +cmidiin_LDADD = $(top_builddir)/librtmidi.la + +sysextest_CXXFLAGS = -Wall -I$(top_srcdir) +sysextest_SOURCES = sysextest.cpp +sysextest_LDADD = $(top_builddir)/librtmidi.la diff --git a/tests/Makefile.in b/tests/Makefile.in deleted file mode 100644 index 42cb354e..00000000 --- a/tests/Makefile.in +++ /dev/null @@ -1,49 +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 -RM = /bin/rm -SRC_PATH = .. -INCLUDE = @top_srcdir@ -OBJECT_PATH = @object_path@ -vpath %.o $(OBJECT_PATH) - -OBJECTS = @top_srcdir@/RtMidi.o - -CC = @CXX@ -DEFS = @CPPFLAGS@ -CFLAGS = @CXXFLAGS@ -CFLAGS += -I$(INCLUDE) -I$(INCLUDE)/include -LIBRARY = @LIBS@ - -%.o : $(SRC_PATH)/%.cpp - $(CC) $(CFLAGS) $(DEFS) -c $(<) -o $(OBJECT_PATH)/$@ - -all : $(PROGRAMS) - -midiprobe : @srcdir@/midiprobe.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o midiprobe $^ $(LIBRARY) - -midiout : @srcdir@/midiout.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o midiout $^ $(LIBRARY) - -qmidiin : @srcdir@/qmidiin.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o qmidiin $^ $(LIBRARY) - -cmidiin : @srcdir@/cmidiin.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o cmidiin $^ $(LIBRARY) - -sysextest : @srcdir@/sysextest.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o sysextest $^ $(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 7bb026ca74f3c9a4308bdb3756a67d2d6a958d99 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Fri, 5 Feb 2016 12:16:18 -0300 Subject: [PATCH 041/388] Run autoreconf instead of running the autotools manually, if possible. --- autogen.sh | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/autogen.sh b/autogen.sh index a8a30461..bf28ad9d 100755 --- a/autogen.sh +++ b/autogen.sh @@ -6,12 +6,24 @@ test -z "$srcdir" && srcdir=. DIE=0 +if test -z "$*"; then + echo "**Warning**: I am going to run \`configure' with arguments for" + echo "developer/maintainer mode. If you wish to pass extra arguments," + echo "(such as --prefix), please specify them on the \`$0'" + echo "command line." + echo "If you wish to run configure yourself, please specify --no-configure." + echo +fi + (test -f $srcdir/configure.ac) || { echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" echo " top-level package directory" exit 1 } +if ! autoreconf --version /dev/null 2>&1 +then + (autoconf --version) < /dev/null > /dev/null 2>&1 || { echo echo "**Error**: You must have \`autoconf' installed." @@ -55,13 +67,6 @@ if test "$DIE" -eq 1; then exit 1 fi -if test -z "$*"; then - echo "**Warning**: I am going to run \`configure' with no arguments." - echo "If you wish to pass any to it, please specify them on the" - echo \`$0\'" command line." - echo -fi - # Make some directories required by automake, if they don't exist if ! [ -d config ]; then mkdir -v config; fi if ! [ -d m4 ]; then mkdir -v m4; fi @@ -80,6 +85,13 @@ automake --add-missing --gnu $am_opt || exit 1 echo "Running autoconf ..." autoconf || exit 1 +else # autoreconf instead + + echo "Running autoreconf --verbose --install ..." + autoreconf --verbose --install || exit 1 + +fi + if ( echo "$@" | grep -q -e "--no-configure" ); then NOCONFIGURE=1 fi From e5bd7b5158da18fbc8d986a6a6490234719f2d9d Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Fri, 5 Feb 2016 15:08:42 -0300 Subject: [PATCH 042/388] Copy doxyfile before running doxygen, fixes out of tree builds. --- configure.ac | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/configure.ac b/configure.ac index bcaada8e..c2f8c4be 100644 --- a/configure.ac +++ b/configure.ac @@ -59,6 +59,14 @@ CXXFLAGS="$CXXFLAGS $cxxflag" AC_CHECK_PROG( DOXYGEN, [doxygen], [doxygen] ) AM_CONDITIONAL( MAKE_DOC, [test "x${DOXYGEN}" != x] ) +# Copy doc files to build dir if necessary +AC_CONFIG_LINKS( [doc/doxygen/Doxyfile:doc/doxygen/Doxyfile] ) +AC_CONFIG_LINKS( [doc/doxygen/footer.html:doc/doxygen/footer.html] ) +AC_CONFIG_LINKS( [doc/doxygen/header.html:doc/doxygen/header.html] ) +AC_CONFIG_LINKS( [doc/doxygen/tutorial.txt:doc/doxygen/tutorial.txt] ) +AC_CONFIG_LINKS( [doc/images/ccrma.gif:doc/images/ccrma.gif] ) +AC_CONFIG_LINKS( [doc/images/mcgill.gif:doc/images/mcgill.gif] ) + # Checks for package options and external software AC_CANONICAL_HOST From d7012fe47f0431d32a0c9ff7ef28783016d106fc Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Fri, 5 Feb 2016 16:36:08 -0300 Subject: [PATCH 043/388] Add the required version number to AM_INIT_AUTOMAKE. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index c2f8c4be..140c115f 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,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 rtmidi.pc Makefile tests/Makefile doc/Makefile]) -AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) +AM_INIT_AUTOMAKE([1.14 -Wall -Werror foreign subdir-objects]) # Enable some nice automake features if they are available m4_ifdef([AM_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) From 7a833879569ac82a9560ae77cd6a4b5a33f4e2cc Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Wed, 10 Feb 2016 08:37:11 -0500 Subject: [PATCH 044/388] Date / release number updates in preparation for new release. --- RtMidi.cpp | 2 +- RtMidi.h | 4 ++-- configure.ac | 2 +- doc/release.txt | 11 ++++++++++- readme | 4 ++-- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 782789ed..812ce2c9 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -8,7 +8,7 @@ RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/ RtMidi: realtime MIDI i/o C++ classes - Copyright (c) 2003-2014 Gary P. Scavone + Copyright (c) 2003-2016 Gary P. Scavone Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff --git a/RtMidi.h b/RtMidi.h index 6fa519ef..1f0175ed 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -8,7 +8,7 @@ RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/ RtMidi: realtime MIDI i/o C++ classes - Copyright (c) 2003-2014 Gary P. Scavone + Copyright (c) 2003-2016 Gary P. Scavone Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -43,7 +43,7 @@ #ifndef RTMIDI_H #define RTMIDI_H -#define RTMIDI_VERSION "2.1.0" +#define RTMIDI_VERSION "2.1.1" #include #include diff --git a/configure.ac b/configure.ac index a52ddb09..6038314b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ # 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.1, 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]) diff --git a/doc/release.txt b/doc/release.txt index d08f706e..ded9722f 100644 --- a/doc/release.txt +++ b/doc/release.txt @@ -1,6 +1,15 @@ RtMidi - a set of C++ classes that provides a common API for realtime MIDI input/output across Linux (ALSA & JACK), Macintosh OS X (CoreMidi & JACK), and Windows (Multimedia, Kernel Streaming). -By Gary P. Scavone, 2003-2014 +By Gary P. Scavone, 2003-2016 + +v2.1.1: (?? February 2016) +- updates to automake routines +- added C API (thanks to Atsushi Eno!) +- JACK ringbuffer allocation change +- OSX virtual port closing fix +- OSX sysex sending fix +- moved Windows kernel streaming code to other branch because it is incomplete +- miscellaneous small fixes v2.1.0: (30 March 2014) - renamed RtError class to RtMidiError and embedded it in RtMidi.h (and deleted RtError.h) diff --git a/readme b/readme index 545ffc61..ece29dfe 100644 --- a/readme +++ b/readme @@ -1,6 +1,6 @@ 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. +By Gary P. Scavone, 2003-2016. This distribution of RtMidi contains the following: @@ -32,7 +32,7 @@ LEGAL AND ETHICAL: 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 + Copyright (c) 2003-2016 Gary P. Scavone Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files From 120350bdb30a9b3b70f8fe0502824e4f040b7635 Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Wed, 10 Feb 2016 08:59:07 -0500 Subject: [PATCH 045/388] Added function definitions for iOS support. --- RtMidi.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/RtMidi.cpp b/RtMidi.cpp index 812ce2c9..678e9406 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -39,6 +39,13 @@ #include "RtMidi.h" #include +#if defined(__MACOSX_CORE__) + #if TARGET_OS_IPHONE + #define AudioGetCurrentHostTime CAHostTimeBase::GetCurrentTime + #define AudioConvertHostTimeToNanos CAHostTimeBase::ConvertToNanos + #endif +#endif + //*********************************************************************// // RtMidi Definitions //*********************************************************************// From 67049ae194284bbc6771e9e1cdc4912082558e07 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Wed, 10 Feb 2016 11:15:59 -0300 Subject: [PATCH 046/388] Add doc/Makefile.in and tests/Makefile.in to .gitignore. --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 9f747efb..89424779 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ /autom4te.cache /configure /m4 +/doc/Makefile.in +/tests/Makefile.in From 58f85d4372c6efbf8974904ed3a5f428248dfdfb Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Wed, 10 Feb 2016 11:39:44 -0300 Subject: [PATCH 047/388] Force doxygen to run before making dist. --- Makefile.am | 4 +--- doc/Makefile.am | 4 +++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 19fbacd8..2382ae47 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,7 +17,5 @@ rtmidi_inc_HEADERS = \ pkgconfigdatadir = $(libdir)/pkgconfig pkgconfigdata_DATA = rtmidi.pc -EXTRA_DIST = autogen.sh readme doc msw +EXTRA_DIST = autogen.sh readme msw -dist-hook: - $(MAKE) -C doc diff --git a/doc/Makefile.am b/doc/Makefile.am index 6a52d94c..b670116b 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -9,7 +9,7 @@ EXTRA_DIST=html INSTIMAGES=html/doxygen.png -DOC_STAMPS=html-build.stamp +DOC_STAMPS=doxygen-build.stamp DOC_DIR=$(HTML_DIR) @@ -29,3 +29,5 @@ clean-local: distclean-local: clean rm -f *.stamp || true if test -d html; then rm -rf html; fi + +html-local: $(DOC_STAMPS) From 4bd9fa407cf841914356b060baf4411dfa74b339 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Wed, 10 Feb 2016 16:19:06 -0300 Subject: [PATCH 048/388] Use the same options for all test programs. This stops automake from generating filenames like "midiprobe-midiprobe.o". --- tests/Makefile.am | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index b6bdcec6..c086634f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,22 +1,19 @@ noinst_PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest -midiprobe_CXXFLAGS = -Wall -I$(top_srcdir) +AM_CXXFLAGS = -Wall -I$(top_srcdir) + midiprobe_SOURCES = midiprobe.cpp midiprobe_LDADD = $(top_builddir)/librtmidi.la -midiout_CXXFLAGS = -Wall -I$(top_srcdir) midiout_SOURCES = midiout.cpp midiout_LDADD = $(top_builddir)/librtmidi.la -qmidiin_CXXFLAGS = -Wall -I$(top_srcdir) qmidiin_SOURCES = qmidiin.cpp qmidiin_LDADD = $(top_builddir)/librtmidi.la -cmidiin_CXXFLAGS = -Wall -I$(top_srcdir) cmidiin_SOURCES = cmidiin.cpp cmidiin_LDADD = $(top_builddir)/librtmidi.la -sysextest_CXXFLAGS = -Wall -I$(top_srcdir) sysextest_SOURCES = sysextest.cpp sysextest_LDADD = $(top_builddir)/librtmidi.la From ebc8bb330a076a62df9da7bb56520e561130f806 Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Thu, 11 Feb 2016 10:46:39 -0500 Subject: [PATCH 049/388] Documentation updates for new release --- doc/doxygen/footer.html | 2 +- doc/doxygen/tutorial.txt | 57 ++++++++++++++++++++-------------------- doc/release.txt | 4 +-- 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/doc/doxygen/footer.html b/doc/doxygen/footer.html index 82ae6c69..8e9922c3 100644 --- a/doc/doxygen/footer.html +++ b/doc/doxygen/footer.html @@ -1,7 +1,7 @@


    -
    ©2003-2014 Gary P. Scavone, McGill University. All Rights Reserved.
    +
    ©2003-2016 Gary P. Scavone, McGill University. All Rights Reserved.
    Maintained by Gary P. Scavone, gary at music.mcgill.ca
    diff --git a/doc/doxygen/tutorial.txt b/doc/doxygen/tutorial.txt index 3b211ad1..0236ece7 100644 --- a/doc/doxygen/tutorial.txt +++ b/doc/doxygen/tutorial.txt @@ -6,24 +6,22 @@ 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 whatsnew What's New (Version 2.1) +\section whatsnew What's New (Version 2.1.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. +There were no API changes made in the current release. The primary changes involved updates to the build system and some small bug fixes. With respect to the previous release (2.1.0), 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 code was moved to a separate branch because it was uncompilable and incomplete. \section download Download -Latest Release (30 March 2014): Version 2.1.0 +Latest Release (11 February 2016): Version 2.1.1 \section start Getting Started @@ -417,30 +415,31 @@ RtMidi was originally developed with Visual C++ version 6.0 but has been tested RtMidi is on github (https://github.com/thestk/rtmidi). Many thanks to the developers that are helping to maintain and improve RtMidi. In years past, the following people provided bug fixes and improvements: -
      -
    • Sebastien Alaiwan (JACK memory leaks, Windows kernel streaming)
    • -
    • Jean-Baptiste Berruchon (Windows sysex code)
    • -
    • Pedro Lopez-Cabanillas (ALSA sequencer API, client naming)
    • -
    • Jason Champion (MSW project file for library build)
    • -
    • Eduardo Coutinho (Windows device names)
    • -
    • Paul Dean (increment optimization)
    • -
    • Luc Deschenaux (sysex issues)
    • -
    • John Dey (OS-X timestamps)
    • -
    • Christoph Eckert (ALSA sysex fixes)
    • -
    • Martin Koegler (various fixes)
    • -
    • Immanuel Litzroth (OS-X sysex fix)
    • -
    • Jon McCormack (Snow Leopard updates)
    • -
    • Axel Schmidt (client naming)
    • -
    • Alexander Svetalkin (JACK MIDI)
    • -
    • Casey Tucker (OS-X driver information, sysex sending)
    • -
    • Bastiaan Verreijt (Windows sysex multi-buffer code)
    • -
    • Dan Wilcox
    • -
    + +- Stephen Sinclair (Git repo and build system) +- Atsushi Eno (C API) +- Sebastien Alaiwan (JACK memory leaks, Windows kernel streaming) +- Jean-Baptiste Berruchon (Windows sysex code) +- Pedro Lopez-Cabanillas (ALSA sequencer API, client naming) +- Jason Champion (MSW project file for library build) +- Eduardo Coutinho (Windows device names) +- Paul Dean (increment optimization) +- Luc Deschenaux (sysex issues) +- John Dey (OS-X timestamps) +- Christoph Eckert (ALSA sysex fixes) +- Martin Koegler (various fixes) +- Immanuel Litzroth (OS-X sysex fix) +- Jon McCormack (Snow Leopard updates) +- Axel Schmidt (client naming) +- Alexander Svetalkin (JACK MIDI) +- Casey Tucker (OS-X driver information, sysex sending) +- Bastiaan Verreijt (Windows sysex multi-buffer code) +- Dan Wilcox \section license License RtMidi: realtime MIDI i/o C++ classes
    - Copyright (c) 2003-2014 Gary P. Scavone + Copyright (c) 2003-2016 Gary P. Scavone Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff --git a/doc/release.txt b/doc/release.txt index ded9722f..e1bfdad9 100644 --- a/doc/release.txt +++ b/doc/release.txt @@ -1,8 +1,8 @@ -RtMidi - a set of C++ classes that provides a common API for realtime MIDI input/output across Linux (ALSA & JACK), Macintosh OS X (CoreMidi & JACK), and Windows (Multimedia, Kernel Streaming). +RtMidi - a set of C++ classes that provides a common API for realtime MIDI input/output across Linux (ALSA & JACK), Macintosh OS X (CoreMidi & JACK), and Windows (Multimedia Library). By Gary P. Scavone, 2003-2016 -v2.1.1: (?? February 2016) +v2.1.1: (11 February 2016) - updates to automake routines - added C API (thanks to Atsushi Eno!) - JACK ringbuffer allocation change From 10a1c64d3932b85ba1a8ff36d67c12fb5ea03685 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Fri, 12 Feb 2016 11:19:33 -0300 Subject: [PATCH 050/388] Ensure version consistency by generating from configure in rtmidi.pc and Doxyfile. --- configure.ac | 3 +-- doc/doxygen/{Doxyfile => Doxyfile.in} | 2 +- rtmidi.pc.in | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) rename doc/doxygen/{Doxyfile => Doxyfile.in} (99%) diff --git a/configure.ac b/configure.ac index a7ef102f..4caafb50 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_INIT(RtMidi, 2.1.1, gary@music.mcgill.ca, rtmidi) AC_CONFIG_AUX_DIR(config) AC_CONFIG_SRCDIR(RtMidi.cpp) -AC_CONFIG_FILES([rtmidi-config rtmidi.pc Makefile tests/Makefile doc/Makefile]) +AC_CONFIG_FILES([rtmidi-config rtmidi.pc Makefile tests/Makefile doc/Makefile doc/doxygen/Doxyfile]) AM_INIT_AUTOMAKE([1.14 -Wall -Werror foreign subdir-objects]) # libtool version: current:revision:age @@ -83,7 +83,6 @@ AC_CHECK_PROG( DOXYGEN, [doxygen], [doxygen] ) AM_CONDITIONAL( MAKE_DOC, [test "x${DOXYGEN}" != x] ) # Copy doc files to build dir if necessary -AC_CONFIG_LINKS( [doc/doxygen/Doxyfile:doc/doxygen/Doxyfile] ) AC_CONFIG_LINKS( [doc/doxygen/footer.html:doc/doxygen/footer.html] ) AC_CONFIG_LINKS( [doc/doxygen/header.html:doc/doxygen/header.html] ) AC_CONFIG_LINKS( [doc/doxygen/tutorial.txt:doc/doxygen/tutorial.txt] ) diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile.in similarity index 99% rename from doc/doxygen/Doxyfile rename to doc/doxygen/Doxyfile.in index 29cc59a3..13429638 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile.in @@ -32,7 +32,7 @@ PROJECT_NAME = RtMidi # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 2.1.0 +PROJECT_NUMBER = @PACKAGE_VERSION # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer diff --git a/rtmidi.pc.in b/rtmidi.pc.in index c94652ba..b5365f6a 100644 --- a/rtmidi.pc.in +++ b/rtmidi.pc.in @@ -5,7 +5,7 @@ includedir=${prefix}/include/rtmidi Name: librtmidi Description: RtMidi - a set of C++ classes that provide a common API for realtime MIDI input/output -Version: 2.1.0 +Version: @PACKAGE_VERSION@ Requires: @req@ Libs: -L${libdir} -lrtmidi Libs.private: -lpthread From 6a98946a8a4683f2980a88d31f50b85c2757cf1f Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Fri, 12 Feb 2016 12:08:13 -0300 Subject: [PATCH 051/388] Add a test to configure.ac to ensure RtMidi.h defines the same version number. --- configure.ac | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/configure.ac b/configure.ac index 4caafb50..1fee36d3 100644 --- a/configure.ac +++ b/configure.ac @@ -28,6 +28,15 @@ m4_define([lt_current_minus_age], [m4_eval(lt_current - lt_age)]) SO_VERSION=lt_version_info AC_SUBST(SO_VERSION) +# Check version number coherency between RtMidi.h and configure.ac +AC_MSG_CHECKING([that version numbers are coherent]) +AC_RUN_IFELSE( + [AC_LANG_PROGRAM([#include + `grep "define RTMIDI_VERSION" $srcdir/RtMidi.h`], + [return strcmp(RTMIDI_VERSION, PACKAGE_VERSION);])], + [AC_MSG_RESULT([yes])], + [AC_MSG_FAILURE([testing RTMIDI_VERSION==PACKAGE_VERSION failed, check that RtMidi.h defines RTMIDI_VERSION as "$PACKAGE_VERSION" or that the first line of configure.ac has been updated.])]) + # Enable some nice automake features if they are available m4_ifdef([AM_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) From 62851ebf86e0b3f9372c040440e0f5613e45b237 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Fri, 12 Feb 2016 11:20:26 -0300 Subject: [PATCH 052/388] Remove some now-unused AC_SUBST from configure.ac. --- configure.ac | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/configure.ac b/configure.ac index a7ef102f..8f9c3db3 100644 --- a/configure.ac +++ b/configure.ac @@ -93,16 +93,6 @@ AC_CONFIG_LINKS( [doc/images/mcgill.gif:doc/images/mcgill.gif] ) # 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) From d162da85675eed0fe549c4c201930b06dd4b206b Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Fri, 12 Feb 2016 11:21:16 -0300 Subject: [PATCH 053/388] Make the m4 and config directories before checking for autoreconf. --- autogen.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/autogen.sh b/autogen.sh index bf28ad9d..8bd52e88 100755 --- a/autogen.sh +++ b/autogen.sh @@ -21,6 +21,10 @@ fi exit 1 } +# Make some directories required by automake, if they don't exist +if ! [ -d config ]; then mkdir -v config; fi +if ! [ -d m4 ]; then mkdir -v m4; fi + if ! autoreconf --version /dev/null 2>&1 then @@ -67,10 +71,6 @@ if test "$DIE" -eq 1; then exit 1 fi -# Make some directories required by automake, if they don't exist -if ! [ -d config ]; then mkdir -v config; fi -if ! [ -d m4 ]; then mkdir -v m4; fi - case $CC in xlc ) am_opt=--include-deps;; From 0b6b494b8a11cca520173cadfcd330dfa0ad55c4 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Mon, 15 Feb 2016 18:30:50 -0300 Subject: [PATCH 054/388] Add missing tests/*.{dsp,dsw} files and doc/release.txt to the dist. --- doc/Makefile.am | 2 +- tests/Makefile.am | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/Makefile.am b/doc/Makefile.am index b670116b..f22d2a3d 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -5,7 +5,7 @@ CLEANFILES=doxygen-build.stamp DOX=Doxyfile -EXTRA_DIST=html +EXTRA_DIST=html release.txt INSTIMAGES=html/doxygen.png diff --git a/tests/Makefile.am b/tests/Makefile.am index c086634f..6fd7db27 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -17,3 +17,6 @@ cmidiin_LDADD = $(top_builddir)/librtmidi.la sysextest_SOURCES = sysextest.cpp sysextest_LDADD = $(top_builddir)/librtmidi.la + +EXTRA_DIST = cmidiin.dsp midiout.dsp midiprobe.dsp qmidiin.dsp \ + sysextest.dsp RtMidi.dsw From 80a215822db0f1dfd7d4870837f6229f38732aae Mon Sep 17 00:00:00 2001 From: Martin Delille Date: Tue, 16 Feb 2016 10:18:06 +0100 Subject: [PATCH 055/388] add error number when MidiInCore::initialize fails --- RtMidi.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index ce6db637..c4c5d4d1 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -570,7 +570,9 @@ void MidiInCore :: initialize( const std::string& clientName ) CFStringRef name = CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ); OSStatus result = MIDIClientCreate(name, NULL, NULL, &client ); if ( result != noErr ) { - errorString_ = "MidiInCore::initialize: error creating OS-X MIDI client object."; + std::ostringstream ost; + ost << "MidiInCore::initialize: error creating OS-X MIDI client object (" << result << ")."; + errorString_ = ost.str(); error( RtMidiError::DRIVER_ERROR, errorString_ ); return; } From a8d9a6a5c917d376f29211adc94ecbb8be463bcc Mon Sep 17 00:00:00 2001 From: Martin Delille Date: Tue, 16 Feb 2016 15:17:26 +0100 Subject: [PATCH 056/388] add error number when MidiOutCore::initialize fails --- RtMidi.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index c4c5d4d1..9a898133 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -861,7 +861,9 @@ void MidiOutCore :: initialize( const std::string& clientName ) CFStringRef name = CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ); OSStatus result = MIDIClientCreate(name, NULL, NULL, &client ); if ( result != noErr ) { - errorString_ = "MidiOutCore::initialize: error creating OS-X MIDI client object."; + std::ostringstream ost; + ost << "MidiInCore::initialize: error creating OS-X MIDI client object (" << result << ")."; + errorString_ = ost.str(); error( RtMidiError::DRIVER_ERROR, errorString_ ); return; } From 3e6e8da345693bb3f4ab491e2360f7a60e48255b Mon Sep 17 00:00:00 2001 From: Martin Delille Date: Thu, 4 Feb 2016 16:45:54 +0100 Subject: [PATCH 057/388] travis script --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..17f5df7b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +os: osx +language: cpp +compiler: +- clang +- gcc +before_script: ./autogen.sh +script: make From b37dca58ea8b323f77b59c4b6e56edbb47291d40 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Wed, 27 Jul 2016 15:50:27 -0400 Subject: [PATCH 058/388] Use Travis to check "make distcheck" --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 17f5df7b..b824ca5b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,4 +4,4 @@ compiler: - clang - gcc before_script: ./autogen.sh -script: make +script: make distcheck From 5d1ddd1d03700d34dfca46f6495682a890927946 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Wed, 27 Jul 2016 15:59:40 -0400 Subject: [PATCH 059/388] add doxygen to travis to fix make distcheck --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b824ca5b..f9c33fb6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,5 +3,8 @@ language: cpp compiler: - clang - gcc -before_script: ./autogen.sh +before_script: +- brew update +- brew install doxygen +- ./autogen.sh script: make distcheck From ba8329dcc41c574a60f7df7d2ea22799f027b4d5 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Wed, 27 Jul 2016 16:10:38 -0400 Subject: [PATCH 060/388] fix travis' broken glibtoolize --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index f9c33fb6..3ccb26d5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,8 @@ compiler: - gcc before_script: - brew update +- brew unlink libtool +- brew install libtool - brew install doxygen - ./autogen.sh script: make distcheck From a8d1414acb968d06d975a9b17c8d97a476f1e5c0 Mon Sep 17 00:00:00 2001 From: Martin Delille Date: Wed, 27 Jul 2016 10:37:12 +0200 Subject: [PATCH 061/388] Nice README with travis badge --- Makefile.am | 2 +- readme => README.md | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) rename readme => README.md (80%) diff --git a/Makefile.am b/Makefile.am index 3b800d48..1606cc77 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,5 +17,5 @@ rtmidi_inc_HEADERS = \ pkgconfigdatadir = $(libdir)/pkgconfig pkgconfigdata_DATA = rtmidi.pc -EXTRA_DIST = autogen.sh readme msw +EXTRA_DIST = autogen.sh README.md msw diff --git a/readme b/README.md similarity index 80% rename from readme rename to README.md index ece29dfe..f76dedcb 100644 --- a/readme +++ b/README.md @@ -1,17 +1,21 @@ -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). +# RtMidi + +[![Build Status](https://travis-ci.org/thestk/rtmidi.svg?branch=master)](https://travis-ci.org/thestk/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-2016. This distribution of RtMidi contains the following: -doc: RtMidi documentation (see doc/html/index.html) -tests: example RtMidi programs +- doc: [RtMidi documentation](doc/html/index.html) +- 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. +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 `autoconf` 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: @@ -22,14 +26,14 @@ 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/. -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-2016 Gary P. Scavone From 956f6b701c2337524a4e1811677fc8de6573938f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6stlin?= Date: Tue, 23 Aug 2016 20:17:41 +0200 Subject: [PATCH 062/388] using samples to provide code examples in doxygen sample snippets are added to doc/doxygen/samples and included with \include into doxygen. this also means, that it is possible to compile the examples and check, if they are (still) compiling. --- doc/doxygen/Doxyfile.in | 2 +- doc/doxygen/samples/getting_started.cpp | 11 +++++++++++ doc/doxygen/tutorial.txt | 22 +--------------------- 3 files changed, 13 insertions(+), 22 deletions(-) create mode 100644 doc/doxygen/samples/getting_started.cpp diff --git a/doc/doxygen/Doxyfile.in b/doc/doxygen/Doxyfile.in index 13429638..acf7b9a6 100644 --- a/doc/doxygen/Doxyfile.in +++ b/doc/doxygen/Doxyfile.in @@ -729,7 +729,7 @@ EXCLUDE_SYMBOLS = # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = +EXAMPLE_PATH = samples # 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/samples/getting_started.cpp b/doc/doxygen/samples/getting_started.cpp new file mode 100644 index 00000000..d6f63771 --- /dev/null +++ b/doc/doxygen/samples/getting_started.cpp @@ -0,0 +1,11 @@ +#include "RtMidi.h" + +int main() { + try { + RtMidiIn midiin; + } catch (RtMidiError &error) { + // Handle the exception here + error.printMessage(); + } + return 0; +} diff --git a/doc/doxygen/tutorial.txt b/doc/doxygen/tutorial.txt index 0236ece7..c8661c98 100644 --- a/doc/doxygen/tutorial.txt +++ b/doc/doxygen/tutorial.txt @@ -27,27 +27,7 @@ Latest Release (11 February 2016): Date: Mon, 12 Sep 2016 12:17:59 +0300 Subject: [PATCH 063/388] Initialize firstErrorOccurred_ to prevent losing all errors, forever. Note that this does not fix the race condition. Fixes #79. --- RtMidi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 339bb02a..6809b333 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -231,7 +231,7 @@ RtMidiOut :: ~RtMidiOut() throw() //*********************************************************************// MidiApi :: MidiApi( void ) - : apiData_( 0 ), connected_( false ), errorCallback_(0), errorCallbackUserData_(0) + : apiData_( 0 ), connected_( false ), errorCallback_(0), firstErrorOccurred_(false), errorCallbackUserData_(0) { } From c7ed35bcab46fae05c77a68c54f9b46701ebb96e Mon Sep 17 00:00:00 2001 From: aib Date: Sun, 18 Sep 2016 13:54:00 +0300 Subject: [PATCH 064/388] Return actual port names in getPortName when using ALSA --- RtMidi.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RtMidi.cpp b/RtMidi.cpp index 6809b333..7feaec45 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1445,6 +1445,8 @@ 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 << ":"; + os << snd_seq_port_info_get_name( pinfo ); 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 << ":"; @@ -1744,6 +1746,8 @@ 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 << ":"; + os << snd_seq_port_info_get_name( pinfo ); 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 << ":"; From 4950a420c49cecbbba6209767150f4343fdbc5e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Mou=C3=ABza?= Date: Mon, 22 Feb 2016 08:03:48 +0100 Subject: [PATCH 065/388] Capture exceptions in the C api. Change the RtMidi*Ptr types to a simple structure. Capture the exceptions thrown by RtMidi in the C api functions. Use the new RtMidi*Ptr types to store the status and error message on error. This leaves the C API mostly unchanged but allows the handling of error in bindings to other languages (especially for dlang). --- rtmidi_c.cpp | 224 +++++++++++++++++++++++++++++++++++++++++---------- rtmidi_c.h | 13 ++- 2 files changed, 191 insertions(+), 46 deletions(-) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index b259e625..cabc29bd 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -44,52 +44,124 @@ void rtmidi_error (MidiApi *api, enum RtMidiErrorType type, const char* errorStr void rtmidi_open_port (RtMidiPtr device, unsigned int portNumber, const char *portName) { - std::string name = portName; - ((RtMidi*) device)->openPort (portNumber, name); + std::string name = portName; + try { + ((RtMidi*) device->ptr)->openPort (portNumber, name); + + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + } } void rtmidi_open_virtual_port (RtMidiPtr device, const char *portName) { - std::string name = portName; - ((RtMidi*) device)->openVirtualPort (name); + std::string name = portName; + try { + ((RtMidi*) device->ptr)->openVirtualPort (name); + + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + } + } void rtmidi_close_port (RtMidiPtr device) { - ((RtMidi*) device)->closePort (); + try { + ((RtMidi*) device->ptr)->closePort (); + + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + } } unsigned int rtmidi_get_port_count (RtMidiPtr device) { - return ((RtMidi*) device)->getPortCount (); + try { + return ((RtMidi*) device->ptr)->getPortCount (); + + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + return -1; + } } const char* rtmidi_get_port_name (RtMidiPtr device, unsigned int portNumber) { - std::string name = ((RtMidi*) device)->getPortName (portNumber); - return strdup (name.c_str ()); + try { + std::string name = ((RtMidi*) device->ptr)->getPortName (portNumber); + return strdup (name.c_str ()); + + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + return ""; + } } /* RtMidiIn API */ RtMidiInPtr rtmidi_in_create_default () { - return new RtMidiIn (); + RtMidiWrapper* wrp = new RtMidiWrapper; + + try { + RtMidiIn* rIn = new RtMidiIn (); + + wrp->ptr = (void*) rIn; + wrp->ok = true; + wrp->msg = ""; + + } catch (const RtMidiError & err) { + wrp->ptr = 0; + wrp->ok = false; + wrp->msg = err.what (); + } + + return wrp; } 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); + std::string name = clientName; + RtMidiWrapper* wrp = new RtMidiWrapper; + + try { + RtMidiIn* rIn = new RtMidiIn ((RtMidi::Api) api, name, queueSizeLimit); + + wrp->ptr = (void*) rIn; + wrp->ok = true; + wrp->msg = ""; + + } catch (const RtMidiError & err) { + wrp->ptr = 0; + wrp->ok = false; + wrp->msg = err.what (); + } + + return wrp; } void rtmidi_in_free (RtMidiInPtr device) { - delete (RtMidiIn*) device; + delete (RtMidiIn*) device->ptr; + delete device; } enum RtMidiApi rtmidi_in_get_current_api (RtMidiPtr device) { - return (RtMidiApi) ((RtMidiIn*) device)->getCurrentApi (); + try { + return (RtMidiApi) ((RtMidiIn*) device->ptr)->getCurrentApi (); + + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + + return RT_MIDI_API_UNSPECIFIED; + } } class CallbackProxyUserData @@ -111,13 +183,25 @@ 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); + try { + void *data = (void *) new CallbackProxyUserData (callback, userData); + ((RtMidiIn*) device->ptr)->setCallback (callback_proxy, data); + + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + } } void rtmidi_in_cancel_callback (RtMidiInPtr device) { - ((RtMidiIn*) device)->cancelCallback (); + try { + ((RtMidiIn*) device->ptr)->cancelCallback (); + + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + } } void rtmidi_in_ignore_types (RtMidiInPtr device, bool midiSysex, bool midiTime, bool midiSense) @@ -127,51 +211,107 @@ void rtmidi_in_ignore_types (RtMidiInPtr device, bool midiSysex, bool midiTime, 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); - *message = (unsigned char *) malloc ((int) ret); - memcpy (*message, v->data (), (int) ret); - delete v; - return ret; - } catch (...) { - return -1; - } + try { + // FIXME: use allocator to achieve efficient buffering + std::vector *v = new std::vector (); + double ret = ((RtMidiIn*) device->ptr)->getMessage (v); + *message = (unsigned char *) malloc ((int) ret); + memcpy (*message, v->data (), (int) ret); + delete v; + return ret; + } + catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + return -1; + } + catch (...) { + device->ok = false; + device->msg = "Unknown error"; + return -1; + } } /* RtMidiOut API */ RtMidiOutPtr rtmidi_out_create_default () { - return new RtMidiOut (); + RtMidiWrapper* wrp = new RtMidiWrapper; + + try { + RtMidiOut* rOut = new RtMidiOut (); + + wrp->ptr = (void*) rOut; + wrp->ok = true; + wrp->msg = ""; + + } catch (const RtMidiError & err) { + wrp->ptr = 0; + wrp->ok = false; + wrp->msg = err.what (); + } + + return wrp; } RtMidiOutPtr rtmidi_out_create (enum RtMidiApi api, const char *clientName) { - std::string name = clientName; - return new RtMidiOut ((RtMidi::Api) api, name); + RtMidiWrapper* wrp = new RtMidiWrapper; + std::string name = clientName; + + try { + RtMidiOut* rOut = new RtMidiOut ((RtMidi::Api) api, name); + + wrp->ptr = (void*) rOut; + wrp->ok = true; + wrp->msg = ""; + + } catch (const RtMidiError & err) { + wrp->ptr = 0; + wrp->ok = false; + wrp->msg = err.what (); + } + + + return wrp; } void rtmidi_out_free (RtMidiOutPtr device) { - delete (RtMidiOut*) device; + delete (RtMidiOut*) device->ptr; + delete device; } enum RtMidiApi rtmidi_out_get_current_api (RtMidiPtr device) { - return (RtMidiApi) ((RtMidiOut*) device)->getCurrentApi (); + try { + return (RtMidiApi) ((RtMidiOut*) device->ptr)->getCurrentApi (); + + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + + return RT_MIDI_API_UNSPECIFIED; + } } int rtmidi_out_send_message (RtMidiOutPtr device, const unsigned char *message, int length) { - try { - // FIXME: use allocator to achieve efficient buffering - std::vector *v = new std::vector (length); - memcpy (v->data (), message, length); - ((RtMidiOut*) device)->sendMessage (v); - delete v; - return 0; - } catch (...) { - return -1; - } + try { + // FIXME: use allocator to achieve efficient buffering + std::vector *v = new std::vector (length); + memcpy (v->data (), message, length); + ((RtMidiOut*) device->ptr)->sendMessage (v); + delete v; + return 0; + } + catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + return -1; + } + catch (...) { + device->ok = false; + device->msg = "Unknown error"; + return -1; + } } diff --git a/rtmidi_c.h b/rtmidi_c.h index c37b655c..d0c7f5a8 100644 --- a/rtmidi_c.h +++ b/rtmidi_c.h @@ -1,6 +1,5 @@ #include - #ifndef RTMIDI_C_H #define RTMIDI_C_H @@ -14,9 +13,15 @@ extern "C" { #endif -typedef void* RtMidiPtr; -typedef void* RtMidiInPtr; -typedef void* RtMidiOutPtr; +struct RtMidiWrapper { + void* ptr; + bool ok; + const char* msg; +}; + +typedef RtMidiWrapper* RtMidiPtr; +typedef RtMidiWrapper* RtMidiInPtr; +typedef RtMidiWrapper* RtMidiOutPtr; enum RtMidiApi { RT_MIDI_API_UNSPECIFIED, /*!< Search for a working compiled API. */ From d0a3ba0290c828f658b51d8e86b0f52e18c9af48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Mou=C3=ABza?= Date: Tue, 23 Feb 2016 21:23:56 +0100 Subject: [PATCH 066/388] C API change in rtmidi_in_get_message RtMidiIn::getMessage return an elapsed time in seconds. It was used to set the size of the message array pointer. We now use the vector size to allocate the needed memory for the message array pointer. We now take an extra argument: size_t * size, to give the caller the size of the created array. --- rtmidi_c.cpp | 13 ++++++++++--- rtmidi_c.h | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index cabc29bd..b267d2b8 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -209,14 +209,21 @@ void rtmidi_in_ignore_types (RtMidiInPtr device, bool midiSysex, bool midiTime, ((RtMidiIn*) device)->ignoreTypes (midiSysex, midiTime, midiSense); } -double rtmidi_in_get_message (RtMidiInPtr device, unsigned char **message) +double rtmidi_in_get_message (RtMidiInPtr device, + unsigned char **message, + size_t * size) { try { // FIXME: use allocator to achieve efficient buffering std::vector *v = new std::vector (); double ret = ((RtMidiIn*) device->ptr)->getMessage (v); - *message = (unsigned char *) malloc ((int) ret); - memcpy (*message, v->data (), (int) ret); + *size = v->size (); + + if (v->size () > 0) { + *message = (unsigned char *) + malloc (sizeof (unsigned char *) * (int) v->size ()); + memcpy (*message, v->data (), (int) v->size ()); + } delete v; return ret; } diff --git a/rtmidi_c.h b/rtmidi_c.h index d0c7f5a8..1434763f 100644 --- a/rtmidi_c.h +++ b/rtmidi_c.h @@ -61,7 +61,7 @@ RTMIDIAPI enum RtMidiApi rtmidi_in_get_current_api (RtMidiPtr device); RTMIDIAPI void rtmidi_in_set_callback (RtMidiInPtr device, RtMidiCCallback callback, void *userData); RTMIDIAPI void rtmidi_in_cancel_callback (RtMidiInPtr device); RTMIDIAPI void rtmidi_in_ignore_types (RtMidiInPtr device, bool midiSysex, bool midiTime, bool midiSense); -RTMIDIAPI double rtmidi_in_get_message (RtMidiInPtr device, unsigned char **message); +RTMIDIAPI double rtmidi_in_get_message (RtMidiInPtr device, unsigned char **message, size_t * size); /* RtMidiOut API */ RTMIDIAPI RtMidiOutPtr rtmidi_out_create_default (); From f8d9bb56bf76d505028b08f6786c1fda9e0acd90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Mou=C3=ABza?= Date: Fri, 26 Feb 2016 00:46:59 +0100 Subject: [PATCH 067/388] Fix: `device->ptr` in rtmidi_in_ignore_types. The use of `->ptr` had been removed when cleaning the sources before the previous commit. --- rtmidi_c.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index b267d2b8..5148a718 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -206,7 +206,7 @@ void rtmidi_in_cancel_callback (RtMidiInPtr device) void rtmidi_in_ignore_types (RtMidiInPtr device, bool midiSysex, bool midiTime, bool midiSense) { - ((RtMidiIn*) device)->ignoreTypes (midiSysex, midiTime, midiSense); + ((RtMidiIn*) device->ptr)->ignoreTypes (midiSysex, midiTime, midiSense); } double rtmidi_in_get_message (RtMidiInPtr device, From be726488a6447ca3fa9054798fd16c1af2b5804c Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Tue, 11 Oct 2016 12:40:35 -0300 Subject: [PATCH 068/388] Example program for MIDI clock messages. --- tests/Makefile.am | 8 +- tests/midiclock.cpp | 228 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 tests/midiclock.cpp diff --git a/tests/Makefile.am b/tests/Makefile.am index 6fd7db27..d120d982 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,5 +1,5 @@ -noinst_PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest +noinst_PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest midiclock_in midiclock_out AM_CXXFLAGS = -Wall -I$(top_srcdir) @@ -18,5 +18,11 @@ cmidiin_LDADD = $(top_builddir)/librtmidi.la sysextest_SOURCES = sysextest.cpp sysextest_LDADD = $(top_builddir)/librtmidi.la +midiclock_in_SOURCES = midiclock.cpp +midiclock_in_LDADD = $(top_builddir)/librtmidi.la + +midiclock_out_SOURCES = midiclock.cpp +midiclock_out_LDADD = $(top_builddir)/librtmidi.la + EXTRA_DIST = cmidiin.dsp midiout.dsp midiprobe.dsp qmidiin.dsp \ sysextest.dsp RtMidi.dsw diff --git a/tests/midiclock.cpp b/tests/midiclock.cpp new file mode 100644 index 00000000..bf06e72e --- /dev/null +++ b/tests/midiclock.cpp @@ -0,0 +1,228 @@ +//*****************************************// +// midiclock.cpp +// +// Simple program to test MIDI clock sync. Run midiclock_in in one +// console and midiclock_out in the other, make sure to choose +// options that connect the clocks between programs on your platform. +// +// (C)2016 Refer to README.md in this archive for copyright. +// +//*****************************************// + +#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 + +// These functions 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 chooseInputPort( RtMidiIn *rtmidi ); +bool chooseOutputPort( RtMidiOut *rtmidi ); + +void mycallback( double deltatime, std::vector< unsigned char > *message, void *user ) +{ + unsigned int *clock_count = reinterpret_cast(user); + + // Ignore longer messages + if (message->size() != 1) + return; + + unsigned int msg = message->at(0); + if (msg == 0xFA) + std::cout << "START received" << std::endl; + if (msg == 0xFB) + std::cout << "CONTINUE received" << std::endl; + if (msg == 0xFC) + std::cout << "STOP received" << std::endl; + if (msg == 0xF8) { + if (++*clock_count == 24) { + double bpm = 60.0 / 24.0 / deltatime; + printf("Quarter note, estimated BPM = %f\n", bpm); + *clock_count = 0; + } + } + else + *clock_count = 0; +} + +int clock_in() +{ + RtMidiIn *midiin = 0; + unsigned int clock_count = 0; + + try { + + // RtMidiIn constructor + midiin = new RtMidiIn(); + + // Call function to select port. + if ( chooseInputPort( midiin ) == false ) goto cleanup; + + // 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, &clock_count ); + + // 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(); + } + + cleanup: + + delete midiin; + + return 0; +} + +int clock_out() +{ + RtMidiOut *midiout = 0; + std::vector message; + int sleep_ms = 0, k = 0, j = 0; + + // RtMidiOut constructor + try { + midiout = new RtMidiOut(); + } + catch ( RtMidiError &error ) { + error.printMessage(); + exit( EXIT_FAILURE ); + } + + // Call function to select port. + try { + if ( chooseOutputPort( midiout ) == false ) goto cleanup; + } + catch ( RtMidiError &error ) { + error.printMessage(); + goto cleanup; + } + + // Period in ms = 90 BPM + // 90*24 ticks / 1 minute, so (60*1000) / (90*24) ~= 28 ms / tick + sleep_ms = 28; + + // Send out a series of MIDI clock messages. + // MIDI start + message.clear(); + message.push_back( 0xFA ); + midiout->sendMessage( &message ); + std::cout << "MIDI start" << std::endl; + + for (j=0; j < 8; j++) + { + if (j > 0) + { + // MIDI continue + message.clear(); + message.push_back( 0xFB ); + midiout->sendMessage( &message ); + std::cout << "MIDI continue" << std::endl; + } + + for (k=0; k < 96; k++) { + // MIDI clock + message.clear(); + message.push_back( 0xF8 ); + midiout->sendMessage( &message ); + if (k % 16 == 0) + std::cout << "MIDI clock (1/16)" << std::endl; + SLEEP( sleep_ms ); + } + + // MIDI stop + message.clear(); + message.push_back( 0xFC ); + midiout->sendMessage( &message ); + std::cout << "MIDI stop" << std::endl; + SLEEP( 500 ); + } + + // MIDI stop + message.clear(); + message.push_back( 0xFC ); + midiout->sendMessage( &message ); + std::cout << "MIDI stop" << std::endl; + + SLEEP( 500 ); + + std::cout << "Done!" << std::endl; + + // Clean up + cleanup: + delete midiout; + + return 0; +} + +int main( int, const char *argv[] ) +{ + std::string prog(argv[0]); + if (prog.find("midiclock_in") != prog.npos) { + clock_in(); + } + else if (prog.find("midiclock_out") != prog.npos) { + clock_out(); + } + else { + std::cout << "Don't know what to do as " << prog << std::endl; + } + return 0; +} + +template +bool choosePort( RT *rtmidi, const char *dir ) +{ + std::string portName; + unsigned int i = 0, nPorts = rtmidi->getPortCount(); + if ( nPorts == 0 ) { + std::cout << "No " << dir << " ports available!" << std::endl; + return false; + } + + if ( nPorts == 1 ) { + std::cout << "\nOpening " << rtmidi->getPortName() << std::endl; + } + else { + for ( i=0; igetPortName(i); + std::cout << " " << dir << " port #" << i << ": " << portName << '\n'; + } + + do { + std::cout << "\nChoose a port number: "; + std::cin >> i; + } while ( i >= nPorts ); + } + + std::cout << "\n"; + rtmidi->openPort( i ); + + return true; +} + +bool chooseInputPort( RtMidiIn *rtmidi ) +{ + return choosePort( rtmidi, "input" ); +} + +bool chooseOutputPort( RtMidiOut *rtmidi ) +{ + return choosePort( rtmidi, "output" ); +} From 4424bdcc900d2f4531be198c82933c8483ec496a Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Tue, 11 Oct 2016 13:00:52 -0300 Subject: [PATCH 069/388] midiclock: Output desired BPM and fix the printed text --- tests/midiclock.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/midiclock.cpp b/tests/midiclock.cpp index bf06e72e..8d2badf8 100644 --- a/tests/midiclock.cpp +++ b/tests/midiclock.cpp @@ -46,7 +46,7 @@ void mycallback( double deltatime, std::vector< unsigned char > *message, void * if (msg == 0xF8) { if (++*clock_count == 24) { double bpm = 60.0 / 24.0 / deltatime; - printf("Quarter note, estimated BPM = %f\n", bpm); + printf("One beat, estimated BPM = %f\n", bpm); *clock_count = 0; } } @@ -117,6 +117,9 @@ int clock_out() // Period in ms = 90 BPM // 90*24 ticks / 1 minute, so (60*1000) / (90*24) ~= 28 ms / tick sleep_ms = 28; + std::cout << "Generating clock at " + << (60.0 / 24.0 / sleep_ms * 1000.0) + << " BPM." << std::endl; // Send out a series of MIDI clock messages. // MIDI start @@ -141,8 +144,8 @@ int clock_out() message.clear(); message.push_back( 0xF8 ); midiout->sendMessage( &message ); - if (k % 16 == 0) - std::cout << "MIDI clock (1/16)" << std::endl; + if (k % 24 == 0) + std::cout << "MIDI clock (one beat)" << std::endl; SLEEP( sleep_ms ); } From 1ab310ae9fc7b5041a2bffa9e5b974222d9314aa Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Tue, 11 Oct 2016 13:05:56 -0300 Subject: [PATCH 070/388] midiclock: use 100 bpm instead of 90 to use an integer number of ms. --- tests/midiclock.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/midiclock.cpp b/tests/midiclock.cpp index 8d2badf8..19bb91ff 100644 --- a/tests/midiclock.cpp +++ b/tests/midiclock.cpp @@ -114,9 +114,9 @@ int clock_out() goto cleanup; } - // Period in ms = 90 BPM - // 90*24 ticks / 1 minute, so (60*1000) / (90*24) ~= 28 ms / tick - sleep_ms = 28; + // Period in ms = 100 BPM + // 100*24 ticks / 1 minute, so (60*1000) / (100*24) = 25 ms / tick + sleep_ms = 25; std::cout << "Generating clock at " << (60.0 / 24.0 / sleep_ms * 1000.0) << " BPM." << std::endl; From 0aeb77e42f7c02b31403f42fe95000135d0e8dcc Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Tue, 11 Oct 2016 14:20:25 -0300 Subject: [PATCH 071/388] Remove travis libtool "fix" which now broke, and appears not to be needed anymore. --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3ccb26d5..f9c33fb6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,6 @@ compiler: - gcc before_script: - brew update -- brew unlink libtool -- brew install libtool - brew install doxygen - ./autogen.sh script: make distcheck From 4487feb46001524debbd7f3de7e9ce87b13dd7b4 Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Thu, 13 Oct 2016 08:35:50 -0400 Subject: [PATCH 072/388] Documentation link update in README. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f76dedcb..04fbdb75 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ By Gary P. Scavone, 2003-2016. This distribution of RtMidi contains the following: -- doc: [RtMidi documentation](doc/html/index.html) +- doc: RtMidi documentation (also online at http://music.mcgill.ca/~gary/rtmidi/) - 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. From 819688f21a470fcac8a80c2a1da88dceff02d765 Mon Sep 17 00:00:00 2001 From: johnty Date: Tue, 25 Oct 2016 17:01:47 -0400 Subject: [PATCH 073/388] changed printf to std::cout to fix compile error + make consistent with rest of program --- tests/midiclock.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/midiclock.cpp b/tests/midiclock.cpp index 19bb91ff..babf4f9f 100644 --- a/tests/midiclock.cpp +++ b/tests/midiclock.cpp @@ -46,7 +46,7 @@ void mycallback( double deltatime, std::vector< unsigned char > *message, void * if (msg == 0xF8) { if (++*clock_count == 24) { double bpm = 60.0 / 24.0 / deltatime; - printf("One beat, estimated BPM = %f\n", bpm); + std::cout << "One beat, estimated BPM = " << bpm < Date: Fri, 16 Dec 2016 12:29:21 +0100 Subject: [PATCH 074/388] C API: allocation strategy change and documentation In rtmidi_in_get_message, we no longer allocate the array pointed to by the message parameter. Instead, we assume it has already been allocated by the caller. This makes it easier to deal with the API from an external language (like C#) where there is no access to the `free()` C stdlib function but still can still pass a pointer to an array. Added some succint documentation in rtmidi_c.h --- rtmidi_c.cpp | 2 -- rtmidi_c.h | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 3 deletions(-) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index 5148a718..fdad494e 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -220,8 +220,6 @@ double rtmidi_in_get_message (RtMidiInPtr device, *size = v->size (); if (v->size () > 0) { - *message = (unsigned char *) - malloc (sizeof (unsigned char *) * (int) v->size ()); memcpy (*message, v->data (), (int) v->size ()); } delete v; diff --git a/rtmidi_c.h b/rtmidi_c.h index 1434763f..bff4f578 100644 --- a/rtmidi_c.h +++ b/rtmidi_c.h @@ -13,17 +13,29 @@ extern "C" { #endif +//! Wraps an RtMidi object for C function return statuses. struct RtMidiWrapper { + //! The wrapped RtMidi object. void* ptr; + + //! True when the last function call was OK. bool ok; + + //! If an error occured (ok != true), set to an error message. const char* msg; }; +//! Typedef for a generic RtMidi pointer. typedef RtMidiWrapper* RtMidiPtr; + +//! Typedef for a generic RtMidiIn pointer. typedef RtMidiWrapper* RtMidiInPtr; + +//! Typedef for a generic RtMidiOut pointer. typedef RtMidiWrapper* RtMidiOutPtr; - enum RtMidiApi { + +enum RtMidiApi { RT_MIDI_API_UNSPECIFIED, /*!< Search for a working compiled API. */ RT_MIDI_API_MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ RT_MIDI_API_LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ @@ -39,35 +51,118 @@ enum RtMidiErrorType { RT_ERROR_DRIVER_ERROR, RT_ERROR_SYSTEM_ERROR, RT_ERROR_THREAD_ERROR }; +/*! The type of a RtMidi callback function. + * \param timeStamp The time at which the message has been received. + * \param message The midi message. + * \param userData Additional user data for the callback. + */ typedef void(* RtMidiCCallback) (double timeStamp, const unsigned char* message, void *userData); +//! Returns the size (with sizeof) of a RtMidiApi instance. RTMIDIAPI int rtmidi_sizeof_rtmidi_api (); /* RtMidi API */ + +/*! Determine the available compiled MIDI APIs. + * If the given `apis` parameter is null, returns the number of available APIs. + * Otherwise, fill the given apis array with the RtMidi::Api values. + * + * \param apis An array or a null value. +*/ RTMIDIAPI int rtmidi_get_compiled_api (enum RtMidiApi **apis); // return length for NULL argument. + +//! Report an error. RTMIDIAPI void rtmidi_error (enum RtMidiErrorType type, const char* errorString); +/*! Open a MIDI port. + * + * \param port Must be greater than 0 + * \param portName Name for the application port. + */ RTMIDIAPI void rtmidi_open_port (RtMidiPtr device, unsigned int portNumber, const char *portName); + +/*! Creates a virtual MIDI port to which other software applications can + * connect. + * + * \param portName Name for the application port. + */ RTMIDIAPI void rtmidi_open_virtual_port (RtMidiPtr device, const char *portName); + +/*! Close a MIDI connection. + */ RTMIDIAPI void rtmidi_close_port (RtMidiPtr device); + +/*! Return the number of available MIDI ports. + */ RTMIDIAPI unsigned int rtmidi_get_port_count (RtMidiPtr device); + +/*! Return a string identifier for the specified MIDI input port number. + */ RTMIDIAPI const char* rtmidi_get_port_name (RtMidiPtr device, unsigned int portNumber); /* RtMidiIn API */ + +//! Create a default RtMidiInPtr value, with no initialization. RTMIDIAPI RtMidiInPtr rtmidi_in_create_default (); + +/*! Create a RtMidiInPtr value, with given api, clientName and queueSizeLimit. + * + * \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. + */ RTMIDIAPI RtMidiInPtr rtmidi_in_create (enum RtMidiApi api, const char *clientName, unsigned int queueSizeLimit); + +//! Deallocate the given pointer. RTMIDIAPI void rtmidi_in_free (RtMidiInPtr device); + +//! Returns the MIDI API specifier for the given instance of RtMidiIn. RTMIDIAPI enum RtMidiApi rtmidi_in_get_current_api (RtMidiPtr device); + +//! Set a callback function to be invoked for incoming MIDI messages. RTMIDIAPI void rtmidi_in_set_callback (RtMidiInPtr device, RtMidiCCallback callback, void *userData); + +//! Cancel use of the current callback function (if one exists). RTMIDIAPI void rtmidi_in_cancel_callback (RtMidiInPtr device); + +//! Specify whether certain MIDI message types should be queued or ignored during input. RTMIDIAPI void rtmidi_in_ignore_types (RtMidiInPtr device, bool midiSysex, bool midiTime, bool midiSense); + +/*! Fill the user-provided array with the data bytes for the next available + * MIDI message in the input queue and return the event delta-time in seconds. + * + * \param message Must point to a char* that is already allocated. + * SYSEX messages maximum size being 1024, a statically + * allocated array could + * be sufficient. + * \param size Is used to return the size of the message obtained. + */ RTMIDIAPI double rtmidi_in_get_message (RtMidiInPtr device, unsigned char **message, size_t * size); /* RtMidiOut API */ + +//! Create a default RtMidiInPtr value, with no initialization. RTMIDIAPI RtMidiOutPtr rtmidi_out_create_default (); + +/*! Create a RtMidiOutPtr value, with given and clientName. + * + * \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. + */ RTMIDIAPI RtMidiOutPtr rtmidi_out_create (enum RtMidiApi api, const char *clientName); + +//! Deallocate the given pointer. RTMIDIAPI void rtmidi_out_free (RtMidiOutPtr device); + +//! Returns the MIDI API specifier for the given instance of RtMidiOut. RTMIDIAPI enum RtMidiApi rtmidi_out_get_current_api (RtMidiPtr device); + +//! Immediately send a single message out an open MIDI output port. RTMIDIAPI int rtmidi_out_send_message (RtMidiOutPtr device, const unsigned char *message, int length); From a13522c26380992decd4bd9beeb083a1e69382e3 Mon Sep 17 00:00:00 2001 From: Saga Musix Date: Mon, 6 Feb 2017 21:27:58 +0100 Subject: [PATCH 075/388] Avoid "unreferenced formal parameter" warning in dummy API. --- RtMidi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RtMidi.h b/RtMidi.h index 1f0175ed..6d3cff20 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -736,7 +736,7 @@ class MidiInDummy: public MidiInApi void openVirtualPort( const std::string /*portName*/ ) {} 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*/ ) {} From cf0035fba862d69990c68a8892b791094f21f116 Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Wed, 15 Feb 2017 14:10:32 -0500 Subject: [PATCH 076/388] Added port name message when connecting in qmidiin.cpp --- tests/qmidiin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qmidiin.cpp b/tests/qmidiin.cpp index afd112b0..dbd9fdf6 100644 --- a/tests/qmidiin.cpp +++ b/tests/qmidiin.cpp @@ -77,7 +77,7 @@ int main( int argc, char *argv[] ) (void) signal(SIGINT, finish); // Periodically check input queue. - std::cout << "Reading MIDI from port ... quit with Ctrl-C.\n"; + std::cout << "Reading MIDI from port " << midiin->getPortName() << " ... quit with Ctrl-C.\n"; while ( !done ) { stamp = midiin->getMessage( &message ); nBytes = message.size(); From 7338b8f22d06c04b3fe7b96952ac5591838b2797 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Thu, 2 Mar 2017 15:40:28 -0300 Subject: [PATCH 077/388] C api: track CallbackProxyUserData and delete it Fixes #104. --- rtmidi_c.cpp | 39 +++++++++++++++++++++++---------------- rtmidi_c.h | 1 + 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index 5148a718..3b6577c3 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -3,6 +3,17 @@ #include "rtmidi_c.h" #include "RtMidi.h" +class CallbackProxyUserData +{ + public: + CallbackProxyUserData (RtMidiCCallback cCallback, void *userData) + : c_callback (cCallback), user_data (userData) + { + } + RtMidiCCallback c_callback; + void *user_data; +}; + /* misc */ int rtmidi_sizeof_rtmidi_api () { @@ -133,11 +144,13 @@ RtMidiInPtr rtmidi_in_create (enum RtMidiApi api, const char *clientName, unsign RtMidiIn* rIn = new RtMidiIn ((RtMidi::Api) api, name, queueSizeLimit); wrp->ptr = (void*) rIn; + wrp->data = 0; wrp->ok = true; wrp->msg = ""; } catch (const RtMidiError & err) { - wrp->ptr = 0; + wrp->ptr = 0; + wrp->data = 0; wrp->ok = false; wrp->msg = err.what (); } @@ -147,6 +160,8 @@ RtMidiInPtr rtmidi_in_create (enum RtMidiApi api, const char *clientName, unsign void rtmidi_in_free (RtMidiInPtr device) { + if (device->data) + delete (CallbackProxyUserData*) device->data; delete (RtMidiIn*) device->ptr; delete device; } @@ -164,17 +179,7 @@ enum RtMidiApi rtmidi_in_get_current_api (RtMidiPtr device) } } -class CallbackProxyUserData -{ - public: - CallbackProxyUserData (RtMidiCCallback cCallback, void *userData) - : c_callback (cCallback), user_data (userData) - { - } - RtMidiCCallback c_callback; - void *user_data; -}; - +static void callback_proxy (double timeStamp, std::vector *message, void *userData) { CallbackProxyUserData* data = reinterpret_cast (userData); @@ -183,13 +188,14 @@ void callback_proxy (double timeStamp, std::vector *message, void void rtmidi_in_set_callback (RtMidiInPtr device, RtMidiCCallback callback, void *userData) { + device->data = (void*) new CallbackProxyUserData (callback, userData); try { - void *data = (void *) new CallbackProxyUserData (callback, userData); - ((RtMidiIn*) device->ptr)->setCallback (callback_proxy, data); - + ((RtMidiIn*) device->ptr)->setCallback (callback_proxy, device->data); } catch (const RtMidiError & err) { device->ok = false; device->msg = err.what (); + delete (CallbackProxyUserData*) device->data; + device->data = 0; } } @@ -197,7 +203,8 @@ void rtmidi_in_cancel_callback (RtMidiInPtr device) { try { ((RtMidiIn*) device->ptr)->cancelCallback (); - + delete (CallbackProxyUserData*) device->data; + device->data = 0; } catch (const RtMidiError & err) { device->ok = false; device->msg = err.what (); diff --git a/rtmidi_c.h b/rtmidi_c.h index 1434763f..01b1bfc5 100644 --- a/rtmidi_c.h +++ b/rtmidi_c.h @@ -15,6 +15,7 @@ extern "C" { struct RtMidiWrapper { void* ptr; + void* data; bool ok; const char* msg; }; From 27cb06529f0c8c9a390b0c28fad4eaa3dbc57634 Mon Sep 17 00:00:00 2001 From: emlai Date: Sun, 16 Apr 2017 04:20:34 +0300 Subject: [PATCH 078/388] Fix CFStringRef memory leak in MidiOutCore::openPort CFRelease call was missing for the temporary CFStringRef. --- RtMidi.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 6809b333..e6263a44 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -945,9 +945,11 @@ void MidiOutCore :: openPort( unsigned int portNumber, const std::string portNam MIDIPortRef port; CoreMidiData *data = static_cast (apiData_); + CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ); OSStatus result = MIDIOutputPortCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), + portNameRef, &port ); + CFRelease( portNameRef ); if ( result != noErr ) { MIDIClientDispose( data->client ); errorString_ = "MidiOutCore::openPort: error creating OS-X MIDI output port."; From caa8ec5c9c2dbcb1741aa7fbc4285d43b6aa8fab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Micha=C3=ABl=20Celerier?= Date: Fri, 21 Apr 2017 17:01:32 +0200 Subject: [PATCH 079/388] MidiInAlsa::portInfo: don't filter SND_SEQ_PORT_TYPE_APPLICATION This patch makes PureData visible to RtMidi on Linux with alsa --- RtMidi.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 6809b333..0ea84588 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1409,7 +1409,9 @@ unsigned int portInfo( snd_seq_t *seq, snd_seq_port_info_t *pinfo, unsigned int 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 ) && - ( ( atyp & SND_SEQ_PORT_TYPE_SYNTH ) == 0 ) ) continue; + ( ( atyp & SND_SEQ_PORT_TYPE_SYNTH ) == 0 ) && + ( ( atyp & SND_SEQ_PORT_TYPE_APPLICATION ) == 0 ) ) continue; + unsigned int caps = snd_seq_port_info_get_capability( pinfo ); if ( ( caps & type ) != type ) continue; if ( count == portNumber ) return 1; From c87a1d276b92d09a6dadf54eb5260dd348e08b9d Mon Sep 17 00:00:00 2001 From: Jake Sandlund Date: Sat, 17 Jun 2017 13:57:32 -0500 Subject: [PATCH 080/388] Add struct and stddef to get compiling under gcc happy --- rtmidi_c.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rtmidi_c.h b/rtmidi_c.h index 01b1bfc5..65939ca3 100644 --- a/rtmidi_c.h +++ b/rtmidi_c.h @@ -1,5 +1,6 @@ #include +#include #ifndef RTMIDI_C_H #define RTMIDI_C_H @@ -20,9 +21,9 @@ struct RtMidiWrapper { const char* msg; }; -typedef RtMidiWrapper* RtMidiPtr; -typedef RtMidiWrapper* RtMidiInPtr; -typedef RtMidiWrapper* RtMidiOutPtr; +typedef struct RtMidiWrapper* RtMidiPtr; +typedef struct RtMidiWrapper* RtMidiInPtr; +typedef struct RtMidiWrapper* RtMidiOutPtr; enum RtMidiApi { RT_MIDI_API_UNSPECIFIED, /*!< Search for a working compiled API. */ From b506b4379e41a02c4780069372feea33acd1dd3f Mon Sep 17 00:00:00 2001 From: Saga Musix Date: Mon, 26 Jun 2017 00:15:11 +0200 Subject: [PATCH 081/388] Make sendMessage parameter const --- RtMidi.cpp | 8 ++++---- RtMidi.h | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 6e84a455..b35dd52e 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1013,7 +1013,7 @@ void MidiOutCore :: openVirtualPort( std::string portName ) data->endpoint = endpoint; } -void MidiOutCore :: sendMessage( std::vector *message ) +void MidiOutCore :: sendMessage( const std::vector *message ) { // We use the MIDISendSysex() function to asynchronously send sysex // messages. Otherwise, we use a single CoreMidi MIDIPacket. @@ -1852,7 +1852,7 @@ void MidiOutAlsa :: openVirtualPort( std::string portName ) } } -void MidiOutAlsa :: sendMessage( std::vector *message ) +void MidiOutAlsa :: sendMessage( const std::vector *message ) { int result; AlsaMidiData *data = static_cast (apiData_); @@ -2349,7 +2349,7 @@ void MidiOutWinMM :: openVirtualPort( std::string /*portName*/ ) error( RtMidiError::WARNING, errorString_ ); } -void MidiOutWinMM :: sendMessage( std::vector *message ) +void MidiOutWinMM :: sendMessage( const std::vector *message ) { if ( !connected_ ) return; @@ -2833,7 +2833,7 @@ void MidiOutJack :: closePort() data->port = NULL; } -void MidiOutJack :: sendMessage( std::vector *message ) +void MidiOutJack :: sendMessage( const std::vector *message ) { int nBytes = message->size(); JackMidiData *data = static_cast (apiData_); diff --git a/RtMidi.h b/RtMidi.h index 6d3cff20..1c04c98d 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -406,7 +406,7 @@ class RtMidiOut : public RtMidi An exception is thrown if an error occurs during output or an output connection was not previously established. */ - void sendMessage( std::vector *message ); + void sendMessage( const std::vector *message ); //! Set an error callback function to be invoked when an error has occured. /*! @@ -529,7 +529,7 @@ class MidiOutApi : public MidiApi MidiOutApi( void ); virtual ~MidiOutApi( void ); - virtual void sendMessage( std::vector *message ) = 0; + virtual void sendMessage( const std::vector *message ) = 0; }; // **************************************************************** // @@ -558,7 +558,7 @@ 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 :: sendMessage( const std::vector *message ) { ((MidiOutApi *)rtapi_)->sendMessage( message ); } inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); } // **************************************************************** // @@ -600,7 +600,7 @@ class MidiOutCore: public MidiOutApi void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector *message ); + void sendMessage( const std::vector *message ); protected: void initialize( const std::string& clientName ); @@ -640,7 +640,7 @@ class MidiOutJack: public MidiOutApi void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector *message ); + void sendMessage( const std::vector *message ); protected: std::string clientName; @@ -680,7 +680,7 @@ class MidiOutAlsa: public MidiOutApi void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector *message ); + void sendMessage( const std::vector *message ); protected: void initialize( const std::string& clientName ); @@ -717,7 +717,7 @@ class MidiOutWinMM: public MidiOutApi void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector *message ); + void sendMessage( const std::vector *message ); protected: void initialize( const std::string& clientName ); @@ -752,7 +752,7 @@ class MidiOutDummy: public MidiOutApi void closePort( void ) {} unsigned int getPortCount( void ) { return 0; } std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } - void sendMessage( std::vector * /*message*/ ) {} + void sendMessage( const std::vector * /*message*/ ) {} protected: void initialize( const std::string& /*clientName*/ ) {} From 2b4e5ab07933d0252052e34fb9489c06deb01549 Mon Sep 17 00:00:00 2001 From: Saga Musix Date: Mon, 26 Jun 2017 00:18:29 +0200 Subject: [PATCH 082/388] Avoid unnecessary vector allocation on heap --- rtmidi_c.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index 3b6577c3..1fbb1aff 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -222,16 +222,15 @@ double rtmidi_in_get_message (RtMidiInPtr device, { try { // FIXME: use allocator to achieve efficient buffering - std::vector *v = new std::vector (); - double ret = ((RtMidiIn*) device->ptr)->getMessage (v); - *size = v->size (); + std::vector v; + double ret = ((RtMidiIn*) device->ptr)->getMessage (&v); + *size = v.size (); - if (v->size () > 0) { + if (v.size () > 0) { *message = (unsigned char *) - malloc (sizeof (unsigned char *) * (int) v->size ()); - memcpy (*message, v->data (), (int) v->size ()); + malloc (sizeof (unsigned char *) * (int) v.size ()); + memcpy (*message, v.data (), (int) v.size ()); } - delete v; return ret; } catch (const RtMidiError & err) { @@ -312,10 +311,8 @@ int rtmidi_out_send_message (RtMidiOutPtr device, const unsigned char *message, { try { // FIXME: use allocator to achieve efficient buffering - std::vector *v = new std::vector (length); - memcpy (v->data (), message, length); - ((RtMidiOut*) device->ptr)->sendMessage (v); - delete v; + std::vector v (message, message + length); + ((RtMidiOut*) device->ptr)->sendMessage (&v); return 0; } catch (const RtMidiError & err) { From a849761cb5c2bea7863eb8e30e95707951e08bc7 Mon Sep 17 00:00:00 2001 From: Tiago Morais Morgado Date: Sun, 23 Jul 2017 13:14:01 +0100 Subject: [PATCH 083/388] fixing a couple of typos --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 04fbdb75..8c961ca3 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ This distribution of RtMidi contains the following: - doc: RtMidi documentation (also online at http://music.mcgill.ca/~gary/rtmidi/) - 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. +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`. @@ -33,7 +33,7 @@ For complete documentation on RtMidi, see the doc directory of the distribution ## 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 MIT License, with the added *feature* that modifications be sent to the developer. RtMidi: realtime MIDI i/o C++ classes Copyright (c) 2003-2016 Gary P. Scavone @@ -49,9 +49,7 @@ The RtMidi license is similar to the the MIT License, with the added *feature* t 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, + 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, From 42b2156b928af257c211dfb55f1745ceeff8e78f Mon Sep 17 00:00:00 2001 From: garyscavone Date: Mon, 21 Aug 2017 11:47:44 -0700 Subject: [PATCH 084/388] Create issue template --- .github/issue_template.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/issue_template.md diff --git a/.github/issue_template.md b/.github/issue_template.md new file mode 100644 index 00000000..f95f70d1 --- /dev/null +++ b/.github/issue_template.md @@ -0,0 +1,7 @@ +The maintainers / developers of RtMidi favour pull requests over issues. We generally do not have access to all the supported platforms to attempt to verify a reported problem. It will help the entire RtMidi community if you can debug a problem you are reporting and suggest a way to fix it yourself. + +- Expected behavior and actual behavior. + +- Steps to reproduce the problem. + +- Specifications like the version of the project, operating system, or hardware. From 26c77d45e0502b78f51aa8d244c5cb791978e5bd Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Tue, 22 Aug 2017 11:42:24 -0300 Subject: [PATCH 085/388] Add a flag to disable appending Win32 port name identifier Closes #100. --- RtMidi.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/RtMidi.cpp b/RtMidi.cpp index 9ca883e6..41eb7b4f 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -46,6 +46,10 @@ #endif #endif +// Default for Windows is to add an identifier to the port names; this +// flag can be undefined to disable this behaviour. +#define RTMIDI_ENSURE_UNIQUE_PORTNAMES + //*********************************************************************// // RtMidi Definitions //*********************************************************************// @@ -2216,10 +2220,12 @@ std::string MidiInWinMM :: getPortName( unsigned int portNumber ) // Next lines added to add the portNumber to the name so that // the device's names are sure to be listed with individual names // even when they have the same brand name +#ifdef RTMIDI_ENSURE_UNIQUE_PORTNAMES std::ostringstream os; os << " "; os << portNumber; stringName += os.str(); +#endif return stringName; } @@ -2291,9 +2297,11 @@ std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) // the device's names are sure to be listed with individual names // even when they have the same brand name std::ostringstream os; +#ifdef RTMIDI_ENSURE_UNIQUE_PORTNAMES os << " "; os << portNumber; stringName += os.str(); +#endif return stringName; } From 88ebcca388cfcd43eb1c8773628ba638e721b4f4 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Tue, 22 Aug 2017 12:09:54 -0300 Subject: [PATCH 086/388] C api: don't assume message array has enough room Now "size" argument must contain size of message array! --- rtmidi_c.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index c9430865..2c76fa91 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -224,11 +224,12 @@ double rtmidi_in_get_message (RtMidiInPtr device, // FIXME: use allocator to achieve efficient buffering std::vector v; double ret = ((RtMidiIn*) device->ptr)->getMessage (&v); - *size = v.size (); - if (v.size () > 0) { + if (v.size () > 0 && v.size() <= *size) { memcpy (*message, v.data (), (int) v.size ()); } + + *size = v.size(); return ret; } catch (const RtMidiError & err) { From c3328c0a83de96d96de15959ca21d6ba16219f92 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Tue, 22 Aug 2017 13:03:25 -0300 Subject: [PATCH 087/388] Improve time difference code for ALSA. --- RtMidi.cpp | 33 ++++++++++++++++++++++++++------- RtMidi.h | 2 ++ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 41eb7b4f..207929a8 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1116,7 +1116,7 @@ struct AlsaMidiData { unsigned char *buffer; pthread_t thread; pthread_t dummy_thread_id; - unsigned long long lastTime; + snd_seq_real_time_t lastTime; int queue_id; // an input queue is needed to get timestamped events int trigger_fds[2]; }; @@ -1134,7 +1134,7 @@ static void *alsaMidiHandler( void *ptr ) AlsaMidiData *apiData = static_cast (data->apiData); long nBytes; - unsigned long long time, lastTime; + double time; bool continueSysex = false; bool doDecode = false; MidiInApi::MidiMessage message; @@ -1276,14 +1276,33 @@ static void *alsaMidiHandler( void *ptr ) // 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; + + // Using method from: + // https://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html + + // Perform the carry for the later subtraction by updating y. + snd_seq_real_time_t &x(ev->time.time); + snd_seq_real_time_t &y(apiData->lastTime); + if (x.tv_nsec < y.tv_nsec) { + int nsec = (y.tv_nsec - x.tv_nsec) / 1000000000 + 1; + y.tv_nsec -= 1000000000 * nsec; + y.tv_sec += nsec; + } + if (x.tv_nsec - y.tv_nsec > 1000000000) { + int nsec = (x.tv_nsec - y.tv_nsec) / 1000000000; + y.tv_nsec += 1000000000 * nsec; + y.tv_sec -= nsec; + } + + // Compute the time difference. + time = x.tv_sec - y.tv_sec + (x.tv_nsec - y.tv_nsec)*1e-9; + + apiData->lastTime = ev->time.time; + if ( data->firstMessage == true ) data->firstMessage = false; else - message.timeStamp = time * 0.000001; + message.timeStamp = time; } else { #if defined(__RTMIDI_DEBUG__) diff --git a/RtMidi.h b/RtMidi.h index 1c04c98d..664cfb03 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -479,6 +479,8 @@ class MidiInApi : public MidiApi // 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. From e3097e2aee9ca7b84260c0044fd92dcc6fec84b9 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Tue, 22 Aug 2017 15:02:36 -0300 Subject: [PATCH 088/388] Functions for the RtMidiIn queue and remove "size" for improved thread safety. Hopefully improves or fixes #51. --- RtMidi.cpp | 98 +++++++++++++++++++++++++++++------------------------- RtMidi.h | 2 ++ 2 files changed, 55 insertions(+), 45 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 207929a8..cafd9ec0 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -349,16 +349,54 @@ double MidiInApi :: getMessage( std::vector *message ) 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; + double timeStamp; + if (!inputData_.queue.pop(message, &timeStamp)) + return 0.0; + + return timeStamp; +} + +bool MidiInApi::MidiQueue::push(const MidiInApi::MidiMessage& msg) +{ + // As long as we haven't reached our queue size limit, push the message. + unsigned int _back = back; + unsigned int _front = front; + unsigned int size; - return deltaTime; + if (back >= front) + size = back - front; + else + size = ringSize - front + back; + + if ( size < ringSize-1 ) + { + ring[back] = msg; + back = (back+1)%ringSize; + return true; + } + + return false; +} + +bool MidiInApi::MidiQueue::pop(std::vector *msg, double* timeStamp) +{ + unsigned int _back = back; + unsigned int _front = front; + unsigned int size; + + if (back >= front) + size = back - front; + else + size = ringSize - front + back; + + if (size == 0) + return false; + + // Copy queued message to the vector pointer argument and then "pop" it. + msg->assign( ring[front].bytes.begin(), ring[front].bytes.end() ); + *timeStamp = ring[front].timeStamp; + front = (front+1)%ringSize; + return true; } //*********************************************************************// @@ -474,13 +512,7 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void * } 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 + if (!data->queue.push(message)) std::cerr << "\nMidiInCore: message queue limit reached!!\n\n"; } message.bytes.clear(); @@ -538,13 +570,7 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void * } 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 + if (!data->queue.push(message)) std::cerr << "\nMidiInCore: message queue limit reached!!\n\n"; } message.bytes.clear(); @@ -1321,13 +1347,7 @@ static void *alsaMidiHandler( void *ptr ) } 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 + if (!data->queue.push(message)) std::cerr << "\nMidiInAlsa: message queue limit reached!!\n\n"; } } @@ -2050,14 +2070,8 @@ static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, } 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"; + if (!data->queue.push(message)) + std::cerr << "\nMidiInWinMM: message queue limit reached!!\n\n"; } // Clear the vector for the next input message. @@ -2530,13 +2544,7 @@ static int jackProcessIn( jack_nframes_t nframes, void *arg ) } 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 + if (!data->queue.push(message)) std::cerr << "\nMidiInJack: message queue limit reached!!\n\n"; } } diff --git a/RtMidi.h b/RtMidi.h index 664cfb03..cf49ce47 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -498,6 +498,8 @@ class MidiInApi : public MidiApi // Default constructor. MidiQueue() :front(0), back(0), size(0), ringSize(0) {} + bool push(const MidiMessage&); + bool pop(std::vector*, double*); }; // The RtMidiInData structure is used to pass private class data to From 4b7bf4f767d5b7b6e3da36d73eee36e035f9a562 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Tue, 22 Aug 2017 16:30:59 -0300 Subject: [PATCH 089/388] Use local copies of front/back indexes. --- RtMidi.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index cafd9ec0..8cfbe363 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -363,14 +363,14 @@ bool MidiInApi::MidiQueue::push(const MidiInApi::MidiMessage& msg) unsigned int _front = front; unsigned int size; - if (back >= front) - size = back - front; + if (_back >= _front) + size = _back - _front; else - size = ringSize - front + back; + size = ringSize - _front + _back; if ( size < ringSize-1 ) { - ring[back] = msg; + ring[_back] = msg; back = (back+1)%ringSize; return true; } @@ -384,17 +384,17 @@ bool MidiInApi::MidiQueue::pop(std::vector *msg, double* timeStam unsigned int _front = front; unsigned int size; - if (back >= front) - size = back - front; + if (_back >= _front) + size = _back - _front; else - size = ringSize - front + back; + size = ringSize - _front + _back; if (size == 0) return false; // Copy queued message to the vector pointer argument and then "pop" it. - msg->assign( ring[front].bytes.begin(), ring[front].bytes.end() ); - *timeStamp = ring[front].timeStamp; + msg->assign( ring[_front].bytes.begin(), ring[_front].bytes.end() ); + *timeStamp = ring[_front].timeStamp; front = (front+1)%ringSize; return true; } From 9a58b5df44f759318933cf333713a7879d6da5b1 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Tue, 22 Aug 2017 16:31:11 -0300 Subject: [PATCH 090/388] Invalidate port handles/endpoints when they are closed. Fixes #74. --- RtMidi.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/RtMidi.cpp b/RtMidi.cpp index 8cfbe363..bee07a00 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -710,10 +710,12 @@ void MidiInCore :: closePort( void ) if ( data->endpoint ) { MIDIEndpointDispose( data->endpoint ); + data->endpoint = 0; } if ( data->port ) { MIDIPortDispose( data->port ); + data->port = 0; } connected_ = false; @@ -1009,10 +1011,12 @@ void MidiOutCore :: closePort( void ) if ( data->endpoint ) { MIDIEndpointDispose( data->endpoint ); + data->endpoint = 0; } if ( data->port ) { MIDIPortDispose( data->port ); + data->port = 0; } connected_ = false; @@ -1880,6 +1884,7 @@ void MidiOutAlsa :: closePort( void ) AlsaMidiData *data = static_cast (apiData_); snd_seq_unsubscribe_port( data->seq, data->subscription ); snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; connected_ = false; } } @@ -2163,6 +2168,7 @@ 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 ); + data->inHandle = INVALID_HANDLE_VALUE; errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (PrepareHeader)."; error( RtMidiError::DRIVER_ERROR, errorString_ ); return; @@ -2172,6 +2178,7 @@ 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 ); + data->inHandle = INVALID_HANDLE_VALUE; errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (AddBuffer)."; error( RtMidiError::DRIVER_ERROR, errorString_ ); return; @@ -2181,6 +2188,7 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portN result = midiInStart( data->inHandle ); if ( result != MMSYSERR_NOERROR ) { midiInClose( data->inHandle ); + data->inHandle = INVALID_HANDLE_VALUE; errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port."; error( RtMidiError::DRIVER_ERROR, errorString_ ); return; @@ -2210,6 +2218,7 @@ void MidiInWinMM :: closePort( void ) delete [] data->sysexBuffer[i]; if ( result != MMSYSERR_NOERROR ) { midiInClose( data->inHandle ); + data->inHandle = INVALID_HANDLE_VALUE; errorString_ = "MidiInWinMM::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader)."; error( RtMidiError::DRIVER_ERROR, errorString_ ); return; @@ -2217,6 +2226,7 @@ void MidiInWinMM :: closePort( void ) } midiInClose( data->inHandle ); + data->inHandle = INVALID_HANDLE_VALUE; connected_ = false; LeaveCriticalSection( &(data->_mutex) ); } @@ -2383,6 +2393,7 @@ void MidiOutWinMM :: closePort( void ) WinMidiData *data = static_cast (apiData_); midiOutReset( data->outHandle ); midiOutClose( data->outHandle ); + data->outHandle = INVALID_HANDLE_VALUE; connected_ = false; } } From 837d6ad7a1c984102db30179c65bb66dbaf1af89 Mon Sep 17 00:00:00 2001 From: Saga Musix Date: Thu, 24 Aug 2017 23:03:12 +0200 Subject: [PATCH 091/388] Add sendMessage overload that does not force the user to allocate heap memory. --- RtMidi.cpp | 32 ++++++++++++++++---------------- RtMidi.h | 23 +++++++++++++++++------ 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index bee07a00..6ee9883c 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1047,11 +1047,11 @@ void MidiOutCore :: openVirtualPort( std::string portName ) data->endpoint = endpoint; } -void MidiOutCore :: sendMessage( const std::vector *message ) +void MidiOutCore :: sendMessage( const unsigned char *message, size_t size ) { // 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 = static_cast (size); if ( nBytes == 0 ) { errorString_ = "MidiOutCore::sendMessage: no data in message argument!"; error( RtMidiError::WARNING, errorString_ ); @@ -1062,7 +1062,7 @@ void MidiOutCore :: sendMessage( const std::vector *message ) CoreMidiData *data = static_cast (apiData_); OSStatus result; - if ( message->at(0) != 0xF0 && nBytes > 3 ) { + if ( message[0] != 0xF0 && nBytes > 3 ) { errorString_ = "MidiOutCore::sendMessage: message format problem ... not sysex but > 3 bytes?"; error( RtMidiError::WARNING, errorString_ ); return; @@ -1076,7 +1076,7 @@ void MidiOutCore :: sendMessage( const 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[nBytes - remainingBytes]; packet = MIDIPacketListAdd( packetList, listSize, packet, timeStamp, bytesForPacket, dataStartPtr); remainingBytes -= bytesForPacket; } @@ -1904,11 +1904,11 @@ void MidiOutAlsa :: openVirtualPort( std::string portName ) } } -void MidiOutAlsa :: sendMessage( const std::vector *message ) +void MidiOutAlsa :: sendMessage( const unsigned char *message, size_t size ) { int result; AlsaMidiData *data = static_cast (apiData_); - unsigned int nBytes = message->size(); + unsigned int nBytes = static_cast (size); if ( nBytes > data->bufferSize ) { data->bufferSize = nBytes; result = snd_midi_event_resize_buffer ( data->coder, nBytes); @@ -1931,7 +1931,7 @@ void MidiOutAlsa :: sendMessage( const std::vector *message ) 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); + for ( unsigned int i=0; ibuffer[i] = message[i]; result = snd_midi_event_encode( data->coder, data->buffer, (long)nBytes, &ev ); if ( result < (int)nBytes ) { errorString_ = "MidiOutAlsa::sendMessage: event parsing error!"; @@ -2405,11 +2405,11 @@ void MidiOutWinMM :: openVirtualPort( std::string /*portName*/ ) error( RtMidiError::WARNING, errorString_ ); } -void MidiOutWinMM :: sendMessage( const std::vector *message ) +void MidiOutWinMM :: sendMessage( const unsigned char *message, size_t size ) { if ( !connected_ ) return; - unsigned int nBytes = static_cast(message->size()); + unsigned int nBytes = static_cast(size); if ( nBytes == 0 ) { errorString_ = "MidiOutWinMM::sendMessage: message argument is empty!"; error( RtMidiError::WARNING, errorString_ ); @@ -2418,7 +2418,7 @@ void MidiOutWinMM :: sendMessage( const std::vector *message ) MMRESULT result; WinMidiData *data = static_cast (apiData_); - if ( message->at(0) == 0xF0 ) { // Sysex message + if ( message[0] == 0xF0 ) { // Sysex message // Allocate buffer for sysex data. char *buffer = (char *) malloc( nBytes ); @@ -2429,7 +2429,7 @@ void MidiOutWinMM :: sendMessage( const 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[i]; ++ptr; } @@ -2883,14 +2883,14 @@ void MidiOutJack :: closePort() data->port = NULL; } -void MidiOutJack :: sendMessage( const std::vector *message ) +void MidiOutJack :: sendMessage( const unsigned char *message, size_t size ) { - int nBytes = message->size(); + int nBytes = static_cast(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, + nBytes ); jack_ringbuffer_write( data->buffSize, ( char * ) &nBytes, sizeof( nBytes ) ); } diff --git a/RtMidi.h b/RtMidi.h index cf49ce47..cf0afbb8 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -408,6 +408,16 @@ class RtMidiOut : public RtMidi */ void sendMessage( const std::vector *message ); + //! 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 ); + //! 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 @@ -533,7 +543,7 @@ class MidiOutApi : public MidiApi MidiOutApi( void ); virtual ~MidiOutApi( void ); - virtual void sendMessage( const std::vector *message ) = 0; + virtual void sendMessage( const unsigned char *message, size_t size ) = 0; }; // **************************************************************** // @@ -562,7 +572,8 @@ inline void RtMidiOut :: closePort( void ) { rtapi_->closePort(); } inline bool RtMidiOut :: isPortOpen() const { return rtapi_->isPortOpen(); } inline unsigned int RtMidiOut :: getPortCount( void ) { return rtapi_->getPortCount(); } inline std::string RtMidiOut :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); } -inline void RtMidiOut :: sendMessage( const std::vector *message ) { ((MidiOutApi *)rtapi_)->sendMessage( message ); } +inline void RtMidiOut :: sendMessage( const std::vector *message ) { ((MidiOutApi *)rtapi_)->sendMessage( &message->at(0), message->size() ); } +inline void RtMidiOut :: sendMessage( const unsigned char *message, size_t size ) { ((MidiOutApi *)rtapi_)->sendMessage( message, size ); } inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); } // **************************************************************** // @@ -604,7 +615,7 @@ class MidiOutCore: public MidiOutApi void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); - void sendMessage( const std::vector *message ); + void sendMessage( const unsigned char *message, size_t size ); protected: void initialize( const std::string& clientName ); @@ -644,7 +655,7 @@ class MidiOutJack: public MidiOutApi void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); - void sendMessage( const std::vector *message ); + void sendMessage( const unsigned char *message, size_t size ); protected: std::string clientName; @@ -721,7 +732,7 @@ class MidiOutWinMM: public MidiOutApi void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); - void sendMessage( const std::vector *message ); + void sendMessage( const unsigned char *message, size_t size ); protected: void initialize( const std::string& clientName ); @@ -756,7 +767,7 @@ class MidiOutDummy: public MidiOutApi void closePort( void ) {} unsigned int getPortCount( void ) { return 0; } std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } - void sendMessage( const std::vector * /*message*/ ) {} + void sendMessage( const unsigned char * /*message*/, size_t /*size*/ ) {} protected: void initialize( const std::string& /*clientName*/ ) {} From 32b2578df516706a2f3f279b4b63b2f88764f258 Mon Sep 17 00:00:00 2001 From: Saga Musix Date: Thu, 24 Aug 2017 23:06:15 +0200 Subject: [PATCH 092/388] Compile fixes for WinMM --- RtMidi.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index bee07a00..72390ce8 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -2075,7 +2075,7 @@ static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, } else { // As long as we haven't reached our queue size limit, push the message. - if (!data->queue.push(message)) + if (!data->queue.push(apiData->message)) std::cerr << "\nMidiInWinMM: message queue limit reached!!\n\n"; } @@ -2168,7 +2168,7 @@ 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 ); - data->inHandle = INVALID_HANDLE_VALUE; + data->inHandle = 0; errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (PrepareHeader)."; error( RtMidiError::DRIVER_ERROR, errorString_ ); return; @@ -2178,7 +2178,7 @@ 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 ); - data->inHandle = INVALID_HANDLE_VALUE; + data->inHandle = 0; errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (AddBuffer)."; error( RtMidiError::DRIVER_ERROR, errorString_ ); return; @@ -2188,7 +2188,7 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portN result = midiInStart( data->inHandle ); if ( result != MMSYSERR_NOERROR ) { midiInClose( data->inHandle ); - data->inHandle = INVALID_HANDLE_VALUE; + data->inHandle = 0; errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port."; error( RtMidiError::DRIVER_ERROR, errorString_ ); return; @@ -2218,7 +2218,7 @@ void MidiInWinMM :: closePort( void ) delete [] data->sysexBuffer[i]; if ( result != MMSYSERR_NOERROR ) { midiInClose( data->inHandle ); - data->inHandle = INVALID_HANDLE_VALUE; + data->inHandle = 0; errorString_ = "MidiInWinMM::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader)."; error( RtMidiError::DRIVER_ERROR, errorString_ ); return; @@ -2226,7 +2226,7 @@ void MidiInWinMM :: closePort( void ) } midiInClose( data->inHandle ); - data->inHandle = INVALID_HANDLE_VALUE; + data->inHandle = 0; connected_ = false; LeaveCriticalSection( &(data->_mutex) ); } @@ -2393,7 +2393,7 @@ void MidiOutWinMM :: closePort( void ) WinMidiData *data = static_cast (apiData_); midiOutReset( data->outHandle ); midiOutClose( data->outHandle ); - data->outHandle = INVALID_HANDLE_VALUE; + data->outHandle = 0; connected_ = false; } } From 4257a55ae2f371d0f2d4ff81f942b313163f543a Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Fri, 25 Aug 2017 17:34:43 -0300 Subject: [PATCH 093/388] Fix sendMessage() alsa api prototype change. --- RtMidi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RtMidi.h b/RtMidi.h index cf0afbb8..83d8fe78 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -695,7 +695,7 @@ class MidiOutAlsa: public MidiOutApi void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); - void sendMessage( const std::vector *message ); + void sendMessage( const unsigned char *message, size_t size ); protected: void initialize( const std::string& clientName ); From df2eb488b5964f40b1fbb24b7bbb3ea348a1a1c9 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Fri, 25 Aug 2017 17:46:26 -0300 Subject: [PATCH 094/388] Fix call to queue.push in Jack. --- RtMidi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 72390ce8..af78afa8 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -2555,7 +2555,7 @@ static int jackProcessIn( jack_nframes_t nframes, void *arg ) } else { // As long as we haven't reached our queue size limit, push the message. - if (!data->queue.push(message)) + if (!rtData->queue.push(message)) std::cerr << "\nMidiInJack: message queue limit reached!!\n\n"; } } From 6fc0f5a571ff753cdcb23677309b80ac7d539443 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Sat, 26 Aug 2017 22:14:18 -0300 Subject: [PATCH 095/388] Don't check all libraries, use AS_IF. Fix AC_ARG_WITH usage to be like the manual suggests: https://autotools.io/autoconf/arguments.html --- configure.ac | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index 39b532cb..8262d402 100644 --- a/configure.ac +++ b/configure.ac @@ -112,11 +112,12 @@ case $host in AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], ) # Look for ALSA flag - AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA sequencer API support (linux only)], [ + AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA sequencer API support (linux only)]) + AS_IF([test "x$with_alsa" == "xyes"], [ 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!))], ) + 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) @@ -136,11 +137,12 @@ case $host in AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], ) # Look for Core flag - AC_ARG_WITH(core, [ --with-core = choose CoreMidi API support (mac only)], [ + AC_ARG_WITH(core, [ --with-core = choose CoreMidi API support (mac only)]) + AS_IF([test "x$with_core" == "xyes"], [ 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" ], ) + LIBS="$LIBS -framework CoreMIDI -framework CoreFoundation -framework CoreAudio" ]) # If no api flags specified, use CoreMidi if [test "$api" == ""; ] then @@ -155,15 +157,17 @@ case $host in *-mingw32*) # Look for WinMM flag - AC_ARG_WITH(winmm, [ --with-winmm = choose Windows MultiMedia (MM) API support (windoze only)], [ + AC_ARG_WITH(winmm, [ --with-winmm = choose Windows MultiMedia (MM) API support (windoze only)]) + AS_IF([test "x$with_winmm" == "xyes"], [ api="$api -D__WINDOWS_MM__" AC_MSG_RESULT(using WinMM) - AC_SUBST( LIBS, [-lwinmm] )], ) + AC_SUBST( LIBS, [-lwinmm] )]) - AC_ARG_WITH(winks, [ --with-winks = choose kernel streaming support (windoze only)], [ + AC_ARG_WITH(winks, [ --with-winks = choose kernel streaming support (windoze only)]) + AS_IF([test "x$with_winks" == "xyes"], [ api="$api -D__WINDOWS_KS__" AC_SUBST( LIBS, ["-lsetupapi -lksuser"] ) - AC_MSG_RESULT(using kernel streaming) ], ) + 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]) From 2d03b14389645fe619e7bcb24bcaf82cabff12dc Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Sat, 26 Aug 2017 23:38:22 -0300 Subject: [PATCH 096/388] Check for jack on all operating systems. --- configure.ac | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index 8262d402..eba4c1c3 100644 --- a/configure.ac +++ b/configure.ac @@ -104,13 +104,15 @@ AC_CANONICAL_HOST AC_SUBST( api, [""] ) AC_SUBST( req, [""] ) AC_MSG_CHECKING(for MIDI API) + +AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (mac and linux only)]) +AS_IF([test "x$with_jack" == "xyes"], [ +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!))]) + case $host in *-*-linux*) - AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (mac and linux only)], [ - 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!))], ) - # Look for ALSA flag AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA sequencer API support (linux only)]) AS_IF([test "x$with_alsa" == "xyes"], [ @@ -131,11 +133,6 @@ case $host in ;; *-apple*) - AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (mac and linux only)], [ - 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!))], ) - # Look for Core flag AC_ARG_WITH(core, [ --with-core = choose CoreMidi API support (mac only)]) AS_IF([test "x$with_core" == "xyes"], [ From ee4643b76397b451761137290f2873bc9cc636f1 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Sun, 27 Aug 2017 16:16:15 -0300 Subject: [PATCH 097/388] Use a pair of POSIX semaphores to ensure outgoing data on closePort (jack) Fixes #24. --- RtMidi.cpp | 32 ++++++++++++++++++++++++++++++++ configure.ac | 7 +++++++ 2 files changed, 39 insertions(+) diff --git a/RtMidi.cpp b/RtMidi.cpp index 95e9c8c4..da99681e 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -2500,6 +2500,9 @@ void MidiOutWinMM :: sendMessage( const unsigned char *message, size_t size ) #include #include #include +#ifdef HAVE_SEMAPHORE + #include +#endif #define JACK_RINGBUFFER_SIZE 16384 // Default size for ringbuffer @@ -2509,6 +2512,10 @@ struct JackMidiData { jack_ringbuffer_t *buffSize; jack_ringbuffer_t *buffMessage; jack_time_t lastTime; +#ifdef HAVE_SEMAPHORE + sem_t sem_cleanup; + sem_t sem_needpost; +#endif MidiInApi :: RtMidiInData *rtMidiIn; }; @@ -2730,6 +2737,11 @@ static int jackProcessOut( jack_nframes_t nframes, void *arg ) jack_ringbuffer_read( data->buffMessage, (char *) midiData, (size_t) space ); } +#ifdef HAVE_SEMAPHORE + if (!sem_trywait(&data->sem_needpost)) + sem_post(&data->sem_cleanup); +#endif + return 0; } @@ -2745,6 +2757,10 @@ void MidiOutJack :: initialize( const std::string& clientName ) data->port = NULL; data->client = NULL; +#ifdef HAVE_SEMAPHORE + sem_init(&data->sem_cleanup, 0, 0); + sem_init(&data->sem_needpost, 0, 0); +#endif this->clientName = clientName; connect(); @@ -2783,6 +2799,11 @@ MidiOutJack :: ~MidiOutJack() jack_client_close( data->client ); } +#ifdef HAVE_SEMAPHORE + sem_destroy(&data->sem_cleanup); + sem_destroy(&data->sem_needpost); +#endif + delete data; } @@ -2879,6 +2900,17 @@ void MidiOutJack :: closePort() JackMidiData *data = static_cast (apiData_); if ( data->port == NULL ) return; + +#ifdef HAVE_SEMAPHORE + struct timespec ts; + if (clock_gettime(CLOCK_REALTIME, &ts) != -1) + { + ts.tv_sec += 1; // wait max one second + sem_post(&data->sem_needpost); + sem_timedwait(&data->sem_cleanup, &ts); + } +#endif + jack_port_unregister( data->client, data->port ); data->port = NULL; } diff --git a/configure.ac b/configure.ac index eba4c1c3..018e7e22 100644 --- a/configure.ac +++ b/configure.ac @@ -60,6 +60,13 @@ AC_CONFIG_MACRO_DIR([m4]) AC_HEADER_STDC #AC_CHECK_HEADERS(sys/ioctl.h unistd.h) +# Check for POSIX semaphore support +AC_CHECK_HEADER([semaphore.h], [ + AC_CHECK_LIB(pthread, sem_init, + 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])) +]) + # Check for debug AC_MSG_CHECKING(whether to compile debug version) AC_ARG_ENABLE(debug, From 84ed63adee8116d2809eae69fb29b7abf8d24042 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Tue, 29 Aug 2017 16:17:22 -0300 Subject: [PATCH 098/388] CoreMIDI: request UTF-8 encoding in getPortName(). We have not in the past documented the string encoding semantics, so from here we now assume that user code should either expect UTF8 or know how to deal with it. Fixes #115. --- RtMidi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index da99681e..b96b0d20 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -871,7 +871,7 @@ 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; From 6f710049e58507d3f4201c13af8962388a25fdfd Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Tue, 29 Aug 2017 16:25:42 -0300 Subject: [PATCH 099/388] Documentation for getPortName utf-8 encoding. --- RtMidi.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RtMidi.h b/RtMidi.h index 83d8fe78..379f6df8 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -293,7 +293,8 @@ class RtMidiIn : public RtMidi //! 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. + \retval An empty string is returned if an invalid port specifier + is provided. User code should assume a UTF-8 encoding. */ std::string getPortName( unsigned int portNumber = 0 ); From e215b1fa3d5c7086ac0865b3a84e690a3cc2c99e Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Tue, 29 Aug 2017 16:31:06 -0300 Subject: [PATCH 100/388] Similar to last commits but for MidiOutCore. --- RtMidi.cpp | 2 +- RtMidi.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index b96b0d20..6a75d8c8 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -945,7 +945,7 @@ 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; diff --git a/RtMidi.h b/RtMidi.h index 379f6df8..0fea8e10 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -398,7 +398,9 @@ class RtMidiOut : public RtMidi //! 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. User code should assume a UTF-8 encoding. */ std::string getPortName( unsigned int portNumber = 0 ); From 4adb2275fb7ae3bd6f4f591112a8aabfd5149cf1 Mon Sep 17 00:00:00 2001 From: sagamusix Date: Wed, 30 Aug 2017 18:20:57 -0300 Subject: [PATCH 101/388] Ensure that port names are always UTF-8 on Windows even when not compiling as UNICODE. --- RtMidi.cpp | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 6a75d8c8..89463dce 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1971,6 +1971,34 @@ void MidiOutAlsa :: sendMessage( const unsigned char *message, size_t size ) #include #include +// Convert a null-terminated wide string or ANSI-encoded string to UTF-8. +static std::string ConvertToUTF8(const TCHAR *str) +{ + std::string u8str; + const WCHAR *wstr = L""; +#if defined( UNICODE ) || defined( _UNICODE ) + wstr = str; +#else + // Convert from ANSI encoding to wide string + int wlength = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); + std::wstring wstrtemp; + if ( wlength ) + { + wstrtemp.assign( wlength - 1, 0 ); + MultiByteToWideChar( CP_ACP, 0, str, -1, &wstrtemp[0], wlength ); + wstr = &wstrtemp[0]; + } +#endif + // Convert from wide string to UTF-8 + int length = WideCharToMultiByte( CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL ); + if ( length ) + { + u8str.assign( length - 1, 0 ); + length = WideCharToMultiByte( CP_UTF8, 0, wstr, -1, &u8str[0], length, NULL, NULL ); + } + return u8str; +} + #define RT_SYSEX_BUFFER_SIZE 1024 #define RT_SYSEX_BUFFER_COUNT 4 @@ -2251,14 +2279,7 @@ std::string MidiInWinMM :: getPortName( unsigned int portNumber ) 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 + stringName = ConvertToUTF8( deviceCaps.szPname ); // Next lines added to add the portNumber to the name so that // the device's names are sure to be listed with individual names @@ -2327,14 +2348,7 @@ std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) 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 + stringName = ConvertToUTF8( deviceCaps.szPname ); // Next lines added to add the portNumber to the name so that // the device's names are sure to be listed with individual names From d38c229014723a6dbc5f7b246f464708d01f588e Mon Sep 17 00:00:00 2001 From: Rory Jaffe Date: Wed, 30 Aug 2017 21:03:52 -0700 Subject: [PATCH 102/388] Remove unnecessary null ptr check before delete, add null ptr check for rtapi_. --- RtMidi.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 89463dce..beab7e4d 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -61,8 +61,7 @@ RtMidi :: RtMidi() RtMidi :: ~RtMidi() { - if ( rtapi_ ) - delete rtapi_; + delete rtapi_; rtapi_ = 0; } @@ -100,8 +99,7 @@ void RtMidi :: getCompiledApi( std::vector &apis ) throw() void RtMidiIn :: openMidiApi( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit ) { - if ( rtapi_ ) - delete rtapi_; + delete rtapi_; rtapi_ = 0; #if defined(__UNIX_JACK__) @@ -145,7 +143,7 @@ RtMidiIn :: RtMidiIn( RtMidi::Api api, const std::string clientName, unsigned in getCompiledApi( apis ); for ( unsigned int i=0; igetPortCount() ) break; + if ( rtapi_ && rtapi_->getPortCount() ) break; } if ( rtapi_ ) return; @@ -169,8 +167,7 @@ RtMidiIn :: ~RtMidiIn() throw() void RtMidiOut :: openMidiApi( RtMidi::Api api, const std::string clientName ) { - if ( rtapi_ ) - delete rtapi_; + delete rtapi_; rtapi_ = 0; #if defined(__UNIX_JACK__) @@ -213,7 +210,7 @@ RtMidiOut :: RtMidiOut( RtMidi::Api api, const std::string clientName ) getCompiledApi( apis ); for ( unsigned int i=0; igetPortCount() ) break; + if ( rtapi_ && rtapi_->getPortCount() ) break; } if ( rtapi_ ) return; From de22ecf99adc5ef3e071b1ab2937b07bf77a9239 Mon Sep 17 00:00:00 2001 From: Rory Jaffe Date: Wed, 30 Aug 2017 21:03:52 -0700 Subject: [PATCH 103/388] Change const std::string to reference for efficiency. --- RtMidi.cpp | 56 ++++++++++++++++----------------- RtMidi.h | 90 +++++++++++++++++++++++++++--------------------------- 2 files changed, 73 insertions(+), 73 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index beab7e4d..78c7d1ba 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -97,7 +97,7 @@ void RtMidi :: getCompiledApi( std::vector &apis ) throw() // RtMidiIn Definitions //*********************************************************************// -void RtMidiIn :: openMidiApi( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit ) +void RtMidiIn :: openMidiApi( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit ) { delete rtapi_; rtapi_ = 0; @@ -124,7 +124,7 @@ void RtMidiIn :: openMidiApi( RtMidi::Api api, const std::string clientName, uns #endif } -RtMidiIn :: RtMidiIn( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit ) +RtMidiIn :: RtMidiIn( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit ) : RtMidi() { if ( api != UNSPECIFIED ) { @@ -165,7 +165,7 @@ RtMidiIn :: ~RtMidiIn() throw() // RtMidiOut Definitions //*********************************************************************// -void RtMidiOut :: openMidiApi( RtMidi::Api api, const std::string clientName ) +void RtMidiOut :: openMidiApi( RtMidi::Api api, const std::string &clientName ) { delete rtapi_; rtapi_ = 0; @@ -192,7 +192,7 @@ void RtMidiOut :: openMidiApi( RtMidi::Api api, const std::string clientName ) #endif } -RtMidiOut :: RtMidiOut( RtMidi::Api api, const std::string clientName ) +RtMidiOut :: RtMidiOut( RtMidi::Api api, const std::string &clientName) { if ( api != UNSPECIFIED ) { // Attempt to open the specified API. @@ -580,7 +580,7 @@ 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 ); } @@ -620,7 +620,7 @@ void MidiInCore :: initialize( const std::string& clientName ) CFRelease(name); } -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!"; @@ -682,7 +682,7 @@ void MidiInCore :: openPort( unsigned int portNumber, const std::string portName connected_ = true; } -void MidiInCore :: openVirtualPort( const std::string portName ) +void MidiInCore :: openVirtualPort( const std::string &portName ) { CoreMidiData *data = static_cast (apiData_); @@ -879,7 +879,7 @@ std::string MidiInCore :: getPortName( unsigned int portNumber ) // Class Definitions: MidiOutCore //*********************************************************************// -MidiOutCore :: MidiOutCore( const std::string clientName ) : MidiOutApi() +MidiOutCore :: MidiOutCore( const std::string &clientName ) : MidiOutApi() { initialize( clientName ); } @@ -948,7 +948,7 @@ std::string MidiOutCore :: getPortName( unsigned int portNumber ) 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!"; @@ -1019,7 +1019,7 @@ void MidiOutCore :: closePort( void ) connected_ = false; } -void MidiOutCore :: openVirtualPort( std::string portName ) +void MidiOutCore :: openVirtualPort( const std::string &portName ) { CoreMidiData *data = static_cast (apiData_); @@ -1360,7 +1360,7 @@ 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 ); } @@ -1509,7 +1509,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!"; @@ -1617,7 +1617,7 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName connected_ = true; } -void MidiInAlsa :: openVirtualPort( std::string portName ) +void MidiInAlsa :: openVirtualPort( const std::string &portName ) { AlsaMidiData *data = static_cast (apiData_); if ( data->vport < 0 ) { @@ -1712,7 +1712,7 @@ void MidiInAlsa :: closePort( void ) // Class Definitions: MidiOutAlsa //*********************************************************************// -MidiOutAlsa :: MidiOutAlsa( const std::string clientName ) : MidiOutApi() +MidiOutAlsa :: MidiOutAlsa( const std::string &clientName ) : MidiOutApi() { initialize( clientName ); } @@ -1810,7 +1810,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!"; @@ -1886,7 +1886,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->vport < 0 ) { @@ -2108,7 +2108,7 @@ static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, apiData->message.bytes.clear(); } -MidiInWinMM :: MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) +MidiInWinMM :: MidiInWinMM( const std::string &clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { initialize( clientName ); } @@ -2147,7 +2147,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!"; @@ -2222,7 +2222,7 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portN 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. errorString_ = "MidiInWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; @@ -2296,7 +2296,7 @@ std::string MidiInWinMM :: getPortName( unsigned int portNumber ) // Class Definitions: MidiOutWinMM //*********************************************************************// -MidiOutWinMM :: MidiOutWinMM( const std::string clientName ) : MidiOutApi() +MidiOutWinMM :: MidiOutWinMM( const std::string &clientName ) : MidiOutApi() { initialize( clientName ); } @@ -2360,7 +2360,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!"; @@ -2409,7 +2409,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. errorString_ = "MidiOutWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; @@ -2582,7 +2582,7 @@ static int jackProcessIn( jack_nframes_t nframes, void *arg ) return 0; } -MidiInJack :: MidiInJack( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) +MidiInJack :: MidiInJack( const std::string &clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { initialize( clientName ); } @@ -2627,7 +2627,7 @@ MidiInJack :: ~MidiInJack() 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_); @@ -2649,7 +2649,7 @@ void MidiInJack :: openPort( unsigned int portNumber, const std::string portName jack_connect( data->client, name.c_str(), jack_port_name( data->port ) ); } -void MidiInJack :: openVirtualPort( const std::string portName ) +void MidiInJack :: openVirtualPort( const std::string &portName ) { JackMidiData *data = static_cast (apiData_); @@ -2756,7 +2756,7 @@ static int jackProcessOut( jack_nframes_t nframes, void *arg ) return 0; } -MidiOutJack :: MidiOutJack( const std::string clientName ) : MidiOutApi() +MidiOutJack :: MidiOutJack( const std::string &clientName ) : MidiOutApi() { initialize( clientName ); } @@ -2818,7 +2818,7 @@ MidiOutJack :: ~MidiOutJack() 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_); @@ -2840,7 +2840,7 @@ void MidiOutJack :: openPort( unsigned int portNumber, const std::string portNam jack_connect( data->client, jack_port_name( data->port ), 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 0fea8e10..528e9293 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -139,10 +139,10 @@ 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; + virtual void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi" ) ) = 0; //! Pure virtual openVirtualPort() function. - virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0; + virtual void openVirtualPort( const std::string &portName = std::string( "RtMidi" ) ) = 0; //! Pure virtual getPortCount() function. virtual unsigned int getPortCount() = 0; @@ -244,7 +244,7 @@ class RtMidiIn : public RtMidi 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" ) ); + void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi Input" ) ); //! Create a virtual input port, with optional name, to allow software connections (OS X, JACK and ALSA only). /*! @@ -256,7 +256,7 @@ 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" ) ); + void openVirtualPort( const std::string &portName = std::string( "RtMidi Input" ) ); //! Set a callback function to be invoked for incoming MIDI messages. /*! @@ -326,7 +326,7 @@ class RtMidiIn : public RtMidi virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ); protected: - void openMidiApi( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit ); + void openMidiApi( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit ); }; @@ -374,7 +374,7 @@ class RtMidiOut : public RtMidi 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" ) ); + 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 ); @@ -391,7 +391,7 @@ class RtMidiOut : public RtMidi 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" ) ); + void openVirtualPort( const std::string &portName = std::string( "RtMidi Output" ) ); //! Return the number of available MIDI output ports. unsigned int getPortCount( void ); @@ -429,7 +429,7 @@ class RtMidiOut : public RtMidi virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ); protected: - void openMidiApi( RtMidi::Api api, const std::string clientName ); + void openMidiApi( RtMidi::Api api, const std::string &clientName ); }; @@ -453,8 +453,8 @@ class MidiApi 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 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; @@ -510,7 +510,7 @@ class MidiInApi : public MidiApi // Default constructor. MidiQueue() - :front(0), back(0), size(0), ringSize(0) {} + :front(0), back(0), size(0), ringSize(0), ring(nullptr) {} bool push(const MidiMessage&); bool pop(std::vector*, double*); }; @@ -556,8 +556,8 @@ 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 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 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 ); } @@ -569,8 +569,8 @@ inline double RtMidiIn :: getMessage( std::vector *message ) { re inline void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); } 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( 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(); } @@ -594,11 +594,11 @@ inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback, vo class MidiInCore: public MidiInApi { public: - MidiInCore( const std::string clientName, unsigned int queueSizeLimit ); + 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( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -610,11 +610,11 @@ class MidiInCore: public MidiInApi class MidiOutCore: public MidiOutApi { public: - MidiOutCore( const std::string clientName ); + 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( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -631,11 +631,11 @@ 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 ); 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( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -650,11 +650,11 @@ class MidiInJack: public MidiInApi class MidiOutJack: public MidiOutApi { public: - MidiOutJack( const std::string clientName ); + 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( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -674,11 +674,11 @@ 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 ); 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( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -690,11 +690,11 @@ class MidiInAlsa: public MidiInApi class MidiOutAlsa: public MidiOutApi { public: - MidiOutAlsa( const std::string clientName ); + MidiOutAlsa( const std::string &clientName ); ~MidiOutAlsa( void ); RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -711,11 +711,11 @@ 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 ); 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( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -727,11 +727,11 @@ class MidiInWinMM: public MidiInApi class MidiOutWinMM: public MidiOutApi { public: - MidiOutWinMM( const std::string clientName ); + 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( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); void closePort( void ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -748,10 +748,10 @@ 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( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {} + void openVirtualPort( const std::string &/*portName*/ ) {} void closePort( void ) {} unsigned int getPortCount( void ) { return 0; } std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } @@ -763,10 +763,10 @@ 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( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {} + void openVirtualPort( const std::string &/*portName*/ ) {} void closePort( void ) {} unsigned int getPortCount( void ) { return 0; } std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } From b0cacfdc2f31f831e6cfabd0e1c282a4befaf81b Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Thu, 31 Aug 2017 11:35:19 -0300 Subject: [PATCH 104/388] Fix RtMidiIn/RtMidiOut constructor signatures wrt std::string&. Remove nullptr since we haven't moved to C++11 yet. --- RtMidi.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index 528e9293..5bad8a9c 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -229,7 +229,7 @@ class RtMidiIn : public RtMidi \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"), + const std::string& clientName = "RtMidi Input Client", unsigned int queueSizeLimit = 100 ); //! If a MIDI connection is still open, it will be closed by the destructor. @@ -359,7 +359,7 @@ class RtMidiOut : public RtMidi JACK (OS-X). */ RtMidiOut( RtMidi::Api api=UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Output Client") ); + const std::string& clientName = "RtMidi Output Client" ); //! The destructor closes any open MIDI connections. ~RtMidiOut( void ) throw(); @@ -510,7 +510,7 @@ class MidiInApi : public MidiApi // Default constructor. MidiQueue() - :front(0), back(0), size(0), ringSize(0), ring(nullptr) {} + :front(0), back(0), size(0), ringSize(0), ring(0) {} bool push(const MidiMessage&); bool pop(std::vector*, double*); }; From 81e31f907a529539457a1519b3926a8cc3570cf4 Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Thu, 31 Aug 2017 09:49:47 -0700 Subject: [PATCH 105/388] Documentation update to clarify that isPortOpen() does not report status of virtual ports. --- RtMidi.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/RtMidi.h b/RtMidi.h index 5bad8a9c..2f4ebd54 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -154,6 +154,10 @@ class RtMidi virtual void closePort( void ) = 0; //! 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. + */ virtual bool isPortOpen( void ) const = 0; //! Set an error callback function to be invoked when an error has occured. @@ -282,6 +286,10 @@ class RtMidiIn : public RtMidi void closePort( void ); //! 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. + */ virtual bool isPortOpen() const; //! Return the number of available MIDI input ports. @@ -380,6 +388,10 @@ class RtMidiOut : public RtMidi void closePort( void ); //! 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. + */ virtual bool isPortOpen() const; //! Create a virtual output port, with optional name, to allow software connections (OS X, JACK and ALSA only). From 41f80e6e69fab167a12b756ef6b7c111403c86f2 Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Thu, 31 Aug 2017 10:18:43 -0700 Subject: [PATCH 106/388] Version and documentation updates in advance of 3.0.0 release. --- README.md | 4 ++-- RtMidi.cpp | 2 +- RtMidi.h | 8 ++++---- configure.ac | 4 ++-- doc/doxygen/Doxyfile.in | 2 +- doc/doxygen/footer.html | 2 +- doc/doxygen/tutorial.txt | 20 +++++++++++++------- doc/release.txt | 9 ++++++++- 8 files changed, 32 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 8c961ca3..ec345e20 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ 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-2016. +By Gary P. Scavone, 2003-2017. This distribution of RtMidi contains the following: @@ -36,7 +36,7 @@ For complete documentation on RtMidi, see the doc directory of the distribution The RtMidi license is similar to the MIT License, with the added *feature* that modifications be sent to the developer. RtMidi: realtime MIDI i/o C++ classes - Copyright (c) 2003-2016 Gary P. Scavone + Copyright (c) 2003-2017 Gary P. Scavone Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff --git a/RtMidi.cpp b/RtMidi.cpp index 78c7d1ba..2c243cdc 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -8,7 +8,7 @@ RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/ RtMidi: realtime MIDI i/o C++ classes - Copyright (c) 2003-2016 Gary P. Scavone + Copyright (c) 2003-2017 Gary P. Scavone Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff --git a/RtMidi.h b/RtMidi.h index 2f4ebd54..b9e8b335 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -8,7 +8,7 @@ RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/ RtMidi: realtime MIDI i/o C++ classes - Copyright (c) 2003-2016 Gary P. Scavone + Copyright (c) 2003-2017 Gary P. Scavone Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -43,7 +43,7 @@ #ifndef RTMIDI_H #define RTMIDI_H -#define RTMIDI_VERSION "2.1.1" +#define RTMIDI_VERSION "3.0.0" #include #include @@ -189,7 +189,7 @@ class RtMidi possible to open a virtual input port to which other MIDI software clients can connect. - by Gary P. Scavone, 2003-2014. + by Gary P. Scavone, 2003-2017. */ /**********************************************************************/ @@ -350,7 +350,7 @@ class RtMidiIn : public RtMidi 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. + by Gary P. Scavone, 2003-2017. */ /**********************************************************************/ diff --git a/configure.ac b/configure.ac index 018e7e22..2474c4c2 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ # Process this file with autoconf to produce a configure script. -AC_INIT(RtMidi, 2.1.1, gary@music.mcgill.ca, rtmidi) +AC_INIT(RtMidi, 3.0.0, gary@music.mcgill.ca, rtmidi) AC_CONFIG_AUX_DIR(config) AC_CONFIG_SRCDIR(RtMidi.cpp) AC_CONFIG_FILES([rtmidi-config rtmidi.pc Makefile tests/Makefile doc/Makefile doc/doxygen/Doxyfile]) @@ -18,7 +18,7 @@ AM_INIT_AUTOMAKE([1.14 -Wall -Werror foreign subdir-objects]) # # If any interfaces have been removed since the last public release, then set # age to 0. -m4_define([lt_current], 3) +m4_define([lt_current], 4) m4_define([lt_revision], 0) m4_define([lt_age], 0) diff --git a/doc/doxygen/Doxyfile.in b/doc/doxygen/Doxyfile.in index acf7b9a6..b6e4db0f 100644 --- a/doc/doxygen/Doxyfile.in +++ b/doc/doxygen/Doxyfile.in @@ -32,7 +32,7 @@ PROJECT_NAME = RtMidi # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = @PACKAGE_VERSION +PROJECT_NUMBER = @PACKAGE_VERSION@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer diff --git a/doc/doxygen/footer.html b/doc/doxygen/footer.html index 8e9922c3..684f5cf5 100644 --- a/doc/doxygen/footer.html +++ b/doc/doxygen/footer.html @@ -1,7 +1,7 @@
    -
    ©2003-2016 Gary P. Scavone, McGill University. All Rights Reserved.
    +
    ©2003-2017 Gary P. Scavone, McGill University. All Rights Reserved.
    Maintained by Gary P. Scavone, gary at music.mcgill.ca
    diff --git a/doc/doxygen/tutorial.txt b/doc/doxygen/tutorial.txt index c8661c98..c9932b0d 100644 --- a/doc/doxygen/tutorial.txt +++ b/doc/doxygen/tutorial.txt @@ -15,13 +15,19 @@ Where applicable, multiple API support can be compiled and a particular API spec 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 whatsnew What's New (Version 2.1.1) +\section whatsnew What's New (Version 3.0.0) -There were no API changes made in the current release. The primary changes involved updates to the build system and some small bug fixes. With respect to the previous release (2.1.0), 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 code was moved to a separate branch because it was uncompilable and incomplete. +The version number has been bumped to 3.0.0 because of the past API change concerning the renaming of the RtError class to RtMidiError. Changes in this release include: + +- see git history for complete list of changes +- new sendMessage() function that does not use std::vector +- various std::string updates, including use of UTF8 for port names +- fixes for the MIDI queue +- various build system updates and code efficiencies \section download Download -Latest Release (11 February 2016):
    Version 2.1.1 +Latest Release (31 August 2017): Version 3.0.0 \section start Getting Started @@ -124,7 +130,7 @@ 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 RtMidiOut class provides simple functionality to immediately send messages over a MIDI connection. No timing functionality is provided. Note that there is an overloaded RtMidiOut::sendMessage() function that does not use std::vectors. 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. @@ -310,7 +316,7 @@ int main() \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 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 RtMidi::isPortOpen() function does not report the status of ports created with the RtMidi::openVirtualPort() function. \section compiling Compiling @@ -396,7 +402,7 @@ RtMidi is on github (https://github.com/thestk/rtmidi). Many thanks to the deve In years past, the following people provided bug fixes and improvements: -- Stephen Sinclair (Git repo and build system) +- Stephen Sinclair (Git repo, code and build system) - Atsushi Eno (C API) - Sebastien Alaiwan (JACK memory leaks, Windows kernel streaming) - Jean-Baptiste Berruchon (Windows sysex code) @@ -419,7 +425,7 @@ In years past, the following people provided bug fixes and improvements: \section license License RtMidi: realtime MIDI i/o C++ classes
    - Copyright (c) 2003-2016 Gary P. Scavone + Copyright (c) 2003-2017 Gary P. Scavone Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff --git a/doc/release.txt b/doc/release.txt index e1bfdad9..60ad69bc 100644 --- a/doc/release.txt +++ b/doc/release.txt @@ -1,6 +1,13 @@ RtMidi - a set of C++ classes that provides a common API for realtime MIDI input/output across Linux (ALSA & JACK), Macintosh OS X (CoreMidi & JACK), and Windows (Multimedia Library). -By Gary P. Scavone, 2003-2016 +By Gary P. Scavone, 2003-2017 (with help from many others!) + +v.3.0.0: (31 August 2017) +- see git history for complete list of changes +- new sendMessage() function that does not use std::vector +- various std::string updates, including use of UTF8 for port names +- fixes for the MIDI queue +- various build system updates and code efficiencies v2.1.1: (11 February 2016) - updates to automake routines From 493e23665cb610a9c31e5511342b66891c1a765b Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Thu, 31 Aug 2017 15:15:19 -0300 Subject: [PATCH 107/388] Fix extraneous size check in queue.pop() and document queue code. --- RtMidi.cpp | 50 +++++++++++++++++++++++++++++++------------------- RtMidi.h | 5 +++-- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 78c7d1ba..8ffe634a 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -344,8 +344,6 @@ double MidiInApi :: getMessage( std::vector *message ) return 0.0; } - if ( inputData_.queue.size == 0 ) return 0.0; - double timeStamp; if (!inputData_.queue.pop(message, &timeStamp)) return 0.0; @@ -353,19 +351,34 @@ double MidiInApi :: getMessage( std::vector *message ) return timeStamp; } -bool MidiInApi::MidiQueue::push(const MidiInApi::MidiMessage& msg) +unsigned int MidiInApi::MidiQueue::size(unsigned int *__back, + unsigned int *__front) { - // As long as we haven't reached our queue size limit, push the message. - unsigned int _back = back; - unsigned int _front = front; - unsigned int size; - + // Access back/front members exactly once and make stack copies for + // size calculation + unsigned int _back = back, _front = front, _size; if (_back >= _front) - size = _back - _front; + _size = _back - _front; else - size = ringSize - _front + _back; + _size = ringSize - _front + _back; + + // Return copies of back/front so no new and unsynchronized accesses + // to member variables are needed. + if (__back) *__back = _back; + if (__front) *__front = _front; + return _size; +} + +// As long as we haven't reached our queue size limit, push the message. +bool MidiInApi::MidiQueue::push(const MidiInApi::MidiMessage& msg) +{ + // Local stack copies of front/back + unsigned int _back, _front, _size; + + // Get back/front indexes exactly once and calculate current size + _size = size(&_back, &_front); - if ( size < ringSize-1 ) + if ( _size < ringSize-1 ) { ring[_back] = msg; back = (back+1)%ringSize; @@ -377,21 +390,20 @@ bool MidiInApi::MidiQueue::push(const MidiInApi::MidiMessage& msg) bool MidiInApi::MidiQueue::pop(std::vector *msg, double* timeStamp) { - unsigned int _back = back; - unsigned int _front = front; - unsigned int size; + // Local stack copies of front/back + unsigned int _back, _front, _size; - if (_back >= _front) - size = _back - _front; - else - size = ringSize - _front + _back; + // Get back/front indexes exactly once and calculate current size + _size = size(&_back, &_front); - if (size == 0) + if (_size == 0) return false; // Copy queued message to the vector pointer argument and then "pop" it. msg->assign( ring[_front].bytes.begin(), ring[_front].bytes.end() ); *timeStamp = ring[_front].timeStamp; + + // Update front front = (front+1)%ringSize; return true; } diff --git a/RtMidi.h b/RtMidi.h index 2f4ebd54..83252125 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -516,15 +516,16 @@ class MidiInApi : public MidiApi 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), ring(0) {} + :front(0), back(0), ringSize(0), ring(0) {} bool push(const MidiMessage&); bool pop(std::vector*, double*); + unsigned int size(unsigned int *back=0, + unsigned int *front=0); }; // The RtMidiInData structure is used to pass private class data to From 6442b215c3304a224068150b53a8d831ef926473 Mon Sep 17 00:00:00 2001 From: Saga Musix Date: Fri, 1 Sep 2017 23:19:00 +0200 Subject: [PATCH 108/388] C API: Make use of new sendMessage overload and directly pass on the pointer+size for message instead of creating a superfluous vector. --- rtmidi_c.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index 2c76fa91..71b9b9d7 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -309,9 +309,7 @@ enum RtMidiApi rtmidi_out_get_current_api (RtMidiPtr device) int rtmidi_out_send_message (RtMidiOutPtr device, const unsigned char *message, int length) { try { - // FIXME: use allocator to achieve efficient buffering - std::vector v (message, message + length); - ((RtMidiOut*) device->ptr)->sendMessage (&v); + ((RtMidiOut*) device->ptr)->sendMessage (message, length); return 0; } catch (const RtMidiError & err) { From 0a192501942aeb4e2ce266af7d75022b9b98ba56 Mon Sep 17 00:00:00 2001 From: Saga Musix Date: Mon, 4 Sep 2017 00:37:28 +0200 Subject: [PATCH 109/388] Invert the RTMIDI_ENSURE_UNIQUE_PORTNAMES mechanism in a way that does not require RtMidi.cpp to be edited manually. --- RtMidi.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 7fe2b817..b0a13f07 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -47,8 +47,8 @@ #endif // Default for Windows is to add an identifier to the port names; this -// flag can be undefined to disable this behaviour. -#define RTMIDI_ENSURE_UNIQUE_PORTNAMES +// flag can be defined (e.g. in your project file) to disable this behaviour. +//#define RTMIDI_DO_NOT_ENSURE_UNIQUE_PORTNAMES //*********************************************************************// // RtMidi Definitions @@ -2293,7 +2293,7 @@ std::string MidiInWinMM :: getPortName( unsigned int portNumber ) // Next lines added to add the portNumber to the name so that // the device's names are sure to be listed with individual names // even when they have the same brand name -#ifdef RTMIDI_ENSURE_UNIQUE_PORTNAMES +#ifndef RTMIDI_DO_NOT_ENSURE_UNIQUE_PORTNAMES std::ostringstream os; os << " "; os << portNumber; @@ -2363,7 +2363,7 @@ std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) // the device's names are sure to be listed with individual names // even when they have the same brand name std::ostringstream os; -#ifdef RTMIDI_ENSURE_UNIQUE_PORTNAMES +#ifndef RTMIDI_DO_NOT_ENSURE_UNIQUE_PORTNAMES os << " "; os << portNumber; stringName += os.str(); From 67804750a5aa9034d578b8073f29eb4dffd4f333 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Fri, 22 Sep 2017 10:39:41 -0300 Subject: [PATCH 110/388] Save timestamp from last *unfiltered* message. --- RtMidi.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index b0a13f07..40bb469c 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -482,7 +482,6 @@ 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; @@ -497,11 +496,10 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void * if ( !continueSysex ) message.timeStamp = time * 0.000000001; } - apiData->lastTime = packet->timeStamp; - if ( apiData->lastTime == 0 ) { // this happens when receiving asynchronous sysex messages - apiData->lastTime = AudioGetCurrentHostTime(); - } - //std::cout << "TimeStamp = " << packet->timeStamp << std::endl; + + // Track whether any non-filtered messages were found in this + // packet for timestamp calculation + bool foundNonFiltered = false; iByte = 0; if ( continueSysex ) { @@ -570,6 +568,7 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void * // Copy the MIDI data to our vector. if ( size ) { + foundNonFiltered = true; message.bytes.assign( &packet->data[iByte], &packet->data[iByte+size] ); if ( !continueSysex ) { // If not a continuing sysex message, invoke the user callback function or queue the message. @@ -588,6 +587,16 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void * } } } + + // Save the time of the last non-filtered message + if (foundNonFiltered) + { + apiData->lastTime = packet->timeStamp; + if ( apiData->lastTime == 0 ) { // this happens when receiving asynchronous sysex messages + apiData->lastTime = AudioGetCurrentHostTime(); + } + } + packet = MIDIPacketNext(packet); } } @@ -2045,7 +2054,6 @@ static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, data->firstMessage = false; } else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001; - apiData->lastTime = timestamp; if ( inputStatus == MIM_DATA ) { // Channel or system message @@ -2106,6 +2114,9 @@ static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, else return; } + // Save the time of the last non-filtered message + apiData->lastTime = timestamp; + if ( data->usingCallback ) { RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData ); From d19b7573f7274edbfe8ece52fae482c66094d767 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Fri, 22 Sep 2017 10:57:43 -0300 Subject: [PATCH 111/388] Add a note about CoInitializeEx et al. Closes #77. --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index ec345e20..c347ed35 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,10 @@ 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. +## Windows + +In some cases, for example to use RtMidi with GS Synth, it may be necessary for your program to call CoInitializeEx and CoUninitialize on entry to and exit from the thread that uses RtMidi. + ## Further reading For complete documentation on RtMidi, see the doc directory of the distribution or surf to http://music.mcgill.ca/~gary/rtmidi/. From 12cd09513101bbdbc687586d19dfcc3be0ced220 Mon Sep 17 00:00:00 2001 From: amosonn Date: Fri, 29 Sep 2017 02:27:20 +0200 Subject: [PATCH 112/388] Remove include of currently installed lib Removed line which adds, when configured with prefix, include to the currently installed version (assuming prefix is always the same). This include causes submodules (i.e. tests) to link against the currently installed library, instead of the newly compiled one, breaking build when upgrading version. --- configure.ac | 1 - 1 file changed, 1 deletion(-) diff --git a/configure.ac b/configure.ac index 2474c4c2..14a1149c 100644 --- a/configure.ac +++ b/configure.ac @@ -77,7 +77,6 @@ AC_ARG_ENABLE(debug, # 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/rtmidi" fi # For -I and -D flags From ab7f08d09f4989d68df7b3ac0c46fccd66213500 Mon Sep 17 00:00:00 2001 From: Francisco Demartino Date: Fri, 29 Sep 2017 22:55:26 +0200 Subject: [PATCH 113/388] rtmidi_c.cpp: initialize wrapper->data --- rtmidi_c.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index 71b9b9d7..f4cc0d12 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -123,11 +123,13 @@ RtMidiInPtr rtmidi_in_create_default () RtMidiIn* rIn = new RtMidiIn (); wrp->ptr = (void*) rIn; + wrp->data = 0; wrp->ok = true; wrp->msg = ""; } catch (const RtMidiError & err) { wrp->ptr = 0; + wrp->data = 0; wrp->ok = false; wrp->msg = err.what (); } From 6f2ad0ee77b5b4ba5cb5c93f55d72bb2d6a70595 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Mon, 2 Oct 2017 18:23:52 -0300 Subject: [PATCH 114/388] rtmidi_c.cpp: more initialize wrapper->data --- rtmidi_c.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index f4cc0d12..bc05c073 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -255,11 +255,13 @@ RtMidiOutPtr rtmidi_out_create_default () RtMidiOut* rOut = new RtMidiOut (); wrp->ptr = (void*) rOut; + wrp->data = 0; wrp->ok = true; wrp->msg = ""; } catch (const RtMidiError & err) { wrp->ptr = 0; + wrp->data = 0; wrp->ok = false; wrp->msg = err.what (); } @@ -276,11 +278,13 @@ RtMidiOutPtr rtmidi_out_create (enum RtMidiApi api, const char *clientName) RtMidiOut* rOut = new RtMidiOut ((RtMidi::Api) api, name); wrp->ptr = (void*) rOut; + wrp->data = 0; wrp->ok = true; wrp->msg = ""; } catch (const RtMidiError & err) { wrp->ptr = 0; + wrp->data = 0; wrp->ok = false; wrp->msg = err.what (); } From b2617818ecbba08da4b66671b15ede283fff8c83 Mon Sep 17 00:00:00 2001 From: "Serge A. Zaitsev" Date: Tue, 3 Oct 2017 12:40:17 +0300 Subject: [PATCH 115/388] c api: use full sturct type name --- rtmidi_c.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rtmidi_c.h b/rtmidi_c.h index 213496a7..315e5cec 100644 --- a/rtmidi_c.h +++ b/rtmidi_c.h @@ -28,13 +28,13 @@ struct RtMidiWrapper { }; //! Typedef for a generic RtMidi pointer. -typedef RtMidiWrapper* RtMidiPtr; +typedef struct RtMidiWrapper* RtMidiPtr; //! Typedef for a generic RtMidiIn pointer. -typedef RtMidiWrapper* RtMidiInPtr; +typedef struct RtMidiWrapper* RtMidiInPtr; //! Typedef for a generic RtMidiOut pointer. -typedef RtMidiWrapper* RtMidiOutPtr; +typedef struct RtMidiWrapper* RtMidiOutPtr; enum RtMidiApi { From 4ce3efe7f0706c3519c9fde0e6442ea1f4e2a376 Mon Sep 17 00:00:00 2001 From: "Serge A. Zaitsev" Date: Tue, 3 Oct 2017 12:42:14 +0300 Subject: [PATCH 116/388] c api: remove RT_MIDI_API_WINDOWS_KS from enum to match RtMidi.h enum definitions --- rtmidi_c.h | 1 - 1 file changed, 1 deletion(-) diff --git a/rtmidi_c.h b/rtmidi_c.h index 315e5cec..f0e6a75b 100644 --- a/rtmidi_c.h +++ b/rtmidi_c.h @@ -43,7 +43,6 @@ enum RtMidiApi { RT_MIDI_API_LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ 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. */ }; From bbbb16fde37ada19ab68d5b44949aeec38c4afa8 Mon Sep 17 00:00:00 2001 From: "Serge A. Zaitsev" Date: Tue, 3 Oct 2017 12:46:01 +0300 Subject: [PATCH 117/388] c api: remove rtmidi_sizeof_rtmidi_api as it can be replaced with sizeof operator --- rtmidi_c.cpp | 6 ------ rtmidi_c.h | 2 -- 2 files changed, 8 deletions(-) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index bc05c073..9db1524e 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -14,12 +14,6 @@ class CallbackProxyUserData void *user_data; }; -/* misc */ -int rtmidi_sizeof_rtmidi_api () -{ - return sizeof (RtMidiApi); -} - /* RtMidi API */ int rtmidi_get_compiled_api (enum RtMidiApi **apis) // return length for NULL argument. { diff --git a/rtmidi_c.h b/rtmidi_c.h index f0e6a75b..b88cc617 100644 --- a/rtmidi_c.h +++ b/rtmidi_c.h @@ -59,8 +59,6 @@ enum RtMidiErrorType { */ typedef void(* RtMidiCCallback) (double timeStamp, const unsigned char* message, void *userData); -//! Returns the size (with sizeof) of a RtMidiApi instance. -RTMIDIAPI int rtmidi_sizeof_rtmidi_api (); /* RtMidi API */ From 8841e3ab8b2d6e089ec6470d03a5dd1f0699d3f2 Mon Sep 17 00:00:00 2001 From: "Serge A. Zaitsev" Date: Tue, 3 Oct 2017 12:48:20 +0300 Subject: [PATCH 118/388] c api: remove unneccessary extra pointer --- rtmidi_c.cpp | 6 +++--- rtmidi_c.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index 9db1524e..19939557 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -15,9 +15,9 @@ class CallbackProxyUserData }; /* RtMidi API */ -int rtmidi_get_compiled_api (enum RtMidiApi **apis) // return length for NULL argument. +int rtmidi_get_compiled_api (enum RtMidiApi *apis) // return length for NULL argument. { - if (!apis || !(*apis)) { + if (!apis) { std::vector *v = new std::vector (); try { RtMidi::getCompiledApi (*v); @@ -32,7 +32,7 @@ int rtmidi_get_compiled_api (enum RtMidiApi **apis) // return length for NULL ar std::vector *v = new std::vector (); RtMidi::getCompiledApi (*v); for (unsigned int i = 0; i < v->size (); i++) - (*apis) [i] = (RtMidiApi) v->at (i); + apis[i] = (RtMidiApi) v->at (i); delete v; return 0; } catch (...) { diff --git a/rtmidi_c.h b/rtmidi_c.h index b88cc617..12e7d79e 100644 --- a/rtmidi_c.h +++ b/rtmidi_c.h @@ -68,7 +68,7 @@ typedef void(* RtMidiCCallback) (double timeStamp, const unsigned char* message, * * \param apis An array or a null value. */ -RTMIDIAPI int rtmidi_get_compiled_api (enum RtMidiApi **apis); // return length for NULL argument. +RTMIDIAPI int rtmidi_get_compiled_api (enum RtMidiApi *apis); // return length for NULL argument. //! Report an error. RTMIDIAPI void rtmidi_error (enum RtMidiErrorType type, const char* errorString); From 909239cd8e31b9c183adb1a3eacad8b906af92f1 Mon Sep 17 00:00:00 2001 From: "Serge A. Zaitsev" Date: Tue, 3 Oct 2017 12:51:33 +0300 Subject: [PATCH 119/388] c api: remove redundant extra pointer in rtmidi_in_get_message --- rtmidi_c.cpp | 6 +++--- rtmidi_c.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index 19939557..696179ae 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -213,8 +213,8 @@ void rtmidi_in_ignore_types (RtMidiInPtr device, bool midiSysex, bool midiTime, } double rtmidi_in_get_message (RtMidiInPtr device, - unsigned char **message, - size_t * size) + unsigned char *message, + size_t *size) { try { // FIXME: use allocator to achieve efficient buffering @@ -222,7 +222,7 @@ double rtmidi_in_get_message (RtMidiInPtr device, double ret = ((RtMidiIn*) device->ptr)->getMessage (&v); if (v.size () > 0 && v.size() <= *size) { - memcpy (*message, v.data (), (int) v.size ()); + memcpy (message, v.data (), (int) v.size ()); } *size = v.size(); diff --git a/rtmidi_c.h b/rtmidi_c.h index 12e7d79e..c470c591 100644 --- a/rtmidi_c.h +++ b/rtmidi_c.h @@ -139,7 +139,7 @@ RTMIDIAPI void rtmidi_in_ignore_types (RtMidiInPtr device, bool midiSysex, bool * be sufficient. * \param size Is used to return the size of the message obtained. */ -RTMIDIAPI double rtmidi_in_get_message (RtMidiInPtr device, unsigned char **message, size_t * size); +RTMIDIAPI double rtmidi_in_get_message (RtMidiInPtr device, unsigned char *message, size_t *size); /* RtMidiOut API */ From 431354f421855739d57ec07cd132d8ef14484e4e Mon Sep 17 00:00:00 2001 From: "Serge A. Zaitsev" Date: Tue, 3 Oct 2017 12:53:33 +0300 Subject: [PATCH 120/388] c api: pass message size to the RtMidiCCallback --- rtmidi_c.cpp | 2 +- rtmidi_c.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index 696179ae..f61da424 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -179,7 +179,7 @@ static void callback_proxy (double timeStamp, std::vector *message, void *userData) { CallbackProxyUserData* data = reinterpret_cast (userData); - data->c_callback (timeStamp, message->data (), data->user_data); + data->c_callback (timeStamp, message->data (), message->size (), data->user_data); } void rtmidi_in_set_callback (RtMidiInPtr device, RtMidiCCallback callback, void *userData) diff --git a/rtmidi_c.h b/rtmidi_c.h index c470c591..5cb91c27 100644 --- a/rtmidi_c.h +++ b/rtmidi_c.h @@ -57,7 +57,8 @@ enum RtMidiErrorType { * \param message The midi message. * \param userData Additional user data for the callback. */ -typedef void(* RtMidiCCallback) (double timeStamp, const unsigned char* message, void *userData); +typedef void(* RtMidiCCallback) (double timeStamp, const unsigned char* message, + size_t messageSize, void *userData); /* RtMidi API */ From b2cac962901ce098366dfe683a1d95d5094e0f46 Mon Sep 17 00:00:00 2001 From: "Serge A. Zaitsev" Date: Tue, 3 Oct 2017 18:44:44 +0300 Subject: [PATCH 121/388] add go bindings --- contrib/go/rtmidi/rtmidi.go | 355 ++++++++++++++++++++++++++++++ contrib/go/rtmidi/rtmidi_stub.cpp | 4 + contrib/go/rtmidi/rtmidi_stub.h | 1 + contrib/go/rtmidi/rtmidi_test.go | 46 ++++ 4 files changed, 406 insertions(+) create mode 100644 contrib/go/rtmidi/rtmidi.go create mode 100644 contrib/go/rtmidi/rtmidi_stub.cpp create mode 100644 contrib/go/rtmidi/rtmidi_stub.h create mode 100644 contrib/go/rtmidi/rtmidi_test.go diff --git a/contrib/go/rtmidi/rtmidi.go b/contrib/go/rtmidi/rtmidi.go new file mode 100644 index 00000000..9a0cb7b8 --- /dev/null +++ b/contrib/go/rtmidi/rtmidi.go @@ -0,0 +1,355 @@ +package rtmidi + +/* +#cgo CXXFLAGS: -g +#cgo LDFLAGS: -g + +#cgo linux CXXFLAGS: -D__LINUX_ALSA__ +#cgo linux LDFLAGS: -lasound -pthread +#cgo windows CXXFLAGS: -D__WINDOWS_MM__ +#cgo windows LDFLAGS: -luuid -lksuser -lwinmm -lole32 +#cgo darwin CXXFLAGS: -D__MACOSX_CORE__ +#cgo darwin LDFLAGS: -framework CoreServices -framework CoreAudio -framework CoreMIDI -framework CoreFoundation + +#include +#include +#include "rtmidi_stub.h" + +extern void goMIDIInCallback(double ts, unsigned char *msg, size_t msgsz, void *arg); + +static inline void midiInCallback(double ts, const unsigned char *msg, size_t msgsz, void *arg) { + goMIDIInCallback(ts, (unsigned char*) msg, msgsz, arg); +} + +static inline void cgoSetCallback(RtMidiPtr in, int cb_id) { + rtmidi_in_set_callback(in, midiInCallback, (void*)(uintptr_t) cb_id); +} +*/ +import "C" +import ( + "errors" + "sync" + "unsafe" +) + +// API is an enumeration of possible MIDI API specifiers. +type API C.enum_RtMidiApi + +const ( + // APIUnspecified searches for a working compiled API. + APIUnspecified API = C.RT_MIDI_API_UNSPECIFIED + // APIMacOSXCore uses Macintosh OS-X Core Midi API. + APIMacOSXCore = C.RT_MIDI_API_MACOSX_CORE + // APILinuxALSA uses the Advanced Linux Sound Architecture API. + APILinuxALSA = C.RT_MIDI_API_LINUX_ALSA + // APIUnixJack uses the JACK Low-Latency MIDI Server API. + APIUnixJack = C.RT_MIDI_API_UNIX_JACK + // APIWindowsMM uses the Microsoft Multimedia MIDI API. + APIWindowsMM = C.RT_MIDI_API_WINDOWS_MM + // APIDummy is a compilable but non-functional API. + APIDummy = C.RT_MIDI_API_RTMIDI_DUMMY +) + +func (api API) String() string { + switch api { + case APIUnspecified: + return "unspecified" + case APILinuxALSA: + return "alsa" + case APIUnixJack: + return "jack" + case APIMacOSXCore: + return "coreaudio" + case APIWindowsMM: + return "winmm" + case APIDummy: + return "dummy" + } + return "?" +} + +// CompiledAPI determines the available compiled MIDI APIs. +func CompiledAPI() (apis []API) { + n := C.rtmidi_get_compiled_api(nil) + capis := make([]C.enum_RtMidiApi, n, n) + C.rtmidi_get_compiled_api(&capis[0]) + for _, capi := range capis { + apis = append(apis, API(capi)) + } + return apis +} + +// MIDI interface provides a common, platform-independent API for realtime MIDI +// device enumeration and handling MIDI ports. +type MIDI interface { + OpenPort(port int, name string) error + OpenVirtualPort(name string) error + Close() error + PortCount() (int, error) + PortName(port int) (string, error) +} + +// MIDIIn interface 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 Message() +// method 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. +type MIDIIn interface { + MIDI + API() (API, error) + IgnoreTypes(midiSysex bool, midiTime bool, midiSense bool) error + SetCallback(func(MIDIIn, []byte, float64)) error + CancelCallback() error + Message() ([]byte, float64, error) + Destroy() +} + +// MIDIOut interface 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. +type MIDIOut interface { + MIDI + API() (API, error) + SendMessage([]byte) error + Destroy() +} + +type midi struct { + midi C.RtMidiPtr +} + +func (m *midi) OpenPort(port int, name string) error { + p := C.CString(name) + defer C.free(unsafe.Pointer(p)) + C.rtmidi_open_port(m.midi, C.uint(port), p) + if !m.midi.ok { + return errors.New(C.GoString(m.midi.msg)) + } + return nil +} + +func (m *midi) OpenVirtualPort(name string) error { + p := C.CString(name) + defer C.free(unsafe.Pointer(p)) + C.rtmidi_open_virtual_port(m.midi, p) + if !m.midi.ok { + return errors.New(C.GoString(m.midi.msg)) + } + return nil +} + +func (m *midi) PortName(port int) (string, error) { + p := C.rtmidi_get_port_name(m.midi, C.uint(port)) + if !m.midi.ok { + return "", errors.New(C.GoString(m.midi.msg)) + } + defer C.free(unsafe.Pointer(p)) + return C.GoString(p), nil +} + +func (m *midi) PortCount() (int, error) { + n := C.rtmidi_get_port_count(m.midi) + if !m.midi.ok { + return 0, errors.New(C.GoString(m.midi.msg)) + } + return int(n), nil +} + +func (m *midi) Close() error { + C.rtmidi_close_port(C.RtMidiPtr(m.midi)) + if !m.midi.ok { + return errors.New(C.GoString(m.midi.msg)) + } + return nil +} + +type midiIn struct { + midi + in C.RtMidiInPtr + cb func(MIDIIn, []byte, float64) +} + +type midiOut struct { + midi + out C.RtMidiOutPtr +} + +// NewMIDIInDefault opens a default MIDIIn port. +func NewMIDIInDefault() (MIDIIn, error) { + in := C.rtmidi_in_create_default() + if !in.ok { + defer C.rtmidi_in_free(in) + return nil, errors.New(C.GoString(in.msg)) + } + return &midiIn{in: in, midi: midi{midi: C.RtMidiPtr(in)}}, nil +} + +// NewMIDIIn opens a single MIDIIn port using the given API. One can provide a +// custom port name and a desired queue size for the incomming MIDI messages. +func NewMIDIIn(api API, name string, queueSize int) (MIDIIn, error) { + p := C.CString(name) + defer C.free(unsafe.Pointer(p)) + in := C.rtmidi_in_create(C.enum_RtMidiApi(api), p, C.uint(queueSize)) + if !in.ok { + defer C.rtmidi_in_free(in) + return nil, errors.New(C.GoString(in.msg)) + } + return &midiIn{in: in, midi: midi{midi: C.RtMidiPtr(in)}}, nil +} + +func (m *midiIn) API() (API, error) { + api := C.rtmidi_in_get_current_api(m.in) + if !m.in.ok { + return APIUnspecified, errors.New(C.GoString(m.in.msg)) + } + return API(api), nil +} + +func (m *midiIn) Close() error { + unregisterMIDIIn(m) + if err := m.midi.Close(); err != nil { + return err + } + C.rtmidi_in_free(m.in) + return nil +} + +func (m *midiIn) IgnoreTypes(midiSysex bool, midiTime bool, midiSense bool) error { + C.rtmidi_in_ignore_types(m.in, C._Bool(midiSysex), C._Bool(midiTime), C._Bool(midiSense)) + if !m.in.ok { + return errors.New(C.GoString(m.in.msg)) + } + return nil +} + +var ( + mu sync.Mutex + inputs = map[int]*midiIn{} +) + +func registerMIDIIn(m *midiIn) int { + mu.Lock() + defer mu.Unlock() + for i := 0; ; i++ { + if _, ok := inputs[i]; !ok { + inputs[i] = m + return i + } + } +} + +func unregisterMIDIIn(m *midiIn) { + mu.Lock() + defer mu.Unlock() + for i := 0; i < len(inputs); i++ { + if inputs[i] == m { + delete(inputs, i) + return + } + } +} + +func findMIDIIn(k int) *midiIn { + mu.Lock() + defer mu.Unlock() + return inputs[k] +} + +//export goMIDIInCallback +func goMIDIInCallback(ts C.double, msg *C.uchar, msgsz C.size_t, arg unsafe.Pointer) { + k := int(uintptr(arg)) + m := findMIDIIn(k) + m.cb(m, C.GoBytes(unsafe.Pointer(msg), C.int(msgsz)), float64(ts)) +} + +func (m *midiIn) SetCallback(cb func(MIDIIn, []byte, float64)) error { + k := registerMIDIIn(m) + m.cb = cb + C.cgoSetCallback(m.in, C.int(k)) + if !m.in.ok { + return errors.New(C.GoString(m.in.msg)) + } + return nil +} + +func (m *midiIn) CancelCallback() error { + unregisterMIDIIn(m) + C.rtmidi_in_cancel_callback(m.in) + if !m.in.ok { + return errors.New(C.GoString(m.in.msg)) + } + return nil +} + +func (m *midiIn) Message() ([]byte, float64, error) { + msg := make([]C.uchar, 64*1024, 64*1024) + sz := C.size_t(len(msg)) + r := C.rtmidi_in_get_message(m.in, &msg[0], &sz) + if !m.in.ok { + return nil, 0, errors.New(C.GoString(m.in.msg)) + } + b := make([]byte, int(sz), int(sz)) + for i, c := range msg[:sz] { + b[i] = byte(c) + } + return b, float64(r), nil +} + +func (m *midiIn) Destroy() { + C.rtmidi_in_free(m.in) +} + +// NewMIDIOutDefault opens a default MIDIOut port. +func NewMIDIOutDefault() (MIDIOut, error) { + out := C.rtmidi_out_create_default() + if !out.ok { + defer C.rtmidi_out_free(out) + return nil, errors.New(C.GoString(out.msg)) + } + return &midiOut{out: out, midi: midi{midi: C.RtMidiPtr(out)}}, nil +} + +// NewMIDIOut opens a single MIDIIn port using the given API with the given port name. +func NewMIDIOut(api API, name string) (MIDIOut, error) { + p := C.CString(name) + defer C.free(unsafe.Pointer(p)) + out := C.rtmidi_out_create(C.enum_RtMidiApi(api), p) + if !out.ok { + defer C.rtmidi_out_free(out) + return nil, errors.New(C.GoString(out.msg)) + } + return &midiOut{out: out, midi: midi{midi: C.RtMidiPtr(out)}}, nil +} + +func (m *midiOut) API() (API, error) { + api := C.rtmidi_out_get_current_api(m.out) + if !m.out.ok { + return APIUnspecified, errors.New(C.GoString(m.out.msg)) + } + return API(api), nil +} + +func (m *midiOut) Close() error { + if err := m.midi.Close(); err != nil { + return err + } + C.rtmidi_out_free(m.out) + return nil +} + +func (m *midiOut) SendMessage(b []byte) error { + p := C.CBytes(b) + defer C.free(unsafe.Pointer(p)) + C.rtmidi_out_send_message(m.out, (*C.uchar)(p), C.int(len(b))) + if !m.out.ok { + return errors.New(C.GoString(m.out.msg)) + } + return nil +} + +func (m *midiOut) Destroy() { + C.rtmidi_out_free(m.out) +} diff --git a/contrib/go/rtmidi/rtmidi_stub.cpp b/contrib/go/rtmidi/rtmidi_stub.cpp new file mode 100644 index 00000000..7a5b6924 --- /dev/null +++ b/contrib/go/rtmidi/rtmidi_stub.cpp @@ -0,0 +1,4 @@ +#include "../../../RtMidi.h" + +#include "../../../RtMidi.cpp" +#include "../../../rtmidi_c.cpp" diff --git a/contrib/go/rtmidi/rtmidi_stub.h b/contrib/go/rtmidi/rtmidi_stub.h new file mode 100644 index 00000000..8a53d4c0 --- /dev/null +++ b/contrib/go/rtmidi/rtmidi_stub.h @@ -0,0 +1 @@ +#include "../../../rtmidi_c.h" diff --git a/contrib/go/rtmidi/rtmidi_test.go b/contrib/go/rtmidi/rtmidi_test.go new file mode 100644 index 00000000..8079fb4f --- /dev/null +++ b/contrib/go/rtmidi/rtmidi_test.go @@ -0,0 +1,46 @@ +package rtmidi + +import ( + "log" +) + +func ExampleCompiledAPI() { + for _, api := range CompiledAPI() { + log.Println("Compiled API: ", api) + } +} + +func ExampleMIDIIn_Message() { + in, err := NewMIDIInDefault() + if err != nil { + log.Fatal(err) + } + defer in.Destroy() + if err := in.OpenPort(0, "RtMidi"); err != nil { + log.Fatal(err) + } + defer in.Close() + + for { + m, t, err := in.Message() + if len(m) > 0 { + log.Println(m, t, err) + } + } +} + +func ExampleMIDIIn_SetCallback() { + in, err := NewMIDIInDefault() + if err != nil { + log.Fatal(err) + } + defer in.Destroy() + if err := in.OpenPort(0, "RtMidi"); err != nil { + log.Fatal(err) + } + defer in.Close() + in.SetCallback(func(m MIDIIn, msg []byte, t float64) { + log.Println(msg, t) + }) + <-make(chan struct{}) +} From e0101bafd389019f01d4a526789a6f072676427f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 9 Oct 2017 17:06:56 +0200 Subject: [PATCH 122/388] Prevent .gitignore and friends from being exported to the final archive --- .gitattributes | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..f49e8216 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +# make sure that .gitignore, .travis.yml,... are not part of a +# source-package generated via 'git archive' +.git* export-ignore +/.* export-ignore From 9970e97f7cb0874ae037df87cc6bdbce4db522f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 9 Oct 2017 21:11:27 +0200 Subject: [PATCH 123/388] Make sure that public classes are properly exported (even if visibility=hidden) Backported from Debian, which included a patch backported from Fedora --- RtMidi.cpp | 4 ++-- RtMidi.h | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 40bb469c..7ab27026 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -124,7 +124,7 @@ void RtMidiIn :: openMidiApi( RtMidi::Api api, const std::string &clientName, un #endif } -RtMidiIn :: RtMidiIn( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit ) +extern RTMIDI_DLL_PUBLIC RtMidiIn :: RtMidiIn( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit ) : RtMidi() { if ( api != UNSPECIFIED ) { @@ -192,7 +192,7 @@ void RtMidiOut :: openMidiApi( RtMidi::Api api, const std::string &clientName ) #endif } -RtMidiOut :: RtMidiOut( RtMidi::Api api, const std::string &clientName) +extern RTMIDI_DLL_PUBLIC RtMidiOut :: RtMidiOut( RtMidi::Api api, const std::string &clientName) { if ( api != UNSPECIFIED ) { // Attempt to open the specified API. diff --git a/RtMidi.h b/RtMidi.h index 7ab50a98..22946829 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -43,6 +43,16 @@ #ifndef RTMIDI_H #define RTMIDI_H +#if defined _WIN32 || defined __CYGWIN__ + #define RTMIDI_DLL_PUBLIC +#else + #if __GNUC__ >= 4 + #define RTMIDI_DLL_PUBLIC __attribute__( (visibility( "default" )) ) + #else + #define RTMIDI_DLL_PUBLIC + #endif +#endif + #define RTMIDI_VERSION "3.0.0" #include @@ -207,7 +217,7 @@ class RtMidi // // **************************************************************** // -class RtMidiIn : public RtMidi +class RTMIDI_DLL_PUBLIC RtMidiIn : public RtMidi { public: @@ -354,7 +364,7 @@ class RtMidiIn : public RtMidi */ /**********************************************************************/ -class RtMidiOut : public RtMidi +class RTMIDI_DLL_PUBLIC RtMidiOut : public RtMidi { public: From f7b216b20bb6da36cfa4b3fa59634485a54ee62a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 9 Oct 2017 21:13:01 +0200 Subject: [PATCH 124/388] Use @api@ in pkg-config's cflags, rather than CPPFLAGS CPPFLAGS is really private to building RtMidi itself --- rtmidi.pc.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtmidi.pc.in b/rtmidi.pc.in index b5365f6a..9af1a049 100644 --- a/rtmidi.pc.in +++ b/rtmidi.pc.in @@ -9,4 +9,4 @@ Version: @PACKAGE_VERSION@ Requires: @req@ Libs: -L${libdir} -lrtmidi Libs.private: -lpthread -Cflags: -pthread -I${includedir} @CPPFLAGS@ \ No newline at end of file +Cflags: -pthread -I${includedir} @api@ From 2618b21e0c61119dce458038f0eeb583baa5a35f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 9 Oct 2017 21:14:06 +0200 Subject: [PATCH 125/388] Extract RTMIDI_VERSION without compiling/running a sample program so it also works when cross-compiling RtMidi (where the resulting binaries cannot be run directly on the host) --- configure.ac | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 14a1149c..36f1958c 100644 --- a/configure.ac +++ b/configure.ac @@ -30,11 +30,9 @@ AC_SUBST(SO_VERSION) # Check version number coherency between RtMidi.h and configure.ac AC_MSG_CHECKING([that version numbers are coherent]) -AC_RUN_IFELSE( - [AC_LANG_PROGRAM([#include - `grep "define RTMIDI_VERSION" $srcdir/RtMidi.h`], - [return strcmp(RTMIDI_VERSION, PACKAGE_VERSION);])], - [AC_MSG_RESULT([yes])], +RTMIDI_VERSION=`sed -n 's/#define RTMIDI_VERSION "\(.*\)"/\1/p' $srcdir/RtMidi.h` +AS_IF( + [test "x$RTMIDI_VERSION" != "x$PACKAGE_VERSION"], [AC_MSG_FAILURE([testing RTMIDI_VERSION==PACKAGE_VERSION failed, check that RtMidi.h defines RTMIDI_VERSION as "$PACKAGE_VERSION" or that the first line of configure.ac has been updated.])]) # Enable some nice automake features if they are available From 35c95a1316943d0b40541c085d9c0b8c1aa528b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 9 Oct 2017 21:15:29 +0200 Subject: [PATCH 126/388] Don't append "$prefix/lib" to the library search-paths. Trying to be too clever, can break the build (cross-compilation anybody?) --- configure.ac | 5 ----- 1 file changed, 5 deletions(-) diff --git a/configure.ac b/configure.ac index 36f1958c..92f60350 100644 --- a/configure.ac +++ b/configure.ac @@ -72,11 +72,6 @@ AC_ARG_ENABLE(debug, [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" -fi - # For -I and -D flags CPPFLAGS="$CPPFLAGS $cppflag" From fabda6aa376d7aa158f4addfb4f12e4d91425431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 9 Oct 2017 22:17:23 +0200 Subject: [PATCH 127/388] cleaned up configure.ac - do not repeatedly use AC_SUBST - use AS_IF instead of "if" - use "text x = y" rather than "test x == y" - consistent use of LIBS (always prepend) - trying to fix --enable-debug --- configure.ac | 108 ++++++++++++++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 48 deletions(-) diff --git a/configure.ac b/configure.ac index 92f60350..09bb98a3 100644 --- a/configure.ac +++ b/configure.ac @@ -27,6 +27,20 @@ m4_define([lt_current_minus_age], [m4_eval(lt_current - lt_age)]) SO_VERSION=lt_version_info AC_SUBST(SO_VERSION) +AC_SUBST(LIBS) +AC_SUBST(api) +AC_SUBST(req) + +cppflags="" +cxxflags="" +api="" +req="" + +# Fill GXX with something before test. +GXX="no" + +# if the user did not provide any CXXFLAGS, we can override them +AS_IF([test "x$CXXFLAGS" = "x" ], [override_cxx=yes], [override_cxx=no]) # Check version number coherency between RtMidi.h and configure.ac AC_MSG_CHECKING([that version numbers are coherent]) @@ -39,17 +53,14 @@ AS_IF( m4_ifdef([AM_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) -# 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 +AS_IF([test "x$AR" = "xno"], [ AC_MSG_ERROR("Could not find ar - needed to create a library"); -fi +]) LT_INIT([win32-dll]) AC_CONFIG_MACRO_DIR([m4]) @@ -67,24 +78,23 @@ AC_CHECK_HEADER([semaphore.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)]) - -# 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" +AC_ARG_ENABLE([debug], + [ --enable-debug = enable various debug output], [ + CPPFLAGS="-D__RTMIDI_DEBUG ${CPPFLAGS}" + cxxflags="${cxxflags} -g" + object_path=Debug + AC_MSG_RESULT([yes])],[ + cxxflags="${cxxflags} -O3" + object_path=Release + AC_MSG_RESULT([no]) + ]) # Check compiler and use -Wall if gnu. -if [test $GXX = "yes" ;] then - AC_SUBST( cxxflag, ["-Wall -Wextra"] ) -fi - -CXXFLAGS="$CXXFLAGS $cxxflag" +AS_IF([test "x$GXX" = "xyes"], [ + CXXFLAGS="-Wall -Wextra ${CXXFLAGS}" +]) +# For debugging and optimization ... overwrite default because it has both -g and -O2 +AS_IF([test "x$override_cxx" = "xyes" ], CXXFLAGS="$CXXFLAGS $cxxflags", CXXFLAGS="$cxxflags $CXXFLAGS") # Checks for doxygen AC_CHECK_PROG( DOXYGEN, [doxygen], [doxygen] ) @@ -100,12 +110,10 @@ AC_CONFIG_LINKS( [doc/images/mcgill.gif:doc/images/mcgill.gif] ) # Checks for package options and external software AC_CANONICAL_HOST -AC_SUBST( api, [""] ) -AC_SUBST( req, [""] ) AC_MSG_CHECKING(for MIDI API) AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (mac and linux only)]) -AS_IF([test "x$with_jack" == "xyes"], [ +AS_IF([test "x$with_jack" = "xyes"], [ 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!))]) @@ -114,18 +122,19 @@ case $host in *-*-linux*) # Look for ALSA flag AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA sequencer API support (linux only)]) - AS_IF([test "x$with_alsa" == "xyes"], [ + AS_IF([test "x$with_alsa" = "xyes"], [ + AC_MSG_RESULT(using ALSA) + AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(ALSA support requires the asound library!)) 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 + AS_IF([test "x${api}" = "x"], AC_MSG_RESULT(using ALSA) - AC_SUBST( api, [-D__LINUX_ALSA__] ) - req="$req alsa" AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(ALSA sequencer support requires the asound library!)) - fi + api="-D__LINUX_ALSA__ ${api}" + req="$req alsa" + ) # Checks for pthread library. AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtMidi requires the pthread library!)) @@ -134,47 +143,50 @@ case $host in *-apple*) # Look for Core flag AC_ARG_WITH(core, [ --with-core = choose CoreMidi API support (mac only)]) - AS_IF([test "x$with_core" == "xyes"], [ - api="$api -D__MACOSX_CORE__" + AS_IF([test "x$with_core" = "xyes"], [ 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" ]) + LIBS="-framework CoreMIDI -framework CoreFoundation -framework CoreAudio ${LIBS}" + api="$api -D__MACOSX_CORE__" + ]) # If no api flags specified, use CoreMidi - if [test "$api" == ""; ] then - AC_SUBST( api, [-D__MACOSX_CORE__] ) + AS_IF([test "x${api}" = "x"], 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 + LIBS="-framework CoreMIDI -framework CoreFoundation -framework CoreAudio ${LIBS}" + api="$api -D__MACOSX_CORE__" + ) ;; *-mingw32*) # Look for WinMM flag AC_ARG_WITH(winmm, [ --with-winmm = choose Windows MultiMedia (MM) API support (windoze only)]) - AS_IF([test "x$with_winmm" == "xyes"], [ - api="$api -D__WINDOWS_MM__" + AS_IF([test "x$with_winmm" = "xyes"], [ AC_MSG_RESULT(using WinMM) - AC_SUBST( LIBS, [-lwinmm] )]) + LIBS="-lwinmm ${LIBS}" + api="$api -D__WINDOWS_MM__" + ]) AC_ARG_WITH(winks, [ --with-winks = choose kernel streaming support (windoze only)]) - AS_IF([test "x$with_winks" == "xyes"], [ + AS_IF([test "x$with_winks" = "xyes"], [ + AC_MSG_RESULT(using kernel streaming) + LIBS="-lsetupapi -lksuser ${LIBS}" 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__] ) + AS_IF([test "x${api}" = "x"], [ AC_MSG_RESULT(using WinMM) - AC_SUBST( LIBS, [-lwinmm] ) - fi + LIBS="-lwinmm ${LIBS}" + api="${api} -D__WINDOWS_MM__" + ]) ;; *) From d5a5c45e92a4cefc3f5072771dc0e3bd9319a0b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 9 Oct 2017 22:19:47 +0200 Subject: [PATCH 128/388] fixed --disable-debug flag --- configure.ac | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 09bb98a3..cb0a6ef2 100644 --- a/configure.ac +++ b/configure.ac @@ -77,16 +77,19 @@ AC_CHECK_HEADER([semaphore.h], [ ]) # Check for debug -AC_MSG_CHECKING(whether to compile debug version) AC_ARG_ENABLE([debug], - [ --enable-debug = enable various debug output], [ + [ --enable-debug = enable various debug output]) + +AC_MSG_CHECKING(whether to compile debug version) +AS_IF([test "x${enable_debug}" = "xyes" ],[ + AC_MSG_RESULT([yes]) CPPFLAGS="-D__RTMIDI_DEBUG ${CPPFLAGS}" cxxflags="${cxxflags} -g" object_path=Debug - AC_MSG_RESULT([yes])],[ + ],[ + AC_MSG_RESULT([no]) cxxflags="${cxxflags} -O3" object_path=Release - AC_MSG_RESULT([no]) ]) # Check compiler and use -Wall if gnu. From b59ad689619b3891d5205f97e3cb1deeaa3d0d74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 9 Oct 2017 22:24:57 +0200 Subject: [PATCH 129/388] us AS_HELP_STRING for pretty help formatting --- configure.ac | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index cb0a6ef2..05dbb4ef 100644 --- a/configure.ac +++ b/configure.ac @@ -77,8 +77,7 @@ AC_CHECK_HEADER([semaphore.h], [ ]) # Check for debug -AC_ARG_ENABLE([debug], - [ --enable-debug = enable various debug output]) +AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug], [enable various debugging output])]) AC_MSG_CHECKING(whether to compile debug version) AS_IF([test "x${enable_debug}" = "xyes" ],[ @@ -115,7 +114,7 @@ AC_CANONICAL_HOST AC_MSG_CHECKING(for MIDI API) -AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (mac and linux only)]) +AC_ARG_WITH(jack, [AS_HELP_STRING([--with-jack], [choose JACK server support (mac and linux only)])]) AS_IF([test "x$with_jack" = "xyes"], [ api="$api -D__UNIX_JACK__" AC_MSG_RESULT(using JACK) @@ -124,7 +123,7 @@ AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the ja case $host in *-*-linux*) # Look for ALSA flag - AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA sequencer API support (linux only)]) + AC_ARG_WITH(alsa, [AS_HELP_STRING([--with-alsa], [choose native ALSA sequencer API support (linux only)])]) AS_IF([test "x$with_alsa" = "xyes"], [ AC_MSG_RESULT(using ALSA) AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(ALSA support requires the asound library!)) @@ -145,7 +144,7 @@ case $host in *-apple*) # Look for Core flag - AC_ARG_WITH(core, [ --with-core = choose CoreMidi API support (mac only)]) + AC_ARG_WITH(core, [AS_HELP_STRING([--with-core], [ choose CoreMidi API support (mac only)])]) AS_IF([test "x$with_core" = "xyes"], [ AC_MSG_RESULT(using CoreMidi) AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, [], [AC_MSG_ERROR(CoreMIDI header files not found!)] ) @@ -166,14 +165,14 @@ case $host in *-mingw32*) # Look for WinMM flag - AC_ARG_WITH(winmm, [ --with-winmm = choose Windows MultiMedia (MM) API support (windoze only)]) + AC_ARG_WITH(winmm, [AS_HELP_STRING([--with-winmm], [ choose Windows MultiMedia (MM) API support (win32 only)])]) AS_IF([test "x$with_winmm" = "xyes"], [ AC_MSG_RESULT(using WinMM) LIBS="-lwinmm ${LIBS}" api="$api -D__WINDOWS_MM__" ]) - AC_ARG_WITH(winks, [ --with-winks = choose kernel streaming support (windoze only)]) + AC_ARG_WITH(winks, [AS_HELP_STRING([--with-winks], [ choose kernel streaming support (win32 only)])]) AS_IF([test "x$with_winks" = "xyes"], [ AC_MSG_RESULT(using kernel streaming) LIBS="-lsetupapi -lksuser ${LIBS}" From a128eec9bce7a824807ba1e45840f34d9c15f917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 9 Oct 2017 22:28:41 +0200 Subject: [PATCH 130/388] grouped all configure-flags together --- configure.ac | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index 05dbb4ef..3cf557e3 100644 --- a/configure.ac +++ b/configure.ac @@ -53,6 +53,14 @@ AS_IF( m4_ifdef([AM_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) +# configure flags +AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug], [enable various debugging output])]) +AC_ARG_WITH(jack, [AS_HELP_STRING([--with-jack], [choose JACK server support (mac and linux only)])]) +AC_ARG_WITH(alsa, [AS_HELP_STRING([--with-alsa], [choose native ALSA sequencer API support (linux only)])]) +AC_ARG_WITH(core, [AS_HELP_STRING([--with-core], [ choose CoreMidi API support (mac only)])]) +AC_ARG_WITH(winmm, [AS_HELP_STRING([--with-winmm], [ choose Windows MultiMedia (MM) API support (win32 only)])]) +AC_ARG_WITH(winks, [AS_HELP_STRING([--with-winks], [ choose kernel streaming support (win32 only)])]) + # Checks for programs. AC_PROG_CXX(g++ CC c++ cxx) @@ -76,9 +84,8 @@ AC_CHECK_HEADER([semaphore.h], [ AC_MSG_WARN([POSIX semaphore support not found; data may be lost on closePort])) ]) -# Check for debug -AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug], [enable various debugging output])]) +# check for debug AC_MSG_CHECKING(whether to compile debug version) AS_IF([test "x${enable_debug}" = "xyes" ],[ AC_MSG_RESULT([yes]) @@ -112,9 +119,11 @@ AC_CONFIG_LINKS( [doc/images/mcgill.gif:doc/images/mcgill.gif] ) # Checks for package options and external software AC_CANONICAL_HOST + + + AC_MSG_CHECKING(for MIDI API) -AC_ARG_WITH(jack, [AS_HELP_STRING([--with-jack], [choose JACK server support (mac and linux only)])]) AS_IF([test "x$with_jack" = "xyes"], [ api="$api -D__UNIX_JACK__" AC_MSG_RESULT(using JACK) @@ -123,7 +132,6 @@ AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the ja case $host in *-*-linux*) # Look for ALSA flag - AC_ARG_WITH(alsa, [AS_HELP_STRING([--with-alsa], [choose native ALSA sequencer API support (linux only)])]) AS_IF([test "x$with_alsa" = "xyes"], [ AC_MSG_RESULT(using ALSA) AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(ALSA support requires the asound library!)) @@ -144,7 +152,6 @@ case $host in *-apple*) # Look for Core flag - AC_ARG_WITH(core, [AS_HELP_STRING([--with-core], [ choose CoreMidi API support (mac only)])]) AS_IF([test "x$with_core" = "xyes"], [ AC_MSG_RESULT(using CoreMidi) AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, [], [AC_MSG_ERROR(CoreMIDI header files not found!)] ) @@ -165,14 +172,12 @@ case $host in *-mingw32*) # Look for WinMM flag - AC_ARG_WITH(winmm, [AS_HELP_STRING([--with-winmm], [ choose Windows MultiMedia (MM) API support (win32 only)])]) AS_IF([test "x$with_winmm" = "xyes"], [ AC_MSG_RESULT(using WinMM) LIBS="-lwinmm ${LIBS}" api="$api -D__WINDOWS_MM__" ]) - AC_ARG_WITH(winks, [AS_HELP_STRING([--with-winks], [ choose kernel streaming support (win32 only)])]) AS_IF([test "x$with_winks" = "xyes"], [ AC_MSG_RESULT(using kernel streaming) LIBS="-lsetupapi -lksuser ${LIBS}" From a9e2dd25fb6ef228e45c4c3179975c92b906b896 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 9 Oct 2017 22:38:35 +0200 Subject: [PATCH 131/388] nicer use of AC_MSG_ERROR --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 3cf557e3..24c7b2a7 100644 --- a/configure.ac +++ b/configure.ac @@ -67,7 +67,7 @@ AC_PROG_CXX(g++ CC c++ cxx) AM_PROG_AR AC_PATH_PROG(AR, ar, no) AS_IF([test "x$AR" = "xno"], [ - AC_MSG_ERROR("Could not find ar - needed to create a library"); + AC_MSG_ERROR([Could not find ar - needed to create a library]) ]) LT_INIT([win32-dll]) From ec409e10bde623bf7d3ac425b7c21fdbc04345a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 9 Oct 2017 22:48:58 +0200 Subject: [PATCH 132/388] even better handling for --enable-debug/--disable-debug using AS_CASE rather than if-cascades. also only set performance-flags if --disable-debug is *explicitely* given --- configure.ac | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index 24c7b2a7..2be93fdd 100644 --- a/configure.ac +++ b/configure.ac @@ -31,8 +31,6 @@ AC_SUBST(LIBS) AC_SUBST(api) AC_SUBST(req) -cppflags="" -cxxflags="" api="" req="" @@ -41,6 +39,7 @@ GXX="no" # if the user did not provide any CXXFLAGS, we can override them AS_IF([test "x$CXXFLAGS" = "x" ], [override_cxx=yes], [override_cxx=no]) +AS_IF([test "x$CFLAGS" = "x" ], [override_c=yes], [override_c=no]) # Check version number coherency between RtMidi.h and configure.ac AC_MSG_CHECKING([that version numbers are coherent]) @@ -87,23 +86,31 @@ AC_CHECK_HEADER([semaphore.h], [ # check for debug AC_MSG_CHECKING(whether to compile debug version) -AS_IF([test "x${enable_debug}" = "xyes" ],[ +debugflags="" +object_path=Release +AS_CASE([${enable_debug}], + [ yes ], [ AC_MSG_RESULT([yes]) CPPFLAGS="-D__RTMIDI_DEBUG ${CPPFLAGS}" - cxxflags="${cxxflags} -g" + debugflags="${debugflags} -g" object_path=Debug - ],[ + ], + [ no ], [ + AC_MSG_RESULT([no!]) + debugflags="${debugflags} -O3" + ], [ AC_MSG_RESULT([no]) - cxxflags="${cxxflags} -O3" - object_path=Release ]) +# For debugging and optimization ... overwrite default because it has both -g and -O2 +AS_IF([test "x$debugflags" != x], + AS_IF([test "x$override_cxx" = "xyes" ], CXXFLAGS="$CXXFLAGS $debugflags", CXXFLAGS="$debugflags $CXXFLAGS") + AS_IF([test "x$override_c" = "xyes" ], CFLAGS="$CFLAGS $debugflags", CFLAGS="$debugflags $CFLAGS") + ) # Check compiler and use -Wall if gnu. AS_IF([test "x$GXX" = "xyes"], [ CXXFLAGS="-Wall -Wextra ${CXXFLAGS}" ]) -# For debugging and optimization ... overwrite default because it has both -g and -O2 -AS_IF([test "x$override_cxx" = "xyes" ], CXXFLAGS="$CXXFLAGS $cxxflags", CXXFLAGS="$cxxflags $CXXFLAGS") # Checks for doxygen AC_CHECK_PROG( DOXYGEN, [doxygen], [doxygen] ) From 31943b30c870f4b1d827c610bd85cde4a68661a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 9 Oct 2017 22:58:46 +0200 Subject: [PATCH 133/388] Fixed some more class-exports for visibility=hidden --- RtMidi.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/RtMidi.h b/RtMidi.h index 22946829..5ea2425c 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -70,7 +70,7 @@ */ /************************************************************************/ -class RtMidiError : public std::exception +class RTMIDI_DLL_PUBLIC RtMidiError : public std::exception { public: //! Defined RtMidiError types. @@ -123,7 +123,7 @@ typedef void (*RtMidiErrorCallback)( RtMidiError::Type type, const std::string & class MidiApi; -class RtMidi +class RTMIDI_DLL_PUBLIC RtMidi { public: @@ -468,7 +468,7 @@ class RTMIDI_DLL_PUBLIC RtMidiOut : public RtMidi // // **************************************************************** // -class MidiApi +class RTMIDI_DLL_PUBLIC MidiApi { public: @@ -499,7 +499,7 @@ class MidiApi void *errorCallbackUserData_; }; -class MidiInApi : public MidiApi +class RTMIDI_DLL_PUBLIC MidiInApi : public MidiApi { public: @@ -563,7 +563,7 @@ class MidiInApi : public MidiApi RtMidiInData inputData_; }; -class MidiOutApi : public MidiApi +class RTMIDI_DLL_PUBLIC MidiOutApi : public MidiApi { public: From 0470e7c5e5fc70ca22351883cab76c8e1222438a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 9 Oct 2017 22:59:12 +0200 Subject: [PATCH 134/388] Enabled visibility=hidden for non-debug builds (only) and only on gcc --- Makefile.am | 2 ++ configure.ac | 3 +++ 2 files changed, 5 insertions(+) diff --git a/Makefile.am b/Makefile.am index 1606cc77..2bbb17c7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,6 +3,8 @@ if MAKE_DOC SUBDIRS += doc endif +AM_CXXFLAGS = @visibility@ + lib_LTLIBRARIES = %D%/librtmidi.la %C%_librtmidi_la_LDFLAGS = -no-undefined -export-dynamic -version-info @SO_VERSION@ %C%_librtmidi_la_SOURCES = \ diff --git a/configure.ac b/configure.ac index 2be93fdd..4390648d 100644 --- a/configure.ac +++ b/configure.ac @@ -30,7 +30,9 @@ AC_SUBST(SO_VERSION) AC_SUBST(LIBS) AC_SUBST(api) AC_SUBST(req) +AC_SUBST(visibility) +visibility="" api="" req="" @@ -110,6 +112,7 @@ AS_IF([test "x$debugflags" != x], # Check compiler and use -Wall if gnu. AS_IF([test "x$GXX" = "xyes"], [ CXXFLAGS="-Wall -Wextra ${CXXFLAGS}" + AS_IF([test "x${enable_debug}" != "xyes" ], visibility="-fvisibility=hidden" ) ]) # Checks for doxygen From 3c788c139fb888026a4fbf6a3ec688f406b5b773 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 9 Oct 2017 23:15:17 +0200 Subject: [PATCH 135/388] removed stray space --- RtMidi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RtMidi.h b/RtMidi.h index 5ea2425c..ba5b38cc 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -468,7 +468,7 @@ class RTMIDI_DLL_PUBLIC RtMidiOut : public RtMidi // // **************************************************************** // -class RTMIDI_DLL_PUBLIC MidiApi +class RTMIDI_DLL_PUBLIC MidiApi { public: From fa6c45cd81accb925d6011d9b39e45f17423a56a Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Mon, 9 Oct 2017 12:06:37 -0300 Subject: [PATCH 136/388] Cover all backends with Travis-CI. (Compilation only.) --- .travis.yml | 55 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index f9c33fb6..ccc9d688 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,47 @@ -os: osx language: cpp -compiler: -- clang -- gcc -before_script: -- brew update -- brew install doxygen -- ./autogen.sh -script: make distcheck +sudo: false # docker VM +matrix: + include: + - os: linux + env: HOST="" API="alsa" + compiler: gcc + - os: linux + env: HOST="" API="alsa" + compiler: clang + - os: linux + env: HOST="" API="jack" + compiler: gcc + - 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 + # jack and asound not found on ARM gnueabihf + # - os: linux + # env: HOST="--host=arm-linux-gnueabihf" API="alsa" + # compiler: gcc + # - os: linux + # env: HOST="--host=arm-linux-gnueabihf" API="jack" + # compiler: gcc + - os: osx + env: HOST="" API="core" + compiler: gcc + - os: osx + env: HOST="" API="core" + compiler: clang +install: +- if [ $TRAVIS_OS_NAME = linux ]; then sudo apt-get install libasound2-dev libjack-dev doxygen g++-mingw-w64-i686 g++-mingw-w64-x86-64 g++-arm-linux-gnueabihf; fi +- if [ $TRAVIS_OS_NAME = osx ]; then brew install doxygen || (brew update && brew install doxygen); fi +- if [ -n "$HOST" ]; then unset CXX; unset CC; fi +script: ./autogen.sh --enable-debug --with-$API $HOST && make +after_script: +- make check +- make distcheck +- make install +# ALSA: no access to /dev/snd/seq +# JACK: Jack server not running +# - tests/midiprobe From bb5f772c4baa1a2744ef4ac6a64b35fc6842b97c Mon Sep 17 00:00:00 2001 From: Michael Dahl Date: Thu, 19 Oct 2017 21:08:42 +0200 Subject: [PATCH 137/388] Removed extern --- RtMidi.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 7ab27026..9fa7e752 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -124,7 +124,7 @@ void RtMidiIn :: openMidiApi( RtMidi::Api api, const std::string &clientName, un #endif } -extern RTMIDI_DLL_PUBLIC RtMidiIn :: RtMidiIn( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit ) +RTMIDI_DLL_PUBLIC RtMidiIn :: RtMidiIn( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit ) : RtMidi() { if ( api != UNSPECIFIED ) { @@ -192,7 +192,7 @@ void RtMidiOut :: openMidiApi( RtMidi::Api api, const std::string &clientName ) #endif } -extern RTMIDI_DLL_PUBLIC RtMidiOut :: RtMidiOut( RtMidi::Api api, const std::string &clientName) +RTMIDI_DLL_PUBLIC RtMidiOut :: RtMidiOut( RtMidi::Api api, const std::string &clientName) { if ( api != UNSPECIFIED ) { // Attempt to open the specified API. From 9eb59e4839f8e230a496a45e3e7e1b5e7570c7fe Mon Sep 17 00:00:00 2001 From: Michael Dahl Date: Thu, 19 Oct 2017 21:19:24 +0200 Subject: [PATCH 138/388] Revert "Enabled visibility=hidden for non-debug builds (only)" This reverts commit 0470e7c5e5fc70ca22351883cab76c8e1222438a. --- Makefile.am | 2 -- configure.ac | 3 --- 2 files changed, 5 deletions(-) diff --git a/Makefile.am b/Makefile.am index 2bbb17c7..1606cc77 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,8 +3,6 @@ if MAKE_DOC SUBDIRS += doc endif -AM_CXXFLAGS = @visibility@ - lib_LTLIBRARIES = %D%/librtmidi.la %C%_librtmidi_la_LDFLAGS = -no-undefined -export-dynamic -version-info @SO_VERSION@ %C%_librtmidi_la_SOURCES = \ diff --git a/configure.ac b/configure.ac index 4390648d..2be93fdd 100644 --- a/configure.ac +++ b/configure.ac @@ -30,9 +30,7 @@ AC_SUBST(SO_VERSION) AC_SUBST(LIBS) AC_SUBST(api) AC_SUBST(req) -AC_SUBST(visibility) -visibility="" api="" req="" @@ -112,7 +110,6 @@ AS_IF([test "x$debugflags" != x], # Check compiler and use -Wall if gnu. AS_IF([test "x$GXX" = "xyes"], [ CXXFLAGS="-Wall -Wextra ${CXXFLAGS}" - AS_IF([test "x${enable_debug}" != "xyes" ], visibility="-fvisibility=hidden" ) ]) # Checks for doxygen From 9458def712cf206b1ec679ea870215ba09df06cb Mon Sep 17 00:00:00 2001 From: Ashley Hedges Date: Fri, 10 Nov 2017 10:51:46 +1300 Subject: [PATCH 139/388] Mac leak fixes for CFStringCreateWithCString without matching CFRelease --- RtMidi.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 9fa7e752..0d8130df 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -667,9 +667,12 @@ void MidiInCore :: openPort( unsigned int portNumber, const std::string &portNam MIDIPortRef port; CoreMidiData *data = static_cast (apiData_); + CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ); OSStatus result = MIDIInputPortCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), - midiInputCallback, (void *)&inputData_, &port ); + portNameRef, + midiInputCallback, (void *)&inputData_, &port ); + CFRelease( portNameRef ); + if ( result != noErr ) { MIDIClientDispose( data->client ); errorString_ = "MidiInCore::openPort: error creating OS-X MIDI input port."; @@ -709,9 +712,12 @@ void MidiInCore :: openVirtualPort( const std::string &portName ) // Create a virtual MIDI input destination. MIDIEndpointRef endpoint; + CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ); OSStatus result = MIDIDestinationCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), + portNameRef, midiInputCallback, (void *)&inputData_, &endpoint ); + CFRelease( portNameRef ); + if ( result != noErr ) { errorString_ = "MidiInCore::openVirtualPort: error creating virtual OS-X MIDI destination."; error( RtMidiError::DRIVER_ERROR, errorString_ ); @@ -1052,9 +1058,12 @@ void MidiOutCore :: openVirtualPort( const std::string &portName ) // Create a virtual MIDI output source. MIDIEndpointRef endpoint; + CFStringRef portNameRef = CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ); OSStatus result = MIDISourceCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), + portNameRef, &endpoint ); + CFRelease( portNameRef ); + if ( result != noErr ) { errorString_ = "MidiOutCore::initialize: error creating OS-X virtual MIDI source."; error( RtMidiError::DRIVER_ERROR, errorString_ ); From 95e24378bbbb7dc1debb24534bef34259ff7df8e Mon Sep 17 00:00:00 2001 From: Rory Jaffe Date: Thu, 23 Nov 2017 10:36:14 -0800 Subject: [PATCH 140/388] Static constructor and destructor calls Closes thetsk/rtmidi#143 --- RtMidi.cpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 0d8130df..a3c9dcd8 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -603,13 +603,13 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void * MidiInCore :: MidiInCore( const std::string &clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { - initialize( clientName ); + MidiInCore::initialize( clientName ); } MidiInCore :: ~MidiInCore( void ) { // Close a connection if it exists. - closePort(); + MidiInCore::closePort(); // Cleanup. CoreMidiData *data = static_cast (apiData_); @@ -908,13 +908,13 @@ std::string MidiInCore :: getPortName( unsigned int portNumber ) MidiOutCore :: MidiOutCore( const std::string &clientName ) : MidiOutApi() { - initialize( clientName ); + MidiOutCore::initialize( clientName ); } MidiOutCore :: ~MidiOutCore( void ) { // Close a connection if it exists. - closePort(); + MidiOutCore::closePort(); // Cleanup. CoreMidiData *data = static_cast (apiData_); @@ -1392,13 +1392,13 @@ static void *alsaMidiHandler( void *ptr ) MidiInAlsa :: MidiInAlsa( const std::string &clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { - initialize( clientName ); + MidiInAlsa::initialize( clientName ); } MidiInAlsa :: ~MidiInAlsa() { // Close a connection if it exists. - closePort(); + MidiInAlsa::closePort(); // Shutdown the input thread. AlsaMidiData *data = static_cast (apiData_); @@ -1744,13 +1744,13 @@ void MidiInAlsa :: closePort( void ) MidiOutAlsa :: MidiOutAlsa( const std::string &clientName ) : MidiOutApi() { - initialize( clientName ); + MidiOutAlsa::initialize( clientName ); } MidiOutAlsa :: ~MidiOutAlsa() { // Close a connection if it exists. - closePort(); + MidiOutAlsa::closePort(); // Cleanup. AlsaMidiData *data = static_cast (apiData_); @@ -2142,13 +2142,13 @@ static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, MidiInWinMM :: MidiInWinMM( const std::string &clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { - initialize( clientName ); + MidiInWinMM::initialize( clientName ); } MidiInWinMM :: ~MidiInWinMM() { // Close a connection if it exists. - closePort(); + MidiInWinMM::closePort(); WinMidiData *data = static_cast (apiData_); DeleteCriticalSection( &(data->_mutex) ); @@ -2330,13 +2330,13 @@ std::string MidiInWinMM :: getPortName( unsigned int portNumber ) MidiOutWinMM :: MidiOutWinMM( const std::string &clientName ) : MidiOutApi() { - initialize( clientName ); + MidiOutWinMM::initialize( clientName ); } MidiOutWinMM :: ~MidiOutWinMM() { // Close a connection if it exists. - closePort(); + MidiOutWinMM::closePort(); // Cleanup. WinMidiData *data = static_cast (apiData_); @@ -2616,7 +2616,7 @@ static int jackProcessIn( jack_nframes_t nframes, void *arg ) MidiInJack :: MidiInJack( const std::string &clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { - initialize( clientName ); + MidiInJack::initialize( clientName ); } void MidiInJack :: initialize( const std::string& clientName ) @@ -2652,7 +2652,7 @@ void MidiInJack :: connect() MidiInJack :: ~MidiInJack() { JackMidiData *data = static_cast (apiData_); - closePort(); + MidiInJack::closePort(); if ( data->client ) jack_client_close( data->client ); @@ -2790,7 +2790,7 @@ static int jackProcessOut( jack_nframes_t nframes, void *arg ) MidiOutJack :: MidiOutJack( const std::string &clientName ) : MidiOutApi() { - initialize( clientName ); + MidiOutJack::initialize( clientName ); } void MidiOutJack :: initialize( const std::string& clientName ) @@ -2833,8 +2833,8 @@ void MidiOutJack :: connect() MidiOutJack :: ~MidiOutJack() { JackMidiData *data = static_cast (apiData_); - closePort(); - + MidiOutJack::closePort(); + // Cleanup jack_ringbuffer_free( data->buffSize ); jack_ringbuffer_free( data->buffMessage ); From 58493c08cb7032b4f1befa7f4e685258e6d41b99 Mon Sep 17 00:00:00 2001 From: Phildo Date: Tue, 5 Dec 2017 13:31:05 -0600 Subject: [PATCH 141/388] corrected readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c347ed35..93e7fbdc 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ This distribution of RtMidi contains the following: 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 `./autogen.sh` before `./configure`. ## Overview From c5a1c7b0ea79cadcd4532bb03c20713330e32d93 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Thu, 11 Jan 2018 07:08:49 -0300 Subject: [PATCH 142/388] Recognize mingw64 as a Windows-related value for $host. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 2be93fdd..6d90133e 100644 --- a/configure.ac +++ b/configure.ac @@ -177,7 +177,7 @@ case $host in ) ;; - *-mingw32*) + *-mingw32*|*-mingw64*) # Look for WinMM flag AS_IF([test "x$with_winmm" = "xyes"], [ AC_MSG_RESULT(using WinMM) From 1784283a5eb47dd39449564d1183decd6362c90e Mon Sep 17 00:00:00 2001 From: Yuri Date: Wed, 10 Jan 2018 21:34:05 -0800 Subject: [PATCH 143/388] Added the FreeBSD compatibility to configure.ac --- configure.ac | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure.ac b/configure.ac index 6d90133e..81d51f4b 100644 --- a/configure.ac +++ b/configure.ac @@ -157,6 +157,11 @@ case $host in AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtMidi requires the pthread library!)) ;; + *-*-freebsd*) + # Checks for pthread library. + AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtMidi requires the pthread library!)) + ;; + *-apple*) # Look for Core flag AS_IF([test "x$with_core" = "xyes"], [ From e0f3ebb429f09f2d36838290953a8f0352134f4b Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Wed, 31 Jan 2018 17:03:20 -0300 Subject: [PATCH 144/388] Add jack to pkg-config requires. --- configure.ac | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 81d51f4b..dad72e2f 100644 --- a/configure.ac +++ b/configure.ac @@ -132,9 +132,11 @@ AC_CANONICAL_HOST AC_MSG_CHECKING(for MIDI API) AS_IF([test "x$with_jack" = "xyes"], [ -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_MSG_RESULT(using JACK) + AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!)) + api="$api -D__UNIX_JACK__" + req="$req jack" +]) case $host in *-*-linux*) From 1182656ceb6b702c6b035d1fe8f39741c092440a Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Mon, 19 Mar 2018 16:05:13 -0300 Subject: [PATCH 145/388] Add a missing call to MIDIPacketNext() when packet length is 0. Fixes #156. --- RtMidi.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index a3c9dcd8..6fddb51c 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -479,7 +479,10 @@ static void midiInputCallback( const MIDIPacketList *list, void *procRef, void * // function. nBytes = packet->length; - if ( nBytes == 0 ) continue; + if ( nBytes == 0 ) { + packet = MIDIPacketNext(packet); + continue; + } // Calculate time stamp. if ( data->firstMessage ) { From b578aabf42b81ae57893c494794742ed202be7c0 Mon Sep 17 00:00:00 2001 From: jgvictores Date: Tue, 27 Mar 2018 12:54:07 +0200 Subject: [PATCH 146/388] add min add CMakeLists.txt --- CMakeLists.txt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..3192da5f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,21 @@ +# 2018 (c) Juan G. Victores +# CopyPolicy: RtMidi license. + +cmake_minimum_required(VERSION 3.0) + +add_library(rtmidi SHARED RtMidi.h + RtMidi.cpp) + +set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h) + +target_include_directories(rtmidi PUBLIC $) + +# Standard installation directories. +include(GNUInstallDirs) + +install(TARGETS rtmidi + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +set_property(GLOBAL APPEND PROPERTY RTMIDI_TARGETS rtmidi) From e65b44221d9b7999a7982264d8c70a12e5b1db40 Mon Sep 17 00:00:00 2001 From: jgvictores Date: Tue, 27 Mar 2018 11:14:37 +0200 Subject: [PATCH 147/388] add project name --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3192da5f..7b82060c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.0) +project(rtmidi) + add_library(rtmidi SHARED RtMidi.h RtMidi.cpp) From 054300d8196fd1b8fe54d09e8c74b0993c9ae98a Mon Sep 17 00:00:00 2001 From: jgvictores Date: Tue, 27 Mar 2018 11:20:38 +0200 Subject: [PATCH 148/388] runtime good for windows --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b82060c..69c23740 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ include(GNUInstallDirs) install(TARGETS rtmidi LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR} # BINDIR if not pure lib project PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) set_property(GLOBAL APPEND PROPERTY RTMIDI_TARGETS rtmidi) From f48162422b68ffd33d387ee93a984b641e2b32a5 Mon Sep 17 00:00:00 2001 From: jgvictores Date: Tue, 27 Mar 2018 11:33:20 +0200 Subject: [PATCH 149/388] easier with static --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 69c23740..e745b8b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,8 @@ cmake_minimum_required(VERSION 3.0) project(rtmidi) -add_library(rtmidi SHARED RtMidi.h - RtMidi.cpp) +add_library(rtmidi RtMidi.h + RtMidi.cpp) set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h) @@ -18,7 +18,7 @@ include(GNUInstallDirs) install(TARGETS rtmidi LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR} # BINDIR if not pure lib project + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) set_property(GLOBAL APPEND PROPERTY RTMIDI_TARGETS rtmidi) From d26494fe0d184395e402de3480e78aa8ce3d5679 Mon Sep 17 00:00:00 2001 From: jgvictores Date: Tue, 27 Mar 2018 17:12:00 +0200 Subject: [PATCH 150/388] add windows properties --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index e745b8b7..b6c4ae25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,11 @@ set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h) target_include_directories(rtmidi PUBLIC $) +if(_WINDOWS) + set_target_properties(rtmidi APPEND PROPERTY COMPILE_DEFINITIONS __WINDOWS_MM__) + target_link_libraries(rtmidi winmm.lib) +endif() + # Standard installation directories. include(GNUInstallDirs) From 6f33c971397793050069aed7ba0e4dd8d2efc6b4 Mon Sep 17 00:00:00 2001 From: jgvictores Date: Tue, 27 Mar 2018 17:39:41 +0200 Subject: [PATCH 151/388] improve win support --- CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b6c4ae25..11d7ee2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,8 +12,9 @@ set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h) target_include_directories(rtmidi PUBLIC $) -if(_WINDOWS) - set_target_properties(rtmidi APPEND PROPERTY COMPILE_DEFINITIONS __WINDOWS_MM__) +if(MSVC) + #MESSAGE("MSVC" ) + set_property(DIRECTORY ${CMAKE_SOURCE_DIR} APPEND PROPERTY COMPILE_DEFINITIONS __WINDOWS_MM__) target_link_libraries(rtmidi winmm.lib) endif() From f8e78db3077b7f546b240dc9f8c2501a4a15a947 Mon Sep 17 00:00:00 2001 From: Chris Chronopoulos Date: Wed, 28 Mar 2018 07:17:54 -0400 Subject: [PATCH 152/388] add setClientName() functionality The ALSA Sequencer API supports the re-setting of the client name after the client has been created. JACK doesn't appear to support this yet (though there way be a way using the metadata API). Other API's may support this, but haven't been tested. This commit adds the method setClientName(const std::string &clientName) to the RtMidi class. For the API's for which this has not been implemented, a warning is thrown using the RtMidiError system. --- RtMidi.cpp | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ RtMidi.h | 13 ++++++++++ 2 files changed, 83 insertions(+) diff --git a/RtMidi.cpp b/RtMidi.cpp index 6fddb51c..9adf3b87 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -93,6 +93,12 @@ void RtMidi :: getCompiledApi( std::vector &apis ) throw() #endif } +void RtMidi :: setClientName( const std::string &clientName ) +{ + rtapi_->setClientName(clientName); +} + + //*********************************************************************// // RtMidiIn Definitions //*********************************************************************// @@ -748,6 +754,14 @@ void MidiInCore :: closePort( void ) connected_ = false; } +void MidiInCore :: setClientName ( const std::string& ) +{ + + errorString_ = "MidiInCore::setClientName: this function is not implemented for the MACOSX_CORE API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + unsigned int MidiInCore :: getPortCount() { CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); @@ -1049,6 +1063,14 @@ void MidiOutCore :: closePort( void ) connected_ = false; } +void MidiOutCore :: setClientName ( const std::string& ) +{ + + errorString_ = "MidiOutCore::setClientName: this function is not implemented for the MACOSX_CORE API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + void MidiOutCore :: openVirtualPort( const std::string &portName ) { CoreMidiData *data = static_cast (apiData_); @@ -1740,6 +1762,14 @@ void MidiInAlsa :: closePort( void ) } } +void MidiInAlsa :: setClientName( const std::string &clientName ) +{ + + AlsaMidiData *data = static_cast ( apiData_ ); + snd_seq_set_client_name( data->seq, clientName.c_str() ); + +} + //*********************************************************************// // API: LINUX ALSA // Class Definitions: MidiOutAlsa @@ -1919,6 +1949,14 @@ void MidiOutAlsa :: closePort( void ) } } +void MidiOutAlsa :: setClientName( const std::string &clientName ) +{ + + AlsaMidiData *data = static_cast ( apiData_ ); + snd_seq_set_client_name( data->seq, clientName.c_str() ); + +} + void MidiOutAlsa :: openVirtualPort( const std::string &portName ) { AlsaMidiData *data = static_cast (apiData_); @@ -2292,6 +2330,14 @@ void MidiInWinMM :: closePort( void ) } } +void MidiInWinMM :: setClientName ( const std::string& ) +{ + + errorString_ = "MidiInWinMM::setClientName: this function is not implemented for the WINDOWS_MM API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + unsigned int MidiInWinMM :: getPortCount() { return midiInGetNumDevs(); @@ -2444,6 +2490,14 @@ void MidiOutWinMM :: closePort( void ) } } +void MidiOutWinMM :: setClientName ( const std::string& ) +{ + + errorString_ = "MidiOutWinMM::setClientName: this function is not implemented for the WINDOWS_MM API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + void MidiOutWinMM :: openVirtualPort( const std::string &/*portName*/ ) { // This function cannot be implemented for the Windows MM MIDI API. @@ -2758,6 +2812,14 @@ void MidiInJack :: closePort() data->port = NULL; } +void MidiInJack:: setClientName( const std::string& ) +{ + + errorString_ = "MidiInJack::setClientName: this function is not implemented for the UNIX_JACK API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + //*********************************************************************// // API: JACK // Class Definitions: MidiOutJack @@ -2961,6 +3023,14 @@ void MidiOutJack :: closePort() data->port = NULL; } +void MidiOutJack:: setClientName( const std::string& ) +{ + + errorString_ = "MidiOutJack::setClientName: this function is not implemented for the UNIX_JACK API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + void MidiOutJack :: sendMessage( const unsigned char *message, size_t size ) { int nBytes = static_cast(size); diff --git a/RtMidi.h b/RtMidi.h index ba5b38cc..6a5e0785 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -163,6 +163,8 @@ class RTMIDI_DLL_PUBLIC RtMidi //! Pure virtual closePort() function. virtual void closePort( void ) = 0; + void setClientName( const std::string &clientName ); + //! Returns true if a port is open and false if not. /*! Note that this only applies to connections made with the openPort() @@ -478,6 +480,7 @@ class RTMIDI_DLL_PUBLIC MidiApi virtual void openPort( unsigned int portNumber, const std::string &portName ) = 0; virtual void openVirtualPort( const std::string &portName ) = 0; virtual void closePort( void ) = 0; + virtual void setClientName( const std::string &clientName ) = 0; virtual unsigned int getPortCount( void ) = 0; virtual std::string getPortName( unsigned int portNumber ) = 0; @@ -623,6 +626,7 @@ class MidiInCore: public MidiInApi void openPort( unsigned int portNumber, const std::string &portName ); void openVirtualPort( const std::string &portName ); void closePort( void ); + void setClientName( const std::string &clientName ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -639,6 +643,7 @@ class MidiOutCore: public MidiOutApi void openPort( unsigned int portNumber, const std::string &portName ); void openVirtualPort( const std::string &portName ); void closePort( void ); + void setClientName( const std::string &clientName ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); void sendMessage( const unsigned char *message, size_t size ); @@ -660,6 +665,7 @@ class MidiInJack: public MidiInApi void openPort( unsigned int portNumber, const std::string &portName ); void openVirtualPort( const std::string &portName ); void closePort( void ); + void setClientName( const std::string &clientName ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -679,6 +685,7 @@ class MidiOutJack: public MidiOutApi void openPort( unsigned int portNumber, const std::string &portName ); void openVirtualPort( const std::string &portName ); void closePort( void ); + void setClientName( const std::string &clientName ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); void sendMessage( const unsigned char *message, size_t size ); @@ -703,6 +710,7 @@ class MidiInAlsa: public MidiInApi void openPort( unsigned int portNumber, const std::string &portName ); void openVirtualPort( const std::string &portName ); void closePort( void ); + void setClientName( const std::string &clientName ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -719,6 +727,7 @@ class MidiOutAlsa: public MidiOutApi void openPort( unsigned int portNumber, const std::string &portName ); void openVirtualPort( const std::string &portName ); void closePort( void ); + void setClientName( const std::string &clientName ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); void sendMessage( const unsigned char *message, size_t size ); @@ -740,6 +749,7 @@ class MidiInWinMM: public MidiInApi void openPort( unsigned int portNumber, const std::string &portName ); void openVirtualPort( const std::string &portName ); void closePort( void ); + void setClientName( const std::string &clientName ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -756,6 +766,7 @@ class MidiOutWinMM: public MidiOutApi void openPort( unsigned int portNumber, const std::string &portName ); void openVirtualPort( const std::string &portName ); void closePort( void ); + void setClientName( const std::string &clientName ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); void sendMessage( const unsigned char *message, size_t size ); @@ -776,6 +787,7 @@ class MidiInDummy: public MidiInApi void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {} void openVirtualPort( const std::string &/*portName*/ ) {} void closePort( void ) {} + void setClientName( const std::string &/*clientName*/ ) {}; unsigned int getPortCount( void ) { return 0; } std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } @@ -791,6 +803,7 @@ class MidiOutDummy: public MidiOutApi void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {} void openVirtualPort( const std::string &/*portName*/ ) {} void closePort( void ) {} + void setClientName( const std::string &/*clientName*/ ) {}; unsigned int getPortCount( void ) { return 0; } std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } void sendMessage( const unsigned char * /*message*/, size_t /*size*/ ) {} From 22cc8b3aff966e61c0aed1361d3fb96462cd9b50 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Wed, 28 Mar 2018 13:12:38 -0300 Subject: [PATCH 153/388] Move MidiInApi and MidiOutApi subclasses into RtMidi.cpp --- RtMidi.cpp | 209 +++++++++++++++++++++++++++++++++++++++++++++++++++++ RtMidi.h | 209 ----------------------------------------------------- 2 files changed, 209 insertions(+), 209 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 9adf3b87..fe6fa538 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -50,6 +50,215 @@ // flag can be defined (e.g. in your project file) to disable this behaviour. //#define RTMIDI_DO_NOT_ENSURE_UNIQUE_PORTNAMES +// **************************************************************** // +// +// MidiInApi and MidiOutApi subclass prototypes. +// +// **************************************************************** // + +#if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__) + #define __RTMIDI_DUMMY__ +#endif + +#if defined(__MACOSX_CORE__) + +class MidiInCore: public MidiInApi +{ + public: + MidiInCore( const std::string &clientName, unsigned int queueSizeLimit ); + ~MidiInCore( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + + protected: + void initialize( const std::string& clientName ); +}; + +class MidiOutCore: public MidiOutApi +{ + public: + MidiOutCore( const std::string &clientName ); + ~MidiOutCore( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( const unsigned char *message, size_t size ); + + protected: + void initialize( const std::string& clientName ); +}; + +#endif + +#if defined(__UNIX_JACK__) + +class MidiInJack: public MidiInApi +{ + public: + MidiInJack( const std::string &clientName, unsigned int queueSizeLimit ); + ~MidiInJack( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + + protected: + std::string clientName; + + void connect( void ); + void initialize( const std::string& clientName ); +}; + +class MidiOutJack: public MidiOutApi +{ + public: + MidiOutJack( const std::string &clientName ); + ~MidiOutJack( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( const unsigned char *message, size_t size ); + + protected: + std::string clientName; + + void connect( void ); + void initialize( const std::string& clientName ); +}; + +#endif + +#if defined(__LINUX_ALSA__) + +class MidiInAlsa: public MidiInApi +{ + public: + MidiInAlsa( const std::string &clientName, unsigned int queueSizeLimit ); + ~MidiInAlsa( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + + protected: + void initialize( const std::string& clientName ); +}; + +class MidiOutAlsa: public MidiOutApi +{ + public: + MidiOutAlsa( const std::string &clientName ); + ~MidiOutAlsa( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( const unsigned char *message, size_t size ); + + protected: + void initialize( const std::string& clientName ); +}; + +#endif + +#if defined(__WINDOWS_MM__) + +class MidiInWinMM: public MidiInApi +{ + public: + MidiInWinMM( const std::string &clientName, unsigned int queueSizeLimit ); + ~MidiInWinMM( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + + protected: + void initialize( const std::string& clientName ); +}; + +class MidiOutWinMM: public MidiOutApi +{ + public: + MidiOutWinMM( const std::string &clientName ); + ~MidiOutWinMM( void ); + RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; }; + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void closePort( void ); + void setClientName( const std::string &clientName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( const unsigned char *message, size_t size ); + + protected: + void initialize( const std::string& clientName ); +}; + +#endif + +#if defined(__RTMIDI_DUMMY__) + +class MidiInDummy: public MidiInApi +{ + public: + MidiInDummy( const std::string &/*clientName*/, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { errorString_ = "MidiInDummy: This class provides no functionality."; error( RtMidiError::WARNING, errorString_ ); } + RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; } + void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {} + void openVirtualPort( const std::string &/*portName*/ ) {} + void closePort( void ) {} + void setClientName( const std::string &/*clientName*/ ) {}; + unsigned int getPortCount( void ) { return 0; } + std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } + + protected: + void initialize( const std::string& /*clientName*/ ) {} +}; + +class MidiOutDummy: public MidiOutApi +{ + public: + MidiOutDummy( const std::string &/*clientName*/ ) { errorString_ = "MidiOutDummy: This class provides no functionality."; error( RtMidiError::WARNING, errorString_ ); } + RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; } + void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {} + void openVirtualPort( const std::string &/*portName*/ ) {} + void closePort( void ) {} + void setClientName( const std::string &/*clientName*/ ) {}; + unsigned int getPortCount( void ) { return 0; } + std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } + void sendMessage( const unsigned char * /*message*/, size_t /*size*/ ) {} + + protected: + void initialize( const std::string& /*clientName*/ ) {} +}; + +#endif + //*********************************************************************// // RtMidi Definitions //*********************************************************************// diff --git a/RtMidi.h b/RtMidi.h index 6a5e0785..36a89df8 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -605,213 +605,4 @@ inline void RtMidiOut :: sendMessage( const std::vector *message inline void RtMidiOut :: sendMessage( const unsigned char *message, size_t size ) { ((MidiOutApi *)rtapi_)->sendMessage( message, size ); } inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); } -// **************************************************************** // -// -// MidiInApi and MidiOutApi subclass prototypes. -// -// **************************************************************** // - -#if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__) - #define __RTMIDI_DUMMY__ -#endif - -#if defined(__MACOSX_CORE__) - -class MidiInCore: public MidiInApi -{ - public: - MidiInCore( const std::string &clientName, unsigned int queueSizeLimit ); - ~MidiInCore( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; }; - void openPort( unsigned int portNumber, const std::string &portName ); - void openVirtualPort( const std::string &portName ); - void closePort( void ); - void setClientName( const std::string &clientName ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - - protected: - void initialize( const std::string& clientName ); -}; - -class MidiOutCore: public MidiOutApi -{ - public: - MidiOutCore( const std::string &clientName ); - ~MidiOutCore( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; }; - void openPort( unsigned int portNumber, const std::string &portName ); - void openVirtualPort( const std::string &portName ); - void closePort( void ); - void setClientName( const std::string &clientName ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( const unsigned char *message, size_t size ); - - protected: - void initialize( const std::string& clientName ); -}; - -#endif - -#if defined(__UNIX_JACK__) - -class MidiInJack: public MidiInApi -{ - public: - MidiInJack( const std::string &clientName, unsigned int queueSizeLimit ); - ~MidiInJack( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; }; - void openPort( unsigned int portNumber, const std::string &portName ); - void openVirtualPort( const std::string &portName ); - void closePort( void ); - void setClientName( const std::string &clientName ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - - protected: - std::string clientName; - - void connect( void ); - void initialize( const std::string& clientName ); -}; - -class MidiOutJack: public MidiOutApi -{ - public: - MidiOutJack( const std::string &clientName ); - ~MidiOutJack( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; }; - void openPort( unsigned int portNumber, const std::string &portName ); - void openVirtualPort( const std::string &portName ); - void closePort( void ); - void setClientName( const std::string &clientName ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( const unsigned char *message, size_t size ); - - protected: - std::string clientName; - - void connect( void ); - void initialize( const std::string& clientName ); -}; - -#endif - -#if defined(__LINUX_ALSA__) - -class MidiInAlsa: public MidiInApi -{ - public: - MidiInAlsa( const std::string &clientName, unsigned int queueSizeLimit ); - ~MidiInAlsa( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; }; - void openPort( unsigned int portNumber, const std::string &portName ); - void openVirtualPort( const std::string &portName ); - void closePort( void ); - void setClientName( const std::string &clientName ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - - protected: - void initialize( const std::string& clientName ); -}; - -class MidiOutAlsa: public MidiOutApi -{ - public: - MidiOutAlsa( const std::string &clientName ); - ~MidiOutAlsa( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; }; - void openPort( unsigned int portNumber, const std::string &portName ); - void openVirtualPort( const std::string &portName ); - void closePort( void ); - void setClientName( const std::string &clientName ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( const unsigned char *message, size_t size ); - - protected: - void initialize( const std::string& clientName ); -}; - -#endif - -#if defined(__WINDOWS_MM__) - -class MidiInWinMM: public MidiInApi -{ - public: - MidiInWinMM( const std::string &clientName, unsigned int queueSizeLimit ); - ~MidiInWinMM( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; }; - void openPort( unsigned int portNumber, const std::string &portName ); - void openVirtualPort( const std::string &portName ); - void closePort( void ); - void setClientName( const std::string &clientName ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - - protected: - void initialize( const std::string& clientName ); -}; - -class MidiOutWinMM: public MidiOutApi -{ - public: - MidiOutWinMM( const std::string &clientName ); - ~MidiOutWinMM( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; }; - void openPort( unsigned int portNumber, const std::string &portName ); - void openVirtualPort( const std::string &portName ); - void closePort( void ); - void setClientName( const std::string &clientName ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( const unsigned char *message, size_t size ); - - protected: - void initialize( const std::string& clientName ); -}; - -#endif - -#if defined(__RTMIDI_DUMMY__) - -class MidiInDummy: public MidiInApi -{ - public: - MidiInDummy( const std::string &/*clientName*/, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { errorString_ = "MidiInDummy: This class provides no functionality."; error( RtMidiError::WARNING, errorString_ ); } - RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; } - void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {} - void openVirtualPort( const std::string &/*portName*/ ) {} - void closePort( void ) {} - void setClientName( const std::string &/*clientName*/ ) {}; - unsigned int getPortCount( void ) { return 0; } - std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } - - protected: - void initialize( const std::string& /*clientName*/ ) {} -}; - -class MidiOutDummy: public MidiOutApi -{ - public: - MidiOutDummy( const std::string &/*clientName*/ ) { errorString_ = "MidiOutDummy: This class provides no functionality."; error( RtMidiError::WARNING, errorString_ ); } - RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; } - void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {} - void openVirtualPort( const std::string &/*portName*/ ) {} - void closePort( void ) {} - void setClientName( const std::string &/*clientName*/ ) {}; - unsigned int getPortCount( void ) { return 0; } - std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } - void sendMessage( const unsigned char * /*message*/, size_t /*size*/ ) {} - - protected: - void initialize( const std::string& /*clientName*/ ) {} -}; - -#endif - #endif From 27ab76264af627dc99bba584d77bf3b210a66a76 Mon Sep 17 00:00:00 2001 From: jgvictores Date: Wed, 28 Mar 2018 19:52:34 +0200 Subject: [PATCH 154/388] Add and configure Config and Uninstall targets - Small regression on public interface --- CMakeLists.txt | 53 ++++++++++++++++--- cmake/templates/RTMIDIConfig.cmake.in | 10 ++++ .../templates/RTMIDIConfigUninstall.cmake.in | 25 +++++++++ 3 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 cmake/templates/RTMIDIConfig.cmake.in create mode 100644 cmake/templates/RTMIDIConfigUninstall.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 11d7ee2b..5850496b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,22 +5,40 @@ cmake_minimum_required(VERSION 3.0) project(rtmidi) +# set include directory +set(RTMIDI_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}) + +# set module path +set(RTMIDI_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) + +if(WIN32) + set_property(DIRECTORY ${CMAKE_SOURCE_DIR} APPEND PROPERTY COMPILE_DEFINITIONS __WINDOWS_MM__) +endif() + add_library(rtmidi RtMidi.h RtMidi.cpp) -set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h) - -target_include_directories(rtmidi PUBLIC $) +#set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h) +#target_include_directories(rtmidi PUBLIC $) -if(MSVC) - #MESSAGE("MSVC" ) - set_property(DIRECTORY ${CMAKE_SOURCE_DIR} APPEND PROPERTY COMPILE_DEFINITIONS __WINDOWS_MM__) +if(WIN32) target_link_libraries(rtmidi winmm.lib) endif() # Standard installation directories. include(GNUInstallDirs) +# set installation path for CMake modules +if(WIN32) + set(RTMIDI_CMAKE_DESTINATION CMake) +else() + set(RTMIDI_CMAKE_DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}/cmake) +endif() + +# install header file +install(FILES "${RTMIDI_INCLUDE_DIRS}/RtMidi.h" + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + install(TARGETS rtmidi LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -28,3 +46,26 @@ install(TARGETS rtmidi PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) set_property(GLOBAL APPEND PROPERTY RTMIDI_TARGETS rtmidi) + +include(CMakePackageConfigHelpers) + +# configure PkgConfig.cmake (install-tree) +configure_package_config_file("${CMAKE_SOURCE_DIR}/cmake/templates/RTMIDIConfig.cmake.in" + "${CMAKE_BINARY_DIR}/RTMIDIConfigForInstall.cmake" + INSTALL_DESTINATION ${RTMIDI_CMAKE_DESTINATION} + PATH_VARS RTMIDI_INCLUDE_DIRS RTMIDI_MODULE_PATH + NO_CHECK_REQUIRED_COMPONENTS_MACRO) + +# install PkgConfig.cmake +install(FILES "${CMAKE_BINARY_DIR}/RTMIDIConfigForInstall.cmake" + RENAME RTMIDIConfig.cmake + DESTINATION ${RTMIDI_CMAKE_DESTINATION}) + +# uninstall target configuration +configure_file( + "${CMAKE_SOURCE_DIR}/cmake/templates/RTMIDIConfigUninstall.cmake.in" + "${CMAKE_BINARY_DIR}/RTMIDIConfigUninstall.cmake" @ONLY) + +# uninstall target creation +add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/RTMIDIConfigUninstall.cmake) diff --git a/cmake/templates/RTMIDIConfig.cmake.in b/cmake/templates/RTMIDIConfig.cmake.in new file mode 100644 index 00000000..4b68dc40 --- /dev/null +++ b/cmake/templates/RTMIDIConfig.cmake.in @@ -0,0 +1,10 @@ +# 2018 (c) Juan G. Victores +# CopyPolicy: RtMidi license. + +@PACKAGE_INIT@ + +set_and_check(RTMIDI_INCLUDE_DIRS "@PACKAGE_RTMIDI_INCLUDE_DIRS@") +set_and_check(RTMIDI_MODULE_PATH "@PACKAGE_RTMIDI_MODULE_PATH@") + +# we don't need this anymore +unset(RTMIDI_MODULE_PATH) diff --git a/cmake/templates/RTMIDIConfigUninstall.cmake.in b/cmake/templates/RTMIDIConfigUninstall.cmake.in new file mode 100644 index 00000000..e57fb768 --- /dev/null +++ b/cmake/templates/RTMIDIConfigUninstall.cmake.in @@ -0,0 +1,25 @@ +# 2018 (c) Juan G. Victores +# CopyPolicy: RtMidi license. + +if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") +endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + +file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) +string(REGEX REPLACE "\n" ";" files "${files}") +foreach(file ${files}) + message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") + if(EXISTS "$ENV{DESTDIR}${file}") + exec_program( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + if(NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") + endif(NOT "${rm_retval}" STREQUAL 0) + else(EXISTS "$ENV{DESTDIR}${file}") + message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") + endif(EXISTS "$ENV{DESTDIR}${file}") +endforeach(file) + From 9f5c64444e428e35133b1467b737dffadef4cd2f Mon Sep 17 00:00:00 2001 From: jgvictores Date: Thu, 29 Mar 2018 08:02:58 +0200 Subject: [PATCH 155/388] begin lib export --- CMakeLists.txt | 19 ++++++++----------- cmake/templates/RTMIDIConfig.cmake.in | 5 +---- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5850496b..0fc1e273 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,12 +5,6 @@ cmake_minimum_required(VERSION 3.0) project(rtmidi) -# set include directory -set(RTMIDI_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}) - -# set module path -set(RTMIDI_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) - if(WIN32) set_property(DIRECTORY ${CMAKE_SOURCE_DIR} APPEND PROPERTY COMPILE_DEFINITIONS __WINDOWS_MM__) endif() @@ -18,8 +12,9 @@ endif() add_library(rtmidi RtMidi.h RtMidi.cpp) -#set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h) -#target_include_directories(rtmidi PUBLIC $) +set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h) + +target_include_directories(rtmidi PUBLIC $) if(WIN32) target_link_libraries(rtmidi winmm.lib) @@ -36,16 +31,18 @@ else() endif() # install header file -install(FILES "${RTMIDI_INCLUDE_DIRS}/RtMidi.h" +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/RtMidi.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +set(RTMIDI_INCLUDE_DIRS ${CMAKE_INSTALL_INCLUDEDIR}) + install(TARGETS rtmidi LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -set_property(GLOBAL APPEND PROPERTY RTMIDI_TARGETS rtmidi) +set(RTMIDI_LIBRARIES $) include(CMakePackageConfigHelpers) @@ -53,7 +50,7 @@ include(CMakePackageConfigHelpers) configure_package_config_file("${CMAKE_SOURCE_DIR}/cmake/templates/RTMIDIConfig.cmake.in" "${CMAKE_BINARY_DIR}/RTMIDIConfigForInstall.cmake" INSTALL_DESTINATION ${RTMIDI_CMAKE_DESTINATION} - PATH_VARS RTMIDI_INCLUDE_DIRS RTMIDI_MODULE_PATH + PATH_VARS RTMIDI_INCLUDE_DIRS RTMIDI_LIBRARIES NO_CHECK_REQUIRED_COMPONENTS_MACRO) # install PkgConfig.cmake diff --git a/cmake/templates/RTMIDIConfig.cmake.in b/cmake/templates/RTMIDIConfig.cmake.in index 4b68dc40..9da2f5ee 100644 --- a/cmake/templates/RTMIDIConfig.cmake.in +++ b/cmake/templates/RTMIDIConfig.cmake.in @@ -4,7 +4,4 @@ @PACKAGE_INIT@ set_and_check(RTMIDI_INCLUDE_DIRS "@PACKAGE_RTMIDI_INCLUDE_DIRS@") -set_and_check(RTMIDI_MODULE_PATH "@PACKAGE_RTMIDI_MODULE_PATH@") - -# we don't need this anymore -unset(RTMIDI_MODULE_PATH) +set_and_check(RTMIDI_LIBRARIES "@PACKAGE_RTMIDI_LIBRARIES@") From 7f2dd0daaf40718a5d8c204e77f73ebca777cb97 Mon Sep 17 00:00:00 2001 From: jgvictores Date: Thu, 29 Mar 2018 10:59:39 +0200 Subject: [PATCH 156/388] attempt to modernize --- CMakeLists.txt | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0fc1e273..30213eb0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,17 +5,19 @@ cmake_minimum_required(VERSION 3.0) project(rtmidi) +set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h) + +target_include_directories(rtmidi PUBLIC $) + +set(RTMIDI_INCLUDE_DIRS ${CMAKE_INSTALL_INCLUDEDIR}) + if(WIN32) - set_property(DIRECTORY ${CMAKE_SOURCE_DIR} APPEND PROPERTY COMPILE_DEFINITIONS __WINDOWS_MM__) + set_property(TARGET rtmidi APPEND PROPERTY COMPILE_DEFINITIONS __WINDOWS_MM__) endif() add_library(rtmidi RtMidi.h RtMidi.cpp) -set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h) - -target_include_directories(rtmidi PUBLIC $) - if(WIN32) target_link_libraries(rtmidi winmm.lib) endif() @@ -30,12 +32,6 @@ else() set(RTMIDI_CMAKE_DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}/cmake) endif() -# install header file -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/RtMidi.h" - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - -set(RTMIDI_INCLUDE_DIRS ${CMAKE_INSTALL_INCLUDEDIR}) - install(TARGETS rtmidi LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} From eed4e09e5238dadaf78e5c7adf5b78736d2d2be0 Mon Sep 17 00:00:00 2001 From: jgvictores Date: Thu, 29 Mar 2018 11:41:20 +0200 Subject: [PATCH 157/388] move around --- CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 30213eb0..93cc0c18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,14 @@ cmake_minimum_required(VERSION 3.0) project(rtmidi) +add_library(rtmidi RtMidi.h + RtMidi.cpp) + set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h) +# Standard installation directories. +include(GNUInstallDirs) + target_include_directories(rtmidi PUBLIC $) set(RTMIDI_INCLUDE_DIRS ${CMAKE_INSTALL_INCLUDEDIR}) @@ -15,16 +21,10 @@ if(WIN32) set_property(TARGET rtmidi APPEND PROPERTY COMPILE_DEFINITIONS __WINDOWS_MM__) endif() -add_library(rtmidi RtMidi.h - RtMidi.cpp) - if(WIN32) target_link_libraries(rtmidi winmm.lib) endif() -# Standard installation directories. -include(GNUInstallDirs) - # set installation path for CMake modules if(WIN32) set(RTMIDI_CMAKE_DESTINATION CMake) @@ -38,7 +38,7 @@ install(TARGETS rtmidi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -set(RTMIDI_LIBRARIES $) +set(RTMIDI_LIBRARIES "$") include(CMakePackageConfigHelpers) From 4c98b8b67c72805ce19a4fb283ba41b6cce96d4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20=C5=81ukawski?= Date: Fri, 30 Mar 2018 09:17:16 +0200 Subject: [PATCH 158/388] Add /build*/ path to .gitignore Quite usual in CMake-driven projects. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 89424779..44b3d6ab 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ /m4 /doc/Makefile.in /tests/Makefile.in +/build*/ From e49150d1bd5bbc242c524df5538ce188d3a4ceca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20=C5=81ukawski?= Date: Fri, 30 Mar 2018 09:18:30 +0200 Subject: [PATCH 159/388] Fix CMake target export mechanisms --- CMakeLists.txt | 67 +++++++++++++++------------ cmake/templates/RTMIDIConfig.cmake.in | 7 --- 2 files changed, 37 insertions(+), 37 deletions(-) delete mode 100644 cmake/templates/RTMIDIConfig.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 93cc0c18..29910d55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,64 +1,71 @@ # 2018 (c) Juan G. Victores # CopyPolicy: RtMidi license. -cmake_minimum_required(VERSION 3.0) +# Set minimum CMake required version for this project. +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) -project(rtmidi) +# Define a project. +project(RtMidi) +# Create library target. add_library(rtmidi RtMidi.h RtMidi.cpp) +# Add headers destination for install rule. set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h) # Standard installation directories. include(GNUInstallDirs) -target_include_directories(rtmidi PUBLIC $) - -set(RTMIDI_INCLUDE_DIRS ${CMAKE_INSTALL_INCLUDEDIR}) - -if(WIN32) - set_property(TARGET rtmidi APPEND PROPERTY COMPILE_DEFINITIONS __WINDOWS_MM__) -endif() +# Set include paths, populate target interface. +target_include_directories(rtmidi PUBLIC $ + $) +# Tweak platform-specific configuration. if(WIN32) - target_link_libraries(rtmidi winmm.lib) -endif() - -# set installation path for CMake modules -if(WIN32) - set(RTMIDI_CMAKE_DESTINATION CMake) -else() - set(RTMIDI_CMAKE_DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}/cmake) + target_compile_definitions(rtmidi PRIVATE __WINDOWS_MM__) + target_link_libraries(rtmidi PRIVATE winmm.lib) endif() +# Add install rule. install(TARGETS rtmidi + EXPORT RtMidiTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -set(RTMIDI_LIBRARIES "$") +# Store the package in the user registry. +export(PACKAGE RtMidi) -include(CMakePackageConfigHelpers) +# Set installation path for CMake files. +if(WIN32) + set(RTMIDI_CMAKE_DESTINATION cmake) +else() + set(RTMIDI_CMAKE_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/RtMidi) +endif() -# configure PkgConfig.cmake (install-tree) -configure_package_config_file("${CMAKE_SOURCE_DIR}/cmake/templates/RTMIDIConfig.cmake.in" - "${CMAKE_BINARY_DIR}/RTMIDIConfigForInstall.cmake" - INSTALL_DESTINATION ${RTMIDI_CMAKE_DESTINATION} - PATH_VARS RTMIDI_INCLUDE_DIRS RTMIDI_LIBRARIES - NO_CHECK_REQUIRED_COMPONENTS_MACRO) +# Create CMake configuration export file. +file(WRITE ${CMAKE_BINARY_DIR}/RtMidiConfig.cmake "include(\${CMAKE_CURRENT_LIST_DIR}/RtMidiTargets.cmake)") -# install PkgConfig.cmake -install(FILES "${CMAKE_BINARY_DIR}/RTMIDIConfigForInstall.cmake" - RENAME RTMIDIConfig.cmake +# Install CMake configuration file. +install(FILES ${CMAKE_BINARY_DIR}/RtMidiConfig.cmake DESTINATION ${RTMIDI_CMAKE_DESTINATION}) -# uninstall target configuration +# Export library target (build-tree). +export(EXPORT RtMidiTargets + NAMESPACE RtMidi::) + +# Export library target (install-tree). +install(EXPORT RtMidiTargets + DESTINATION ${RTMIDI_CMAKE_DESTINATION} + NAMESPACE RtMidi::) + +# Configure uninstall target. configure_file( "${CMAKE_SOURCE_DIR}/cmake/templates/RTMIDIConfigUninstall.cmake.in" "${CMAKE_BINARY_DIR}/RTMIDIConfigUninstall.cmake" @ONLY) -# uninstall target creation +# Create uninstall target. add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/RTMIDIConfigUninstall.cmake) diff --git a/cmake/templates/RTMIDIConfig.cmake.in b/cmake/templates/RTMIDIConfig.cmake.in deleted file mode 100644 index 9da2f5ee..00000000 --- a/cmake/templates/RTMIDIConfig.cmake.in +++ /dev/null @@ -1,7 +0,0 @@ -# 2018 (c) Juan G. Victores -# CopyPolicy: RtMidi license. - -@PACKAGE_INIT@ - -set_and_check(RTMIDI_INCLUDE_DIRS "@PACKAGE_RTMIDI_INCLUDE_DIRS@") -set_and_check(RTMIDI_LIBRARIES "@PACKAGE_RTMIDI_LIBRARIES@") From 655a4226c022c26604e1f3b6077913824acb979a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20=C5=81ukawski?= Date: Fri, 30 Mar 2018 09:30:46 +0200 Subject: [PATCH 160/388] Propagate WIN32 usage requirements to downstreams The __WINDOWS_MM__ macro is used in RtMidi.h and RtMidi.c to switch between available APIs through polymorphism. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 29910d55..997e1ed5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,8 +23,8 @@ target_include_directories(rtmidi PUBLIC $ Date: Sat, 31 Mar 2018 20:00:26 +0200 Subject: [PATCH 161/388] Revert "Propagate WIN32 usage requirements to downstreams" This reverts commit 655a422 as a follow-up to 22cc8b3 at master. No need to propagate anything since implementation classes (which include the Windows MM API) are not exposed anymore in the header file. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 997e1ed5..29910d55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,8 +23,8 @@ target_include_directories(rtmidi PUBLIC $ Date: Sat, 31 Mar 2018 20:10:14 +0200 Subject: [PATCH 162/388] Set project language, improve some comments --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 29910d55..45689524 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,8 +4,8 @@ # Set minimum CMake required version for this project. cmake_minimum_required(VERSION 3.0 FATAL_ERROR) -# Define a project. -project(RtMidi) +# Define a C++ project. +project(RtMidi LANGUAGES CXX) # Create library target. add_library(rtmidi RtMidi.h @@ -14,7 +14,7 @@ add_library(rtmidi RtMidi.h # Add headers destination for install rule. set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h) -# Standard installation directories. +# Set standard installation directories. include(GNUInstallDirs) # Set include paths, populate target interface. @@ -48,7 +48,7 @@ endif() # Create CMake configuration export file. file(WRITE ${CMAKE_BINARY_DIR}/RtMidiConfig.cmake "include(\${CMAKE_CURRENT_LIST_DIR}/RtMidiTargets.cmake)") -# Install CMake configuration file. +# Install CMake configuration export file. install(FILES ${CMAKE_BINARY_DIR}/RtMidiConfig.cmake DESTINATION ${RTMIDI_CMAKE_DESTINATION}) From b2c9a68fbfa11def601a8ddc4325d8a58024792c Mon Sep 17 00:00:00 2001 From: jgvictores Date: Mon, 2 Apr 2018 15:18:59 +0200 Subject: [PATCH 163/388] Add UNIX/APPLE compile_definitions/link_libraries Tested on Ubuntu Xenial (gcc 4.5) and Windows 10 (VS 15, win32). Refs: - http://www.music.mcgill.ca/~gary/rtmidi/ - https://github.com/thestk/rtmidi/blob/22cc8b3aff966e61c0aed1361d3fb96462cd9b50/contrib/go/rtmidi/rtmidi.go#L7-L12 - https://stackoverflow.com/questions/17070101/why-i-cannot-link-the-mac-framework-file-with-cmake --- CMakeLists.txt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 45689524..d09c8a14 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,9 +22,19 @@ target_include_directories(rtmidi PUBLIC $) # Tweak platform-specific configuration. -if(WIN32) +if(UNIX) + target_compile_definitions(rtmidi PRIVATE __LINUX_ALSA__) + target_link_libraries(rtmidi PRIVATE asound pthread) +elseif(WIN32) target_compile_definitions(rtmidi PRIVATE __WINDOWS_MM__) target_link_libraries(rtmidi PRIVATE winmm.lib) +elseif(APPLE) + target_compile_definitions(rtmidi PRIVATE __MACOSX_CORE__) + target_link_libraries(rtmidi PRIVATE "-framework CoreServices") + target_link_libraries(rtmidi PRIVATE "-framework CoreAudio") + target_link_libraries(rtmidi PRIVATE "-framework CoreMIDI" + target_link_libraries(rtmidi PRIVATE "-framework CoreFoundation") + set_target_properties(rtmidi PROPERTIES LINK_FLAGS "-Wl,-F/Library/Frameworks") endif() # Add install rule. From 9055d979cb80bc17a1e2a4d717cd8ec83459ae6a Mon Sep 17 00:00:00 2001 From: jgvictores Date: Mon, 2 Apr 2018 15:23:59 +0200 Subject: [PATCH 164/388] add missing parenthesis --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d09c8a14..a925b462 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ elseif(APPLE) target_compile_definitions(rtmidi PRIVATE __MACOSX_CORE__) target_link_libraries(rtmidi PRIVATE "-framework CoreServices") target_link_libraries(rtmidi PRIVATE "-framework CoreAudio") - target_link_libraries(rtmidi PRIVATE "-framework CoreMIDI" + target_link_libraries(rtmidi PRIVATE "-framework CoreMIDI") target_link_libraries(rtmidi PRIVATE "-framework CoreFoundation") set_target_properties(rtmidi PROPERTIES LINK_FLAGS "-Wl,-F/Library/Frameworks") endif() From c43ac9a69ecf969691f021e98538f4bc5954051c Mon Sep 17 00:00:00 2001 From: jgvictores Date: Mon, 2 Apr 2018 15:32:25 +0200 Subject: [PATCH 165/388] Fix authors (remove from generic template) --- CMakeLists.txt | 2 +- cmake/templates/RTMIDIConfigUninstall.cmake.in | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a925b462..3c1e8bea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# 2018 (c) Juan G. Victores +# 2018 (c) Juan G. Victores, Bartek Łukawski. # CopyPolicy: RtMidi license. # Set minimum CMake required version for this project. diff --git a/cmake/templates/RTMIDIConfigUninstall.cmake.in b/cmake/templates/RTMIDIConfigUninstall.cmake.in index e57fb768..db894b3f 100644 --- a/cmake/templates/RTMIDIConfigUninstall.cmake.in +++ b/cmake/templates/RTMIDIConfigUninstall.cmake.in @@ -1,6 +1,3 @@ -# 2018 (c) Juan G. Victores -# CopyPolicy: RtMidi license. - if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") @@ -22,4 +19,3 @@ foreach(file ${files}) message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") endif(EXISTS "$ENV{DESTDIR}${file}") endforeach(file) - From 3830c29bcb258fb2506eaeb0f296b3ecb76161d2 Mon Sep 17 00:00:00 2001 From: Chris Chronopoulos Date: Thu, 12 Apr 2018 10:18:39 -0400 Subject: [PATCH 166/388] add setPortName() functionality (#159) * add setPortName() functionality This commit adds a new method setPortName(const std::string &portName) to the RtMidi class. Port renaming is implemented for the ALSA and JACK API's. For the other API's, a warning is thrown using RtMidiError. Note that port renaming in JACK is implemented using jack_port_rename(), which is available on jack2 versions >= 1.9.11, and jack1 versions >= 0.125.0. * add autoconf check for jack_port_rename --- RtMidi.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ RtMidi.h | 2 ++ configure.ac | 5 +++ 3 files changed, 94 insertions(+) diff --git a/RtMidi.cpp b/RtMidi.cpp index fe6fa538..f6968c1e 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -72,6 +72,7 @@ class MidiInCore: public MidiInApi void openVirtualPort( const std::string &portName ); void closePort( void ); void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -89,6 +90,7 @@ class MidiOutCore: public MidiOutApi void openVirtualPort( const std::string &portName ); void closePort( void ); void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); void sendMessage( const unsigned char *message, size_t size ); @@ -111,6 +113,7 @@ class MidiInJack: public MidiInApi void openVirtualPort( const std::string &portName ); void closePort( void ); void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -131,6 +134,7 @@ class MidiOutJack: public MidiOutApi void openVirtualPort( const std::string &portName ); void closePort( void ); void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); void sendMessage( const unsigned char *message, size_t size ); @@ -156,6 +160,7 @@ class MidiInAlsa: public MidiInApi void openVirtualPort( const std::string &portName ); void closePort( void ); void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -173,6 +178,7 @@ class MidiOutAlsa: public MidiOutApi void openVirtualPort( const std::string &portName ); void closePort( void ); void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); void sendMessage( const unsigned char *message, size_t size ); @@ -195,6 +201,7 @@ class MidiInWinMM: public MidiInApi void openVirtualPort( const std::string &portName ); void closePort( void ); void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -212,6 +219,7 @@ class MidiOutWinMM: public MidiOutApi void openVirtualPort( const std::string &portName ); void closePort( void ); void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); void sendMessage( const unsigned char *message, size_t size ); @@ -233,6 +241,7 @@ class MidiInDummy: public MidiInApi void openVirtualPort( const std::string &/*portName*/ ) {} void closePort( void ) {} void setClientName( const std::string &/*clientName*/ ) {}; + void setPortName( const std::string &/*portName*/ ) {}; unsigned int getPortCount( void ) { return 0; } std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } @@ -249,6 +258,7 @@ class MidiOutDummy: public MidiOutApi void openVirtualPort( const std::string &/*portName*/ ) {} void closePort( void ) {} void setClientName( const std::string &/*clientName*/ ) {}; + void setPortName( const std::string &/*portName*/ ) {}; unsigned int getPortCount( void ) { return 0; } std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } void sendMessage( const unsigned char * /*message*/, size_t /*size*/ ) {} @@ -307,6 +317,11 @@ void RtMidi :: setClientName( const std::string &clientName ) rtapi_->setClientName(clientName); } +void RtMidi :: setPortName( const std::string &portName ) +{ + rtapi_->setPortName(portName); +} + //*********************************************************************// // RtMidiIn Definitions @@ -971,6 +986,14 @@ void MidiInCore :: setClientName ( const std::string& ) } +void MidiInCore :: setPortName ( const std::string& ) +{ + + errorString_ = "MidiInCore::setPortName: this function is not implemented for the MACOSX_CORE API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + unsigned int MidiInCore :: getPortCount() { CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); @@ -1280,6 +1303,14 @@ void MidiOutCore :: setClientName ( const std::string& ) } +void MidiOutCore :: setPortName ( const std::string& ) +{ + + errorString_ = "MidiOutCore::setPortName: this function is not implemented for the MACOSX_CORE API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + void MidiOutCore :: openVirtualPort( const std::string &portName ) { CoreMidiData *data = static_cast (apiData_); @@ -1979,6 +2010,16 @@ void MidiInAlsa :: setClientName( const std::string &clientName ) } +void MidiInAlsa :: setPortName( const std::string &portName ) +{ + AlsaMidiData *data = static_cast (apiData_); + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + snd_seq_get_port_info( data->seq, data->vport, pinfo ); + snd_seq_port_info_set_name( pinfo, portName.c_str() ); + snd_seq_set_port_info( data->seq, data->vport, pinfo ); +} + //*********************************************************************// // API: LINUX ALSA // Class Definitions: MidiOutAlsa @@ -2166,6 +2207,16 @@ void MidiOutAlsa :: setClientName( const std::string &clientName ) } +void MidiOutAlsa :: setPortName( const std::string &portName ) +{ + AlsaMidiData *data = static_cast (apiData_); + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + snd_seq_get_port_info( data->seq, data->vport, pinfo ); + snd_seq_port_info_set_name( pinfo, portName.c_str() ); + snd_seq_set_port_info( data->seq, data->vport, pinfo ); +} + void MidiOutAlsa :: openVirtualPort( const std::string &portName ) { AlsaMidiData *data = static_cast (apiData_); @@ -2547,6 +2598,14 @@ void MidiInWinMM :: setClientName ( const std::string& ) } +void MidiInWinMM :: setPortName ( const std::string& ) +{ + + errorString_ = "MidiInWinMM::setPortName: this function is not implemented for the WINDOWS_MM API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + unsigned int MidiInWinMM :: getPortCount() { return midiInGetNumDevs(); @@ -2707,6 +2766,14 @@ void MidiOutWinMM :: setClientName ( const std::string& ) } +void MidiOutWinMM :: setPortName ( const std::string& ) +{ + + errorString_ = "MidiOutWinMM::setPortName: this function is not implemented for the WINDOWS_MM API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + void MidiOutWinMM :: openVirtualPort( const std::string &/*portName*/ ) { // This function cannot be implemented for the Windows MM MIDI API. @@ -3029,6 +3096,16 @@ void MidiInJack:: setClientName( const std::string& ) } +void MidiInJack :: setPortName( const std::string &portName ) +{ + JackMidiData *data = static_cast (apiData_); +#ifdef __JACK_HAS_PORT_RENAME__ + jack_port_rename( data->client, data->port, portName.c_str() ); +#else + jack_port_set_name( data->port, portName.c_str() ); +#endif +} + //*********************************************************************// // API: JACK // Class Definitions: MidiOutJack @@ -3240,6 +3317,16 @@ void MidiOutJack:: setClientName( const std::string& ) } +void MidiOutJack :: setPortName( const std::string &portName ) +{ + JackMidiData *data = static_cast (apiData_); +#ifdef __JACK_HAS_PORT_RENAME__ + jack_port_rename( data->client, data->port, portName.c_str() ); +#else + jack_port_set_name( data->port, portName.c_str() ); +#endif +} + void MidiOutJack :: sendMessage( const unsigned char *message, size_t size ) { int nBytes = static_cast(size); diff --git a/RtMidi.h b/RtMidi.h index 36a89df8..fac740e1 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -164,6 +164,7 @@ class RTMIDI_DLL_PUBLIC RtMidi virtual void closePort( void ) = 0; void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); //! Returns true if a port is open and false if not. /*! @@ -481,6 +482,7 @@ class RTMIDI_DLL_PUBLIC MidiApi virtual void openVirtualPort( const std::string &portName ) = 0; virtual void closePort( void ) = 0; virtual void setClientName( const std::string &clientName ) = 0; + virtual void setPortName( const std::string &portName ) = 0; virtual unsigned int getPortCount( void ) = 0; virtual std::string getPortName( unsigned int portNumber ) = 0; diff --git a/configure.ac b/configure.ac index dad72e2f..92e3d299 100644 --- a/configure.ac +++ b/configure.ac @@ -138,6 +138,11 @@ AS_IF([test "x$with_jack" = "xyes"], [ req="$req jack" ]) +AS_IF([test "x$with_jack" = "xyes"], [ + AC_MSG_RESULT(using JACK) + AC_CHECK_LIB(jack, jack_port_rename, AC_DEFINE(__JACK_HAS_PORT_RENAME__), ) +]) + case $host in *-*-linux*) # Look for ALSA flag From 81eabf2563431160496f091937b5ead4d205376e Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Thu, 12 Apr 2018 11:21:13 -0300 Subject: [PATCH 167/388] Remove underscores from JACK_HAS_PORT_RENAME. --- RtMidi.cpp | 4 ++-- configure.ac | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index f6968c1e..7744b05b 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -3099,7 +3099,7 @@ void MidiInJack:: setClientName( const std::string& ) void MidiInJack :: setPortName( const std::string &portName ) { JackMidiData *data = static_cast (apiData_); -#ifdef __JACK_HAS_PORT_RENAME__ +#ifdef JACK_HAS_PORT_RENAME jack_port_rename( data->client, data->port, portName.c_str() ); #else jack_port_set_name( data->port, portName.c_str() ); @@ -3320,7 +3320,7 @@ void MidiOutJack:: setClientName( const std::string& ) void MidiOutJack :: setPortName( const std::string &portName ) { JackMidiData *data = static_cast (apiData_); -#ifdef __JACK_HAS_PORT_RENAME__ +#ifdef JACK_HAS_PORT_RENAME jack_port_rename( data->client, data->port, portName.c_str() ); #else jack_port_set_name( data->port, portName.c_str() ); diff --git a/configure.ac b/configure.ac index 92e3d299..b756b4f8 100644 --- a/configure.ac +++ b/configure.ac @@ -140,7 +140,7 @@ AS_IF([test "x$with_jack" = "xyes"], [ AS_IF([test "x$with_jack" = "xyes"], [ AC_MSG_RESULT(using JACK) - AC_CHECK_LIB(jack, jack_port_rename, AC_DEFINE(__JACK_HAS_PORT_RENAME__), ) + AC_CHECK_LIB(jack, jack_port_rename, AC_DEFINE(JACK_HAS_PORT_RENAME), ) ]) case $host in From e1c9b904b32631831ca74c196bb57622e0b00355 Mon Sep 17 00:00:00 2001 From: Chris Chronopoulos Date: Thu, 12 Apr 2018 10:18:39 -0400 Subject: [PATCH 168/388] add setPortName() functionality (#159) * add setPortName() functionality This commit adds a new method setPortName(const std::string &portName) to the RtMidi class. Port renaming is implemented for the ALSA and JACK API's. For the other API's, a warning is thrown using RtMidiError. Note that port renaming in JACK is implemented using jack_port_rename(), which is available on jack2 versions >= 1.9.11, and jack1 versions >= 0.125.0. * add autoconf check for jack_port_rename --- RtMidi.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ RtMidi.h | 2 ++ configure.ac | 5 +++ 3 files changed, 94 insertions(+) diff --git a/RtMidi.cpp b/RtMidi.cpp index fe6fa538..f6968c1e 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -72,6 +72,7 @@ class MidiInCore: public MidiInApi void openVirtualPort( const std::string &portName ); void closePort( void ); void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -89,6 +90,7 @@ class MidiOutCore: public MidiOutApi void openVirtualPort( const std::string &portName ); void closePort( void ); void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); void sendMessage( const unsigned char *message, size_t size ); @@ -111,6 +113,7 @@ class MidiInJack: public MidiInApi void openVirtualPort( const std::string &portName ); void closePort( void ); void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -131,6 +134,7 @@ class MidiOutJack: public MidiOutApi void openVirtualPort( const std::string &portName ); void closePort( void ); void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); void sendMessage( const unsigned char *message, size_t size ); @@ -156,6 +160,7 @@ class MidiInAlsa: public MidiInApi void openVirtualPort( const std::string &portName ); void closePort( void ); void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -173,6 +178,7 @@ class MidiOutAlsa: public MidiOutApi void openVirtualPort( const std::string &portName ); void closePort( void ); void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); void sendMessage( const unsigned char *message, size_t size ); @@ -195,6 +201,7 @@ class MidiInWinMM: public MidiInApi void openVirtualPort( const std::string &portName ); void closePort( void ); void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); @@ -212,6 +219,7 @@ class MidiOutWinMM: public MidiOutApi void openVirtualPort( const std::string &portName ); void closePort( void ); void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); unsigned int getPortCount( void ); std::string getPortName( unsigned int portNumber ); void sendMessage( const unsigned char *message, size_t size ); @@ -233,6 +241,7 @@ class MidiInDummy: public MidiInApi void openVirtualPort( const std::string &/*portName*/ ) {} void closePort( void ) {} void setClientName( const std::string &/*clientName*/ ) {}; + void setPortName( const std::string &/*portName*/ ) {}; unsigned int getPortCount( void ) { return 0; } std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } @@ -249,6 +258,7 @@ class MidiOutDummy: public MidiOutApi void openVirtualPort( const std::string &/*portName*/ ) {} void closePort( void ) {} void setClientName( const std::string &/*clientName*/ ) {}; + void setPortName( const std::string &/*portName*/ ) {}; unsigned int getPortCount( void ) { return 0; } std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } void sendMessage( const unsigned char * /*message*/, size_t /*size*/ ) {} @@ -307,6 +317,11 @@ void RtMidi :: setClientName( const std::string &clientName ) rtapi_->setClientName(clientName); } +void RtMidi :: setPortName( const std::string &portName ) +{ + rtapi_->setPortName(portName); +} + //*********************************************************************// // RtMidiIn Definitions @@ -971,6 +986,14 @@ void MidiInCore :: setClientName ( const std::string& ) } +void MidiInCore :: setPortName ( const std::string& ) +{ + + errorString_ = "MidiInCore::setPortName: this function is not implemented for the MACOSX_CORE API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + unsigned int MidiInCore :: getPortCount() { CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); @@ -1280,6 +1303,14 @@ void MidiOutCore :: setClientName ( const std::string& ) } +void MidiOutCore :: setPortName ( const std::string& ) +{ + + errorString_ = "MidiOutCore::setPortName: this function is not implemented for the MACOSX_CORE API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + void MidiOutCore :: openVirtualPort( const std::string &portName ) { CoreMidiData *data = static_cast (apiData_); @@ -1979,6 +2010,16 @@ void MidiInAlsa :: setClientName( const std::string &clientName ) } +void MidiInAlsa :: setPortName( const std::string &portName ) +{ + AlsaMidiData *data = static_cast (apiData_); + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + snd_seq_get_port_info( data->seq, data->vport, pinfo ); + snd_seq_port_info_set_name( pinfo, portName.c_str() ); + snd_seq_set_port_info( data->seq, data->vport, pinfo ); +} + //*********************************************************************// // API: LINUX ALSA // Class Definitions: MidiOutAlsa @@ -2166,6 +2207,16 @@ void MidiOutAlsa :: setClientName( const std::string &clientName ) } +void MidiOutAlsa :: setPortName( const std::string &portName ) +{ + AlsaMidiData *data = static_cast (apiData_); + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + snd_seq_get_port_info( data->seq, data->vport, pinfo ); + snd_seq_port_info_set_name( pinfo, portName.c_str() ); + snd_seq_set_port_info( data->seq, data->vport, pinfo ); +} + void MidiOutAlsa :: openVirtualPort( const std::string &portName ) { AlsaMidiData *data = static_cast (apiData_); @@ -2547,6 +2598,14 @@ void MidiInWinMM :: setClientName ( const std::string& ) } +void MidiInWinMM :: setPortName ( const std::string& ) +{ + + errorString_ = "MidiInWinMM::setPortName: this function is not implemented for the WINDOWS_MM API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + unsigned int MidiInWinMM :: getPortCount() { return midiInGetNumDevs(); @@ -2707,6 +2766,14 @@ void MidiOutWinMM :: setClientName ( const std::string& ) } +void MidiOutWinMM :: setPortName ( const std::string& ) +{ + + errorString_ = "MidiOutWinMM::setPortName: this function is not implemented for the WINDOWS_MM API!"; + error( RtMidiError::WARNING, errorString_ ); + +} + void MidiOutWinMM :: openVirtualPort( const std::string &/*portName*/ ) { // This function cannot be implemented for the Windows MM MIDI API. @@ -3029,6 +3096,16 @@ void MidiInJack:: setClientName( const std::string& ) } +void MidiInJack :: setPortName( const std::string &portName ) +{ + JackMidiData *data = static_cast (apiData_); +#ifdef __JACK_HAS_PORT_RENAME__ + jack_port_rename( data->client, data->port, portName.c_str() ); +#else + jack_port_set_name( data->port, portName.c_str() ); +#endif +} + //*********************************************************************// // API: JACK // Class Definitions: MidiOutJack @@ -3240,6 +3317,16 @@ void MidiOutJack:: setClientName( const std::string& ) } +void MidiOutJack :: setPortName( const std::string &portName ) +{ + JackMidiData *data = static_cast (apiData_); +#ifdef __JACK_HAS_PORT_RENAME__ + jack_port_rename( data->client, data->port, portName.c_str() ); +#else + jack_port_set_name( data->port, portName.c_str() ); +#endif +} + void MidiOutJack :: sendMessage( const unsigned char *message, size_t size ) { int nBytes = static_cast(size); diff --git a/RtMidi.h b/RtMidi.h index 36a89df8..fac740e1 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -164,6 +164,7 @@ class RTMIDI_DLL_PUBLIC RtMidi virtual void closePort( void ) = 0; void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); //! Returns true if a port is open and false if not. /*! @@ -481,6 +482,7 @@ class RTMIDI_DLL_PUBLIC MidiApi virtual void openVirtualPort( const std::string &portName ) = 0; virtual void closePort( void ) = 0; virtual void setClientName( const std::string &clientName ) = 0; + virtual void setPortName( const std::string &portName ) = 0; virtual unsigned int getPortCount( void ) = 0; virtual std::string getPortName( unsigned int portNumber ) = 0; diff --git a/configure.ac b/configure.ac index dad72e2f..92e3d299 100644 --- a/configure.ac +++ b/configure.ac @@ -138,6 +138,11 @@ AS_IF([test "x$with_jack" = "xyes"], [ req="$req jack" ]) +AS_IF([test "x$with_jack" = "xyes"], [ + AC_MSG_RESULT(using JACK) + AC_CHECK_LIB(jack, jack_port_rename, AC_DEFINE(__JACK_HAS_PORT_RENAME__), ) +]) + case $host in *-*-linux*) # Look for ALSA flag From e3671886d8b83e8c43b4eff207cc09c6b0f08026 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Thu, 12 Apr 2018 11:21:13 -0300 Subject: [PATCH 169/388] Remove underscores from JACK_HAS_PORT_RENAME. --- RtMidi.cpp | 4 ++-- configure.ac | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index f6968c1e..7744b05b 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -3099,7 +3099,7 @@ void MidiInJack:: setClientName( const std::string& ) void MidiInJack :: setPortName( const std::string &portName ) { JackMidiData *data = static_cast (apiData_); -#ifdef __JACK_HAS_PORT_RENAME__ +#ifdef JACK_HAS_PORT_RENAME jack_port_rename( data->client, data->port, portName.c_str() ); #else jack_port_set_name( data->port, portName.c_str() ); @@ -3320,7 +3320,7 @@ void MidiOutJack:: setClientName( const std::string& ) void MidiOutJack :: setPortName( const std::string &portName ) { JackMidiData *data = static_cast (apiData_); -#ifdef __JACK_HAS_PORT_RENAME__ +#ifdef JACK_HAS_PORT_RENAME jack_port_rename( data->client, data->port, portName.c_str() ); #else jack_port_set_name( data->port, portName.c_str() ); diff --git a/configure.ac b/configure.ac index 92e3d299..b756b4f8 100644 --- a/configure.ac +++ b/configure.ac @@ -140,7 +140,7 @@ AS_IF([test "x$with_jack" = "xyes"], [ AS_IF([test "x$with_jack" = "xyes"], [ AC_MSG_RESULT(using JACK) - AC_CHECK_LIB(jack, jack_port_rename, AC_DEFINE(__JACK_HAS_PORT_RENAME__), ) + AC_CHECK_LIB(jack, jack_port_rename, AC_DEFINE(JACK_HAS_PORT_RENAME), ) ]) case $host in From 8930d6ee771707bf4e331f75edd8f90862eb2891 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Fri, 13 Jul 2018 17:03:47 -0400 Subject: [PATCH 170/388] cmake: read version from configure.ac --- CMakeLists.txt | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c1e8bea..332be600 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# 2018 (c) Juan G. Victores, Bartek Łukawski. +# 2018 (c) Juan G. Victores, Bartek Łukawski, Stephen Sinclair # CopyPolicy: RtMidi license. # Set minimum CMake required version for this project. @@ -11,8 +11,23 @@ project(RtMidi LANGUAGES CXX) add_library(rtmidi RtMidi.h RtMidi.cpp) +# Read version info from configure.ac +set(R "m4_define\\(\\[lt_([a-z]+)\\], ([0-9]+)\\)") +file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/configure.ac" CONFIGAC + REGEX ${R}) +foreach(_S ${CONFIGAC}) + string(REGEX REPLACE ${R} "\\1" k ${_S}) + string(REGEX REPLACE ${R} "\\2" v ${_S}) + set(SO_${k} ${v}) +endforeach() +math(EXPR SO_current_minus_age "${SO_current} - ${SO_age}") +set(SO_VER ${SO_current_minus_age}) +set(FULL_VER "${SO_current_minus_age}.${SO_revision}.${SO_age}") + # Add headers destination for install rule. -set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h) +set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h + SOVERSION ${SO_VER} + VERSION ${FULL_VER}) # Set standard installation directories. include(GNUInstallDirs) From 4e35607fe0bf5f630a6d041322061d43208cacfd Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Fri, 13 Jul 2018 18:22:14 -0400 Subject: [PATCH 171/388] cmake: Build shared lib by default. --- CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 332be600..ea16b489 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,12 +4,14 @@ # Set minimum CMake required version for this project. cmake_minimum_required(VERSION 3.0 FATAL_ERROR) +# Options +option(BUILD_SHARED_LIBS "Compile library as shared lib." TRUE) + # Define a C++ project. project(RtMidi LANGUAGES CXX) # Create library target. -add_library(rtmidi RtMidi.h - RtMidi.cpp) +add_library(rtmidi SHARED RtMidi.h RtMidi.cpp) # Read version info from configure.ac set(R "m4_define\\(\\[lt_([a-z]+)\\], ([0-9]+)\\)") From 36309fef616ef3bc9cb7e75a42b94cff6fa4ec66 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Fri, 13 Jul 2018 18:24:47 -0400 Subject: [PATCH 172/388] cmake: build test programs. --- CMakeLists.txt | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ea16b489..0532c6c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ cmake_minimum_required(VERSION 3.0 FATAL_ERROR) # Options option(BUILD_SHARED_LIBS "Compile library as shared lib." TRUE) +option(BUILD_TESTS "Compile test programs." TRUE) # Define a C++ project. project(RtMidi LANGUAGES CXX) @@ -35,8 +36,8 @@ set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h include(GNUInstallDirs) # Set include paths, populate target interface. -target_include_directories(rtmidi PUBLIC $ - $) +include_directories(rtmidi PUBLIC $ + $) # Tweak platform-specific configuration. if(UNIX) @@ -54,6 +55,19 @@ elseif(APPLE) set_target_properties(rtmidi PROPERTIES LINK_FLAGS "-Wl,-F/Library/Frameworks") endif() +# Add tests if requested. +if(BUILD_TESTS) + add_executable(cmidiin tests/cmidiin.cpp) + add_executable(midiclock tests/midiclock.cpp) + add_executable(midiout tests/midiout.cpp) + add_executable(midiprobe tests/midiprobe.cpp) + add_executable(qmidiin tests/qmidiin.cpp) + add_executable(sysextest tests/sysextest.cpp) + set_target_properties(cmidiin midiclock midiout midiprobe qmidiin sysextest + PROPERTIES RUNTIME_OUTPUT_DIRECTORY tests + LINK_LIBRARIES rtmidi) +endif() + # Add install rule. install(TARGETS rtmidi EXPORT RtMidiTargets From 5634c4d5087c85e08a51a23f1710bc548aac78e8 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Fri, 13 Jul 2018 18:49:16 -0400 Subject: [PATCH 173/388] cmake: Allow to specify backend API as options, and add Jack. --- CMakeLists.txt | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0532c6c3..d42469fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,10 +4,20 @@ # Set minimum CMake required version for this project. cmake_minimum_required(VERSION 3.0 FATAL_ERROR) -# Options +# Check for Jack (any OS) +find_package(PkgConfig) +pkg_check_modules(jack jack) + +# Build Options option(BUILD_SHARED_LIBS "Compile library as shared lib." TRUE) option(BUILD_TESTS "Compile test programs." TRUE) +# API Options +option(RTMIDI_API_JACK "Compile with JACK support." ${jack_FOUND}) +option(RTMIDI_API_ALSA "Compile with ALSA support." ${UNIX}) +option(RTMIDI_API_WINMM "Compile with WINMM support." ${WIN32}) +option(RTMIDI_API_CORE "Compile with CoreMIDI support." ${APPLE}) + # Define a C++ project. project(RtMidi LANGUAGES CXX) @@ -39,14 +49,25 @@ include(GNUInstallDirs) include_directories(rtmidi PUBLIC $ $) -# Tweak platform-specific configuration. -if(UNIX) +# Tweak API-specific configuration. +if(RTMIDI_API_JACK AND jack_FOUND) + target_compile_definitions(rtmidi PRIVATE __UNIX_JACK__) + target_include_directories(rtmidi PRIVATE ${jack_INCLUDEDIR}) + target_link_libraries(rtmidi PRIVATE ${jack_LIBRARIES}) +endif() +if(RTMIDI_API_ALSA) + find_package(ALSA) + if (ALSA_LIBRARY) target_compile_definitions(rtmidi PRIVATE __LINUX_ALSA__) - target_link_libraries(rtmidi PRIVATE asound pthread) -elseif(WIN32) + target_include_directories(rtmidi PRIVATE ${ALSA_INCLUDE_DIR}) + target_link_libraries(rtmidi PRIVATE ${ALSA_LIBRARY}) + endif() +endif() +if(RTMIDI_API_WINMM) target_compile_definitions(rtmidi PRIVATE __WINDOWS_MM__) target_link_libraries(rtmidi PRIVATE winmm.lib) -elseif(APPLE) +endif() +if(RTMIDI_API_CORE) target_compile_definitions(rtmidi PRIVATE __MACOSX_CORE__) target_link_libraries(rtmidi PRIVATE "-framework CoreServices") target_link_libraries(rtmidi PRIVATE "-framework CoreAudio") From 2c3b459ccb0aba60c073b6a9758540d32b31ac05 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Fri, 13 Jul 2018 18:53:04 -0400 Subject: [PATCH 174/388] cmake: some Windows-related extras. According to @jgvictores this should help with DLL generation. --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index d42469fb..56284c2e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,12 @@ cmake_minimum_required(VERSION 3.0 FATAL_ERROR) find_package(PkgConfig) pkg_check_modules(jack jack) +# Necessary for Windows +if(WIN32) + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) + set(CMAKE_DEBUG_POSTFIX "d") +endif() + # Build Options option(BUILD_SHARED_LIBS "Compile library as shared lib." TRUE) option(BUILD_TESTS "Compile test programs." TRUE) From f57d6b8810708bffa19d49b6222c355ee3c13f07 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Sat, 14 Jul 2018 13:06:31 -0400 Subject: [PATCH 175/388] autoconf: separate OS defaults and MIDI API testing Similar to thestk/rtaudio#135. --- configure.ac | 176 +++++++++++++++++++++++++++------------------------ 1 file changed, 92 insertions(+), 84 deletions(-) diff --git a/configure.ac b/configure.ac index b756b4f8..e0cac4e2 100644 --- a/configure.ac +++ b/configure.ac @@ -126,100 +126,108 @@ AC_CONFIG_LINKS( [doc/images/mcgill.gif:doc/images/mcgill.gif] ) # Checks for package options and external software AC_CANONICAL_HOST - - - -AC_MSG_CHECKING(for MIDI API) - -AS_IF([test "x$with_jack" = "xyes"], [ - AC_MSG_RESULT(using JACK) - AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!)) - api="$api -D__UNIX_JACK__" - req="$req jack" -]) - -AS_IF([test "x$with_jack" = "xyes"], [ - AC_MSG_RESULT(using JACK) +# Aggregate options into a single string. +AS_IF([test "x$with_jack" = "xyes"], [systems="$systems jack"]) +AS_IF([test "x$with_alsa" = "xyes"], [systems="$systems alsa"]) +AS_IF([test "x$with_core" = "xyes"], [systems="$systems core"]) +AS_IF([test "x$with_winmm" = "xyes"], [systems="$systems winmm"]) +AS_IF([test "x$with_winks" = "xyes"], [systems="$systems winks"]) +AS_IF([test "x$with_dummy" = "xyes"], [systems="$systems dummy"]) +required=" $systems " + +# If none, assign defaults if any are known for this OS. +# User must specified with-* options for any unknown OS. +AS_IF([test "x$systems" = "x"], + AS_CASE([$host], + [*-*-linux*], [systems="alsa jack"], + [*-apple*], [systems="core jack"], + [*-mingw32*], [systems="winmm winks jack"], + [*-mingw64*], [systems="winmm winks jack"] + )) + +# If any were specifically requested disabled, do it. +AS_IF([test "x$with_jack" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v jack`]) +AS_IF([test "x$with_alsa" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v alsa`]) +AS_IF([test "x$with_winmm" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v winmm`]) +AS_IF([test "x$with_winks" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v winks`]) +AS_IF([test "x$with_core" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v core`]) +AS_IF([test "x$with_dummy" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v dummy`]) +systems=" `echo $systems|tr \\\\n ' '` " + +# For each MIDI system, check if it is selected and found. +# Note: Order specified above is not necessarily respected. However, +# *actual* priority is set at run-time, see RtMidiIn::openMidiApi and RtMidiOut::openMidiApi. +# One AS_CASE per system, since they are not mutually-exclusive. + +AS_CASE(["$systems"], [*" jack "*], [ + AC_CHECK_LIB(jack, jack_client_open, + [api="$api -D__UNIX_JACK__" + req="$req jack" + need_pthread=yes + found="$found Jack" + LIBS="-ljack $LIBS"], + AS_CASE(["$required"], [*" jack "*], + AC_MSG_ERROR([JACK support requires the jack library!]))) AC_CHECK_LIB(jack, jack_port_rename, AC_DEFINE(JACK_HAS_PORT_RENAME), ) ]) -case $host in - *-*-linux*) - # Look for ALSA flag - AS_IF([test "x$with_alsa" = "xyes"], [ - AC_MSG_RESULT(using ALSA) - AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(ALSA support requires the asound library!)) - api="$api -D__LINUX_ALSA__" - req="$req alsa" - ]) +AS_CASE(["$systems"], [*" alsa "*], [ + AC_CHECK_LIB(asound, snd_seq_open, + [api="$api -D__LINUX_ALSA__" + req="$req alsa" + need_pthread=yes + found="$found ALSA" + LIBS="-lasound $LIBS"], + AS_CASE(["$required"], [*" alsa "*], + AC_MSG_ERROR([ALSA support requires the asound library!]))) +]) - AS_IF([test "x${api}" = "x"], - AC_MSG_RESULT(using ALSA) - AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(ALSA sequencer support requires the asound library!)) - api="-D__LINUX_ALSA__ ${api}" - req="$req alsa" - ) +AS_CASE(["$systems"], [*" core "*], [ + AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, + [api="$api -D__MACOSX_CORE__" + need_pthread=yes + found="$found CoreMIDI", + LIBS="$LIBS -framework CoreMIDI -framework CoreFoundation -framework CoreAudio"], + AS_CASE(["$required"], [*" core "*], + AC_MSG_ERROR([CoreMIDI header files not found!]))) +]) - # Checks for pthread library. - AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtMidi requires the pthread library!)) - ;; - - *-*-freebsd*) - # Checks for pthread library. - AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtMidi requires the pthread library!)) - ;; - - *-apple*) - # Look for Core flag - AS_IF([test "x$with_core" = "xyes"], [ - AC_MSG_RESULT(using CoreMidi) - AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, [], [AC_MSG_ERROR(CoreMIDI header files not found!)] ) - LIBS="-framework CoreMIDI -framework CoreFoundation -framework CoreAudio ${LIBS}" - api="$api -D__MACOSX_CORE__" - ]) +AS_CASE(["$systems"], [*" winmm "*], [ + AC_CHECK_HEADERS(windows.h mmsystem.h, + [api="$api -D__WINDOWS_MM__" + CPPFLAGS="-I$srcdir/include $CPPFLAGS" + need_ole32=yes + found="$found WinMM" + api="$api -D__WINDOWS_MM__" + LIBS="-lwinmm ${LIBS}"]) +]) - # If no api flags specified, use CoreMidi - AS_IF([test "x${api}" = "x"], - AC_MSG_RESULT(using CoreMidi) - AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, - [], - [AC_MSG_ERROR(CoreMIDI header files not found!)] ) - LIBS="-framework CoreMIDI -framework CoreFoundation -framework CoreAudio ${LIBS}" - api="$api -D__MACOSX_CORE__" - ) - ;; - - *-mingw32*|*-mingw64*) - # Look for WinMM flag - AS_IF([test "x$with_winmm" = "xyes"], [ - AC_MSG_RESULT(using WinMM) - LIBS="-lwinmm ${LIBS}" - api="$api -D__WINDOWS_MM__" - ]) +AS_CASE(["$systems"], [*" winks "*], [ + AC_CHECK_HEADERS(windows.h audioclient.h avrt.h mmdeviceapi.h, + [api="$api -D__WINDOWS_WINKS__" + CPPFLAGS="-I$srcdir/include $CPPFLAGS" + need_ole32=yes + found="$found kernel-streaming" + api="$api -D__WINDOWS_WINKS__" + LIBS="-lsetupapi -lksuser ${LIBS}"]) +]) - AS_IF([test "x$with_winks" = "xyes"], [ - AC_MSG_RESULT(using kernel streaming) - LIBS="-lsetupapi -lksuser ${LIBS}" - api="$api -D__WINDOWS_KS__" - ]) +AS_IF([test -n "$need_ole32"], [LIBS="-lole32 $LIBS"]) - # 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!) )],) +AS_IF([test -n "$need_pthread"],[ + AC_MSG_CHECKING([for pthread]) + AC_CHECK_LIB(pthread, pthread_create, , + AC_MSG_ERROR([RtAudio requires the pthread library!]))]) - # If no api flags specified, use WinMM - AS_IF([test "x${api}" = "x"], [ - AC_MSG_RESULT(using WinMM) - LIBS="-lwinmm ${LIBS}" - api="${api} -D__WINDOWS_MM__" - ]) - ;; +AC_MSG_CHECKING([for MIDI API]) - *) - # Default case for unknown realtime systems. - AC_MSG_ERROR(Unknown system type for MIDI support!) - ;; -esac +# Error case: no known realtime systems found. +AS_IF([test x"$api" = "x"], [ + AC_MSG_RESULT([none]) + AC_MSG_ERROR([No known system type found for MIDI support!]) +], [ + AC_MSG_RESULT([$found]) +]) CPPFLAGS="$CPPFLAGS $api" From a131e8ca88f2e932444ce6bc7c2eb44f08fc5047 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Sat, 14 Jul 2018 18:45:24 -0400 Subject: [PATCH 176/388] cmake: make CMakeLists.txt more similar to RtAudio's --- CMakeLists.txt | 197 ++++++++++++++---- ...make.in => RtMidiConfigUninstall.cmake.in} | 0 2 files changed, 156 insertions(+), 41 deletions(-) rename cmake/{templates/RTMIDIConfigUninstall.cmake.in => RtMidiConfigUninstall.cmake.in} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 56284c2e..0cb50c74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,9 +4,16 @@ # Set minimum CMake required version for this project. cmake_minimum_required(VERSION 3.0 FATAL_ERROR) +# Define a C++ project. +project(RtMidi LANGUAGES CXX) + # Check for Jack (any OS) +find_library(JACK_LIB jack) find_package(PkgConfig) pkg_check_modules(jack jack) +if(JACK_LIB OR jack_FOUND) + set(HAVE_JACK TRUE) +endif() # Necessary for Windows if(WIN32) @@ -15,22 +22,31 @@ if(WIN32) endif() # Build Options -option(BUILD_SHARED_LIBS "Compile library as shared lib." TRUE) -option(BUILD_TESTS "Compile test programs." TRUE) +option(BUILD_SHARED_LIBS "Compile library shared lib." TRUE) +option(BUILD_STATIC_LIBS "Compile library static lib." TRUE) +option(BUILD_TESTING "Compile test programs." TRUE) +set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type (Release,Debug)") # API Options -option(RTMIDI_API_JACK "Compile with JACK support." ${jack_FOUND}) +option(RTMIDI_API_JACK "Compile with JACK support." ${HAVE_JACK}) option(RTMIDI_API_ALSA "Compile with ALSA support." ${UNIX}) option(RTMIDI_API_WINMM "Compile with WINMM support." ${WIN32}) option(RTMIDI_API_CORE "Compile with CoreMIDI support." ${APPLE}) -# Define a C++ project. -project(RtMidi LANGUAGES CXX) +# Add -Wall if possible +if (CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") +endif (CMAKE_COMPILER_IS_GNUCXX) -# Create library target. -add_library(rtmidi SHARED RtMidi.h RtMidi.cpp) +# Add debug flags +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + add_definitions(-D__RTMIDI_DEBUG__) + if (CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") + endif (CMAKE_COMPILER_IS_GNUCXX) +endif () -# Read version info from configure.ac +# Read libtool version info from configure.ac set(R "m4_define\\(\\[lt_([a-z]+)\\], ([0-9]+)\\)") file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/configure.ac" CONFIGAC REGEX ${R}) @@ -40,63 +56,158 @@ foreach(_S ${CONFIGAC}) set(SO_${k} ${v}) endforeach() math(EXPR SO_current_minus_age "${SO_current} - ${SO_age}") -set(SO_VER ${SO_current_minus_age}) +set(SO_VER "${SO_current_minus_age}") set(FULL_VER "${SO_current_minus_age}.${SO_revision}.${SO_age}") -# Add headers destination for install rule. -set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h - SOVERSION ${SO_VER} - VERSION ${FULL_VER}) - -# Set standard installation directories. -include(GNUInstallDirs) +# Read package version info from configure.ac +set(R "AC_INIT\\(RtMidi, ([0-9\\.]+),.*\\)") +file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/configure.ac" CONFIGAC + REGEX ${R}) +string(REGEX REPLACE ${R} "\\1" PACKAGE_VERSION ${CONFIGAC}) -# Set include paths, populate target interface. -include_directories(rtmidi PUBLIC $ - $) +# Init variables +set(rtmidi_SOURCES RtMidi.cpp RtMidi.h) +set(LINKLIBS) +set(INCDIRS) +set(PKGCONFIG_REQUIRES) +set(API_DEFS) +set(API_LIST) # Tweak API-specific configuration. -if(RTMIDI_API_JACK AND jack_FOUND) - target_compile_definitions(rtmidi PRIVATE __UNIX_JACK__) - target_include_directories(rtmidi PRIVATE ${jack_INCLUDEDIR}) - target_link_libraries(rtmidi PRIVATE ${jack_LIBRARIES}) + +# Jack +if(RTMIDI_API_JACK) + if (NOT HAVE_JACK) + message(FATAL_ERROR "Jack API requested but no Jack dev libraries found") + endif() + set(NEED_PTHREAD ON) + list(APPEND PKGCONFIG_REQUIRES "jack") + list(APPEND API_DEFS "-D__UNIX_JACK__") + list(APPEND API_LIST "jack") + if(jack_FOUND) + list(APPEND LINKLIBS ${jack_LIBRARIES}) + list(APPEND INCDIRS ${jack_INCLUDEDIR}) + else() + list(APPEND LINKLIBS ${JACK_LIB}) + endif() endif() + +# ALSA if(RTMIDI_API_ALSA) + set(NEED_PTHREAD ON) find_package(ALSA) - if (ALSA_LIBRARY) - target_compile_definitions(rtmidi PRIVATE __LINUX_ALSA__) - target_include_directories(rtmidi PRIVATE ${ALSA_INCLUDE_DIR}) - target_link_libraries(rtmidi PRIVATE ${ALSA_LIBRARY}) + if (NOT ALSA_FOUND) + message(FATAL_ERROR "ALSA API requested but no ALSA dev libraries found") endif() + list(APPEND INCDIRS ${ALSA_INCLUDE_DIR}) + list(APPEND LINKLIBS ${ALSA_LIBRARY}) + list(APPEND PKGCONFIG_REQUIRES "alsa") + list(APPEND API_DEFS "-D__LINUX_ALSA__") + list(APPEND API_LIST "alsa") endif() + +# WinMM if(RTMIDI_API_WINMM) - target_compile_definitions(rtmidi PRIVATE __WINDOWS_MM__) - target_link_libraries(rtmidi PRIVATE winmm.lib) + list(APPEND API_DEFS "-D__WINDOWS_MM__") + list(APPEND API_LIST "winmm") + list(APPEND LINKLIBS winmm) endif() + +# CoreMIDI if(RTMIDI_API_CORE) - target_compile_definitions(rtmidi PRIVATE __MACOSX_CORE__) - target_link_libraries(rtmidi PRIVATE "-framework CoreServices") - target_link_libraries(rtmidi PRIVATE "-framework CoreAudio") - target_link_libraries(rtmidi PRIVATE "-framework CoreMIDI") - target_link_libraries(rtmidi PRIVATE "-framework CoreFoundation") - set_target_properties(rtmidi PROPERTIES LINK_FLAGS "-Wl,-F/Library/Frameworks") + list(APPEND API_DEFS "-D__MACOSX_CORE__") + list(APPEND LINKLIBS "-framework CoreServices") + list(APPEND LINKLIBS "-framework CoreAudio") + list(APPEND LINKLIBS "-framework CoreMIDI") + list(APPEND LINKLIBS "-framework CoreFoundation") + list(APPEND LINKFLAGS "-Wl,-F/Library/Frameworks") +endif() + +# pthread +if (NEED_PTHREAD) + find_package(Threads REQUIRED + CMAKE_THREAD_PREFER_PTHREAD + THREADS_PREFER_PTHREAD_FLAG) + list(APPEND LINKLIBS Threads::Threads) +endif() + +# Create library targets. +cmake_policy(SET CMP0042 OLD) +set(LIB_TARGETS) +if(BUILD_SHARED_LIBS) + add_library(rtmidi SHARED ${rtmidi_SOURCES}) + list(APPEND LIB_TARGETS rtmidi) + + # Add headers destination for install rule. + set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h + SOVERSION ${SO_VER} + VERSION ${FULL_VER}) + + # Set include paths, populate target interface. + target_include_directories(rtmidi PRIVATE + $ + $ + ${INCDIRS}) + + # Set compile-time definitions + target_compile_definitions(rtmidi PRIVATE ${API_DEFS}) + + target_link_libraries(rtmidi ${LINKLIBS}) +endif() + +if(BUILD_STATIC_LIBS) + add_library(rtmidi_static STATIC ${rtmidi_SOURCES}) + list(APPEND LIB_TARGETS rtmidi_static) + + # Add headers destination for install rule. + set_target_properties(rtmidi_static PROPERTIES PUBLIC_HEADER RtMidi.h + SOVERSION ${SO_VER} + VERSION ${FULL_VER}) + + # Set include paths, populate target interface. + target_include_directories(rtmidi_static PRIVATE + $ + $ + ${INCDIRS}) + + # Set compile-time definitions + target_compile_definitions(rtmidi_static PRIVATE ${API_DEFS}) + + target_link_libraries(rtmidi_static ${LINKLIBS}) endif() +# Set standard installation directories. +include(GNUInstallDirs) + # Add tests if requested. -if(BUILD_TESTS) +if(BUILD_TESTING) add_executable(cmidiin tests/cmidiin.cpp) add_executable(midiclock tests/midiclock.cpp) add_executable(midiout tests/midiout.cpp) add_executable(midiprobe tests/midiprobe.cpp) add_executable(qmidiin tests/qmidiin.cpp) add_executable(sysextest tests/sysextest.cpp) + list(GET LIB_TARGETS 0 LIBRTMIDI) set_target_properties(cmidiin midiclock midiout midiprobe qmidiin sysextest PROPERTIES RUNTIME_OUTPUT_DIRECTORY tests - LINK_LIBRARIES rtmidi) + INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR} + LINK_LIBRARIES ${LIBRTMIDI}) endif() +# Set standard installation directories. +include(GNUInstallDirs) + +# Message +string(REPLACE ";" " " apilist "${API_LIST}") +message(STATUS "Compiling with support for: ${apilist}") + +# PkgConfig file +string(REPLACE ";" " " req "${PKGCONFIG_REQUIRES}") +string(REPLACE ";" " " api "${API_DEFS}") +configure_file("rtmidi.pc.in" "rtmidi.pc" @ONLY) + # Add install rule. -install(TARGETS rtmidi +install(TARGETS ${LIB_TARGETS} EXPORT RtMidiTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -131,9 +242,13 @@ install(EXPORT RtMidiTargets # Configure uninstall target. configure_file( - "${CMAKE_SOURCE_DIR}/cmake/templates/RTMIDIConfigUninstall.cmake.in" - "${CMAKE_BINARY_DIR}/RTMIDIConfigUninstall.cmake" @ONLY) + "${CMAKE_SOURCE_DIR}/cmake/RtMidiConfigUninstall.cmake.in" + "${CMAKE_BINARY_DIR}/RtMidiConfigUninstall.cmake" @ONLY) # Create uninstall target. add_custom_target(uninstall - COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/RTMIDIConfigUninstall.cmake) + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/RtMidiConfigUninstall.cmake) + +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/rtmidi.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) diff --git a/cmake/templates/RTMIDIConfigUninstall.cmake.in b/cmake/RtMidiConfigUninstall.cmake.in similarity index 100% rename from cmake/templates/RTMIDIConfigUninstall.cmake.in rename to cmake/RtMidiConfigUninstall.cmake.in From a8b57e97bdf491e7369451d5cda21a97a0547846 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Sat, 14 Jul 2018 19:36:40 -0400 Subject: [PATCH 177/388] cmake: forgot the C API! --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0cb50c74..76953836 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,7 +66,7 @@ file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/configure.ac" CONFIGAC string(REGEX REPLACE ${R} "\\1" PACKAGE_VERSION ${CONFIGAC}) # Init variables -set(rtmidi_SOURCES RtMidi.cpp RtMidi.h) +set(rtmidi_SOURCES RtMidi.cpp RtMidi.h rtmidi_c.cpp rtmidi_c.h) set(LINKLIBS) set(INCDIRS) set(PKGCONFIG_REQUIRES) From 54c26150ce63f15b9604a7d00cdbf99119020108 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Wed, 18 Jul 2018 15:31:01 -0400 Subject: [PATCH 178/388] C-API: add compile-time assertions to ensure enum alignment --- rtmidi_c.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index f61da424..2174c8f4 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -3,6 +3,34 @@ #include "rtmidi_c.h" #include "RtMidi.h" +/* Compile-time assertions that will break if the enums are changed in + * the future without synchronizing them properly. If you get (g++) + * "error: ‘StaticAssert::StaticAssert() [with bool b = false]’ is + * private within this context", it means enums are not aligned. */ +template class StaticAssert { private: StaticAssert() {} }; +template<> class StaticAssert{ public: StaticAssert() {} }; +#define ENUM_EQUAL(x,y) StaticAssert<(int)x==(int)y>() +class StaticAssertions { StaticAssertions() { + ENUM_EQUAL( RT_MIDI_API_UNSPECIFIED, RtMidi::Api::UNSPECIFIED ); + ENUM_EQUAL( RT_MIDI_API_MACOSX_CORE, RtMidi::Api::MACOSX_CORE ); + ENUM_EQUAL( RT_MIDI_API_LINUX_ALSA, RtMidi::Api::LINUX_ALSA ); + ENUM_EQUAL( RT_MIDI_API_UNIX_JACK, RtMidi::Api::UNIX_JACK ); + ENUM_EQUAL( RT_MIDI_API_WINDOWS_MM, RtMidi::Api::WINDOWS_MM ); + ENUM_EQUAL( RT_MIDI_API_RTMIDI_DUMMY, RtMidi::Api::RTMIDI_DUMMY ); + + ENUM_EQUAL( RT_ERROR_WARNING, RtMidiError::Type::WARNING ); + ENUM_EQUAL( RT_ERROR_DEBUG_WARNING, RtMidiError::Type::DEBUG_WARNING ); + ENUM_EQUAL( RT_ERROR_UNSPECIFIED, RtMidiError::Type::UNSPECIFIED ); + ENUM_EQUAL( RT_ERROR_NO_DEVICES_FOUND, RtMidiError::Type::NO_DEVICES_FOUND ); + ENUM_EQUAL( RT_ERROR_INVALID_DEVICE, RtMidiError::Type::INVALID_DEVICE ); + ENUM_EQUAL( RT_ERROR_MEMORY_ERROR, RtMidiError::Type::MEMORY_ERROR ); + ENUM_EQUAL( RT_ERROR_INVALID_PARAMETER, RtMidiError::Type::INVALID_PARAMETER ); + ENUM_EQUAL( RT_ERROR_INVALID_USE, RtMidiError::Type::INVALID_USE ); + ENUM_EQUAL( RT_ERROR_DRIVER_ERROR, RtMidiError::Type::DRIVER_ERROR ); + ENUM_EQUAL( RT_ERROR_SYSTEM_ERROR, RtMidiError::Type::SYSTEM_ERROR ); + ENUM_EQUAL( RT_ERROR_THREAD_ERROR, RtMidiError::Type::THREAD_ERROR ); +}}; + class CallbackProxyUserData { public: From 95490953a89309a0bdbd8a14acd154c5ea570910 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Wed, 18 Jul 2018 17:46:30 -0400 Subject: [PATCH 179/388] c-api: add array size argument for rtmidi_get_compiled_api --- contrib/go/rtmidi/rtmidi.go | 4 ++-- rtmidi_c.cpp | 38 +++++++++++++++---------------------- rtmidi_c.h | 6 +++++- 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/contrib/go/rtmidi/rtmidi.go b/contrib/go/rtmidi/rtmidi.go index 9a0cb7b8..67669148 100644 --- a/contrib/go/rtmidi/rtmidi.go +++ b/contrib/go/rtmidi/rtmidi.go @@ -70,9 +70,9 @@ func (api API) String() string { // CompiledAPI determines the available compiled MIDI APIs. func CompiledAPI() (apis []API) { - n := C.rtmidi_get_compiled_api(nil) + n := C.rtmidi_get_compiled_api(nil, 0) capis := make([]C.enum_RtMidiApi, n, n) - C.rtmidi_get_compiled_api(&capis[0]) + C.rtmidi_get_compiled_api(&capis[0], n) for _, capi := range capis { apis = append(apis, API(capi)) } diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index 2174c8f4..a95a785f 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -43,30 +43,22 @@ class CallbackProxyUserData }; /* RtMidi API */ -int rtmidi_get_compiled_api (enum RtMidiApi *apis) // return length for NULL argument. +int rtmidi_get_compiled_api (enum RtMidiApi *apis, unsigned int apis_size) { - if (!apis) { - std::vector *v = new std::vector (); - try { - RtMidi::getCompiledApi (*v); - int size = v->size (); - delete v; - return size; - } catch (...) { - return -1; - } - } else { - try { - std::vector *v = new std::vector (); - RtMidi::getCompiledApi (*v); - for (unsigned int i = 0; i < v->size (); i++) - apis[i] = (RtMidiApi) v->at (i); - delete v; - return 0; - } catch (...) { - return -1; - } - } + std::vector v; + try { + RtMidi::getCompiledApi(v); + } catch (...) { + return -1; + } + if (apis) { + unsigned int i; + for (i = 0; i < v.size() && i < apis_size; i++) + apis[i] = (RtMidiApi) v[i]; + return (int)i; + } + // return length for NULL argument. + return v.size(); } void rtmidi_error (MidiApi *api, enum RtMidiErrorType type, const char* errorString) diff --git a/rtmidi_c.h b/rtmidi_c.h index 5cb91c27..93f37802 100644 --- a/rtmidi_c.h +++ b/rtmidi_c.h @@ -68,8 +68,12 @@ typedef void(* RtMidiCCallback) (double timeStamp, const unsigned char* message, * Otherwise, fill the given apis array with the RtMidi::Api values. * * \param apis An array or a null value. + * \param apis_size Number of elements pointed to by apis + * \return number of items needed for apis array if apis==NULL, or + * number of items written to apis array otherwise. A negative + * return value indicates an error. */ -RTMIDIAPI int rtmidi_get_compiled_api (enum RtMidiApi *apis); // return length for NULL argument. +RTMIDIAPI int rtmidi_get_compiled_api (enum RtMidiApi *apis, unsigned int apis_size); //! Report an error. RTMIDIAPI void rtmidi_error (enum RtMidiErrorType type, const char* errorString); From 4c3755d2c9d93cd86e9be18af93017bfba004895 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Wed, 18 Jul 2018 20:56:52 -0400 Subject: [PATCH 180/388] fix 54c26150 for pre-C++11 compilers --- rtmidi_c.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp index a95a785f..08e13e5b 100644 --- a/rtmidi_c.cpp +++ b/rtmidi_c.cpp @@ -11,24 +11,24 @@ template class StaticAssert { private: StaticAssert() {} }; template<> class StaticAssert{ public: StaticAssert() {} }; #define ENUM_EQUAL(x,y) StaticAssert<(int)x==(int)y>() class StaticAssertions { StaticAssertions() { - ENUM_EQUAL( RT_MIDI_API_UNSPECIFIED, RtMidi::Api::UNSPECIFIED ); - ENUM_EQUAL( RT_MIDI_API_MACOSX_CORE, RtMidi::Api::MACOSX_CORE ); - ENUM_EQUAL( RT_MIDI_API_LINUX_ALSA, RtMidi::Api::LINUX_ALSA ); - ENUM_EQUAL( RT_MIDI_API_UNIX_JACK, RtMidi::Api::UNIX_JACK ); - ENUM_EQUAL( RT_MIDI_API_WINDOWS_MM, RtMidi::Api::WINDOWS_MM ); - ENUM_EQUAL( RT_MIDI_API_RTMIDI_DUMMY, RtMidi::Api::RTMIDI_DUMMY ); - - ENUM_EQUAL( RT_ERROR_WARNING, RtMidiError::Type::WARNING ); - ENUM_EQUAL( RT_ERROR_DEBUG_WARNING, RtMidiError::Type::DEBUG_WARNING ); - ENUM_EQUAL( RT_ERROR_UNSPECIFIED, RtMidiError::Type::UNSPECIFIED ); - ENUM_EQUAL( RT_ERROR_NO_DEVICES_FOUND, RtMidiError::Type::NO_DEVICES_FOUND ); - ENUM_EQUAL( RT_ERROR_INVALID_DEVICE, RtMidiError::Type::INVALID_DEVICE ); - ENUM_EQUAL( RT_ERROR_MEMORY_ERROR, RtMidiError::Type::MEMORY_ERROR ); - ENUM_EQUAL( RT_ERROR_INVALID_PARAMETER, RtMidiError::Type::INVALID_PARAMETER ); - ENUM_EQUAL( RT_ERROR_INVALID_USE, RtMidiError::Type::INVALID_USE ); - ENUM_EQUAL( RT_ERROR_DRIVER_ERROR, RtMidiError::Type::DRIVER_ERROR ); - ENUM_EQUAL( RT_ERROR_SYSTEM_ERROR, RtMidiError::Type::SYSTEM_ERROR ); - ENUM_EQUAL( RT_ERROR_THREAD_ERROR, RtMidiError::Type::THREAD_ERROR ); + ENUM_EQUAL( RT_MIDI_API_UNSPECIFIED, RtMidi::UNSPECIFIED ); + ENUM_EQUAL( RT_MIDI_API_MACOSX_CORE, RtMidi::MACOSX_CORE ); + ENUM_EQUAL( RT_MIDI_API_LINUX_ALSA, RtMidi::LINUX_ALSA ); + ENUM_EQUAL( RT_MIDI_API_UNIX_JACK, RtMidi::UNIX_JACK ); + ENUM_EQUAL( RT_MIDI_API_WINDOWS_MM, RtMidi::WINDOWS_MM ); + ENUM_EQUAL( RT_MIDI_API_RTMIDI_DUMMY, RtMidi::RTMIDI_DUMMY ); + + ENUM_EQUAL( RT_ERROR_WARNING, RtMidiError::WARNING ); + ENUM_EQUAL( RT_ERROR_DEBUG_WARNING, RtMidiError::DEBUG_WARNING ); + ENUM_EQUAL( RT_ERROR_UNSPECIFIED, RtMidiError::UNSPECIFIED ); + ENUM_EQUAL( RT_ERROR_NO_DEVICES_FOUND, RtMidiError::NO_DEVICES_FOUND ); + ENUM_EQUAL( RT_ERROR_INVALID_DEVICE, RtMidiError::INVALID_DEVICE ); + ENUM_EQUAL( RT_ERROR_MEMORY_ERROR, RtMidiError::MEMORY_ERROR ); + ENUM_EQUAL( RT_ERROR_INVALID_PARAMETER, RtMidiError::INVALID_PARAMETER ); + ENUM_EQUAL( RT_ERROR_INVALID_USE, RtMidiError::INVALID_USE ); + ENUM_EQUAL( RT_ERROR_DRIVER_ERROR, RtMidiError::DRIVER_ERROR ); + ENUM_EQUAL( RT_ERROR_SYSTEM_ERROR, RtMidiError::SYSTEM_ERROR ); + ENUM_EQUAL( RT_ERROR_THREAD_ERROR, RtMidiError::THREAD_ERROR ); }}; class CallbackProxyUserData From d784ce02c1c4a483155e72514b6abf12f1634fb9 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Wed, 18 Jul 2018 21:55:34 -0400 Subject: [PATCH 181/388] Check for null termination in ports array returned by jack_get_ports Fixes #23. --- RtMidi.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/RtMidi.cpp b/RtMidi.cpp index 7744b05b..b1108a99 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -3067,7 +3067,9 @@ std::string MidiInJack :: getPortName( unsigned int portNumber ) return retStr; } - if ( ports[portNumber] == NULL ) { + unsigned int i; + for (i=0; i Date: Sat, 21 Jul 2018 19:27:29 -0400 Subject: [PATCH 182/388] go: fix rtmidi_get_compiled_api call by casting to _Ctype_uint. --- contrib/go/rtmidi/rtmidi.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/go/rtmidi/rtmidi.go b/contrib/go/rtmidi/rtmidi.go index 67669148..0a8d3522 100644 --- a/contrib/go/rtmidi/rtmidi.go +++ b/contrib/go/rtmidi/rtmidi.go @@ -72,7 +72,7 @@ func (api API) String() string { func CompiledAPI() (apis []API) { n := C.rtmidi_get_compiled_api(nil, 0) capis := make([]C.enum_RtMidiApi, n, n) - C.rtmidi_get_compiled_api(&capis[0], n) + C.rtmidi_get_compiled_api(&capis[0], _Ctype_uint(n)) for _, capi := range capis { apis = append(apis, API(capi)) } From 578f74098235a712a0f82939ade37d4600a80ee6 Mon Sep 17 00:00:00 2001 From: Thiago Goulart Date: Tue, 7 Aug 2018 01:01:34 -0700 Subject: [PATCH 183/388] Fix a couple of problems when using cmake to build on macOS. 1. Since both UNIX and APPLE are defined, the ALSA option needs further disambiguation. 2. Fix a bad path when using rtmid as a subproject. --- CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 76953836..df2f7661 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,9 @@ set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type (Release,Debug)") # API Options option(RTMIDI_API_JACK "Compile with JACK support." ${HAVE_JACK}) -option(RTMIDI_API_ALSA "Compile with ALSA support." ${UNIX}) +if(UNIX AND NOT APPLE) + option(RTMIDI_API_ALSA "Compile with ALSA support." ON) +endif() option(RTMIDI_API_WINMM "Compile with WINMM support." ${WIN32}) option(RTMIDI_API_CORE "Compile with CoreMIDI support." ${APPLE}) @@ -242,7 +244,7 @@ install(EXPORT RtMidiTargets # Configure uninstall target. configure_file( - "${CMAKE_SOURCE_DIR}/cmake/RtMidiConfigUninstall.cmake.in" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/RtMidiConfigUninstall.cmake.in" "${CMAKE_BINARY_DIR}/RtMidiConfigUninstall.cmake" @ONLY) # Create uninstall target. From 7adbc8e0b848af2567ea6ecb901e646c51612abf Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Wed, 8 Aug 2018 09:37:57 +0200 Subject: [PATCH 184/388] 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 185/388] 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 186/388] 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 187/388] 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 188/388] 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 189/388] 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 190/388] 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 191/388] 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 192/388] 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 193/388] 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 194/388] 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 195/388] 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 196/388] 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 197/388] 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 198/388] 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 199/388] 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 200/388] 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 201/388] 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 202/388] 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 203/388] 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 204/388] 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 205/388] 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 206/388] 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 207/388] 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 208/388] 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 209/388] 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 210/388] 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 211/388] 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 212/388] 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 213/388] 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 214/388] 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 215/388] 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 216/388] 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 217/388] 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 218/388] 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 219/388] 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 220/388] 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 221/388] 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 222/388] 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 223/388] 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 224/388] 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 225/388] 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 226/388] 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 227/388] 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 228/388] 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 229/388] 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 230/388] 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 231/388] 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 232/388] 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 233/388] 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 234/388] 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 235/388] 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 236/388] 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 237/388] 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 238/388] 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 239/388] 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 240/388] 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 241/388] 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 242/388] 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 243/388] 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 244/388] 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 245/388] 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 246/388] 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 247/388] 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 248/388] 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 249/388] 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 250/388] 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 251/388] 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 252/388] 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 253/388] 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 254/388] 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 255/388] 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 256/388] 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 257/388] 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 258/388] 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 259/388] 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 260/388] 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 261/388] 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 262/388] 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 263/388] 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 264/388] 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 265/388] 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 266/388] 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 267/388] 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 268/388] 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 269/388] 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 270/388] 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 271/388] 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 272/388] 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 273/388] 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 274/388] 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 275/388] 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 276/388] 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 277/388] 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 278/388] 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 279/388] 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 280/388] 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 281/388] 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 282/388] 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 283/388] 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 284/388] 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 285/388] 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 286/388] 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 287/388] 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 288/388] 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 289/388] 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 290/388] 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 291/388] 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 292/388] 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 293/388] 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 294/388] 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 295/388] 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 296/388] 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 297/388] 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 298/388] 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 299/388] 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 300/388] 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 301/388] 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 302/388] 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 303/388] 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 304/388] 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 305/388] 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 306/388] 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 307/388] 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 308/388] 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 309/388] 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 310/388] 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 311/388] 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 312/388] 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 313/388] 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 314/388] 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 315/388] 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 316/388] 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 317/388] 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 318/388] 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 319/388] 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 320/388] 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 321/388] 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 322/388] 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 323/388] 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 324/388] 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 325/388] 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 326/388] 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 327/388] 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 328/388] 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 329/388] 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 330/388] 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 331/388] 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 332/388] 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 333/388] 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 334/388] 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 335/388] 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 336/388] 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 337/388] 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 338/388] 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 339/388] 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 340/388] 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 341/388] 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 342/388] 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 343/388] 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 344/388] 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 345/388] 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 346/388] 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 347/388] 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 348/388] 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 349/388] 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 350/388] 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 351/388] 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 352/388] 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 353/388] 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 354/388] 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 355/388] 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 356/388] 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 357/388] 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 358/388] 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 359/388] 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 360/388] 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 361/388] 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 362/388] 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 363/388] 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 364/388] 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 365/388] 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 366/388] 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 367/388] 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 368/388] 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 369/388] 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 370/388] 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 371/388] 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 372/388] 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 373/388] 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 374/388] 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 375/388] 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 cef3675ac9ec13b1a060676d88ee353f52032508 Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Fri, 10 Aug 2018 21:11:10 -0400 Subject: [PATCH 376/388] Update platform availability of jack in configure help. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index e0cac4e2..de890922 100644 --- a/configure.ac +++ b/configure.ac @@ -54,7 +54,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) # configure flags AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug], [enable various debugging output])]) -AC_ARG_WITH(jack, [AS_HELP_STRING([--with-jack], [choose JACK server support (mac and linux only)])]) +AC_ARG_WITH(jack, [AS_HELP_STRING([--with-jack], [choose JACK server support])]) AC_ARG_WITH(alsa, [AS_HELP_STRING([--with-alsa], [choose native ALSA sequencer API support (linux only)])]) AC_ARG_WITH(core, [AS_HELP_STRING([--with-core], [ choose CoreMidi API support (mac only)])]) AC_ARG_WITH(winmm, [AS_HELP_STRING([--with-winmm], [ choose Windows MultiMedia (MM) API support (win32 only)])]) From fa87b8f60102d1a524407faa8c52b4a0c4f917b3 Mon Sep 17 00:00:00 2001 From: Tobias Schlemmer Date: Sat, 11 Aug 2018 11:54:28 +0200 Subject: [PATCH 377/388] 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 378/388] 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 379/388] 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 380/388] 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 381/388] 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 382/388] 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 383/388] 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 384/388] 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 385/388] 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 386/388] 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 "" From 31556719650cd5666feca4f2eb1b21d3f2c1a28f Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Tue, 14 Aug 2018 15:24:03 -0300 Subject: [PATCH 387/388] alsa: fix a switch fallthrough warning --- RtMidi.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/RtMidi.cpp b/RtMidi.cpp index b1108a99..61dd55fd 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1567,6 +1567,7 @@ static void *alsaMidiHandler( void *ptr ) break; } } + break; default: doDecode = true; From c57c8180c1bca9e2794783ba5ba07db1607eab5f Mon Sep 17 00:00:00 2001 From: Ryan Schmidt Date: Sat, 25 Aug 2018 21:23:28 -0500 Subject: [PATCH 388/388] Fix capitalization of "CoreMIDI" --- README.md | 2 +- RtMidi.h | 2 +- configure.ac | 2 +- contrib/go/rtmidi/rtmidi.go | 2 +- doc/release.txt | 6 +++--- rtmidi_c.h | 2 +- tests/midiprobe.cpp | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 93e7fbdc..2ec68cb0 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://travis-ci.org/thestk/rtmidi.svg?branch=master)](https://travis-ci.org/thestk/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). +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-2017. diff --git a/RtMidi.h b/RtMidi.h index fac740e1..8c47f4c7 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -130,7 +130,7 @@ class RTMIDI_DLL_PUBLIC RtMidi //! MIDI API specifier arguments. enum Api { UNSPECIFIED, /*!< Search for a working compiled API. */ - MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ + MACOSX_CORE, /*!< Macintosh OS-X CoreMIDI 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. */ diff --git a/configure.ac b/configure.ac index de890922..c16d8043 100644 --- a/configure.ac +++ b/configure.ac @@ -56,7 +56,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug], [enable various debugging output])]) AC_ARG_WITH(jack, [AS_HELP_STRING([--with-jack], [choose JACK server support])]) AC_ARG_WITH(alsa, [AS_HELP_STRING([--with-alsa], [choose native ALSA sequencer API support (linux only)])]) -AC_ARG_WITH(core, [AS_HELP_STRING([--with-core], [ choose CoreMidi API support (mac only)])]) +AC_ARG_WITH(core, [AS_HELP_STRING([--with-core], [ choose CoreMIDI API support (mac only)])]) AC_ARG_WITH(winmm, [AS_HELP_STRING([--with-winmm], [ choose Windows MultiMedia (MM) API support (win32 only)])]) AC_ARG_WITH(winks, [AS_HELP_STRING([--with-winks], [ choose kernel streaming support (win32 only)])]) diff --git a/contrib/go/rtmidi/rtmidi.go b/contrib/go/rtmidi/rtmidi.go index 0a8d3522..0ac7decb 100644 --- a/contrib/go/rtmidi/rtmidi.go +++ b/contrib/go/rtmidi/rtmidi.go @@ -38,7 +38,7 @@ type API C.enum_RtMidiApi const ( // APIUnspecified searches for a working compiled API. APIUnspecified API = C.RT_MIDI_API_UNSPECIFIED - // APIMacOSXCore uses Macintosh OS-X Core Midi API. + // APIMacOSXCore uses Macintosh OS-X CoreMIDI API. APIMacOSXCore = C.RT_MIDI_API_MACOSX_CORE // APILinuxALSA uses the Advanced Linux Sound Architecture API. APILinuxALSA = C.RT_MIDI_API_LINUX_ALSA diff --git a/doc/release.txt b/doc/release.txt index 60ad69bc..c1a2c4ea 100644 --- a/doc/release.txt +++ b/doc/release.txt @@ -1,4 +1,4 @@ -RtMidi - a set of C++ classes that provides a common API for realtime MIDI input/output across Linux (ALSA & JACK), Macintosh OS X (CoreMidi & JACK), and Windows (Multimedia Library). +RtMidi - a set of C++ classes that provides a common API for realtime MIDI input/output across Linux (ALSA & JACK), Macintosh OS X (CoreMIDI & JACK), and Windows (Multimedia Library). By Gary P. Scavone, 2003-2017 (with help from many others!) @@ -20,11 +20,11 @@ v2.1.1: (11 February 2016) v2.1.0: (30 March 2014) - renamed RtError class to RtMidiError and embedded it in RtMidi.h (and deleted RtError.h) -- fix to CoreMidi implementation to support dynamic port changes +- fix to CoreMIDI implementation to support dynamic port changes - removed global ALSA sequencer objects because they were not thread safe (Martin Koegler) - fix for ALSA timing ignore flag (Devin Anderson) - fix for ALSA incorrect use of snd_seq_create_port() function (Tobias Schlemmer) -- fix for international character support in CoreMidi (Martin Finke) +- fix for international character support in CoreMIDI (Martin Finke) - fix for unicode conversion in WinMM (Dan Wilcox) - added custom error hook that allows the client to capture an RtMidi error outside of the RtMidi code (Pavel Mogilevskiy) - added RtMidi::isPortOpen function (Pavel Mogilevskiy) diff --git a/rtmidi_c.h b/rtmidi_c.h index 93f37802..eeafb0be 100644 --- a/rtmidi_c.h +++ b/rtmidi_c.h @@ -39,7 +39,7 @@ typedef struct RtMidiWrapper* RtMidiOutPtr; enum RtMidiApi { RT_MIDI_API_UNSPECIFIED, /*!< Search for a working compiled API. */ - RT_MIDI_API_MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ + RT_MIDI_API_MACOSX_CORE, /*!< Macintosh OS-X CoreMIDI API. */ RT_MIDI_API_LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ RT_MIDI_API_UNIX_JACK, /*!< The Jack Low-Latency MIDI Server API. */ RT_MIDI_API_WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ diff --git a/tests/midiprobe.cpp b/tests/midiprobe.cpp index d9611edd..7ae4fe65 100644 --- a/tests/midiprobe.cpp +++ b/tests/midiprobe.cpp @@ -13,7 +13,7 @@ int main() { // Create an api map. std::map apiMap; - apiMap[RtMidi::MACOSX_CORE] = "OS-X CoreMidi"; + apiMap[RtMidi::MACOSX_CORE] = "OS-X CoreMIDI"; apiMap[RtMidi::WINDOWS_MM] = "Windows MultiMedia"; apiMap[RtMidi::UNIX_JACK] = "Jack Client"; apiMap[RtMidi::LINUX_ALSA] = "Linux ALSA";