Use github rtaudio repo with pulse support
This commit is contained in:
parent
ad473b259b
commit
6462ac9107
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "rtaudio"]
|
||||||
|
path = rtaudio
|
||||||
|
url = https://github.com/tmatth/RtAudio.git
|
||||||
19
Makefile
19
Makefile
@ -2,7 +2,7 @@
|
|||||||
# settings for C++ compiler:
|
# settings for C++ compiler:
|
||||||
C = gcc
|
C = gcc
|
||||||
CC = g++
|
CC = g++
|
||||||
CFLAGS = -O2 -Wall # -D_DEBUG -g
|
CFLAGS = -O2 -Wall -fPIC # -D_DEBUG -g
|
||||||
INCDIR = -Irtaudio -Irtaudio/include -I../lua/src
|
INCDIR = -Irtaudio -Irtaudio/include -I../lua/src
|
||||||
|
|
||||||
# linker settings:
|
# linker settings:
|
||||||
@ -13,16 +13,23 @@ LIB = $(LNAME)
|
|||||||
LIBDIR =
|
LIBDIR =
|
||||||
|
|
||||||
# settings for optional libSDL backend:
|
# settings for optional libSDL backend:
|
||||||
INCDIR += -I../archive/baseCode/include
|
INCDIR += $(shell sdl-config --cflags)
|
||||||
SDLLIB = -lSDLmain -lSDL
|
SDLLIB = $(shell sdl-config --libs)
|
||||||
SDLDIR = -L/usr/lib -L../archive/baseCode/lib
|
|
||||||
|
USE_PULSE=1
|
||||||
|
|
||||||
#--- platform specific settings ------------------------------------
|
#--- platform specific settings ------------------------------------
|
||||||
ARCH = $(shell uname -s)
|
ARCH = $(shell uname -s)
|
||||||
ifeq ($(ARCH),Linux)
|
ifeq ($(ARCH),Linux)
|
||||||
LIBS = $(LIBDIR) $(LIB) -lpthread -lasound
|
LIBS = $(LIBDIR) $(LIB) -lpthread -lasound
|
||||||
|
|
||||||
|
ifeq ($(USE_PULSE),1)
|
||||||
|
INCDIR += $(shell pkg-config --cflags libpulse-simple)
|
||||||
|
LIBS += $(shell pkg-config --libs libpulse-simple)
|
||||||
|
endif
|
||||||
|
|
||||||
LUALIB = -llua -ldl
|
LUALIB = -llua -ldl
|
||||||
CFLAGS += -DHAVE_GETTIMEOFDAY -D__LINUX_ALSA__ #-D__LINUX_OSS__
|
CFLAGS += -DHAVE_GETTIMEOFDAY $(if $(filter 1,$(USE_PULSE)),-D__LINUX_PULSE__,-D__LINUX_ALSA__) #-D__LINUX_OSS__
|
||||||
DLLFLAGS = -fPIC -shared
|
DLLFLAGS = -fPIC -shared
|
||||||
DLLSUFFIX = .so
|
DLLSUFFIX = .so
|
||||||
EXESUFFIX =
|
EXESUFFIX =
|
||||||
@ -79,7 +86,7 @@ proAudioRt$(DLLSUFFIX): proAudioRt_lua.o
|
|||||||
sdl: playAudioSdl$(EXESUFFIX)
|
sdl: playAudioSdl$(EXESUFFIX)
|
||||||
|
|
||||||
playAudioSdl$(EXESUFFIX): playAudioSdl.o proAudio.o proAudioSdl.o stb_vorbis.o
|
playAudioSdl$(EXESUFFIX): playAudioSdl.o proAudio.o proAudioSdl.o stb_vorbis.o
|
||||||
$(CC) $(CFLAGS) $^ $(SDLDIR) $(SDLLIB) -o $@
|
$(CC) $(CFLAGS) $^ $(SDLLIB) -o $@
|
||||||
|
|
||||||
# generic rules
|
# generic rules
|
||||||
.c.o:
|
.c.o:
|
||||||
|
|||||||
1
rtaudio
Submodule
1
rtaudio
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 2c846516ff496ba471bb039932a206a4e37b71ae
|
||||||
7889
rtaudio/RtAudio.cpp
7889
rtaudio/RtAudio.cpp
File diff suppressed because it is too large
Load Diff
@ -1,946 +0,0 @@
|
|||||||
/************************************************************************/
|
|
||||||
/*! \class RtAudio
|
|
||||||
\brief Realtime audio i/o C++ classes.
|
|
||||||
|
|
||||||
RtAudio provides a common API (Application Programming Interface)
|
|
||||||
for realtime audio input/output across Linux (native ALSA, Jack,
|
|
||||||
and OSS), SGI, Macintosh OS X (CoreAudio and Jack), and Windows
|
|
||||||
(DirectSound and ASIO) operating systems.
|
|
||||||
|
|
||||||
RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/
|
|
||||||
|
|
||||||
RtAudio: realtime audio i/o C++ classes
|
|
||||||
Copyright (c) 2001-2008 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 RtAudio.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
// RtAudio: Version 4.0.4
|
|
||||||
|
|
||||||
#ifndef __RTAUDIO_H
|
|
||||||
#define __RTAUDIO_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include "RtError.h"
|
|
||||||
|
|
||||||
/*! \typedef typedef unsigned long RtAudioFormat;
|
|
||||||
\brief RtAudio data format type.
|
|
||||||
|
|
||||||
Support for signed integers and floats. Audio data fed to/from an
|
|
||||||
RtAudio stream is assumed to ALWAYS be in host byte order. The
|
|
||||||
internal routines will automatically take care of any necessary
|
|
||||||
byte-swapping between the host format and the soundcard. Thus,
|
|
||||||
endian-ness is not a concern in the following format definitions.
|
|
||||||
|
|
||||||
- \e RTAUDIO_SINT8: 8-bit signed integer.
|
|
||||||
- \e RTAUDIO_SINT16: 16-bit signed integer.
|
|
||||||
- \e RTAUDIO_SINT24: Upper 3 bytes of 32-bit signed integer.
|
|
||||||
- \e RTAUDIO_SINT32: 32-bit signed integer.
|
|
||||||
- \e RTAUDIO_FLOAT32: Normalized between plus/minus 1.0.
|
|
||||||
- \e RTAUDIO_FLOAT64: Normalized between plus/minus 1.0.
|
|
||||||
*/
|
|
||||||
typedef unsigned long RtAudioFormat;
|
|
||||||
static const RtAudioFormat RTAUDIO_SINT8 = 0x1; // 8-bit signed integer.
|
|
||||||
static const RtAudioFormat RTAUDIO_SINT16 = 0x2; // 16-bit signed integer.
|
|
||||||
static const RtAudioFormat RTAUDIO_SINT24 = 0x4; // Lower 3 bytes of 32-bit signed integer.
|
|
||||||
static const RtAudioFormat RTAUDIO_SINT32 = 0x8; // 32-bit signed integer.
|
|
||||||
static const RtAudioFormat RTAUDIO_FLOAT32 = 0x10; // Normalized between plus/minus 1.0.
|
|
||||||
static const RtAudioFormat RTAUDIO_FLOAT64 = 0x20; // Normalized between plus/minus 1.0.
|
|
||||||
|
|
||||||
/*! \typedef typedef unsigned long RtAudioStreamFlags;
|
|
||||||
\brief RtAudio stream option flags.
|
|
||||||
|
|
||||||
The following flags can be OR'ed together to allow a client to
|
|
||||||
make changes to the default stream behavior:
|
|
||||||
|
|
||||||
- \e RTAUDIO_NONINTERLEAVED: Use non-interleaved buffers (default = interleaved).
|
|
||||||
- \e RTAUDIO_MINIMIZE_LATENCY: Attempt to set stream parameters for lowest possible latency.
|
|
||||||
- \e RTAUDIO_HOG_DEVICE: Attempt grab device for exclusive use.
|
|
||||||
|
|
||||||
By default, RtAudio streams pass and receive audio data from the
|
|
||||||
client in an interleaved format. By passing the
|
|
||||||
RTAUDIO_NONINTERLEAVED flag to the openStream() function, audio
|
|
||||||
data will instead be presented in non-interleaved buffers. In
|
|
||||||
this case, each buffer argument in the RtAudioCallback function
|
|
||||||
will point to a single array of data, with \c nFrames samples for
|
|
||||||
each channel concatenated back-to-back. For example, the first
|
|
||||||
sample of data for the second channel would be located at index \c
|
|
||||||
nFrames (assuming the \c buffer pointer was recast to the correct
|
|
||||||
data type for the stream).
|
|
||||||
|
|
||||||
Certain audio APIs offer a number of parameters that influence the
|
|
||||||
I/O latency of a stream. By default, RtAudio will attempt to set
|
|
||||||
these parameters internally for robust (glitch-free) performance
|
|
||||||
(though some APIs, like Windows Direct Sound, make this difficult).
|
|
||||||
By passing the RTAUDIO_MINIMIZE_LATENCY flag to the openStream()
|
|
||||||
function, internal stream settings will be influenced in an attempt
|
|
||||||
to minimize stream latency, though possibly at the expense of stream
|
|
||||||
performance.
|
|
||||||
|
|
||||||
If the RTAUDIO_HOG_DEVICE flag is set, RtAudio will attempt to
|
|
||||||
open the input and/or output stream device(s) for exclusive use.
|
|
||||||
Note that this is not possible with all supported audio APIs.
|
|
||||||
*/
|
|
||||||
typedef unsigned int RtAudioStreamFlags;
|
|
||||||
static const RtAudioStreamFlags RTAUDIO_NONINTERLEAVED = 0x1; // Use non-interleaved buffers (default = interleaved).
|
|
||||||
static const RtAudioStreamFlags RTAUDIO_MINIMIZE_LATENCY = 0x2; // Attempt to set stream parameters for lowest possible latency.
|
|
||||||
static const RtAudioStreamFlags RTAUDIO_HOG_DEVICE = 0x4; // Attempt grab device and prevent use by others.
|
|
||||||
|
|
||||||
/*! \typedef typedef unsigned long RtAudioStreamStatus;
|
|
||||||
\brief RtAudio stream status (over- or underflow) flags.
|
|
||||||
|
|
||||||
Notification of a stream over- or underflow is indicated by a
|
|
||||||
non-zero stream \c status argument in the RtAudioCallback function.
|
|
||||||
The stream status can be one of the following two options,
|
|
||||||
depending on whether the stream is open for output and/or input:
|
|
||||||
|
|
||||||
- \e RTAUDIO_INPUT_OVERFLOW: Input data was discarded because of an overflow condition at the driver.
|
|
||||||
- \e RTAUDIO_OUTPUT_UNDERFLOW: The output buffer ran low, likely producing a break in the output sound.
|
|
||||||
*/
|
|
||||||
typedef unsigned int RtAudioStreamStatus;
|
|
||||||
static const RtAudioStreamStatus RTAUDIO_INPUT_OVERFLOW = 0x1; // Input data was discarded because of an overflow condition at the driver.
|
|
||||||
static const RtAudioStreamStatus RTAUDIO_OUTPUT_UNDERFLOW = 0x2; // The output buffer ran low, likely causing a gap in the output sound.
|
|
||||||
|
|
||||||
//! RtAudio callback function prototype.
|
|
||||||
/*!
|
|
||||||
All RtAudio clients must create a function of type RtAudioCallback
|
|
||||||
to read and/or write data from/to the audio stream. When the
|
|
||||||
underlying audio system is ready for new input or output data, this
|
|
||||||
function will be invoked.
|
|
||||||
|
|
||||||
\param outputBuffer For output (or duplex) streams, the client
|
|
||||||
should write \c nFrames of audio sample frames into this
|
|
||||||
buffer. This argument should be recast to the datatype
|
|
||||||
specified when the stream was opened. For input-only
|
|
||||||
streams, this argument will be NULL.
|
|
||||||
|
|
||||||
\param inputBuffer For input (or duplex) streams, this buffer will
|
|
||||||
hold \c nFrames of input audio sample frames. This
|
|
||||||
argument should be recast to the datatype specified when the
|
|
||||||
stream was opened. For output-only streams, this argument
|
|
||||||
will be NULL.
|
|
||||||
|
|
||||||
\param nFrames The number of sample frames of input or output
|
|
||||||
data in the buffers. The actual buffer size in bytes is
|
|
||||||
dependent on the data type and number of channels in use.
|
|
||||||
|
|
||||||
\param streamTime The number of seconds that have elapsed since the
|
|
||||||
stream was started.
|
|
||||||
|
|
||||||
\param status If non-zero, this argument indicates a data overflow
|
|
||||||
or underflow condition for the stream. The particular
|
|
||||||
condition can be determined by comparison with the
|
|
||||||
RtAudioStreamStatus flags.
|
|
||||||
|
|
||||||
\param userData A pointer to optional data provided by the client
|
|
||||||
when opening the stream (default = NULL).
|
|
||||||
|
|
||||||
To continue normal stream operation, the RtAudioCallback function
|
|
||||||
should return a value of zero. To stop the stream and drain the
|
|
||||||
output buffer, the function should return a value of one. To abort
|
|
||||||
the stream immediately, the client should return a value of two.
|
|
||||||
*/
|
|
||||||
typedef int (*RtAudioCallback)( void *outputBuffer, void *inputBuffer,
|
|
||||||
unsigned int nFrames,
|
|
||||||
double streamTime,
|
|
||||||
RtAudioStreamStatus status,
|
|
||||||
void *userData );
|
|
||||||
|
|
||||||
|
|
||||||
// **************************************************************** //
|
|
||||||
//
|
|
||||||
// RtAudio class declaration.
|
|
||||||
//
|
|
||||||
// RtAudio is a "controller" used to select an available audio i/o
|
|
||||||
// interface. It presents a common API for the user to call but all
|
|
||||||
// functionality is implemented by the class RtApi and its
|
|
||||||
// subclasses. RtAudio creates an instance of an RtApi subclass
|
|
||||||
// based on the user's API choice. If no choice is made, RtAudio
|
|
||||||
// attempts to make a "logical" API selection.
|
|
||||||
//
|
|
||||||
// **************************************************************** //
|
|
||||||
|
|
||||||
class RtApi;
|
|
||||||
|
|
||||||
class RtAudio
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
//! Audio API specifier arguments.
|
|
||||||
enum Api {
|
|
||||||
UNSPECIFIED, /*!< Search for a working compiled API. */
|
|
||||||
LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */
|
|
||||||
LINUX_OSS, /*!< The Linux Open Sound System API. */
|
|
||||||
UNIX_JACK, /*!< The Jack Low-Latency Audio Server API. */
|
|
||||||
MACOSX_CORE, /*!< Macintosh OS-X Core Audio API. */
|
|
||||||
WINDOWS_ASIO, /*!< The Steinberg Audio Stream I/O API. */
|
|
||||||
WINDOWS_DS, /*!< The Microsoft Direct Sound API. */
|
|
||||||
RTAUDIO_DUMMY /*!< A compilable but non-functional API. */
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The public device information structure for returning queried values.
|
|
||||||
struct DeviceInfo {
|
|
||||||
bool probed; /*!< true if the device capabilities were successfully probed. */
|
|
||||||
std::string name; /*!< Character string device identifier. */
|
|
||||||
unsigned int outputChannels; /*!< Maximum output channels supported by device. */
|
|
||||||
unsigned int inputChannels; /*!< Maximum input channels supported by device. */
|
|
||||||
unsigned int duplexChannels; /*!< Maximum simultaneous input/output channels supported by device. */
|
|
||||||
bool isDefaultOutput; /*!< true if this is the default output device. */
|
|
||||||
bool isDefaultInput; /*!< true if this is the default input device. */
|
|
||||||
std::vector<unsigned int> sampleRates; /*!< Supported sample rates (queried from list of standard rates). */
|
|
||||||
RtAudioFormat nativeFormats; /*!< Bit mask of supported data formats. */
|
|
||||||
|
|
||||||
// Default constructor.
|
|
||||||
DeviceInfo()
|
|
||||||
:probed(false), outputChannels(0), inputChannels(0), duplexChannels(0),
|
|
||||||
isDefaultOutput(false), isDefaultInput(false), nativeFormats(0) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The structure for specifying input or ouput stream parameters.
|
|
||||||
struct StreamParameters {
|
|
||||||
unsigned int deviceId; /*!< Device index (0 to getDeviceCount() - 1). */
|
|
||||||
unsigned int nChannels; /*!< Number of channels. */
|
|
||||||
unsigned int firstChannel; /*!< First channel index on device (default = 0). */
|
|
||||||
|
|
||||||
// Default constructor.
|
|
||||||
StreamParameters()
|
|
||||||
: deviceId(0), nChannels(0), firstChannel(0) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The structure for specifying stream options.
|
|
||||||
/*!
|
|
||||||
The following flags can be OR'ed together to allow a client to
|
|
||||||
make changes to the default stream behavior:
|
|
||||||
|
|
||||||
- \e RTAUDIO_NONINTERLEAVED: Use non-interleaved buffers (default = interleaved).
|
|
||||||
- \e RTAUDIO_MINIMIZE_LATENCY: Attempt to set stream parameters for lowest possible latency.
|
|
||||||
- \e RTAUDIO_HOG_DEVICE: Attempt grab device for exclusive use.
|
|
||||||
|
|
||||||
By default, RtAudio streams pass and receive audio data from the
|
|
||||||
client in an interleaved format. By passing the
|
|
||||||
RTAUDIO_NONINTERLEAVED flag to the openStream() function, audio
|
|
||||||
data will instead be presented in non-interleaved buffers. In
|
|
||||||
this case, each buffer argument in the RtAudioCallback function
|
|
||||||
will point to a single array of data, with \c nFrames samples for
|
|
||||||
each channel concatenated back-to-back. For example, the first
|
|
||||||
sample of data for the second channel would be located at index \c
|
|
||||||
nFrames (assuming the \c buffer pointer was recast to the correct
|
|
||||||
data type for the stream).
|
|
||||||
|
|
||||||
Certain audio APIs offer a number of parameters that influence the
|
|
||||||
I/O latency of a stream. By default, RtAudio will attempt to set
|
|
||||||
these parameters internally for robust (glitch-free) performance
|
|
||||||
(though some APIs, like Windows Direct Sound, make this difficult).
|
|
||||||
By passing the RTAUDIO_MINIMIZE_LATENCY flag to the openStream()
|
|
||||||
function, internal stream settings will be influenced in an attempt
|
|
||||||
to minimize stream latency, though possibly at the expense of stream
|
|
||||||
performance.
|
|
||||||
|
|
||||||
If the RTAUDIO_HOG_DEVICE flag is set, RtAudio will attempt to
|
|
||||||
open the input and/or output stream device(s) for exclusive use.
|
|
||||||
Note that this is not possible with all supported audio APIs.
|
|
||||||
|
|
||||||
The \c numberOfBuffers parameter can be used to control stream
|
|
||||||
latency in the Windows DirectSound, Linux OSS, and Linux Alsa APIs
|
|
||||||
only. A value of two is usually the smallest allowed. Larger
|
|
||||||
numbers can potentially result in more robust stream performance,
|
|
||||||
though likely at the cost of stream latency. The value set by the
|
|
||||||
user is replaced during execution of the RtAudio::openStream()
|
|
||||||
function by the value actually used by the system.
|
|
||||||
|
|
||||||
The \c streamName parameter can be used to set the client name
|
|
||||||
when using the Jack API. By default, the client name is set to
|
|
||||||
RtApiJack. However, if you wish to create multiple instances of
|
|
||||||
RtAudio with Jack, each instance must have a unique client name.
|
|
||||||
*/
|
|
||||||
struct StreamOptions {
|
|
||||||
RtAudioStreamFlags flags; /*!< A bit-mask of stream flags (RTAUDIO_NONINTERLEAVED, RTAUDIO_MINIMIZE_LATENCY, RTAUDIO_HOG_DEVICE). */
|
|
||||||
unsigned int numberOfBuffers; /*!< Number of stream buffers. */
|
|
||||||
std::string streamName; /*!< A stream name (currently used only in Jack). */
|
|
||||||
|
|
||||||
// Default constructor.
|
|
||||||
StreamOptions()
|
|
||||||
: flags(0), numberOfBuffers(0) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
//! A static function to determine the available compiled audio 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<RtAudio::Api> &apis ) throw();
|
|
||||||
|
|
||||||
//! The class constructor.
|
|
||||||
/*!
|
|
||||||
The constructor performs minor initialization tasks. No exceptions
|
|
||||||
can be thrown.
|
|
||||||
|
|
||||||
If no API argument is specified and multiple API support has been
|
|
||||||
compiled, the default order of use is JACK, ALSA, OSS (Linux
|
|
||||||
systems) and ASIO, DS (Windows systems).
|
|
||||||
*/
|
|
||||||
RtAudio( RtAudio::Api api=UNSPECIFIED ) throw();
|
|
||||||
|
|
||||||
//! The destructor.
|
|
||||||
/*!
|
|
||||||
If a stream is running or open, it will be stopped and closed
|
|
||||||
automatically.
|
|
||||||
*/
|
|
||||||
~RtAudio() throw();
|
|
||||||
|
|
||||||
//! Returns the audio API specifier for the current instance of RtAudio.
|
|
||||||
RtAudio::Api getCurrentApi( void ) throw();
|
|
||||||
|
|
||||||
//! A public function that queries for the number of audio devices available.
|
|
||||||
/*!
|
|
||||||
This function performs a system query of available devices each time it
|
|
||||||
is called, thus supporting devices connected \e after instantiation. If
|
|
||||||
a system error occurs during processing, a warning will be issued.
|
|
||||||
*/
|
|
||||||
unsigned int getDeviceCount( void ) throw();
|
|
||||||
|
|
||||||
//! Return an RtAudio::DeviceInfo structure for a specified device number.
|
|
||||||
/*!
|
|
||||||
|
|
||||||
Any device integer between 0 and getDeviceCount() - 1 is valid.
|
|
||||||
If an invalid argument is provided, an RtError (type = INVALID_USE)
|
|
||||||
will be thrown. If a device is busy or otherwise unavailable, the
|
|
||||||
structure member "probed" will have a value of "false" and all
|
|
||||||
other members are undefined. If the specified device is the
|
|
||||||
current default input or output device, the corresponding
|
|
||||||
"isDefault" member will have a value of "true".
|
|
||||||
*/
|
|
||||||
RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
|
|
||||||
|
|
||||||
//! A function that returns the index of the default output device.
|
|
||||||
/*!
|
|
||||||
If the underlying audio API does not provide a "default
|
|
||||||
device", or if no devices are available, the return value will be
|
|
||||||
0. Note that this is a valid device identifier and it is the
|
|
||||||
client's responsibility to verify that a device is available
|
|
||||||
before attempting to open a stream.
|
|
||||||
*/
|
|
||||||
unsigned int getDefaultOutputDevice( void ) throw();
|
|
||||||
|
|
||||||
//! A function that returns the index of the default input device.
|
|
||||||
/*!
|
|
||||||
If the underlying audio API does not provide a "default
|
|
||||||
device", or if no devices are available, the return value will be
|
|
||||||
0. Note that this is a valid device identifier and it is the
|
|
||||||
client's responsibility to verify that a device is available
|
|
||||||
before attempting to open a stream.
|
|
||||||
*/
|
|
||||||
unsigned int getDefaultInputDevice( void ) throw();
|
|
||||||
|
|
||||||
//! A public function for opening a stream with the specified parameters.
|
|
||||||
/*!
|
|
||||||
An RtError (type = SYSTEM_ERROR) is thrown if a stream cannot be
|
|
||||||
opened with the specified parameters or an error occurs during
|
|
||||||
processing. An RtError (type = INVALID_USE) is thrown if any
|
|
||||||
invalid device ID or channel number parameters are specified.
|
|
||||||
|
|
||||||
\param outputParameters Specifies output stream parameters to use
|
|
||||||
when opening a stream, including a device ID, number of channels,
|
|
||||||
and starting channel number. For input-only streams, this
|
|
||||||
argument should be NULL. The device ID is an index value between
|
|
||||||
0 and getDeviceCount() - 1.
|
|
||||||
\param inputParameters Specifies input stream parameters to use
|
|
||||||
when opening a stream, including a device ID, number of channels,
|
|
||||||
and starting channel number. For output-only streams, this
|
|
||||||
argument should be NULL. The device ID is an index value between
|
|
||||||
0 and getDeviceCount() - 1.
|
|
||||||
\param format An RtAudioFormat specifying the desired sample data format.
|
|
||||||
\param sampleRate The desired sample rate (sample frames per second).
|
|
||||||
\param *bufferFrames A pointer to a value indicating the desired
|
|
||||||
internal buffer size in sample frames. The actual value
|
|
||||||
used by the device is returned via the same pointer. A
|
|
||||||
value of zero can be specified, in which case the lowest
|
|
||||||
allowable value is determined.
|
|
||||||
\param callback A client-defined function that will be invoked
|
|
||||||
when input data is available and/or output data is needed.
|
|
||||||
\param userData An optional pointer to data that can be accessed
|
|
||||||
from within the callback function.
|
|
||||||
\param options An optional pointer to a structure containing various
|
|
||||||
global stream options, including a list of OR'ed RtAudioStreamFlags
|
|
||||||
and a suggested number of stream buffers that can be used to
|
|
||||||
control stream latency. More buffers typically result in more
|
|
||||||
robust performance, though at a cost of greater latency. If a
|
|
||||||
value of zero is specified, a system-specific median value is
|
|
||||||
chosen. If the RTAUDIO_MINIMIZE_LATENCY flag bit is set, the
|
|
||||||
lowest allowable value is used. The actual value used is
|
|
||||||
returned via the structure argument. The parameter is API dependent.
|
|
||||||
*/
|
|
||||||
void openStream( RtAudio::StreamParameters *outputParameters,
|
|
||||||
RtAudio::StreamParameters *inputParameters,
|
|
||||||
RtAudioFormat format, unsigned int sampleRate,
|
|
||||||
unsigned int *bufferFrames, RtAudioCallback callback,
|
|
||||||
void *userData = NULL, RtAudio::StreamOptions *options = NULL );
|
|
||||||
|
|
||||||
//! A function that closes a stream and frees any associated stream memory.
|
|
||||||
/*!
|
|
||||||
If a stream is not open, this function issues a warning and
|
|
||||||
returns (no exception is thrown).
|
|
||||||
*/
|
|
||||||
void closeStream( void ) throw();
|
|
||||||
|
|
||||||
//! A function that starts a stream.
|
|
||||||
/*!
|
|
||||||
An RtError (type = SYSTEM_ERROR) is thrown if an error occurs
|
|
||||||
during processing. An RtError (type = INVALID_USE) is thrown if a
|
|
||||||
stream is not open. A warning is issued if the stream is already
|
|
||||||
running.
|
|
||||||
*/
|
|
||||||
void startStream( void );
|
|
||||||
|
|
||||||
//! Stop a stream, allowing any samples remaining in the output queue to be played.
|
|
||||||
/*!
|
|
||||||
An RtError (type = SYSTEM_ERROR) is thrown if an error occurs
|
|
||||||
during processing. An RtError (type = INVALID_USE) is thrown if a
|
|
||||||
stream is not open. A warning is issued if the stream is already
|
|
||||||
stopped.
|
|
||||||
*/
|
|
||||||
void stopStream( void );
|
|
||||||
|
|
||||||
//! Stop a stream, discarding any samples remaining in the input/output queue.
|
|
||||||
/*!
|
|
||||||
An RtError (type = SYSTEM_ERROR) is thrown if an error occurs
|
|
||||||
during processing. An RtError (type = INVALID_USE) is thrown if a
|
|
||||||
stream is not open. A warning is issued if the stream is already
|
|
||||||
stopped.
|
|
||||||
*/
|
|
||||||
void abortStream( void );
|
|
||||||
|
|
||||||
//! Returns true if a stream is open and false if not.
|
|
||||||
bool isStreamOpen( void ) throw();
|
|
||||||
|
|
||||||
//! Returns true if the stream is running and false if it is stopped or not open.
|
|
||||||
bool isStreamRunning( void ) throw();
|
|
||||||
|
|
||||||
//! Returns the number of elapsed seconds since the stream was started.
|
|
||||||
/*!
|
|
||||||
If a stream is not open, an RtError (type = INVALID_USE) will be thrown.
|
|
||||||
*/
|
|
||||||
double getStreamTime( void );
|
|
||||||
|
|
||||||
//! Returns the internal stream latency in sample frames.
|
|
||||||
/*!
|
|
||||||
The stream latency refers to delay in audio input and/or output
|
|
||||||
caused by internal buffering by the audio system and/or hardware.
|
|
||||||
For duplex streams, the returned value will represent the sum of
|
|
||||||
the input and output latencies. If a stream is not open, an
|
|
||||||
RtError (type = INVALID_USE) will be thrown. If the API does not
|
|
||||||
report latency, the return value will be zero.
|
|
||||||
*/
|
|
||||||
long getStreamLatency( void );
|
|
||||||
|
|
||||||
//! Specify whether warning messages should be printed to stderr.
|
|
||||||
void showWarnings( bool value = true ) throw();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
void openRtApi( RtAudio::Api api );
|
|
||||||
RtApi *rtapi_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Operating system dependent thread functionality.
|
|
||||||
#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__)
|
|
||||||
#include <windows.h>
|
|
||||||
#include <process.h>
|
|
||||||
|
|
||||||
typedef unsigned long ThreadHandle;
|
|
||||||
typedef CRITICAL_SECTION StreamMutex;
|
|
||||||
|
|
||||||
#elif defined(__LINUX_ALSA__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__)
|
|
||||||
// Using pthread library for various flavors of unix.
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
typedef pthread_t ThreadHandle;
|
|
||||||
typedef pthread_mutex_t StreamMutex;
|
|
||||||
|
|
||||||
#else // Setup for "dummy" behavior
|
|
||||||
|
|
||||||
#define __RTAUDIO_DUMMY__
|
|
||||||
typedef int ThreadHandle;
|
|
||||||
typedef int StreamMutex;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// This global structure type is used to pass callback information
|
|
||||||
// between the private RtAudio stream structure and global callback
|
|
||||||
// handling functions.
|
|
||||||
struct CallbackInfo {
|
|
||||||
void *object; // Used as a "this" pointer.
|
|
||||||
ThreadHandle thread;
|
|
||||||
void *callback;
|
|
||||||
void *userData;
|
|
||||||
void *apiInfo; // void pointer for API specific callback information
|
|
||||||
bool isRunning;
|
|
||||||
|
|
||||||
// Default constructor.
|
|
||||||
CallbackInfo()
|
|
||||||
:object(0), callback(0), userData(0), apiInfo(0), isRunning(false) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// **************************************************************** //
|
|
||||||
//
|
|
||||||
// RtApi class declaration.
|
|
||||||
//
|
|
||||||
// Subclasses of RtApi contain all API- and OS-specific code necessary
|
|
||||||
// to fully implement the RtAudio API.
|
|
||||||
//
|
|
||||||
// Note that RtApi is an abstract base class and cannot be
|
|
||||||
// explicitly instantiated. The class RtAudio will create an
|
|
||||||
// instance of an RtApi subclass (RtApiOss, RtApiAlsa,
|
|
||||||
// RtApiJack, RtApiCore, RtApiAl, RtApiDs, or RtApiAsio).
|
|
||||||
//
|
|
||||||
// **************************************************************** //
|
|
||||||
|
|
||||||
#if defined( HAVE_GETTIMEOFDAY )
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
class RtApi
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
RtApi();
|
|
||||||
virtual ~RtApi();
|
|
||||||
virtual RtAudio::Api getCurrentApi( void ) = 0;
|
|
||||||
virtual unsigned int getDeviceCount( void ) = 0;
|
|
||||||
virtual RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) = 0;
|
|
||||||
virtual unsigned int getDefaultInputDevice( void );
|
|
||||||
virtual unsigned int getDefaultOutputDevice( void );
|
|
||||||
void openStream( RtAudio::StreamParameters *outputParameters,
|
|
||||||
RtAudio::StreamParameters *inputParameters,
|
|
||||||
RtAudioFormat format, unsigned int sampleRate,
|
|
||||||
unsigned int *bufferFrames, RtAudioCallback callback,
|
|
||||||
void *userData, RtAudio::StreamOptions *options );
|
|
||||||
virtual void closeStream( void );
|
|
||||||
virtual void startStream( void ) = 0;
|
|
||||||
virtual void stopStream( void ) = 0;
|
|
||||||
virtual void abortStream( void ) = 0;
|
|
||||||
long getStreamLatency( void );
|
|
||||||
virtual double getStreamTime( void );
|
|
||||||
bool isStreamOpen( void ) { return stream_.state != STREAM_CLOSED; };
|
|
||||||
bool isStreamRunning( void ) { return stream_.state == STREAM_RUNNING; };
|
|
||||||
void showWarnings( bool value ) { showWarnings_ = value; };
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
static const unsigned int MAX_SAMPLE_RATES;
|
|
||||||
static const unsigned int SAMPLE_RATES[];
|
|
||||||
|
|
||||||
enum { FAILURE, SUCCESS };
|
|
||||||
|
|
||||||
enum StreamState {
|
|
||||||
STREAM_STOPPED,
|
|
||||||
STREAM_RUNNING,
|
|
||||||
STREAM_CLOSED = -50
|
|
||||||
};
|
|
||||||
|
|
||||||
enum StreamMode {
|
|
||||||
OUTPUT,
|
|
||||||
INPUT,
|
|
||||||
DUPLEX,
|
|
||||||
UNINITIALIZED = -75
|
|
||||||
};
|
|
||||||
|
|
||||||
// A protected structure used for buffer conversion.
|
|
||||||
struct ConvertInfo {
|
|
||||||
int channels;
|
|
||||||
int inJump, outJump;
|
|
||||||
RtAudioFormat inFormat, outFormat;
|
|
||||||
std::vector<int> inOffset;
|
|
||||||
std::vector<int> outOffset;
|
|
||||||
};
|
|
||||||
|
|
||||||
// A protected structure for audio streams.
|
|
||||||
struct RtApiStream {
|
|
||||||
unsigned int device[2]; // Playback and record, respectively.
|
|
||||||
void *apiHandle; // void pointer for API specific stream handle information
|
|
||||||
StreamMode mode; // OUTPUT, INPUT, or DUPLEX.
|
|
||||||
StreamState state; // STOPPED, RUNNING, or CLOSED
|
|
||||||
char *userBuffer[2]; // Playback and record, respectively.
|
|
||||||
char *deviceBuffer;
|
|
||||||
bool doConvertBuffer[2]; // Playback and record, respectively.
|
|
||||||
bool userInterleaved;
|
|
||||||
bool deviceInterleaved[2]; // Playback and record, respectively.
|
|
||||||
bool doByteSwap[2]; // Playback and record, respectively.
|
|
||||||
unsigned int sampleRate;
|
|
||||||
unsigned int bufferSize;
|
|
||||||
unsigned int nBuffers;
|
|
||||||
unsigned int nUserChannels[2]; // Playback and record, respectively.
|
|
||||||
unsigned int nDeviceChannels[2]; // Playback and record channels, respectively.
|
|
||||||
unsigned int channelOffset[2]; // Playback and record, respectively.
|
|
||||||
unsigned long latency[2]; // Playback and record, respectively.
|
|
||||||
RtAudioFormat userFormat;
|
|
||||||
RtAudioFormat deviceFormat[2]; // Playback and record, respectively.
|
|
||||||
StreamMutex mutex;
|
|
||||||
CallbackInfo callbackInfo;
|
|
||||||
ConvertInfo convertInfo[2];
|
|
||||||
double streamTime; // Number of elapsed seconds since the stream started.
|
|
||||||
|
|
||||||
#if defined(HAVE_GETTIMEOFDAY)
|
|
||||||
struct timeval lastTickTimestamp;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
RtApiStream()
|
|
||||||
:apiHandle(0), deviceBuffer(0) { device[0] = 11111; device[1] = 11111; }
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef signed short Int16;
|
|
||||||
typedef signed int Int32;
|
|
||||||
typedef float Float32;
|
|
||||||
typedef double Float64;
|
|
||||||
|
|
||||||
std::ostringstream errorStream_;
|
|
||||||
std::string errorText_;
|
|
||||||
bool showWarnings_;
|
|
||||||
RtApiStream stream_;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Protected, api-specific method that attempts to open a device
|
|
||||||
with the given parameters. This function MUST be implemented by
|
|
||||||
all subclasses. If an error is encountered during the probe, a
|
|
||||||
"warning" message is reported and FAILURE is returned. A
|
|
||||||
successful probe is indicated by a return value of SUCCESS.
|
|
||||||
*/
|
|
||||||
virtual bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
|
|
||||||
unsigned int firstChannel, unsigned int sampleRate,
|
|
||||||
RtAudioFormat format, unsigned int *bufferSize,
|
|
||||||
RtAudio::StreamOptions *options );
|
|
||||||
|
|
||||||
//! A protected function used to increment the stream time.
|
|
||||||
void tickStreamTime( void );
|
|
||||||
|
|
||||||
//! Protected common method to clear an RtApiStream structure.
|
|
||||||
void clearStreamInfo();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Protected common method that throws an RtError (type =
|
|
||||||
INVALID_USE) if a stream is not open.
|
|
||||||
*/
|
|
||||||
void verifyStream( void );
|
|
||||||
|
|
||||||
//! Protected common error method to allow global control over error handling.
|
|
||||||
void error( RtError::Type type );
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Protected method used to perform format, channel number, and/or interleaving
|
|
||||||
conversions between the user and device buffers.
|
|
||||||
*/
|
|
||||||
void convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info );
|
|
||||||
|
|
||||||
//! Protected common method used to perform byte-swapping on buffers.
|
|
||||||
void byteSwapBuffer( char *buffer, unsigned int samples, RtAudioFormat format );
|
|
||||||
|
|
||||||
//! Protected common method that returns the number of bytes for a given format.
|
|
||||||
unsigned int formatBytes( RtAudioFormat format );
|
|
||||||
|
|
||||||
//! Protected common method that sets up the parameters for buffer conversion.
|
|
||||||
void setConvertInfo( StreamMode mode, unsigned int firstChannel );
|
|
||||||
};
|
|
||||||
|
|
||||||
// **************************************************************** //
|
|
||||||
//
|
|
||||||
// Inline RtAudio definitions.
|
|
||||||
//
|
|
||||||
// **************************************************************** //
|
|
||||||
|
|
||||||
inline RtAudio::Api RtAudio :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); }
|
|
||||||
inline unsigned int RtAudio :: getDeviceCount( void ) throw() { return rtapi_->getDeviceCount(); }
|
|
||||||
inline RtAudio::DeviceInfo RtAudio :: getDeviceInfo( unsigned int device ) { return rtapi_->getDeviceInfo( device ); }
|
|
||||||
inline unsigned int RtAudio :: getDefaultInputDevice( void ) throw() { return rtapi_->getDefaultInputDevice(); }
|
|
||||||
inline unsigned int RtAudio :: getDefaultOutputDevice( void ) throw() { return rtapi_->getDefaultOutputDevice(); }
|
|
||||||
inline void RtAudio :: closeStream( void ) throw() { return rtapi_->closeStream(); }
|
|
||||||
inline void RtAudio :: startStream( void ) { return rtapi_->startStream(); }
|
|
||||||
inline void RtAudio :: stopStream( void ) { return rtapi_->stopStream(); }
|
|
||||||
inline void RtAudio :: abortStream( void ) { return rtapi_->abortStream(); }
|
|
||||||
inline bool RtAudio :: isStreamOpen( void ) throw() { return rtapi_->isStreamOpen(); }
|
|
||||||
inline bool RtAudio :: isStreamRunning( void ) throw() { return rtapi_->isStreamRunning(); }
|
|
||||||
inline long RtAudio :: getStreamLatency( void ) { return rtapi_->getStreamLatency(); }
|
|
||||||
inline double RtAudio :: getStreamTime( void ) { return rtapi_->getStreamTime(); }
|
|
||||||
inline void RtAudio :: showWarnings( bool value ) throw() { rtapi_->showWarnings( value ); }
|
|
||||||
|
|
||||||
// RtApi Subclass prototypes.
|
|
||||||
|
|
||||||
#if defined(__MACOSX_CORE__)
|
|
||||||
|
|
||||||
#include <CoreAudio/AudioHardware.h>
|
|
||||||
|
|
||||||
class RtApiCore: public RtApi
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
RtApiCore();
|
|
||||||
~RtApiCore();
|
|
||||||
RtAudio::Api getCurrentApi( void ) { return RtAudio::MACOSX_CORE; };
|
|
||||||
unsigned int getDeviceCount( void );
|
|
||||||
RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
|
|
||||||
unsigned int getDefaultOutputDevice( void );
|
|
||||||
unsigned int getDefaultInputDevice( void );
|
|
||||||
void closeStream( void );
|
|
||||||
void startStream( void );
|
|
||||||
void stopStream( void );
|
|
||||||
void abortStream( void );
|
|
||||||
long getStreamLatency( void );
|
|
||||||
|
|
||||||
// This function is intended for internal use only. It must be
|
|
||||||
// public because it is called by the internal callback handler,
|
|
||||||
// which is not a member of RtAudio. External use of this function
|
|
||||||
// will most likely produce highly undesireable results!
|
|
||||||
bool callbackEvent( AudioDeviceID deviceId,
|
|
||||||
const AudioBufferList *inBufferList,
|
|
||||||
const AudioBufferList *outBufferList );
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
|
|
||||||
unsigned int firstChannel, unsigned int sampleRate,
|
|
||||||
RtAudioFormat format, unsigned int *bufferSize,
|
|
||||||
RtAudio::StreamOptions *options );
|
|
||||||
static const char* getErrorCode( OSStatus code );
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__UNIX_JACK__)
|
|
||||||
|
|
||||||
class RtApiJack: public RtApi
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
RtApiJack();
|
|
||||||
~RtApiJack();
|
|
||||||
RtAudio::Api getCurrentApi( void ) { return RtAudio::UNIX_JACK; };
|
|
||||||
unsigned int getDeviceCount( void );
|
|
||||||
RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
|
|
||||||
void closeStream( void );
|
|
||||||
void startStream( void );
|
|
||||||
void stopStream( void );
|
|
||||||
void abortStream( void );
|
|
||||||
long getStreamLatency( void );
|
|
||||||
|
|
||||||
// This function is intended for internal use only. It must be
|
|
||||||
// public because it is called by the internal callback handler,
|
|
||||||
// which is not a member of RtAudio. External use of this function
|
|
||||||
// will most likely produce highly undesireable results!
|
|
||||||
bool callbackEvent( unsigned long nframes );
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
|
|
||||||
unsigned int firstChannel, unsigned int sampleRate,
|
|
||||||
RtAudioFormat format, unsigned int *bufferSize,
|
|
||||||
RtAudio::StreamOptions *options );
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__WINDOWS_ASIO__)
|
|
||||||
|
|
||||||
class RtApiAsio: public RtApi
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
RtApiAsio();
|
|
||||||
~RtApiAsio();
|
|
||||||
RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_ASIO; };
|
|
||||||
unsigned int getDeviceCount( void );
|
|
||||||
RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
|
|
||||||
void closeStream( void );
|
|
||||||
void startStream( void );
|
|
||||||
void stopStream( void );
|
|
||||||
void abortStream( void );
|
|
||||||
long getStreamLatency( void );
|
|
||||||
|
|
||||||
// This function is intended for internal use only. It must be
|
|
||||||
// public because it is called by the internal callback handler,
|
|
||||||
// which is not a member of RtAudio. External use of this function
|
|
||||||
// will most likely produce highly undesireable results!
|
|
||||||
bool callbackEvent( long bufferIndex );
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
std::vector<RtAudio::DeviceInfo> devices_;
|
|
||||||
void saveDeviceInfo( void );
|
|
||||||
bool coInitialized_;
|
|
||||||
bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
|
|
||||||
unsigned int firstChannel, unsigned int sampleRate,
|
|
||||||
RtAudioFormat format, unsigned int *bufferSize,
|
|
||||||
RtAudio::StreamOptions *options );
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__WINDOWS_DS__)
|
|
||||||
|
|
||||||
class RtApiDs: public RtApi
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
RtApiDs();
|
|
||||||
~RtApiDs();
|
|
||||||
RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_DS; };
|
|
||||||
unsigned int getDeviceCount( void );
|
|
||||||
unsigned int getDefaultOutputDevice( void );
|
|
||||||
unsigned int getDefaultInputDevice( void );
|
|
||||||
RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
|
|
||||||
void closeStream( void );
|
|
||||||
void startStream( void );
|
|
||||||
void stopStream( void );
|
|
||||||
void abortStream( void );
|
|
||||||
long getStreamLatency( void );
|
|
||||||
|
|
||||||
// This function is intended for internal use only. It must be
|
|
||||||
// public because it is called by the internal callback handler,
|
|
||||||
// which is not a member of RtAudio. External use of this function
|
|
||||||
// will most likely produce highly undesireable results!
|
|
||||||
void callbackEvent( void );
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
bool coInitialized_;
|
|
||||||
bool buffersRolling;
|
|
||||||
long duplexPrerollBytes;
|
|
||||||
bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
|
|
||||||
unsigned int firstChannel, unsigned int sampleRate,
|
|
||||||
RtAudioFormat format, unsigned int *bufferSize,
|
|
||||||
RtAudio::StreamOptions *options );
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__LINUX_ALSA__)
|
|
||||||
|
|
||||||
class RtApiAlsa: public RtApi
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
RtApiAlsa();
|
|
||||||
~RtApiAlsa();
|
|
||||||
RtAudio::Api getCurrentApi() { return RtAudio::LINUX_ALSA; };
|
|
||||||
unsigned int getDeviceCount( void );
|
|
||||||
RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
|
|
||||||
void closeStream( void );
|
|
||||||
void startStream( void );
|
|
||||||
void stopStream( void );
|
|
||||||
void abortStream( void );
|
|
||||||
|
|
||||||
// This function is intended for internal use only. It must be
|
|
||||||
// public because it is called by the internal callback handler,
|
|
||||||
// which is not a member of RtAudio. External use of this function
|
|
||||||
// will most likely produce highly undesireable results!
|
|
||||||
void callbackEvent( void );
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
std::vector<RtAudio::DeviceInfo> devices_;
|
|
||||||
void saveDeviceInfo( void );
|
|
||||||
bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
|
|
||||||
unsigned int firstChannel, unsigned int sampleRate,
|
|
||||||
RtAudioFormat format, unsigned int *bufferSize,
|
|
||||||
RtAudio::StreamOptions *options );
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__LINUX_OSS__)
|
|
||||||
|
|
||||||
class RtApiOss: public RtApi
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
RtApiOss();
|
|
||||||
~RtApiOss();
|
|
||||||
RtAudio::Api getCurrentApi() { return RtAudio::LINUX_OSS; };
|
|
||||||
unsigned int getDeviceCount( void );
|
|
||||||
RtAudio::DeviceInfo getDeviceInfo( unsigned int device );
|
|
||||||
void closeStream( void );
|
|
||||||
void startStream( void );
|
|
||||||
void stopStream( void );
|
|
||||||
void abortStream( void );
|
|
||||||
|
|
||||||
// This function is intended for internal use only. It must be
|
|
||||||
// public because it is called by the internal callback handler,
|
|
||||||
// which is not a member of RtAudio. External use of this function
|
|
||||||
// will most likely produce highly undesireable results!
|
|
||||||
void callbackEvent( void );
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
|
|
||||||
unsigned int firstChannel, unsigned int sampleRate,
|
|
||||||
RtAudioFormat format, unsigned int *bufferSize,
|
|
||||||
RtAudio::StreamOptions *options );
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__RTAUDIO_DUMMY__)
|
|
||||||
|
|
||||||
class RtApiDummy: public RtApi
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
RtApiDummy() { errorText_ = "RtApiDummy: This class provides no functionality."; error( RtError::WARNING ); };
|
|
||||||
RtAudio::Api getCurrentApi( void ) { return RtAudio::RTAUDIO_DUMMY; };
|
|
||||||
unsigned int getDeviceCount( void ) { return 0; };
|
|
||||||
RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) { RtAudio::DeviceInfo info; return info; };
|
|
||||||
void closeStream( void ) {};
|
|
||||||
void startStream( void ) {};
|
|
||||||
void stopStream( void ) {};
|
|
||||||
void abortStream( void ) {};
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
|
|
||||||
unsigned int firstChannel, unsigned int sampleRate,
|
|
||||||
RtAudioFormat format, unsigned int *bufferSize,
|
|
||||||
RtAudio::StreamOptions *options ) { return false; };
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Indentation settings for Vim and Emacs
|
|
||||||
//
|
|
||||||
// Local Variables:
|
|
||||||
// c-basic-offset: 2
|
|
||||||
// indent-tabs-mode: nil
|
|
||||||
// End:
|
|
||||||
//
|
|
||||||
// vim: et sts=2 sw=2
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
/************************************************************************/
|
|
||||||
/*! \class RtError
|
|
||||||
\brief Exception handling class for RtAudio & RtMidi.
|
|
||||||
|
|
||||||
The RtError class is quite simple but it does allow errors to be
|
|
||||||
"caught" by RtError::Type. See the RtAudio and RtMidi
|
|
||||||
documentation to know which methods can throw an RtError.
|
|
||||||
|
|
||||||
*/
|
|
||||||
/************************************************************************/
|
|
||||||
|
|
||||||
#ifndef RTERROR_H
|
|
||||||
#define RTERROR_H
|
|
||||||
|
|
||||||
#include <exception>
|
|
||||||
//#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
class RtError : public std::exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! Defined RtError 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.
|
|
||||||
RtError( const std::string& message, Type type = RtError::UNSPECIFIED ) throw() : message_(message), type_(type) {}
|
|
||||||
|
|
||||||
//! The destructor.
|
|
||||||
virtual ~RtError( void ) throw() {}
|
|
||||||
|
|
||||||
//! Prints thrown error message to stderr.
|
|
||||||
virtual void printMessage( ) throw() { std::fprintf(stderr,"%s\n", message_.c_str()); }
|
|
||||||
|
|
||||||
//! Returns the thrown error message type.
|
|
||||||
virtual const Type& getType(void) throw() { return type_; }
|
|
||||||
|
|
||||||
//! Returns the thrown error message string.
|
|
||||||
virtual const std::string& getMessage(void) 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_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,257 +0,0 @@
|
|||||||
/*
|
|
||||||
Steinberg Audio Stream I/O API
|
|
||||||
(c) 1996, Steinberg Soft- und Hardware GmbH
|
|
||||||
|
|
||||||
asio.cpp
|
|
||||||
|
|
||||||
asio functions entries which translate the
|
|
||||||
asio interface to the asiodrvr class methods
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include "asiosys.h" // platform definition
|
|
||||||
#include "asio.h"
|
|
||||||
|
|
||||||
#if MAC
|
|
||||||
#include "asiodrvr.h"
|
|
||||||
|
|
||||||
#pragma export on
|
|
||||||
|
|
||||||
AsioDriver *theAsioDriver = 0;
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
|
|
||||||
long main()
|
|
||||||
{
|
|
||||||
return 'ASIO';
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif WINDOWS
|
|
||||||
|
|
||||||
#include "windows.h"
|
|
||||||
#include "iasiodrv.h"
|
|
||||||
#include "asiodrivers.h"
|
|
||||||
|
|
||||||
IASIO *theAsioDriver = 0;
|
|
||||||
extern AsioDrivers *asioDrivers;
|
|
||||||
|
|
||||||
#elif SGI || SUN || BEOS || LINUX
|
|
||||||
#include "asiodrvr.h"
|
|
||||||
static AsioDriver *theAsioDriver = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------------------
|
|
||||||
ASIOError ASIOInit(ASIODriverInfo *info)
|
|
||||||
{
|
|
||||||
#if MAC || SGI || SUN || BEOS || LINUX
|
|
||||||
if(theAsioDriver)
|
|
||||||
{
|
|
||||||
delete theAsioDriver;
|
|
||||||
theAsioDriver = 0;
|
|
||||||
}
|
|
||||||
info->driverVersion = 0;
|
|
||||||
strcpy(info->name, "No ASIO Driver");
|
|
||||||
theAsioDriver = getDriver();
|
|
||||||
if(!theAsioDriver)
|
|
||||||
{
|
|
||||||
strcpy(info->errorMessage, "Not enough memory for the ASIO driver!");
|
|
||||||
return ASE_NotPresent;
|
|
||||||
}
|
|
||||||
if(!theAsioDriver->init(info->sysRef))
|
|
||||||
{
|
|
||||||
theAsioDriver->getErrorMessage(info->errorMessage);
|
|
||||||
delete theAsioDriver;
|
|
||||||
theAsioDriver = 0;
|
|
||||||
return ASE_NotPresent;
|
|
||||||
}
|
|
||||||
strcpy(info->errorMessage, "No ASIO Driver Error");
|
|
||||||
theAsioDriver->getDriverName(info->name);
|
|
||||||
info->driverVersion = theAsioDriver->getDriverVersion();
|
|
||||||
return ASE_OK;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
info->driverVersion = 0;
|
|
||||||
strcpy(info->name, "No ASIO Driver");
|
|
||||||
if(theAsioDriver) // must be loaded!
|
|
||||||
{
|
|
||||||
if(!theAsioDriver->init(info->sysRef))
|
|
||||||
{
|
|
||||||
theAsioDriver->getErrorMessage(info->errorMessage);
|
|
||||||
theAsioDriver = 0;
|
|
||||||
return ASE_NotPresent;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(info->errorMessage, "No ASIO Driver Error");
|
|
||||||
theAsioDriver->getDriverName(info->name);
|
|
||||||
info->driverVersion = theAsioDriver->getDriverVersion();
|
|
||||||
return ASE_OK;
|
|
||||||
}
|
|
||||||
return ASE_NotPresent;
|
|
||||||
|
|
||||||
#endif // !MAC
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIOExit(void)
|
|
||||||
{
|
|
||||||
if(theAsioDriver)
|
|
||||||
{
|
|
||||||
#if WINDOWS
|
|
||||||
asioDrivers->removeCurrentDriver();
|
|
||||||
#else
|
|
||||||
delete theAsioDriver;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
theAsioDriver = 0;
|
|
||||||
return ASE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIOStart(void)
|
|
||||||
{
|
|
||||||
if(!theAsioDriver)
|
|
||||||
return ASE_NotPresent;
|
|
||||||
return theAsioDriver->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIOStop(void)
|
|
||||||
{
|
|
||||||
if(!theAsioDriver)
|
|
||||||
return ASE_NotPresent;
|
|
||||||
return theAsioDriver->stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels)
|
|
||||||
{
|
|
||||||
if(!theAsioDriver)
|
|
||||||
{
|
|
||||||
*numInputChannels = *numOutputChannels = 0;
|
|
||||||
return ASE_NotPresent;
|
|
||||||
}
|
|
||||||
return theAsioDriver->getChannels(numInputChannels, numOutputChannels);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency)
|
|
||||||
{
|
|
||||||
if(!theAsioDriver)
|
|
||||||
{
|
|
||||||
*inputLatency = *outputLatency = 0;
|
|
||||||
return ASE_NotPresent;
|
|
||||||
}
|
|
||||||
return theAsioDriver->getLatencies(inputLatency, outputLatency);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity)
|
|
||||||
{
|
|
||||||
if(!theAsioDriver)
|
|
||||||
{
|
|
||||||
*minSize = *maxSize = *preferredSize = *granularity = 0;
|
|
||||||
return ASE_NotPresent;
|
|
||||||
}
|
|
||||||
return theAsioDriver->getBufferSize(minSize, maxSize, preferredSize, granularity);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate)
|
|
||||||
{
|
|
||||||
if(!theAsioDriver)
|
|
||||||
return ASE_NotPresent;
|
|
||||||
return theAsioDriver->canSampleRate(sampleRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate)
|
|
||||||
{
|
|
||||||
if(!theAsioDriver)
|
|
||||||
return ASE_NotPresent;
|
|
||||||
return theAsioDriver->getSampleRate(currentRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate)
|
|
||||||
{
|
|
||||||
if(!theAsioDriver)
|
|
||||||
return ASE_NotPresent;
|
|
||||||
return theAsioDriver->setSampleRate(sampleRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources)
|
|
||||||
{
|
|
||||||
if(!theAsioDriver)
|
|
||||||
{
|
|
||||||
*numSources = 0;
|
|
||||||
return ASE_NotPresent;
|
|
||||||
}
|
|
||||||
return theAsioDriver->getClockSources(clocks, numSources);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIOSetClockSource(long reference)
|
|
||||||
{
|
|
||||||
if(!theAsioDriver)
|
|
||||||
return ASE_NotPresent;
|
|
||||||
return theAsioDriver->setClockSource(reference);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIOGetSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)
|
|
||||||
{
|
|
||||||
if(!theAsioDriver)
|
|
||||||
return ASE_NotPresent;
|
|
||||||
return theAsioDriver->getSamplePosition(sPos, tStamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info)
|
|
||||||
{
|
|
||||||
if(!theAsioDriver)
|
|
||||||
{
|
|
||||||
info->channelGroup = -1;
|
|
||||||
info->type = ASIOSTInt16MSB;
|
|
||||||
strcpy(info->name, "None");
|
|
||||||
return ASE_NotPresent;
|
|
||||||
}
|
|
||||||
return theAsioDriver->getChannelInfo(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
|
|
||||||
long bufferSize, ASIOCallbacks *callbacks)
|
|
||||||
{
|
|
||||||
if(!theAsioDriver)
|
|
||||||
{
|
|
||||||
ASIOBufferInfo *info = bufferInfos;
|
|
||||||
for(long i = 0; i < numChannels; i++, info++)
|
|
||||||
info->buffers[0] = info->buffers[1] = 0;
|
|
||||||
return ASE_NotPresent;
|
|
||||||
}
|
|
||||||
return theAsioDriver->createBuffers(bufferInfos, numChannels, bufferSize, callbacks);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIODisposeBuffers(void)
|
|
||||||
{
|
|
||||||
if(!theAsioDriver)
|
|
||||||
return ASE_NotPresent;
|
|
||||||
return theAsioDriver->disposeBuffers();
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIOControlPanel(void)
|
|
||||||
{
|
|
||||||
if(!theAsioDriver)
|
|
||||||
return ASE_NotPresent;
|
|
||||||
return theAsioDriver->controlPanel();
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIOFuture(long selector, void *opt)
|
|
||||||
{
|
|
||||||
if(!theAsioDriver)
|
|
||||||
return ASE_NotPresent;
|
|
||||||
return theAsioDriver->future(selector, opt);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError ASIOOutputReady(void)
|
|
||||||
{
|
|
||||||
if(!theAsioDriver)
|
|
||||||
return ASE_NotPresent;
|
|
||||||
return theAsioDriver->outputReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MAC
|
|
||||||
} // extern "C"
|
|
||||||
#pragma export off
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,186 +0,0 @@
|
|||||||
#include <string.h>
|
|
||||||
#include "asiodrivers.h"
|
|
||||||
|
|
||||||
AsioDrivers* asioDrivers = 0;
|
|
||||||
|
|
||||||
bool loadAsioDriver(char *name);
|
|
||||||
|
|
||||||
bool loadAsioDriver(char *name)
|
|
||||||
{
|
|
||||||
if(!asioDrivers)
|
|
||||||
asioDrivers = new AsioDrivers();
|
|
||||||
if(asioDrivers)
|
|
||||||
return asioDrivers->loadDriver(name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#if MAC
|
|
||||||
|
|
||||||
bool resolveASIO(unsigned long aconnID);
|
|
||||||
|
|
||||||
AsioDrivers::AsioDrivers() : CodeFragments("ASIO Drivers", 'AsDr', 'Asio')
|
|
||||||
{
|
|
||||||
connID = -1;
|
|
||||||
curIndex = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
AsioDrivers::~AsioDrivers()
|
|
||||||
{
|
|
||||||
removeCurrentDriver();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AsioDrivers::getCurrentDriverName(char *name)
|
|
||||||
{
|
|
||||||
if(curIndex >= 0)
|
|
||||||
return getName(curIndex, name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
long AsioDrivers::getDriverNames(char **names, long maxDrivers)
|
|
||||||
{
|
|
||||||
for(long i = 0; i < getNumFragments() && i < maxDrivers; i++)
|
|
||||||
getName(i, names[i]);
|
|
||||||
return getNumFragments() < maxDrivers ? getNumFragments() : maxDrivers;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AsioDrivers::loadDriver(char *name)
|
|
||||||
{
|
|
||||||
char dname[64];
|
|
||||||
unsigned long newID;
|
|
||||||
|
|
||||||
for(long i = 0; i < getNumFragments(); i++)
|
|
||||||
{
|
|
||||||
if(getName(i, dname) && !strcmp(name, dname))
|
|
||||||
{
|
|
||||||
if(newInstance(i, &newID))
|
|
||||||
{
|
|
||||||
if(resolveASIO(newID))
|
|
||||||
{
|
|
||||||
if(connID != -1)
|
|
||||||
removeInstance(curIndex, connID);
|
|
||||||
curIndex = i;
|
|
||||||
connID = newID;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsioDrivers::removeCurrentDriver()
|
|
||||||
{
|
|
||||||
if(connID != -1)
|
|
||||||
removeInstance(curIndex, connID);
|
|
||||||
connID = -1;
|
|
||||||
curIndex = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#elif WINDOWS
|
|
||||||
|
|
||||||
#include "iasiodrv.h"
|
|
||||||
|
|
||||||
extern IASIO* theAsioDriver;
|
|
||||||
|
|
||||||
AsioDrivers::AsioDrivers() : AsioDriverList()
|
|
||||||
{
|
|
||||||
curIndex = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
AsioDrivers::~AsioDrivers()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AsioDrivers::getCurrentDriverName(char *name)
|
|
||||||
{
|
|
||||||
if(curIndex >= 0)
|
|
||||||
return asioGetDriverName(curIndex, name, 32) == 0 ? true : false;
|
|
||||||
name[0] = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
long AsioDrivers::getDriverNames(char **names, long maxDrivers)
|
|
||||||
{
|
|
||||||
for(long i = 0; i < asioGetNumDev() && i < maxDrivers; i++)
|
|
||||||
asioGetDriverName(i, names[i], 32);
|
|
||||||
return asioGetNumDev() < maxDrivers ? asioGetNumDev() : maxDrivers;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AsioDrivers::loadDriver(char *name)
|
|
||||||
{
|
|
||||||
char dname[64];
|
|
||||||
char curName[64];
|
|
||||||
|
|
||||||
for(long i = 0; i < asioGetNumDev(); i++)
|
|
||||||
{
|
|
||||||
if(!asioGetDriverName(i, dname, 32) && !strcmp(name, dname))
|
|
||||||
{
|
|
||||||
curName[0] = 0;
|
|
||||||
getCurrentDriverName(curName); // in case we fail...
|
|
||||||
removeCurrentDriver();
|
|
||||||
|
|
||||||
if(!asioOpenDriver(i, (void **)&theAsioDriver))
|
|
||||||
{
|
|
||||||
curIndex = i;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
theAsioDriver = 0;
|
|
||||||
if(curName[0] && strcmp(dname, curName))
|
|
||||||
loadDriver(curName); // try restore
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsioDrivers::removeCurrentDriver()
|
|
||||||
{
|
|
||||||
if(curIndex != -1)
|
|
||||||
asioCloseDriver(curIndex);
|
|
||||||
curIndex = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif SGI || BEOS
|
|
||||||
|
|
||||||
#include "asiolist.h"
|
|
||||||
|
|
||||||
AsioDrivers::AsioDrivers()
|
|
||||||
: AsioDriverList()
|
|
||||||
{
|
|
||||||
curIndex = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
AsioDrivers::~AsioDrivers()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AsioDrivers::getCurrentDriverName(char *name)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
long AsioDrivers::getDriverNames(char **names, long maxDrivers)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AsioDrivers::loadDriver(char *name)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsioDrivers::removeCurrentDriver()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
#error implement me
|
|
||||||
#endif
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
#ifndef __AsioDrivers__
|
|
||||||
#define __AsioDrivers__
|
|
||||||
|
|
||||||
#include "ginclude.h"
|
|
||||||
|
|
||||||
#if MAC
|
|
||||||
#include "CodeFragments.hpp"
|
|
||||||
|
|
||||||
class AsioDrivers : public CodeFragments
|
|
||||||
|
|
||||||
#elif WINDOWS
|
|
||||||
#include <windows.h>
|
|
||||||
#include "asiolist.h"
|
|
||||||
|
|
||||||
class AsioDrivers : public AsioDriverList
|
|
||||||
|
|
||||||
#elif SGI || BEOS
|
|
||||||
#include "asiolist.h"
|
|
||||||
|
|
||||||
class AsioDrivers : public AsioDriverList
|
|
||||||
|
|
||||||
#else
|
|
||||||
#error implement me
|
|
||||||
#endif
|
|
||||||
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AsioDrivers();
|
|
||||||
~AsioDrivers();
|
|
||||||
|
|
||||||
bool getCurrentDriverName(char *name);
|
|
||||||
long getDriverNames(char **names, long maxDrivers);
|
|
||||||
bool loadDriver(char *name);
|
|
||||||
void removeCurrentDriver();
|
|
||||||
long getCurrentDriverIndex() {return curIndex;}
|
|
||||||
protected:
|
|
||||||
unsigned long connID;
|
|
||||||
long curIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
Steinberg Audio Stream I/O API
|
|
||||||
(c) 1996, Steinberg Soft- und Hardware GmbH
|
|
||||||
charlie (May 1996)
|
|
||||||
|
|
||||||
asiodrvr.h
|
|
||||||
c++ superclass to implement asio functionality. from this,
|
|
||||||
you can derive whatever required
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _asiodrvr_
|
|
||||||
#define _asiodrvr_
|
|
||||||
|
|
||||||
// cpu and os system we are running on
|
|
||||||
#include "asiosys.h"
|
|
||||||
// basic "C" interface
|
|
||||||
#include "asio.h"
|
|
||||||
|
|
||||||
class AsioDriver;
|
|
||||||
extern AsioDriver *getDriver(); // for generic constructor
|
|
||||||
|
|
||||||
#if WINDOWS
|
|
||||||
#include <windows.h>
|
|
||||||
#include "combase.h"
|
|
||||||
#include "iasiodrv.h"
|
|
||||||
class AsioDriver : public IASIO ,public CUnknown
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AsioDriver(LPUNKNOWN pUnk, HRESULT *phr);
|
|
||||||
|
|
||||||
DECLARE_IUNKNOWN
|
|
||||||
// Factory method
|
|
||||||
static CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
|
|
||||||
// IUnknown
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE NonDelegatingQueryInterface(REFIID riid,void **ppvObject);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
class AsioDriver
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AsioDriver();
|
|
||||||
#endif
|
|
||||||
virtual ~AsioDriver();
|
|
||||||
|
|
||||||
virtual ASIOBool init(void* sysRef);
|
|
||||||
virtual void getDriverName(char *name); // max 32 bytes incl. terminating zero
|
|
||||||
virtual long getDriverVersion();
|
|
||||||
virtual void getErrorMessage(char *string); // max 124 bytes incl.
|
|
||||||
|
|
||||||
virtual ASIOError start();
|
|
||||||
virtual ASIOError stop();
|
|
||||||
|
|
||||||
virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels);
|
|
||||||
virtual ASIOError getLatencies(long *inputLatency, long *outputLatency);
|
|
||||||
virtual ASIOError getBufferSize(long *minSize, long *maxSize,
|
|
||||||
long *preferredSize, long *granularity);
|
|
||||||
|
|
||||||
virtual ASIOError canSampleRate(ASIOSampleRate sampleRate);
|
|
||||||
virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate);
|
|
||||||
virtual ASIOError setSampleRate(ASIOSampleRate sampleRate);
|
|
||||||
virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources);
|
|
||||||
virtual ASIOError setClockSource(long reference);
|
|
||||||
|
|
||||||
virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp);
|
|
||||||
virtual ASIOError getChannelInfo(ASIOChannelInfo *info);
|
|
||||||
|
|
||||||
virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
|
|
||||||
long bufferSize, ASIOCallbacks *callbacks);
|
|
||||||
virtual ASIOError disposeBuffers();
|
|
||||||
|
|
||||||
virtual ASIOError controlPanel();
|
|
||||||
virtual ASIOError future(long selector, void *opt);
|
|
||||||
virtual ASIOError outputReady();
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
@ -1,268 +0,0 @@
|
|||||||
#include <windows.h>
|
|
||||||
#include "iasiodrv.h"
|
|
||||||
#include "asiolist.h"
|
|
||||||
|
|
||||||
#define ASIODRV_DESC "description"
|
|
||||||
#define INPROC_SERVER "InprocServer32"
|
|
||||||
#define ASIO_PATH "software\\asio"
|
|
||||||
#define COM_CLSID "clsid"
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// Local Functions
|
|
||||||
// ******************************************************************
|
|
||||||
static LONG findDrvPath (char *clsidstr,char *dllpath,int dllpathsize)
|
|
||||||
{
|
|
||||||
HKEY hkEnum,hksub,hkpath;
|
|
||||||
char databuf[512];
|
|
||||||
LONG cr,rc = -1;
|
|
||||||
DWORD datatype,datasize;
|
|
||||||
DWORD index;
|
|
||||||
OFSTRUCT ofs;
|
|
||||||
HFILE hfile;
|
|
||||||
BOOL found = FALSE;
|
|
||||||
|
|
||||||
CharLowerBuff(clsidstr,strlen(clsidstr));
|
|
||||||
if ((cr = RegOpenKey(HKEY_CLASSES_ROOT,COM_CLSID,&hkEnum)) == ERROR_SUCCESS) {
|
|
||||||
|
|
||||||
index = 0;
|
|
||||||
while (cr == ERROR_SUCCESS && !found) {
|
|
||||||
cr = RegEnumKey(hkEnum,index++,(LPTSTR)databuf,512);
|
|
||||||
if (cr == ERROR_SUCCESS) {
|
|
||||||
CharLowerBuff(databuf,strlen(databuf));
|
|
||||||
if (!(strcmp(databuf,clsidstr))) {
|
|
||||||
if ((cr = RegOpenKeyEx(hkEnum,(LPCTSTR)databuf,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
|
|
||||||
if ((cr = RegOpenKeyEx(hksub,(LPCTSTR)INPROC_SERVER,0,KEY_READ,&hkpath)) == ERROR_SUCCESS) {
|
|
||||||
datatype = REG_SZ; datasize = (DWORD)dllpathsize;
|
|
||||||
cr = RegQueryValueEx(hkpath,0,0,&datatype,(LPBYTE)dllpath,&datasize);
|
|
||||||
if (cr == ERROR_SUCCESS) {
|
|
||||||
memset(&ofs,0,sizeof(OFSTRUCT));
|
|
||||||
ofs.cBytes = sizeof(OFSTRUCT);
|
|
||||||
hfile = OpenFile(dllpath,&ofs,OF_EXIST);
|
|
||||||
if (hfile) rc = 0;
|
|
||||||
}
|
|
||||||
RegCloseKey(hkpath);
|
|
||||||
}
|
|
||||||
RegCloseKey(hksub);
|
|
||||||
}
|
|
||||||
found = TRUE; // break out
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RegCloseKey(hkEnum);
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static LPASIODRVSTRUCT newDrvStruct (HKEY hkey,char *keyname,int drvID,LPASIODRVSTRUCT lpdrv)
|
|
||||||
{
|
|
||||||
HKEY hksub;
|
|
||||||
char databuf[256];
|
|
||||||
char dllpath[MAXPATHLEN];
|
|
||||||
WORD wData[100];
|
|
||||||
CLSID clsid;
|
|
||||||
DWORD datatype,datasize;
|
|
||||||
LONG cr,rc;
|
|
||||||
|
|
||||||
if (!lpdrv) {
|
|
||||||
if ((cr = RegOpenKeyEx(hkey,(LPCTSTR)keyname,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
|
|
||||||
|
|
||||||
datatype = REG_SZ; datasize = 256;
|
|
||||||
cr = RegQueryValueEx(hksub,COM_CLSID,0,&datatype,(LPBYTE)databuf,&datasize);
|
|
||||||
if (cr == ERROR_SUCCESS) {
|
|
||||||
rc = findDrvPath (databuf,dllpath,MAXPATHLEN);
|
|
||||||
if (rc == 0) {
|
|
||||||
lpdrv = new ASIODRVSTRUCT[1];
|
|
||||||
if (lpdrv) {
|
|
||||||
memset(lpdrv,0,sizeof(ASIODRVSTRUCT));
|
|
||||||
lpdrv->drvID = drvID;
|
|
||||||
MultiByteToWideChar(CP_ACP,0,(LPCSTR)databuf,-1,(LPWSTR)wData,100);
|
|
||||||
if ((cr = CLSIDFromString((LPOLESTR)wData,(LPCLSID)&clsid)) == S_OK) {
|
|
||||||
memcpy(&lpdrv->clsid,&clsid,sizeof(CLSID));
|
|
||||||
}
|
|
||||||
|
|
||||||
datatype = REG_SZ; datasize = 256;
|
|
||||||
cr = RegQueryValueEx(hksub,ASIODRV_DESC,0,&datatype,(LPBYTE)databuf,&datasize);
|
|
||||||
if (cr == ERROR_SUCCESS) {
|
|
||||||
strcpy(lpdrv->drvname,databuf);
|
|
||||||
}
|
|
||||||
else strcpy(lpdrv->drvname,keyname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RegCloseKey(hksub);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else lpdrv->next = newDrvStruct(hkey,keyname,drvID+1,lpdrv->next);
|
|
||||||
|
|
||||||
return lpdrv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void deleteDrvStruct (LPASIODRVSTRUCT lpdrv)
|
|
||||||
{
|
|
||||||
IASIO *iasio;
|
|
||||||
|
|
||||||
if (lpdrv != 0) {
|
|
||||||
deleteDrvStruct(lpdrv->next);
|
|
||||||
if (lpdrv->asiodrv) {
|
|
||||||
iasio = (IASIO *)lpdrv->asiodrv;
|
|
||||||
iasio->Release();
|
|
||||||
}
|
|
||||||
delete lpdrv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static LPASIODRVSTRUCT getDrvStruct (int drvID,LPASIODRVSTRUCT lpdrv)
|
|
||||||
{
|
|
||||||
while (lpdrv) {
|
|
||||||
if (lpdrv->drvID == drvID) return lpdrv;
|
|
||||||
lpdrv = lpdrv->next;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// ******************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
// ******************************************************************
|
|
||||||
// AsioDriverList
|
|
||||||
// ******************************************************************
|
|
||||||
AsioDriverList::AsioDriverList ()
|
|
||||||
{
|
|
||||||
HKEY hkEnum = 0;
|
|
||||||
char keyname[MAXDRVNAMELEN];
|
|
||||||
LPASIODRVSTRUCT pdl;
|
|
||||||
LONG cr;
|
|
||||||
DWORD index = 0;
|
|
||||||
BOOL fin = FALSE;
|
|
||||||
|
|
||||||
numdrv = 0;
|
|
||||||
lpdrvlist = 0;
|
|
||||||
|
|
||||||
cr = RegOpenKey(HKEY_LOCAL_MACHINE,ASIO_PATH,&hkEnum);
|
|
||||||
while (cr == ERROR_SUCCESS) {
|
|
||||||
if ((cr = RegEnumKey(hkEnum,index++,(LPTSTR)keyname,MAXDRVNAMELEN))== ERROR_SUCCESS) {
|
|
||||||
lpdrvlist = newDrvStruct (hkEnum,keyname,0,lpdrvlist);
|
|
||||||
}
|
|
||||||
else fin = TRUE;
|
|
||||||
}
|
|
||||||
if (hkEnum) RegCloseKey(hkEnum);
|
|
||||||
|
|
||||||
pdl = lpdrvlist;
|
|
||||||
while (pdl) {
|
|
||||||
numdrv++;
|
|
||||||
pdl = pdl->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numdrv) CoInitialize(0); // initialize COM
|
|
||||||
}
|
|
||||||
|
|
||||||
AsioDriverList::~AsioDriverList ()
|
|
||||||
{
|
|
||||||
if (numdrv) {
|
|
||||||
deleteDrvStruct(lpdrvlist);
|
|
||||||
CoUninitialize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LONG AsioDriverList::asioGetNumDev (VOID)
|
|
||||||
{
|
|
||||||
return (LONG)numdrv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LONG AsioDriverList::asioOpenDriver (int drvID,LPVOID *asiodrv)
|
|
||||||
{
|
|
||||||
LPASIODRVSTRUCT lpdrv = 0;
|
|
||||||
long rc;
|
|
||||||
|
|
||||||
if (!asiodrv) return DRVERR_INVALID_PARAM;
|
|
||||||
|
|
||||||
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
|
|
||||||
if (!lpdrv->asiodrv) {
|
|
||||||
rc = CoCreateInstance(lpdrv->clsid,0,CLSCTX_INPROC_SERVER,lpdrv->clsid,asiodrv);
|
|
||||||
if (rc == S_OK) {
|
|
||||||
lpdrv->asiodrv = *asiodrv;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// else if (rc == REGDB_E_CLASSNOTREG)
|
|
||||||
// strcpy (info->messageText, "Driver not registered in the Registration Database!");
|
|
||||||
}
|
|
||||||
else rc = DRVERR_DEVICE_ALREADY_OPEN;
|
|
||||||
}
|
|
||||||
else rc = DRVERR_DEVICE_NOT_FOUND;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LONG AsioDriverList::asioCloseDriver (int drvID)
|
|
||||||
{
|
|
||||||
LPASIODRVSTRUCT lpdrv = 0;
|
|
||||||
IASIO *iasio;
|
|
||||||
|
|
||||||
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
|
|
||||||
if (lpdrv->asiodrv) {
|
|
||||||
iasio = (IASIO *)lpdrv->asiodrv;
|
|
||||||
iasio->Release();
|
|
||||||
lpdrv->asiodrv = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
LONG AsioDriverList::asioGetDriverName (int drvID,char *drvname,int drvnamesize)
|
|
||||||
{
|
|
||||||
LPASIODRVSTRUCT lpdrv = 0;
|
|
||||||
|
|
||||||
if (!drvname) return DRVERR_INVALID_PARAM;
|
|
||||||
|
|
||||||
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
|
|
||||||
if (strlen(lpdrv->drvname) < (unsigned int)drvnamesize) {
|
|
||||||
strcpy(drvname,lpdrv->drvname);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
memcpy(drvname,lpdrv->drvname,drvnamesize-4);
|
|
||||||
drvname[drvnamesize-4] = '.';
|
|
||||||
drvname[drvnamesize-3] = '.';
|
|
||||||
drvname[drvnamesize-2] = '.';
|
|
||||||
drvname[drvnamesize-1] = 0;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return DRVERR_DEVICE_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
LONG AsioDriverList::asioGetDriverPath (int drvID,char *dllpath,int dllpathsize)
|
|
||||||
{
|
|
||||||
LPASIODRVSTRUCT lpdrv = 0;
|
|
||||||
|
|
||||||
if (!dllpath) return DRVERR_INVALID_PARAM;
|
|
||||||
|
|
||||||
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
|
|
||||||
if (strlen(lpdrv->dllpath) < (unsigned int)dllpathsize) {
|
|
||||||
strcpy(dllpath,lpdrv->dllpath);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
dllpath[0] = 0;
|
|
||||||
return DRVERR_INVALID_PARAM;
|
|
||||||
}
|
|
||||||
return DRVERR_DEVICE_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
LONG AsioDriverList::asioGetDriverCLSID (int drvID,CLSID *clsid)
|
|
||||||
{
|
|
||||||
LPASIODRVSTRUCT lpdrv = 0;
|
|
||||||
|
|
||||||
if (!clsid) return DRVERR_INVALID_PARAM;
|
|
||||||
|
|
||||||
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
|
|
||||||
memcpy(clsid,&lpdrv->clsid,sizeof(CLSID));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return DRVERR_DEVICE_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
#ifndef __asiolist__
|
|
||||||
#define __asiolist__
|
|
||||||
|
|
||||||
#define DRVERR -5000
|
|
||||||
#define DRVERR_INVALID_PARAM DRVERR-1
|
|
||||||
#define DRVERR_DEVICE_ALREADY_OPEN DRVERR-2
|
|
||||||
#define DRVERR_DEVICE_NOT_FOUND DRVERR-3
|
|
||||||
|
|
||||||
#define MAXPATHLEN 512
|
|
||||||
#define MAXDRVNAMELEN 128
|
|
||||||
|
|
||||||
struct asiodrvstruct
|
|
||||||
{
|
|
||||||
int drvID;
|
|
||||||
CLSID clsid;
|
|
||||||
char dllpath[MAXPATHLEN];
|
|
||||||
char drvname[MAXDRVNAMELEN];
|
|
||||||
LPVOID asiodrv;
|
|
||||||
struct asiodrvstruct *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct asiodrvstruct ASIODRVSTRUCT;
|
|
||||||
typedef ASIODRVSTRUCT *LPASIODRVSTRUCT;
|
|
||||||
|
|
||||||
class AsioDriverList {
|
|
||||||
public:
|
|
||||||
AsioDriverList();
|
|
||||||
~AsioDriverList();
|
|
||||||
|
|
||||||
LONG asioOpenDriver (int,VOID **);
|
|
||||||
LONG asioCloseDriver (int);
|
|
||||||
|
|
||||||
// nice to have
|
|
||||||
LONG asioGetNumDev (VOID);
|
|
||||||
LONG asioGetDriverName (int,char *,int);
|
|
||||||
LONG asioGetDriverPath (int,char *,int);
|
|
||||||
LONG asioGetDriverCLSID (int,CLSID *);
|
|
||||||
|
|
||||||
// or use directly access
|
|
||||||
LPASIODRVSTRUCT lpdrvlist;
|
|
||||||
int numdrv;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef class AsioDriverList *LPASIODRIVERLIST;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,82 +0,0 @@
|
|||||||
#ifndef __asiosys__
|
|
||||||
#define __asiosys__
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#undef MAC
|
|
||||||
#define PPC 0
|
|
||||||
#define WINDOWS 1
|
|
||||||
#define SGI 0
|
|
||||||
#define SUN 0
|
|
||||||
#define LINUX 0
|
|
||||||
#define BEOS 0
|
|
||||||
|
|
||||||
#define NATIVE_INT64 0
|
|
||||||
#define IEEE754_64FLOAT 1
|
|
||||||
|
|
||||||
#elif BEOS
|
|
||||||
#define MAC 0
|
|
||||||
#define PPC 0
|
|
||||||
#define WINDOWS 0
|
|
||||||
#define PC 0
|
|
||||||
#define SGI 0
|
|
||||||
#define SUN 0
|
|
||||||
#define LINUX 0
|
|
||||||
|
|
||||||
#define NATIVE_INT64 0
|
|
||||||
#define IEEE754_64FLOAT 1
|
|
||||||
|
|
||||||
#ifndef DEBUG
|
|
||||||
#define DEBUG 0
|
|
||||||
#if DEBUG
|
|
||||||
void DEBUGGERMESSAGE(char *string);
|
|
||||||
#else
|
|
||||||
#define DEBUGGERMESSAGE(a)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#elif SGI
|
|
||||||
#define MAC 0
|
|
||||||
#define PPC 0
|
|
||||||
#define WINDOWS 0
|
|
||||||
#define PC 0
|
|
||||||
#define SUN 0
|
|
||||||
#define LINUX 0
|
|
||||||
#define BEOS 0
|
|
||||||
|
|
||||||
#define NATIVE_INT64 0
|
|
||||||
#define IEEE754_64FLOAT 1
|
|
||||||
|
|
||||||
#ifndef DEBUG
|
|
||||||
#define DEBUG 0
|
|
||||||
#if DEBUG
|
|
||||||
void DEBUGGERMESSAGE(char *string);
|
|
||||||
#else
|
|
||||||
#define DEBUGGERMESSAGE(a)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else // MAC
|
|
||||||
|
|
||||||
#define MAC 1
|
|
||||||
#define PPC 1
|
|
||||||
#define WINDOWS 0
|
|
||||||
#define PC 0
|
|
||||||
#define SGI 0
|
|
||||||
#define SUN 0
|
|
||||||
#define LINUX 0
|
|
||||||
#define BEOS 0
|
|
||||||
|
|
||||||
#define NATIVE_INT64 0
|
|
||||||
#define IEEE754_64FLOAT 1
|
|
||||||
|
|
||||||
#ifndef DEBUG
|
|
||||||
#define DEBUG 0
|
|
||||||
#if DEBUG
|
|
||||||
void DEBUGGERMESSAGE(char *string);
|
|
||||||
#else
|
|
||||||
#define DEBUGGERMESSAGE(a)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,38 +0,0 @@
|
|||||||
#ifndef __gInclude__
|
|
||||||
#define __gInclude__
|
|
||||||
|
|
||||||
#if SGI
|
|
||||||
#undef BEOS
|
|
||||||
#undef MAC
|
|
||||||
#undef WINDOWS
|
|
||||||
//
|
|
||||||
#define ASIO_BIG_ENDIAN 1
|
|
||||||
#define ASIO_CPU_MIPS 1
|
|
||||||
#elif defined WIN32
|
|
||||||
#undef BEOS
|
|
||||||
#undef MAC
|
|
||||||
#undef SGI
|
|
||||||
#define WINDOWS 1
|
|
||||||
#define ASIO_LITTLE_ENDIAN 1
|
|
||||||
#define ASIO_CPU_X86 1
|
|
||||||
#elif BEOS
|
|
||||||
#undef MAC
|
|
||||||
#undef SGI
|
|
||||||
#undef WINDOWS
|
|
||||||
#define ASIO_LITTLE_ENDIAN 1
|
|
||||||
#define ASIO_CPU_X86 1
|
|
||||||
//
|
|
||||||
#else
|
|
||||||
#define MAC 1
|
|
||||||
#undef BEOS
|
|
||||||
#undef WINDOWS
|
|
||||||
#undef SGI
|
|
||||||
#define ASIO_BIG_ENDIAN 1
|
|
||||||
#define ASIO_CPU_PPC 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// always
|
|
||||||
#define NATIVE_INT64 0
|
|
||||||
#define IEEE754_64FLOAT 1
|
|
||||||
|
|
||||||
#endif // __gInclude__
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
#include "asiosys.h"
|
|
||||||
#include "asio.h"
|
|
||||||
|
|
||||||
/* Forward Declarations */
|
|
||||||
|
|
||||||
#ifndef __ASIODRIVER_FWD_DEFINED__
|
|
||||||
#define __ASIODRIVER_FWD_DEFINED__
|
|
||||||
typedef interface IASIO IASIO;
|
|
||||||
#endif /* __ASIODRIVER_FWD_DEFINED__ */
|
|
||||||
|
|
||||||
interface IASIO : public IUnknown
|
|
||||||
{
|
|
||||||
|
|
||||||
virtual ASIOBool init(void *sysHandle) = 0;
|
|
||||||
virtual void getDriverName(char *name) = 0;
|
|
||||||
virtual long getDriverVersion() = 0;
|
|
||||||
virtual void getErrorMessage(char *string) = 0;
|
|
||||||
virtual ASIOError start() = 0;
|
|
||||||
virtual ASIOError stop() = 0;
|
|
||||||
virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels) = 0;
|
|
||||||
virtual ASIOError getLatencies(long *inputLatency, long *outputLatency) = 0;
|
|
||||||
virtual ASIOError getBufferSize(long *minSize, long *maxSize,
|
|
||||||
long *preferredSize, long *granularity) = 0;
|
|
||||||
virtual ASIOError canSampleRate(ASIOSampleRate sampleRate) = 0;
|
|
||||||
virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate) = 0;
|
|
||||||
virtual ASIOError setSampleRate(ASIOSampleRate sampleRate) = 0;
|
|
||||||
virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources) = 0;
|
|
||||||
virtual ASIOError setClockSource(long reference) = 0;
|
|
||||||
virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0;
|
|
||||||
virtual ASIOError getChannelInfo(ASIOChannelInfo *info) = 0;
|
|
||||||
virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
|
|
||||||
long bufferSize, ASIOCallbacks *callbacks) = 0;
|
|
||||||
virtual ASIOError disposeBuffers() = 0;
|
|
||||||
virtual ASIOError controlPanel() = 0;
|
|
||||||
virtual ASIOError future(long selector,void *opt) = 0;
|
|
||||||
virtual ASIOError outputReady() = 0;
|
|
||||||
};
|
|
||||||
@ -1,563 +0,0 @@
|
|||||||
/*
|
|
||||||
IASIOThiscallResolver.cpp see the comments in iasiothiscallresolver.h for
|
|
||||||
the top level description - this comment describes the technical details of
|
|
||||||
the implementation.
|
|
||||||
|
|
||||||
The latest version of this file is available from:
|
|
||||||
http://www.audiomulch.com/~rossb/code/calliasio
|
|
||||||
|
|
||||||
please email comments to Ross Bencina <rossb@audiomulch.com>
|
|
||||||
|
|
||||||
BACKGROUND
|
|
||||||
|
|
||||||
The IASIO interface declared in the Steinberg ASIO 2 SDK declares
|
|
||||||
functions with no explicit calling convention. This causes MSVC++ to default
|
|
||||||
to using the thiscall convention, which is a proprietary convention not
|
|
||||||
implemented by some non-microsoft compilers - notably borland BCC,
|
|
||||||
C++Builder, and gcc. MSVC++ is the defacto standard compiler used by
|
|
||||||
Steinberg. As a result of this situation, the ASIO sdk will compile with
|
|
||||||
any compiler, however attempting to execute the compiled code will cause a
|
|
||||||
crash due to different default calling conventions on non-Microsoft
|
|
||||||
compilers.
|
|
||||||
|
|
||||||
IASIOThiscallResolver solves the problem by providing an adapter class that
|
|
||||||
delegates to the IASIO interface using the correct calling convention
|
|
||||||
(thiscall). Due to the lack of support for thiscall in the Borland and GCC
|
|
||||||
compilers, the calls have been implemented in assembly language.
|
|
||||||
|
|
||||||
A number of macros are defined for thiscall function calls with different
|
|
||||||
numbers of parameters, with and without return values - it may be possible
|
|
||||||
to modify the format of these macros to make them work with other inline
|
|
||||||
assemblers.
|
|
||||||
|
|
||||||
|
|
||||||
THISCALL DEFINITION
|
|
||||||
|
|
||||||
A number of definitions of the thiscall calling convention are floating
|
|
||||||
around the internet. The following definition has been validated against
|
|
||||||
output from the MSVC++ compiler:
|
|
||||||
|
|
||||||
For non-vararg functions, thiscall works as follows: the object (this)
|
|
||||||
pointer is passed in ECX. All arguments are passed on the stack in
|
|
||||||
right to left order. The return value is placed in EAX. The callee
|
|
||||||
clears the passed arguments from the stack.
|
|
||||||
|
|
||||||
|
|
||||||
FINDING FUNCTION POINTERS FROM AN IASIO POINTER
|
|
||||||
|
|
||||||
The first field of a COM object is a pointer to its vtble. Thus a pointer
|
|
||||||
to an object implementing the IASIO interface also points to a pointer to
|
|
||||||
that object's vtbl. The vtble is a table of function pointers for all of
|
|
||||||
the virtual functions exposed by the implemented interfaces.
|
|
||||||
|
|
||||||
If we consider a variable declared as a pointer to IASO:
|
|
||||||
|
|
||||||
IASIO *theAsioDriver
|
|
||||||
|
|
||||||
theAsioDriver points to:
|
|
||||||
|
|
||||||
object implementing IASIO
|
|
||||||
{
|
|
||||||
IASIOvtbl *vtbl
|
|
||||||
other data
|
|
||||||
}
|
|
||||||
|
|
||||||
in other words, theAsioDriver points to a pointer to an IASIOvtbl
|
|
||||||
|
|
||||||
vtbl points to a table of function pointers:
|
|
||||||
|
|
||||||
IASIOvtbl ( interface IASIO : public IUnknown )
|
|
||||||
{
|
|
||||||
(IUnknown functions)
|
|
||||||
0 virtual HRESULT STDMETHODCALLTYPE (*QueryInterface)(REFIID riid, void **ppv) = 0;
|
|
||||||
4 virtual ULONG STDMETHODCALLTYPE (*AddRef)() = 0;
|
|
||||||
8 virtual ULONG STDMETHODCALLTYPE (*Release)() = 0;
|
|
||||||
|
|
||||||
(IASIO functions)
|
|
||||||
12 virtual ASIOBool (*init)(void *sysHandle) = 0;
|
|
||||||
16 virtual void (*getDriverName)(char *name) = 0;
|
|
||||||
20 virtual long (*getDriverVersion)() = 0;
|
|
||||||
24 virtual void (*getErrorMessage)(char *string) = 0;
|
|
||||||
28 virtual ASIOError (*start)() = 0;
|
|
||||||
32 virtual ASIOError (*stop)() = 0;
|
|
||||||
36 virtual ASIOError (*getChannels)(long *numInputChannels, long *numOutputChannels) = 0;
|
|
||||||
40 virtual ASIOError (*getLatencies)(long *inputLatency, long *outputLatency) = 0;
|
|
||||||
44 virtual ASIOError (*getBufferSize)(long *minSize, long *maxSize,
|
|
||||||
long *preferredSize, long *granularity) = 0;
|
|
||||||
48 virtual ASIOError (*canSampleRate)(ASIOSampleRate sampleRate) = 0;
|
|
||||||
52 virtual ASIOError (*getSampleRate)(ASIOSampleRate *sampleRate) = 0;
|
|
||||||
56 virtual ASIOError (*setSampleRate)(ASIOSampleRate sampleRate) = 0;
|
|
||||||
60 virtual ASIOError (*getClockSources)(ASIOClockSource *clocks, long *numSources) = 0;
|
|
||||||
64 virtual ASIOError (*setClockSource)(long reference) = 0;
|
|
||||||
68 virtual ASIOError (*getSamplePosition)(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0;
|
|
||||||
72 virtual ASIOError (*getChannelInfo)(ASIOChannelInfo *info) = 0;
|
|
||||||
76 virtual ASIOError (*createBuffers)(ASIOBufferInfo *bufferInfos, long numChannels,
|
|
||||||
long bufferSize, ASIOCallbacks *callbacks) = 0;
|
|
||||||
80 virtual ASIOError (*disposeBuffers)() = 0;
|
|
||||||
84 virtual ASIOError (*controlPanel)() = 0;
|
|
||||||
88 virtual ASIOError (*future)(long selector,void *opt) = 0;
|
|
||||||
92 virtual ASIOError (*outputReady)() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
The numbers in the left column show the byte offset of each function ptr
|
|
||||||
from the beginning of the vtbl. These numbers are used in the code below
|
|
||||||
to select different functions.
|
|
||||||
|
|
||||||
In order to find the address of a particular function, theAsioDriver
|
|
||||||
must first be dereferenced to find the value of the vtbl pointer:
|
|
||||||
|
|
||||||
mov eax, theAsioDriver
|
|
||||||
mov edx, [theAsioDriver] // edx now points to vtbl[0]
|
|
||||||
|
|
||||||
Then an offset must be added to the vtbl pointer to select a
|
|
||||||
particular function, for example vtbl+44 points to the slot containing
|
|
||||||
a pointer to the getBufferSize function.
|
|
||||||
|
|
||||||
Finally vtbl+x must be dereferenced to obtain the value of the function
|
|
||||||
pointer stored in that address:
|
|
||||||
|
|
||||||
call [edx+44] // call the function pointed to by
|
|
||||||
// the value in the getBufferSize field of the vtbl
|
|
||||||
|
|
||||||
|
|
||||||
SEE ALSO
|
|
||||||
|
|
||||||
Martin Fay's OpenASIO DLL at http://www.martinfay.com solves the same
|
|
||||||
problem by providing a new COM interface which wraps IASIO with an
|
|
||||||
interface that uses portable calling conventions. OpenASIO must be compiled
|
|
||||||
with MSVC, and requires that you ship the OpenASIO DLL with your
|
|
||||||
application.
|
|
||||||
|
|
||||||
|
|
||||||
ACKNOWLEDGEMENTS
|
|
||||||
|
|
||||||
Ross Bencina: worked out the thiscall details above, wrote the original
|
|
||||||
Borland asm macros, and a patch for asio.cpp (which is no longer needed).
|
|
||||||
Thanks to Martin Fay for introducing me to the issues discussed here,
|
|
||||||
and to Rene G. Ceballos for assisting with asm dumps from MSVC++.
|
|
||||||
|
|
||||||
Antti Silvast: converted the original calliasio to work with gcc and NASM
|
|
||||||
by implementing the asm code in a separate file.
|
|
||||||
|
|
||||||
Fraser Adams: modified the original calliasio containing the Borland inline
|
|
||||||
asm to add inline asm for gcc i.e. Intel syntax for Borland and AT&T syntax
|
|
||||||
for gcc. This seems a neater approach for gcc than to have a separate .asm
|
|
||||||
file and it means that we only need one version of the thiscall patch.
|
|
||||||
|
|
||||||
Fraser Adams: rewrote the original calliasio patch in the form of the
|
|
||||||
IASIOThiscallResolver class in order to avoid modifications to files from
|
|
||||||
the Steinberg SDK, which may have had potential licence issues.
|
|
||||||
|
|
||||||
Andrew Baldwin: contributed fixes for compatibility problems with more
|
|
||||||
recent versions of the gcc assembler.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// We only need IASIOThiscallResolver at all if we are on Win32. For other
|
|
||||||
// platforms we simply bypass the IASIOThiscallResolver definition to allow us
|
|
||||||
// to be safely #include'd whatever the platform to keep client code portable
|
|
||||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
|
||||||
|
|
||||||
|
|
||||||
// If microsoft compiler we can call IASIO directly so IASIOThiscallResolver
|
|
||||||
// is not used.
|
|
||||||
#if !defined(_MSC_VER)
|
|
||||||
|
|
||||||
|
|
||||||
#include <new>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
// We have a mechanism in iasiothiscallresolver.h to ensure that asio.h is
|
|
||||||
// #include'd before it in client code, we do NOT want to do this test here.
|
|
||||||
#define iasiothiscallresolver_sourcefile 1
|
|
||||||
#include "iasiothiscallresolver.h"
|
|
||||||
#undef iasiothiscallresolver_sourcefile
|
|
||||||
|
|
||||||
// iasiothiscallresolver.h redefines ASIOInit for clients, but we don't want
|
|
||||||
// this macro defined in this translation unit.
|
|
||||||
#undef ASIOInit
|
|
||||||
|
|
||||||
|
|
||||||
// theAsioDriver is a global pointer to the current IASIO instance which the
|
|
||||||
// ASIO SDK uses to perform all actions on the IASIO interface. We substitute
|
|
||||||
// our own forwarding interface into this pointer.
|
|
||||||
extern IASIO* theAsioDriver;
|
|
||||||
|
|
||||||
|
|
||||||
// The following macros define the inline assembler for BORLAND first then gcc
|
|
||||||
|
|
||||||
#if defined(__BCPLUSPLUS__) || defined(__BORLANDC__)
|
|
||||||
|
|
||||||
|
|
||||||
#define CALL_THISCALL_0( resultName, thisPtr, funcOffset )\
|
|
||||||
void *this_ = (thisPtr); \
|
|
||||||
__asm { \
|
|
||||||
mov ecx, this_ ; \
|
|
||||||
mov eax, [ecx] ; \
|
|
||||||
call [eax+funcOffset] ; \
|
|
||||||
mov resultName, eax ; \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define CALL_VOID_THISCALL_1( thisPtr, funcOffset, param1 )\
|
|
||||||
void *this_ = (thisPtr); \
|
|
||||||
__asm { \
|
|
||||||
mov eax, param1 ; \
|
|
||||||
push eax ; \
|
|
||||||
mov ecx, this_ ; \
|
|
||||||
mov eax, [ecx] ; \
|
|
||||||
call [eax+funcOffset] ; \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define CALL_THISCALL_1( resultName, thisPtr, funcOffset, param1 )\
|
|
||||||
void *this_ = (thisPtr); \
|
|
||||||
__asm { \
|
|
||||||
mov eax, param1 ; \
|
|
||||||
push eax ; \
|
|
||||||
mov ecx, this_ ; \
|
|
||||||
mov eax, [ecx] ; \
|
|
||||||
call [eax+funcOffset] ; \
|
|
||||||
mov resultName, eax ; \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define CALL_THISCALL_1_DOUBLE( resultName, thisPtr, funcOffset, param1 )\
|
|
||||||
void *this_ = (thisPtr); \
|
|
||||||
void *doubleParamPtr_ (¶m1); \
|
|
||||||
__asm { \
|
|
||||||
mov eax, doubleParamPtr_ ; \
|
|
||||||
push [eax+4] ; \
|
|
||||||
push [eax] ; \
|
|
||||||
mov ecx, this_ ; \
|
|
||||||
mov eax, [ecx] ; \
|
|
||||||
call [eax+funcOffset] ; \
|
|
||||||
mov resultName, eax ; \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define CALL_THISCALL_2( resultName, thisPtr, funcOffset, param1, param2 )\
|
|
||||||
void *this_ = (thisPtr); \
|
|
||||||
__asm { \
|
|
||||||
mov eax, param2 ; \
|
|
||||||
push eax ; \
|
|
||||||
mov eax, param1 ; \
|
|
||||||
push eax ; \
|
|
||||||
mov ecx, this_ ; \
|
|
||||||
mov eax, [ecx] ; \
|
|
||||||
call [eax+funcOffset] ; \
|
|
||||||
mov resultName, eax ; \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define CALL_THISCALL_4( resultName, thisPtr, funcOffset, param1, param2, param3, param4 )\
|
|
||||||
void *this_ = (thisPtr); \
|
|
||||||
__asm { \
|
|
||||||
mov eax, param4 ; \
|
|
||||||
push eax ; \
|
|
||||||
mov eax, param3 ; \
|
|
||||||
push eax ; \
|
|
||||||
mov eax, param2 ; \
|
|
||||||
push eax ; \
|
|
||||||
mov eax, param1 ; \
|
|
||||||
push eax ; \
|
|
||||||
mov ecx, this_ ; \
|
|
||||||
mov eax, [ecx] ; \
|
|
||||||
call [eax+funcOffset] ; \
|
|
||||||
mov resultName, eax ; \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
|
|
||||||
|
|
||||||
#define CALL_THISCALL_0( resultName, thisPtr, funcOffset ) \
|
|
||||||
__asm__ __volatile__ ("movl (%1), %%edx\n\t" \
|
|
||||||
"call *"#funcOffset"(%%edx)\n\t" \
|
|
||||||
:"=a"(resultName) /* Output Operands */ \
|
|
||||||
:"c"(thisPtr) /* Input Operands */ \
|
|
||||||
); \
|
|
||||||
|
|
||||||
|
|
||||||
#define CALL_VOID_THISCALL_1( thisPtr, funcOffset, param1 ) \
|
|
||||||
__asm__ __volatile__ ("pushl %0\n\t" \
|
|
||||||
"movl (%1), %%edx\n\t" \
|
|
||||||
"call *"#funcOffset"(%%edx)\n\t" \
|
|
||||||
: /* Output Operands */ \
|
|
||||||
:"r"(param1), /* Input Operands */ \
|
|
||||||
"c"(thisPtr) \
|
|
||||||
); \
|
|
||||||
|
|
||||||
|
|
||||||
#define CALL_THISCALL_1( resultName, thisPtr, funcOffset, param1 ) \
|
|
||||||
__asm__ __volatile__ ("pushl %1\n\t" \
|
|
||||||
"movl (%2), %%edx\n\t" \
|
|
||||||
"call *"#funcOffset"(%%edx)\n\t" \
|
|
||||||
:"=a"(resultName) /* Output Operands */ \
|
|
||||||
:"r"(param1), /* Input Operands */ \
|
|
||||||
"c"(thisPtr) \
|
|
||||||
); \
|
|
||||||
|
|
||||||
|
|
||||||
#define CALL_THISCALL_1_DOUBLE( resultName, thisPtr, funcOffset, param1 ) \
|
|
||||||
__asm__ __volatile__ ("pushl 4(%1)\n\t" \
|
|
||||||
"pushl (%1)\n\t" \
|
|
||||||
"movl (%2), %%edx\n\t" \
|
|
||||||
"call *"#funcOffset"(%%edx);\n\t" \
|
|
||||||
:"=a"(resultName) /* Output Operands */ \
|
|
||||||
:"a"(¶m1), /* Input Operands */ \
|
|
||||||
/* Note: Using "r" above instead of "a" fails */ \
|
|
||||||
/* when using GCC 3.3.3, and maybe later versions*/\
|
|
||||||
"c"(thisPtr) \
|
|
||||||
); \
|
|
||||||
|
|
||||||
|
|
||||||
#define CALL_THISCALL_2( resultName, thisPtr, funcOffset, param1, param2 ) \
|
|
||||||
__asm__ __volatile__ ("pushl %1\n\t" \
|
|
||||||
"pushl %2\n\t" \
|
|
||||||
"movl (%3), %%edx\n\t" \
|
|
||||||
"call *"#funcOffset"(%%edx)\n\t" \
|
|
||||||
:"=a"(resultName) /* Output Operands */ \
|
|
||||||
:"r"(param2), /* Input Operands */ \
|
|
||||||
"r"(param1), \
|
|
||||||
"c"(thisPtr) \
|
|
||||||
); \
|
|
||||||
|
|
||||||
|
|
||||||
#define CALL_THISCALL_4( resultName, thisPtr, funcOffset, param1, param2, param3, param4 )\
|
|
||||||
__asm__ __volatile__ ("pushl %1\n\t" \
|
|
||||||
"pushl %2\n\t" \
|
|
||||||
"pushl %3\n\t" \
|
|
||||||
"pushl %4\n\t" \
|
|
||||||
"movl (%5), %%edx\n\t" \
|
|
||||||
"call *"#funcOffset"(%%edx)\n\t" \
|
|
||||||
:"=a"(resultName) /* Output Operands */ \
|
|
||||||
:"r"(param4), /* Input Operands */ \
|
|
||||||
"r"(param3), \
|
|
||||||
"r"(param2), \
|
|
||||||
"r"(param1), \
|
|
||||||
"c"(thisPtr) \
|
|
||||||
); \
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Our static singleton instance.
|
|
||||||
IASIOThiscallResolver IASIOThiscallResolver::instance;
|
|
||||||
|
|
||||||
// Constructor called to initialize static Singleton instance above. Note that
|
|
||||||
// it is important not to clear that_ incase it has already been set by the call
|
|
||||||
// to placement new in ASIOInit().
|
|
||||||
IASIOThiscallResolver::IASIOThiscallResolver()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructor called from ASIOInit() below
|
|
||||||
IASIOThiscallResolver::IASIOThiscallResolver(IASIO* that)
|
|
||||||
: that_( that )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implement IUnknown methods as assert(false). IASIOThiscallResolver is not
|
|
||||||
// really a COM object, just a wrapper which will work with the ASIO SDK.
|
|
||||||
// If you wanted to use ASIO without the SDK you might want to implement COM
|
|
||||||
// aggregation in these methods.
|
|
||||||
HRESULT STDMETHODCALLTYPE IASIOThiscallResolver::QueryInterface(REFIID riid, void **ppv)
|
|
||||||
{
|
|
||||||
(void)riid; // suppress unused variable warning
|
|
||||||
|
|
||||||
assert( false ); // this function should never be called by the ASIO SDK.
|
|
||||||
|
|
||||||
*ppv = NULL;
|
|
||||||
return E_NOINTERFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG STDMETHODCALLTYPE IASIOThiscallResolver::AddRef()
|
|
||||||
{
|
|
||||||
assert( false ); // this function should never be called by the ASIO SDK.
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG STDMETHODCALLTYPE IASIOThiscallResolver::Release()
|
|
||||||
{
|
|
||||||
assert( false ); // this function should never be called by the ASIO SDK.
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Implement the IASIO interface methods by performing the vptr manipulation
|
|
||||||
// described above then delegating to the real implementation.
|
|
||||||
ASIOBool IASIOThiscallResolver::init(void *sysHandle)
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_1( result, that_, 12, sysHandle );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IASIOThiscallResolver::getDriverName(char *name)
|
|
||||||
{
|
|
||||||
CALL_VOID_THISCALL_1( that_, 16, name );
|
|
||||||
}
|
|
||||||
|
|
||||||
long IASIOThiscallResolver::getDriverVersion()
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_0( result, that_, 20 );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IASIOThiscallResolver::getErrorMessage(char *string)
|
|
||||||
{
|
|
||||||
CALL_VOID_THISCALL_1( that_, 24, string );
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError IASIOThiscallResolver::start()
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_0( result, that_, 28 );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError IASIOThiscallResolver::stop()
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_0( result, that_, 32 );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError IASIOThiscallResolver::getChannels(long *numInputChannels, long *numOutputChannels)
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_2( result, that_, 36, numInputChannels, numOutputChannels );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError IASIOThiscallResolver::getLatencies(long *inputLatency, long *outputLatency)
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_2( result, that_, 40, inputLatency, outputLatency );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError IASIOThiscallResolver::getBufferSize(long *minSize, long *maxSize,
|
|
||||||
long *preferredSize, long *granularity)
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_4( result, that_, 44, minSize, maxSize, preferredSize, granularity );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError IASIOThiscallResolver::canSampleRate(ASIOSampleRate sampleRate)
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_1_DOUBLE( result, that_, 48, sampleRate );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError IASIOThiscallResolver::getSampleRate(ASIOSampleRate *sampleRate)
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_1( result, that_, 52, sampleRate );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError IASIOThiscallResolver::setSampleRate(ASIOSampleRate sampleRate)
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_1_DOUBLE( result, that_, 56, sampleRate );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError IASIOThiscallResolver::getClockSources(ASIOClockSource *clocks, long *numSources)
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_2( result, that_, 60, clocks, numSources );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError IASIOThiscallResolver::setClockSource(long reference)
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_1( result, that_, 64, reference );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError IASIOThiscallResolver::getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_2( result, that_, 68, sPos, tStamp );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError IASIOThiscallResolver::getChannelInfo(ASIOChannelInfo *info)
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_1( result, that_, 72, info );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError IASIOThiscallResolver::createBuffers(ASIOBufferInfo *bufferInfos,
|
|
||||||
long numChannels, long bufferSize, ASIOCallbacks *callbacks)
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_4( result, that_, 76, bufferInfos, numChannels, bufferSize, callbacks );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError IASIOThiscallResolver::disposeBuffers()
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_0( result, that_, 80 );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError IASIOThiscallResolver::controlPanel()
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_0( result, that_, 84 );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError IASIOThiscallResolver::future(long selector,void *opt)
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_2( result, that_, 88, selector, opt );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASIOError IASIOThiscallResolver::outputReady()
|
|
||||||
{
|
|
||||||
ASIOBool result;
|
|
||||||
CALL_THISCALL_0( result, that_, 92 );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Implement our substitute ASIOInit() method
|
|
||||||
ASIOError IASIOThiscallResolver::ASIOInit(ASIODriverInfo *info)
|
|
||||||
{
|
|
||||||
// To ensure that our instance's vptr is correctly constructed, even if
|
|
||||||
// ASIOInit is called prior to main(), we explicitly call its constructor
|
|
||||||
// (potentially over the top of an existing instance). Note that this is
|
|
||||||
// pretty ugly, and is only safe because IASIOThiscallResolver has no
|
|
||||||
// destructor and contains no objects with destructors.
|
|
||||||
new((void*)&instance) IASIOThiscallResolver( theAsioDriver );
|
|
||||||
|
|
||||||
// Interpose between ASIO client code and the real driver.
|
|
||||||
theAsioDriver = &instance;
|
|
||||||
|
|
||||||
// Note that we never need to switch theAsioDriver back to point to the
|
|
||||||
// real driver because theAsioDriver is reset to zero in ASIOExit().
|
|
||||||
|
|
||||||
// Delegate to the real ASIOInit
|
|
||||||
return ::ASIOInit(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* !defined(_MSC_VER) */
|
|
||||||
|
|
||||||
#endif /* Win32 */
|
|
||||||
|
|
||||||
@ -1,201 +0,0 @@
|
|||||||
// ****************************************************************************
|
|
||||||
//
|
|
||||||
// Changed: I have modified this file slightly (includes) to work with
|
|
||||||
// RtAudio. RtAudio.cpp must include this file after asio.h.
|
|
||||||
//
|
|
||||||
// File: IASIOThiscallResolver.h
|
|
||||||
// Description: The IASIOThiscallResolver class implements the IASIO
|
|
||||||
// interface and acts as a proxy to the real IASIO interface by
|
|
||||||
// calling through its vptr table using the thiscall calling
|
|
||||||
// convention. To put it another way, we interpose
|
|
||||||
// IASIOThiscallResolver between ASIO SDK code and the driver.
|
|
||||||
// This is necessary because most non-Microsoft compilers don't
|
|
||||||
// implement the thiscall calling convention used by IASIO.
|
|
||||||
//
|
|
||||||
// iasiothiscallresolver.cpp contains the background of this
|
|
||||||
// problem plus a technical description of the vptr
|
|
||||||
// manipulations.
|
|
||||||
//
|
|
||||||
// In order to use this mechanism one simply has to add
|
|
||||||
// iasiothiscallresolver.cpp to the list of files to compile
|
|
||||||
// and #include <iasiothiscallresolver.h>
|
|
||||||
//
|
|
||||||
// Note that this #include must come after the other ASIO SDK
|
|
||||||
// #includes, for example:
|
|
||||||
//
|
|
||||||
// #include <windows.h>
|
|
||||||
// #include <asiosys.h>
|
|
||||||
// #include <asio.h>
|
|
||||||
// #include <asiodrivers.h>
|
|
||||||
// #include <iasiothiscallresolver.h>
|
|
||||||
//
|
|
||||||
// Actually the important thing is to #include
|
|
||||||
// <iasiothiscallresolver.h> after <asio.h>. We have
|
|
||||||
// incorporated a test to enforce this ordering.
|
|
||||||
//
|
|
||||||
// The code transparently takes care of the interposition by
|
|
||||||
// using macro substitution to intercept calls to ASIOInit()
|
|
||||||
// and ASIOExit(). We save the original ASIO global
|
|
||||||
// "theAsioDriver" in our "that" variable, and then set
|
|
||||||
// "theAsioDriver" to equal our IASIOThiscallResolver instance.
|
|
||||||
//
|
|
||||||
// Whilst this method of resolving the thiscall problem requires
|
|
||||||
// the addition of #include <iasiothiscallresolver.h> to client
|
|
||||||
// code it has the advantage that it does not break the terms
|
|
||||||
// of the ASIO licence by publishing it. We are NOT modifying
|
|
||||||
// any Steinberg code here, we are merely implementing the IASIO
|
|
||||||
// interface in the same way that we would need to do if we
|
|
||||||
// wished to provide an open source ASIO driver.
|
|
||||||
//
|
|
||||||
// For compilation with MinGW -lole32 needs to be added to the
|
|
||||||
// linker options. For BORLAND, linking with Import32.lib is
|
|
||||||
// sufficient.
|
|
||||||
//
|
|
||||||
// The dependencies are with: CoInitialize, CoUninitialize,
|
|
||||||
// CoCreateInstance, CLSIDFromString - used by asiolist.cpp
|
|
||||||
// and are required on Windows whether ThiscallResolver is used
|
|
||||||
// or not.
|
|
||||||
//
|
|
||||||
// Searching for the above strings in the root library path
|
|
||||||
// of your compiler should enable the correct libraries to be
|
|
||||||
// identified if they aren't immediately obvious.
|
|
||||||
//
|
|
||||||
// Note that the current implementation of IASIOThiscallResolver
|
|
||||||
// is not COM compliant - it does not correctly implement the
|
|
||||||
// IUnknown interface. Implementing it is not necessary because
|
|
||||||
// it is not called by parts of the ASIO SDK which call through
|
|
||||||
// theAsioDriver ptr. The IUnknown methods are implemented as
|
|
||||||
// assert(false) to ensure that the code fails if they are
|
|
||||||
// ever called.
|
|
||||||
// Restrictions: None. Public Domain & Open Source distribute freely
|
|
||||||
// You may use IASIOThiscallResolver commercially as well as
|
|
||||||
// privately.
|
|
||||||
// You the user assume the responsibility for the use of the
|
|
||||||
// files, binary or text, and there is no guarantee or warranty,
|
|
||||||
// expressed or implied, including but not limited to the
|
|
||||||
// implied warranties of merchantability and fitness for a
|
|
||||||
// particular purpose. You assume all responsibility and agree
|
|
||||||
// to hold no entity, copyright holder or distributors liable
|
|
||||||
// for any loss of data or inaccurate representations of data
|
|
||||||
// as a result of using IASIOThiscallResolver.
|
|
||||||
// Version: 1.4 Added separate macro CALL_THISCALL_1_DOUBLE from
|
|
||||||
// Andrew Baldwin, and volatile for whole gcc asm blocks,
|
|
||||||
// both for compatibility with newer gcc versions. Cleaned up
|
|
||||||
// Borland asm to use one less register.
|
|
||||||
// 1.3 Switched to including assert.h for better compatibility.
|
|
||||||
// Wrapped entire .h and .cpp contents with a check for
|
|
||||||
// _MSC_VER to provide better compatibility with MS compilers.
|
|
||||||
// Changed Singleton implementation to use static instance
|
|
||||||
// instead of freestore allocated instance. Removed ASIOExit
|
|
||||||
// macro as it is no longer needed.
|
|
||||||
// 1.2 Removed semicolons from ASIOInit and ASIOExit macros to
|
|
||||||
// allow them to be embedded in expressions (if statements).
|
|
||||||
// Cleaned up some comments. Removed combase.c dependency (it
|
|
||||||
// doesn't compile with BCB anyway) by stubbing IUnknown.
|
|
||||||
// 1.1 Incorporated comments from Ross Bencina including things
|
|
||||||
// such as changing name from ThiscallResolver to
|
|
||||||
// IASIOThiscallResolver, tidying up the constructor, fixing
|
|
||||||
// a bug in IASIOThiscallResolver::ASIOExit() and improving
|
|
||||||
// portability through the use of conditional compilation
|
|
||||||
// 1.0 Initial working version.
|
|
||||||
// Created: 6/09/2003
|
|
||||||
// Authors: Fraser Adams
|
|
||||||
// Ross Bencina
|
|
||||||
// Rene G. Ceballos
|
|
||||||
// Martin Fay
|
|
||||||
// Antti Silvast
|
|
||||||
// Andrew Baldwin
|
|
||||||
//
|
|
||||||
// ****************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef included_iasiothiscallresolver_h
|
|
||||||
#define included_iasiothiscallresolver_h
|
|
||||||
|
|
||||||
// We only need IASIOThiscallResolver at all if we are on Win32. For other
|
|
||||||
// platforms we simply bypass the IASIOThiscallResolver definition to allow us
|
|
||||||
// to be safely #include'd whatever the platform to keep client code portable
|
|
||||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
|
||||||
|
|
||||||
|
|
||||||
// If microsoft compiler we can call IASIO directly so IASIOThiscallResolver
|
|
||||||
// is not used.
|
|
||||||
#if !defined(_MSC_VER)
|
|
||||||
|
|
||||||
|
|
||||||
// The following is in order to ensure that this header is only included after
|
|
||||||
// the other ASIO headers (except for the case of iasiothiscallresolver.cpp).
|
|
||||||
// We need to do this because IASIOThiscallResolver works by eclipsing the
|
|
||||||
// original definition of ASIOInit() with a macro (see below).
|
|
||||||
#if !defined(iasiothiscallresolver_sourcefile)
|
|
||||||
#if !defined(__ASIO_H)
|
|
||||||
#error iasiothiscallresolver.h must be included AFTER asio.h
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include "iasiodrv.h" /* From ASIO SDK */
|
|
||||||
|
|
||||||
|
|
||||||
class IASIOThiscallResolver : public IASIO {
|
|
||||||
private:
|
|
||||||
IASIO* that_; // Points to the real IASIO
|
|
||||||
|
|
||||||
static IASIOThiscallResolver instance; // Singleton instance
|
|
||||||
|
|
||||||
// Constructors - declared private so construction is limited to
|
|
||||||
// our Singleton instance
|
|
||||||
IASIOThiscallResolver();
|
|
||||||
IASIOThiscallResolver(IASIO* that);
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Methods from the IUnknown interface. We don't fully implement IUnknown
|
|
||||||
// because the ASIO SDK never calls these methods through theAsioDriver ptr.
|
|
||||||
// These methods are implemented as assert(false).
|
|
||||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv);
|
|
||||||
virtual ULONG STDMETHODCALLTYPE AddRef();
|
|
||||||
virtual ULONG STDMETHODCALLTYPE Release();
|
|
||||||
|
|
||||||
// Methods from the IASIO interface, implemented as forwarning calls to that.
|
|
||||||
virtual ASIOBool init(void *sysHandle);
|
|
||||||
virtual void getDriverName(char *name);
|
|
||||||
virtual long getDriverVersion();
|
|
||||||
virtual void getErrorMessage(char *string);
|
|
||||||
virtual ASIOError start();
|
|
||||||
virtual ASIOError stop();
|
|
||||||
virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels);
|
|
||||||
virtual ASIOError getLatencies(long *inputLatency, long *outputLatency);
|
|
||||||
virtual ASIOError getBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);
|
|
||||||
virtual ASIOError canSampleRate(ASIOSampleRate sampleRate);
|
|
||||||
virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate);
|
|
||||||
virtual ASIOError setSampleRate(ASIOSampleRate sampleRate);
|
|
||||||
virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources);
|
|
||||||
virtual ASIOError setClockSource(long reference);
|
|
||||||
virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp);
|
|
||||||
virtual ASIOError getChannelInfo(ASIOChannelInfo *info);
|
|
||||||
virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels, long bufferSize, ASIOCallbacks *callbacks);
|
|
||||||
virtual ASIOError disposeBuffers();
|
|
||||||
virtual ASIOError controlPanel();
|
|
||||||
virtual ASIOError future(long selector,void *opt);
|
|
||||||
virtual ASIOError outputReady();
|
|
||||||
|
|
||||||
// Class method, see ASIOInit() macro below.
|
|
||||||
static ASIOError ASIOInit(ASIODriverInfo *info); // Delegates to ::ASIOInit
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Replace calls to ASIOInit with our interposing version.
|
|
||||||
// This macro enables us to perform thiscall resolution simply by #including
|
|
||||||
// <iasiothiscallresolver.h> after the asio #includes (this file _must_ be
|
|
||||||
// included _after_ the asio #includes)
|
|
||||||
|
|
||||||
#define ASIOInit(name) IASIOThiscallResolver::ASIOInit((name))
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* !defined(_MSC_VER) */
|
|
||||||
|
|
||||||
#endif /* Win32 */
|
|
||||||
|
|
||||||
#endif /* included_iasiothiscallresolver_h */
|
|
||||||
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,61 +0,0 @@
|
|||||||
RtAudio - a set of C++ classes that provide a common API for realtime audio input/output across Linux (native ALSA, JACK, and OSS), Macintosh OS X (CoreAudio and JACK), and Windows (DirectSound and ASIO) operating systems.
|
|
||||||
|
|
||||||
By Gary P. Scavone, 2001-2008.
|
|
||||||
|
|
||||||
This distribution of RtAudio contains the following:
|
|
||||||
|
|
||||||
doc: RtAudio documentation (see doc/html/index.html)
|
|
||||||
tests: example RtAudio programs
|
|
||||||
asio: header and source files necessary for ASIO compilation
|
|
||||||
tests/Windows: Visual C++ .net test program workspace and projects
|
|
||||||
|
|
||||||
OVERVIEW:
|
|
||||||
|
|
||||||
RtAudio is a set of C++ classes that provide a common API (Application Programming Interface) for realtime audio input/output across Linux (native ALSA, JACK, and OSS), Macintosh OS X, SGI, and Windows (DirectSound and ASIO) operating systems. RtAudio significantly simplifies the process of interacting with computer audio hardware. It was designed with the following objectives:
|
|
||||||
|
|
||||||
- object-oriented C++ design
|
|
||||||
- simple, common API across all supported platforms
|
|
||||||
- only one source and two header files for easy inclusion in programming projects
|
|
||||||
- allow simultaneous multi-api support
|
|
||||||
- support dynamic connection of devices
|
|
||||||
- provide extensive audio device parameter control
|
|
||||||
- allow audio device capability probing
|
|
||||||
- automatic internal conversion for data format, channel number compensation, (de)interleaving, and byte-swapping
|
|
||||||
|
|
||||||
RtAudio incorporates the concept of audio streams, which represent audio output (playback) and/or input (recording). Available audio devices and their capabilities can be enumerated and then specified when opening a stream. Where applicable, multiple API support can be compiled and a particular API specified when creating an RtAudio instance. See the \ref apinotes section for information specific to each of the supported audio APIs.
|
|
||||||
|
|
||||||
FURTHER READING:
|
|
||||||
|
|
||||||
For complete documentation on RtAudio, see the doc directory of the distribution or surf to http://www.music.mcgill.ca/~gary/rtaudio/.
|
|
||||||
|
|
||||||
|
|
||||||
LEGAL AND ETHICAL:
|
|
||||||
|
|
||||||
The RtAudio license is similar to the MIT License.
|
|
||||||
|
|
||||||
RtAudio: a set of realtime audio i/o C++ classes
|
|
||||||
Copyright (c) 2001-2008 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.
|
|
||||||
Loading…
x
Reference in New Issue
Block a user