mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-09 08:14:58 +01:00
2nd attempt at updated Waves audio backend, with added -fms-extensions as previously applied (but not updated in Waves' repo) to allow anonymous unions, as used by PortMidi
This commit is contained in:
parent
1ac8815296
commit
19d21045af
58 changed files with 9353 additions and 7631 deletions
|
|
@ -1,127 +1,127 @@
|
||||||
/* pmutil.h -- some helpful utilities for building midi
|
/* pmutil.h -- some helpful utilities for building midi
|
||||||
applications that use PortMidi
|
applications that use PortMidi
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
typedef void PmQueue;
|
typedef void PmQueue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A single-reader, single-writer queue is created by
|
A single-reader, single-writer queue is created by
|
||||||
Pm_QueueCreate(), which takes the number of messages and
|
Pm_QueueCreate(), which takes the number of messages and
|
||||||
the message size as parameters. The queue only accepts
|
the message size as parameters. The queue only accepts
|
||||||
fixed sized messages. Returns NULL if memory cannot be allocated.
|
fixed sized messages. Returns NULL if memory cannot be allocated.
|
||||||
|
|
||||||
This queue implementation uses the "light pipe" algorithm which
|
This queue implementation uses the "light pipe" algorithm which
|
||||||
operates correctly even with multi-processors and out-of-order
|
operates correctly even with multi-processors and out-of-order
|
||||||
memory writes. (see Alexander Dokumentov, "Lock-free Interprocess
|
memory writes. (see Alexander Dokumentov, "Lock-free Interprocess
|
||||||
Communication," Dr. Dobbs Portal, http://www.ddj.com/,
|
Communication," Dr. Dobbs Portal, http://www.ddj.com/,
|
||||||
articleID=189401457, June 15, 2006. This algorithm requires
|
articleID=189401457, June 15, 2006. This algorithm requires
|
||||||
that messages be translated to a form where no words contain
|
that messages be translated to a form where no words contain
|
||||||
zeros. Each word becomes its own "data valid" tag. Because of
|
zeros. Each word becomes its own "data valid" tag. Because of
|
||||||
this translation, we cannot return a pointer to data still in
|
this translation, we cannot return a pointer to data still in
|
||||||
the queue when the "peek" method is called. Instead, a buffer
|
the queue when the "peek" method is called. Instead, a buffer
|
||||||
is preallocated so that data can be copied there. Pm_QueuePeek()
|
is preallocated so that data can be copied there. Pm_QueuePeek()
|
||||||
dequeues a message into this buffer and returns a pointer to
|
dequeues a message into this buffer and returns a pointer to
|
||||||
it. A subsequent Pm_Dequeue() will copy from this buffer.
|
it. A subsequent Pm_Dequeue() will copy from this buffer.
|
||||||
|
|
||||||
This implementation does not try to keep reader/writer data in
|
This implementation does not try to keep reader/writer data in
|
||||||
separate cache lines or prevent thrashing on cache lines.
|
separate cache lines or prevent thrashing on cache lines.
|
||||||
However, this algorithm differs by doing inserts/removals in
|
However, this algorithm differs by doing inserts/removals in
|
||||||
units of messages rather than units of machine words. Some
|
units of messages rather than units of machine words. Some
|
||||||
performance improvement might be obtained by not clearing data
|
performance improvement might be obtained by not clearing data
|
||||||
immediately after a read, but instead by waiting for the end
|
immediately after a read, but instead by waiting for the end
|
||||||
of the cache line, especially if messages are smaller than
|
of the cache line, especially if messages are smaller than
|
||||||
cache lines. See the Dokumentov article for explanation.
|
cache lines. See the Dokumentov article for explanation.
|
||||||
|
|
||||||
The algorithm is extended to handle "overflow" reporting. To report
|
The algorithm is extended to handle "overflow" reporting. To report
|
||||||
an overflow, the sender writes the current tail position to a field.
|
an overflow, the sender writes the current tail position to a field.
|
||||||
The receiver must acknowlege receipt by zeroing the field. The sender
|
The receiver must acknowlege receipt by zeroing the field. The sender
|
||||||
will not send more until the field is zeroed.
|
will not send more until the field is zeroed.
|
||||||
|
|
||||||
Pm_QueueDestroy() destroys the queue and frees its storage.
|
Pm_QueueDestroy() destroys the queue and frees its storage.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PMEXPORT PmQueue *Pm_QueueCreate(long num_msgs, int32_t bytes_per_msg);
|
PMEXPORT PmQueue *Pm_QueueCreate(long num_msgs, int32_t bytes_per_msg);
|
||||||
PMEXPORT PmError Pm_QueueDestroy(PmQueue *queue);
|
PMEXPORT PmError Pm_QueueDestroy(PmQueue *queue);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Pm_Dequeue() removes one item from the queue, copying it into msg.
|
Pm_Dequeue() removes one item from the queue, copying it into msg.
|
||||||
Returns 1 if successful, and 0 if the queue is empty.
|
Returns 1 if successful, and 0 if the queue is empty.
|
||||||
Returns pmBufferOverflow if what would have been the next thing
|
Returns pmBufferOverflow if what would have been the next thing
|
||||||
in the queue was dropped due to overflow. (So when overflow occurs,
|
in the queue was dropped due to overflow. (So when overflow occurs,
|
||||||
the receiver can receive a queue full of messages before getting the
|
the receiver can receive a queue full of messages before getting the
|
||||||
overflow report. This protocol ensures that the reader will be
|
overflow report. This protocol ensures that the reader will be
|
||||||
notified when data is lost due to overflow.
|
notified when data is lost due to overflow.
|
||||||
*/
|
*/
|
||||||
PMEXPORT PmError Pm_Dequeue(PmQueue *queue, void *msg);
|
PMEXPORT PmError Pm_Dequeue(PmQueue *queue, void *msg);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Pm_Enqueue() inserts one item into the queue, copying it from msg.
|
Pm_Enqueue() inserts one item into the queue, copying it from msg.
|
||||||
Returns pmNoError if successful and pmBufferOverflow if the queue was
|
Returns pmNoError if successful and pmBufferOverflow if the queue was
|
||||||
already full. If pmBufferOverflow is returned, the overflow flag is set.
|
already full. If pmBufferOverflow is returned, the overflow flag is set.
|
||||||
*/
|
*/
|
||||||
PMEXPORT PmError Pm_Enqueue(PmQueue *queue, void *msg);
|
PMEXPORT PmError Pm_Enqueue(PmQueue *queue, void *msg);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Pm_QueueFull() returns non-zero if the queue is full
|
Pm_QueueFull() returns non-zero if the queue is full
|
||||||
Pm_QueueEmpty() returns non-zero if the queue is empty
|
Pm_QueueEmpty() returns non-zero if the queue is empty
|
||||||
|
|
||||||
Either condition may change immediately because a parallel
|
Either condition may change immediately because a parallel
|
||||||
enqueue or dequeue operation could be in progress. Furthermore,
|
enqueue or dequeue operation could be in progress. Furthermore,
|
||||||
Pm_QueueEmpty() is optimistic: it may say false, when due to
|
Pm_QueueEmpty() is optimistic: it may say false, when due to
|
||||||
out-of-order writes, the full message has not arrived. Therefore,
|
out-of-order writes, the full message has not arrived. Therefore,
|
||||||
Pm_Dequeue() could still return 0 after Pm_QueueEmpty() returns
|
Pm_Dequeue() could still return 0 after Pm_QueueEmpty() returns
|
||||||
false. On the other hand, Pm_QueueFull() is pessimistic: if it
|
false. On the other hand, Pm_QueueFull() is pessimistic: if it
|
||||||
returns false, then Pm_Enqueue() is guaranteed to succeed.
|
returns false, then Pm_Enqueue() is guaranteed to succeed.
|
||||||
|
|
||||||
Error conditions: Pm_QueueFull() returns pmBadPtr if queue is NULL.
|
Error conditions: Pm_QueueFull() returns pmBadPtr if queue is NULL.
|
||||||
Pm_QueueEmpty() returns FALSE if queue is NULL.
|
Pm_QueueEmpty() returns FALSE if queue is NULL.
|
||||||
*/
|
*/
|
||||||
PMEXPORT int Pm_QueueFull(PmQueue *queue);
|
PMEXPORT int Pm_QueueFull(PmQueue *queue);
|
||||||
PMEXPORT int Pm_QueueEmpty(PmQueue *queue);
|
PMEXPORT int Pm_QueueEmpty(PmQueue *queue);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Pm_QueuePeek() returns a pointer to the item at the head of the queue,
|
Pm_QueuePeek() returns a pointer to the item at the head of the queue,
|
||||||
or NULL if the queue is empty. The item is not removed from the queue.
|
or NULL if the queue is empty. The item is not removed from the queue.
|
||||||
Pm_QueuePeek() will not indicate when an overflow occurs. If you want
|
Pm_QueuePeek() will not indicate when an overflow occurs. If you want
|
||||||
to get and check pmBufferOverflow messages, use the return value of
|
to get and check pmBufferOverflow messages, use the return value of
|
||||||
Pm_QueuePeek() *only* as an indication that you should call
|
Pm_QueuePeek() *only* as an indication that you should call
|
||||||
Pm_Dequeue(). At the point where a direct call to Pm_Dequeue() would
|
Pm_Dequeue(). At the point where a direct call to Pm_Dequeue() would
|
||||||
return pmBufferOverflow, Pm_QueuePeek() will return NULL but internally
|
return pmBufferOverflow, Pm_QueuePeek() will return NULL but internally
|
||||||
clear the pmBufferOverflow flag, enabling Pm_Enqueue() to resume
|
clear the pmBufferOverflow flag, enabling Pm_Enqueue() to resume
|
||||||
enqueuing messages. A subsequent call to Pm_QueuePeek()
|
enqueuing messages. A subsequent call to Pm_QueuePeek()
|
||||||
will return a pointer to the first message *after* the overflow.
|
will return a pointer to the first message *after* the overflow.
|
||||||
Using this as an indication to call Pm_Dequeue(), the first call
|
Using this as an indication to call Pm_Dequeue(), the first call
|
||||||
to Pm_Dequeue() will return pmBufferOverflow. The second call will
|
to Pm_Dequeue() will return pmBufferOverflow. The second call will
|
||||||
return success, copying the same message pointed to by the previous
|
return success, copying the same message pointed to by the previous
|
||||||
Pm_QueuePeek().
|
Pm_QueuePeek().
|
||||||
|
|
||||||
When to use Pm_QueuePeek(): (1) when you need to look at the message
|
When to use Pm_QueuePeek(): (1) when you need to look at the message
|
||||||
data to decide who should be called to receive it. (2) when you need
|
data to decide who should be called to receive it. (2) when you need
|
||||||
to know a message is ready but cannot accept the message.
|
to know a message is ready but cannot accept the message.
|
||||||
|
|
||||||
Note that Pm_QueuePeek() is not a fast check, so if possible, you
|
Note that Pm_QueuePeek() is not a fast check, so if possible, you
|
||||||
might as well just call Pm_Dequeue() and accept the data if it is there.
|
might as well just call Pm_Dequeue() and accept the data if it is there.
|
||||||
*/
|
*/
|
||||||
PMEXPORT void *Pm_QueuePeek(PmQueue *queue);
|
PMEXPORT void *Pm_QueuePeek(PmQueue *queue);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Pm_SetOverflow() allows the writer (enqueuer) to signal an overflow
|
Pm_SetOverflow() allows the writer (enqueuer) to signal an overflow
|
||||||
condition to the reader (dequeuer). E.g. when transfering data from
|
condition to the reader (dequeuer). E.g. when transfering data from
|
||||||
the OS to an application, if the OS indicates a buffer overrun,
|
the OS to an application, if the OS indicates a buffer overrun,
|
||||||
Pm_SetOverflow() can be used to insure that the reader receives a
|
Pm_SetOverflow() can be used to insure that the reader receives a
|
||||||
pmBufferOverflow result from Pm_Dequeue(). Returns pmBadPtr if queue
|
pmBufferOverflow result from Pm_Dequeue(). Returns pmBadPtr if queue
|
||||||
is NULL, returns pmBufferOverflow if buffer is already in an overflow
|
is NULL, returns pmBufferOverflow if buffer is already in an overflow
|
||||||
state, returns pmNoError if successfully set overflow state.
|
state, returns pmNoError if successfully set overflow state.
|
||||||
*/
|
*/
|
||||||
PMEXPORT PmError Pm_SetOverflow(PmQueue *queue);
|
PMEXPORT PmError Pm_SetOverflow(PmQueue *queue);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
|
||||||
|
|
@ -1,178 +1,178 @@
|
||||||
/* pminternal.h -- header for interface implementations */
|
/* pminternal.h -- header for interface implementations */
|
||||||
|
|
||||||
/* this file is included by files that implement library internals */
|
/* this file is included by files that implement library internals */
|
||||||
/* Here is a guide to implementers:
|
/* Here is a guide to implementers:
|
||||||
provide an initialization function similar to pm_winmm_init()
|
provide an initialization function similar to pm_winmm_init()
|
||||||
add your initialization function to pm_init()
|
add your initialization function to pm_init()
|
||||||
Note that your init function should never require not-standard
|
Note that your init function should never require not-standard
|
||||||
libraries or fail in any way. If the interface is not available,
|
libraries or fail in any way. If the interface is not available,
|
||||||
simply do not call pm_add_device. This means that non-standard
|
simply do not call pm_add_device. This means that non-standard
|
||||||
libraries should try to do dynamic linking at runtime using a DLL
|
libraries should try to do dynamic linking at runtime using a DLL
|
||||||
and return without error if the DLL cannot be found or if there
|
and return without error if the DLL cannot be found or if there
|
||||||
is any other failure.
|
is any other failure.
|
||||||
implement functions as indicated in pm_fns_type to open, read, write,
|
implement functions as indicated in pm_fns_type to open, read, write,
|
||||||
close, etc.
|
close, etc.
|
||||||
call pm_add_device() for each input and output device, passing it a
|
call pm_add_device() for each input and output device, passing it a
|
||||||
pm_fns_type structure.
|
pm_fns_type structure.
|
||||||
assumptions about pm_fns_type functions are given below.
|
assumptions about pm_fns_type functions are given below.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int pm_initialized; /* see note in portmidi.c */
|
extern int pm_initialized; /* see note in portmidi.c */
|
||||||
|
|
||||||
/* these are defined in system-specific file */
|
/* these are defined in system-specific file */
|
||||||
void *pm_alloc(size_t s);
|
void *pm_alloc(size_t s);
|
||||||
void pm_free(void *ptr);
|
void pm_free(void *ptr);
|
||||||
|
|
||||||
/* if an error occurs while opening or closing a midi stream, set these: */
|
/* if an error occurs while opening or closing a midi stream, set these: */
|
||||||
extern int pm_hosterror;
|
extern int pm_hosterror;
|
||||||
extern char pm_hosterror_text[PM_HOST_ERROR_MSG_LEN];
|
extern char pm_hosterror_text[PM_HOST_ERROR_MSG_LEN];
|
||||||
|
|
||||||
struct pm_internal_struct;
|
struct pm_internal_struct;
|
||||||
|
|
||||||
/* these do not use PmInternal because it is not defined yet... */
|
/* these do not use PmInternal because it is not defined yet... */
|
||||||
typedef PmError (*pm_write_short_fn)(struct pm_internal_struct *midi,
|
typedef PmError (*pm_write_short_fn)(struct pm_internal_struct *midi,
|
||||||
PmEvent *buffer);
|
PmEvent *buffer);
|
||||||
typedef PmError (*pm_begin_sysex_fn)(struct pm_internal_struct *midi,
|
typedef PmError (*pm_begin_sysex_fn)(struct pm_internal_struct *midi,
|
||||||
PmTimestamp timestamp);
|
PmTimestamp timestamp);
|
||||||
typedef PmError (*pm_end_sysex_fn)(struct pm_internal_struct *midi,
|
typedef PmError (*pm_end_sysex_fn)(struct pm_internal_struct *midi,
|
||||||
PmTimestamp timestamp);
|
PmTimestamp timestamp);
|
||||||
typedef PmError (*pm_write_byte_fn)(struct pm_internal_struct *midi,
|
typedef PmError (*pm_write_byte_fn)(struct pm_internal_struct *midi,
|
||||||
unsigned char byte, PmTimestamp timestamp);
|
unsigned char byte, PmTimestamp timestamp);
|
||||||
typedef PmError (*pm_write_realtime_fn)(struct pm_internal_struct *midi,
|
typedef PmError (*pm_write_realtime_fn)(struct pm_internal_struct *midi,
|
||||||
PmEvent *buffer);
|
PmEvent *buffer);
|
||||||
typedef PmError (*pm_write_flush_fn)(struct pm_internal_struct *midi,
|
typedef PmError (*pm_write_flush_fn)(struct pm_internal_struct *midi,
|
||||||
PmTimestamp timestamp);
|
PmTimestamp timestamp);
|
||||||
typedef PmTimestamp (*pm_synchronize_fn)(struct pm_internal_struct *midi);
|
typedef PmTimestamp (*pm_synchronize_fn)(struct pm_internal_struct *midi);
|
||||||
/* pm_open_fn should clean up all memory and close the device if any part
|
/* pm_open_fn should clean up all memory and close the device if any part
|
||||||
of the open fails */
|
of the open fails */
|
||||||
typedef PmError (*pm_open_fn)(struct pm_internal_struct *midi,
|
typedef PmError (*pm_open_fn)(struct pm_internal_struct *midi,
|
||||||
void *driverInfo);
|
void *driverInfo);
|
||||||
typedef PmError (*pm_abort_fn)(struct pm_internal_struct *midi);
|
typedef PmError (*pm_abort_fn)(struct pm_internal_struct *midi);
|
||||||
/* pm_close_fn should clean up all memory and close the device if any
|
/* pm_close_fn should clean up all memory and close the device if any
|
||||||
part of the close fails. */
|
part of the close fails. */
|
||||||
typedef PmError (*pm_close_fn)(struct pm_internal_struct *midi);
|
typedef PmError (*pm_close_fn)(struct pm_internal_struct *midi);
|
||||||
typedef PmError (*pm_poll_fn)(struct pm_internal_struct *midi);
|
typedef PmError (*pm_poll_fn)(struct pm_internal_struct *midi);
|
||||||
typedef void (*pm_host_error_fn)(struct pm_internal_struct *midi, char * msg,
|
typedef void (*pm_host_error_fn)(struct pm_internal_struct *midi, char * msg,
|
||||||
unsigned int len);
|
unsigned int len);
|
||||||
typedef unsigned int (*pm_has_host_error_fn)(struct pm_internal_struct *midi);
|
typedef unsigned int (*pm_has_host_error_fn)(struct pm_internal_struct *midi);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
pm_write_short_fn write_short; /* output short MIDI msg */
|
pm_write_short_fn write_short; /* output short MIDI msg */
|
||||||
pm_begin_sysex_fn begin_sysex; /* prepare to send a sysex message */
|
pm_begin_sysex_fn begin_sysex; /* prepare to send a sysex message */
|
||||||
pm_end_sysex_fn end_sysex; /* marks end of sysex message */
|
pm_end_sysex_fn end_sysex; /* marks end of sysex message */
|
||||||
pm_write_byte_fn write_byte; /* accumulate one more sysex byte */
|
pm_write_byte_fn write_byte; /* accumulate one more sysex byte */
|
||||||
pm_write_realtime_fn write_realtime; /* send real-time message within sysex */
|
pm_write_realtime_fn write_realtime; /* send real-time message within sysex */
|
||||||
pm_write_flush_fn write_flush; /* send any accumulated but unsent data */
|
pm_write_flush_fn write_flush; /* send any accumulated but unsent data */
|
||||||
pm_synchronize_fn synchronize; /* synchronize portmidi time to stream time */
|
pm_synchronize_fn synchronize; /* synchronize portmidi time to stream time */
|
||||||
pm_open_fn open; /* open MIDI device */
|
pm_open_fn open; /* open MIDI device */
|
||||||
pm_abort_fn abort; /* abort */
|
pm_abort_fn abort; /* abort */
|
||||||
pm_close_fn close; /* close device */
|
pm_close_fn close; /* close device */
|
||||||
pm_poll_fn poll; /* read pending midi events into portmidi buffer */
|
pm_poll_fn poll; /* read pending midi events into portmidi buffer */
|
||||||
pm_has_host_error_fn has_host_error; /* true when device has had host
|
pm_has_host_error_fn has_host_error; /* true when device has had host
|
||||||
error message */
|
error message */
|
||||||
pm_host_error_fn host_error; /* provide text readable host error message
|
pm_host_error_fn host_error; /* provide text readable host error message
|
||||||
for device (clears and resets) */
|
for device (clears and resets) */
|
||||||
} pm_fns_node, *pm_fns_type;
|
} pm_fns_node, *pm_fns_type;
|
||||||
|
|
||||||
|
|
||||||
/* when open fails, the dictionary gets this set of functions: */
|
/* when open fails, the dictionary gets this set of functions: */
|
||||||
extern pm_fns_node pm_none_dictionary;
|
extern pm_fns_node pm_none_dictionary;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PmDeviceInfo pub; /* some portmidi state also saved in here (for autmatic
|
PmDeviceInfo pub; /* some portmidi state also saved in here (for autmatic
|
||||||
device closing (see PmDeviceInfo struct) */
|
device closing (see PmDeviceInfo struct) */
|
||||||
void *descriptor; /* ID number passed to win32 multimedia API open */
|
void *descriptor; /* ID number passed to win32 multimedia API open */
|
||||||
void *internalDescriptor; /* points to PmInternal device, allows automatic
|
void *internalDescriptor; /* points to PmInternal device, allows automatic
|
||||||
device closing */
|
device closing */
|
||||||
pm_fns_type dictionary;
|
pm_fns_type dictionary;
|
||||||
} descriptor_node, *descriptor_type;
|
} descriptor_node, *descriptor_type;
|
||||||
|
|
||||||
extern int pm_descriptor_max;
|
extern int pm_descriptor_max;
|
||||||
extern descriptor_type descriptors;
|
extern descriptor_type descriptors;
|
||||||
extern int pm_descriptor_index;
|
extern int pm_descriptor_index;
|
||||||
|
|
||||||
typedef uint32_t (*time_get_proc_type)(void *time_info);
|
typedef uint32_t (*time_get_proc_type)(void *time_info);
|
||||||
|
|
||||||
typedef struct pm_internal_struct {
|
typedef struct pm_internal_struct {
|
||||||
int device_id; /* which device is open (index to descriptors) */
|
int device_id; /* which device is open (index to descriptors) */
|
||||||
short write_flag; /* MIDI_IN, or MIDI_OUT */
|
short write_flag; /* MIDI_IN, or MIDI_OUT */
|
||||||
|
|
||||||
PmTimeProcPtr time_proc; /* where to get the time */
|
PmTimeProcPtr time_proc; /* where to get the time */
|
||||||
void *time_info; /* pass this to get_time() */
|
void *time_info; /* pass this to get_time() */
|
||||||
int32_t buffer_len; /* how big is the buffer or queue? */
|
int32_t buffer_len; /* how big is the buffer or queue? */
|
||||||
PmQueue *queue;
|
PmQueue *queue;
|
||||||
|
|
||||||
int32_t latency; /* time delay in ms between timestamps and actual output */
|
int32_t latency; /* time delay in ms between timestamps and actual output */
|
||||||
/* set to zero to get immediate, simple blocking output */
|
/* set to zero to get immediate, simple blocking output */
|
||||||
/* if latency is zero, timestamps will be ignored; */
|
/* if latency is zero, timestamps will be ignored; */
|
||||||
/* if midi input device, this field ignored */
|
/* if midi input device, this field ignored */
|
||||||
|
|
||||||
int sysex_in_progress; /* when sysex status is seen, this flag becomes
|
int sysex_in_progress; /* when sysex status is seen, this flag becomes
|
||||||
* true until EOX is seen. When true, new data is appended to the
|
* true until EOX is seen. When true, new data is appended to the
|
||||||
* stream of outgoing bytes. When overflow occurs, sysex data is
|
* stream of outgoing bytes. When overflow occurs, sysex data is
|
||||||
* dropped (until an EOX or non-real-timei status byte is seen) so
|
* dropped (until an EOX or non-real-timei status byte is seen) so
|
||||||
* that, if the overflow condition is cleared, we don't start
|
* that, if the overflow condition is cleared, we don't start
|
||||||
* sending data from the middle of a sysex message. If a sysex
|
* sending data from the middle of a sysex message. If a sysex
|
||||||
* message is filtered, sysex_in_progress is false, causing the
|
* message is filtered, sysex_in_progress is false, causing the
|
||||||
* message to be dropped. */
|
* message to be dropped. */
|
||||||
PmMessage sysex_message; /* buffer for 4 bytes of sysex data */
|
PmMessage sysex_message; /* buffer for 4 bytes of sysex data */
|
||||||
int sysex_message_count; /* how many bytes in sysex_message so far */
|
int sysex_message_count; /* how many bytes in sysex_message so far */
|
||||||
|
|
||||||
int32_t filters; /* flags that filter incoming message classes */
|
int32_t filters; /* flags that filter incoming message classes */
|
||||||
int32_t channel_mask; /* filter incoming messages based on channel */
|
int32_t channel_mask; /* filter incoming messages based on channel */
|
||||||
PmTimestamp last_msg_time; /* timestamp of last message */
|
PmTimestamp last_msg_time; /* timestamp of last message */
|
||||||
PmTimestamp sync_time; /* time of last synchronization */
|
PmTimestamp sync_time; /* time of last synchronization */
|
||||||
PmTimestamp now; /* set by PmWrite to current time */
|
PmTimestamp now; /* set by PmWrite to current time */
|
||||||
int first_message; /* initially true, used to run first synchronization */
|
int first_message; /* initially true, used to run first synchronization */
|
||||||
pm_fns_type dictionary; /* implementation functions */
|
pm_fns_type dictionary; /* implementation functions */
|
||||||
void *descriptor; /* system-dependent state */
|
void *descriptor; /* system-dependent state */
|
||||||
/* the following are used to expedite sysex data */
|
/* the following are used to expedite sysex data */
|
||||||
/* on windows, in debug mode, based on some profiling, these optimizations
|
/* on windows, in debug mode, based on some profiling, these optimizations
|
||||||
* cut the time to process sysex bytes from about 7.5 to 0.26 usec/byte,
|
* cut the time to process sysex bytes from about 7.5 to 0.26 usec/byte,
|
||||||
* but this does not count time in the driver, so I don't know if it is
|
* but this does not count time in the driver, so I don't know if it is
|
||||||
* important
|
* important
|
||||||
*/
|
*/
|
||||||
unsigned char *fill_base; /* addr of ptr to sysex data */
|
unsigned char *fill_base; /* addr of ptr to sysex data */
|
||||||
uint32_t *fill_offset_ptr; /* offset of next sysex byte */
|
uint32_t *fill_offset_ptr; /* offset of next sysex byte */
|
||||||
int32_t fill_length; /* how many sysex bytes to write */
|
int32_t fill_length; /* how many sysex bytes to write */
|
||||||
} PmInternal;
|
} PmInternal;
|
||||||
|
|
||||||
|
|
||||||
/* defined by system specific implementation, e.g. pmwinmm, used by PortMidi */
|
/* defined by system specific implementation, e.g. pmwinmm, used by PortMidi */
|
||||||
void pm_init(void);
|
void pm_init(void);
|
||||||
void pm_term(void);
|
void pm_term(void);
|
||||||
|
|
||||||
/* defined by portMidi, used by pmwinmm */
|
/* defined by portMidi, used by pmwinmm */
|
||||||
PmError none_write_short(PmInternal *midi, PmEvent *buffer);
|
PmError none_write_short(PmInternal *midi, PmEvent *buffer);
|
||||||
PmError none_write_byte(PmInternal *midi, unsigned char byte,
|
PmError none_write_byte(PmInternal *midi, unsigned char byte,
|
||||||
PmTimestamp timestamp);
|
PmTimestamp timestamp);
|
||||||
PmTimestamp none_synchronize(PmInternal *midi);
|
PmTimestamp none_synchronize(PmInternal *midi);
|
||||||
|
|
||||||
PmError pm_fail_fn(PmInternal *midi);
|
PmError pm_fail_fn(PmInternal *midi);
|
||||||
PmError pm_fail_timestamp_fn(PmInternal *midi, PmTimestamp timestamp);
|
PmError pm_fail_timestamp_fn(PmInternal *midi, PmTimestamp timestamp);
|
||||||
PmError pm_success_fn(PmInternal *midi);
|
PmError pm_success_fn(PmInternal *midi);
|
||||||
PmError pm_add_device(char *interf, char *name, int input, void *descriptor,
|
PmError pm_add_device(char *interf, char *name, int input, void *descriptor,
|
||||||
pm_fns_type dictionary);
|
pm_fns_type dictionary);
|
||||||
uint32_t pm_read_bytes(PmInternal *midi, const unsigned char *data, int len,
|
uint32_t pm_read_bytes(PmInternal *midi, const unsigned char *data, int len,
|
||||||
PmTimestamp timestamp);
|
PmTimestamp timestamp);
|
||||||
void pm_read_short(PmInternal *midi, PmEvent *event);
|
void pm_read_short(PmInternal *midi, PmEvent *event);
|
||||||
|
|
||||||
#define none_write_flush pm_fail_timestamp_fn
|
#define none_write_flush pm_fail_timestamp_fn
|
||||||
#define none_sysex pm_fail_timestamp_fn
|
#define none_sysex pm_fail_timestamp_fn
|
||||||
#define none_poll pm_fail_fn
|
#define none_poll pm_fail_fn
|
||||||
#define success_poll pm_success_fn
|
#define success_poll pm_success_fn
|
||||||
|
|
||||||
#define MIDI_REALTIME_MASK 0xf8
|
#define MIDI_REALTIME_MASK 0xf8
|
||||||
#define is_real_time(msg) \
|
#define is_real_time(msg) \
|
||||||
((Pm_MessageStatus(msg) & MIDI_REALTIME_MASK) == MIDI_REALTIME_MASK)
|
((Pm_MessageStatus(msg) & MIDI_REALTIME_MASK) == MIDI_REALTIME_MASK)
|
||||||
|
|
||||||
int pm_find_default_device(char *pattern, int is_input);
|
int pm_find_default_device(char *pattern, int is_input);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,59 +1,59 @@
|
||||||
/* pmmac.c -- PortMidi os-dependent code */
|
/* pmmac.c -- PortMidi os-dependent code */
|
||||||
|
|
||||||
/* This file only needs to implement:
|
/* This file only needs to implement:
|
||||||
pm_init(), which calls various routines to register the
|
pm_init(), which calls various routines to register the
|
||||||
available midi devices,
|
available midi devices,
|
||||||
Pm_GetDefaultInputDeviceID(), and
|
Pm_GetDefaultInputDeviceID(), and
|
||||||
Pm_GetDefaultOutputDeviceID().
|
Pm_GetDefaultOutputDeviceID().
|
||||||
It is seperate from pmmacosxcm because we might want to register
|
It is seperate from pmmacosxcm because we might want to register
|
||||||
non-CoreMIDI devices.
|
non-CoreMIDI devices.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "stdlib.h"
|
#include "stdlib.h"
|
||||||
#include "portmidi.h"
|
#include "portmidi.h"
|
||||||
#include "pmutil.h"
|
#include "pmutil.h"
|
||||||
#include "pminternal.h"
|
#include "pminternal.h"
|
||||||
#include "pmmacosxcm.h"
|
#include "pmmacosxcm.h"
|
||||||
|
|
||||||
PmDeviceID pm_default_input_device_id = -1;
|
PmDeviceID pm_default_input_device_id = -1;
|
||||||
PmDeviceID pm_default_output_device_id = -1;
|
PmDeviceID pm_default_output_device_id = -1;
|
||||||
|
|
||||||
void pm_init()
|
void pm_init()
|
||||||
{
|
{
|
||||||
PmError err = pm_macosxcm_init();
|
PmError err = pm_macosxcm_init();
|
||||||
// this is set when we return to Pm_Initialize, but we need it
|
// this is set when we return to Pm_Initialize, but we need it
|
||||||
// now in order to (successfully) call Pm_CountDevices()
|
// now in order to (successfully) call Pm_CountDevices()
|
||||||
pm_initialized = TRUE;
|
pm_initialized = TRUE;
|
||||||
if (!err) {
|
if (!err) {
|
||||||
pm_default_input_device_id = find_default_device(
|
pm_default_input_device_id = find_default_device(
|
||||||
"/PortMidi/PM_RECOMMENDED_INPUT_DEVICE", TRUE,
|
"/PortMidi/PM_RECOMMENDED_INPUT_DEVICE", TRUE,
|
||||||
pm_default_input_device_id);
|
pm_default_input_device_id);
|
||||||
pm_default_output_device_id = find_default_device(
|
pm_default_output_device_id = find_default_device(
|
||||||
"/PortMidi/PM_RECOMMENDED_OUTPUT_DEVICE", FALSE,
|
"/PortMidi/PM_RECOMMENDED_OUTPUT_DEVICE", FALSE,
|
||||||
pm_default_output_device_id);
|
pm_default_output_device_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void pm_term(void)
|
void pm_term(void)
|
||||||
{
|
{
|
||||||
pm_macosxcm_term();
|
pm_macosxcm_term();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PmDeviceID Pm_GetDefaultInputDeviceID()
|
PmDeviceID Pm_GetDefaultInputDeviceID()
|
||||||
{
|
{
|
||||||
Pm_Initialize();
|
Pm_Initialize();
|
||||||
return pm_default_input_device_id;
|
return pm_default_input_device_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
PmDeviceID Pm_GetDefaultOutputDeviceID() {
|
PmDeviceID Pm_GetDefaultOutputDeviceID() {
|
||||||
Pm_Initialize();
|
Pm_Initialize();
|
||||||
return pm_default_output_device_id;
|
return pm_default_output_device_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *pm_alloc(size_t s) { return malloc(s); }
|
void *pm_alloc(size_t s) { return malloc(s); }
|
||||||
|
|
||||||
void pm_free(void *ptr) { free(ptr); }
|
void pm_free(void *ptr) { free(ptr); }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* pmmac.h */
|
/* pmmac.h */
|
||||||
|
|
||||||
extern PmDeviceID pm_default_input_device_id;
|
extern PmDeviceID pm_default_input_device_id;
|
||||||
extern PmDeviceID pm_default_output_device_id;
|
extern PmDeviceID pm_default_output_device_id;
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/* system-specific definitions */
|
/* system-specific definitions */
|
||||||
|
|
||||||
PmError pm_macosxcm_init(void);
|
PmError pm_macosxcm_init(void);
|
||||||
void pm_macosxcm_term(void);
|
void pm_macosxcm_term(void);
|
||||||
|
|
||||||
PmDeviceID find_default_device(char *path, int input, PmDeviceID id);
|
PmDeviceID find_default_device(char *path, int input, PmDeviceID id);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,143 +1,143 @@
|
||||||
/* pmwin.c -- PortMidi os-dependent code */
|
/* pmwin.c -- PortMidi os-dependent code */
|
||||||
|
|
||||||
/* This file only needs to implement:
|
/* This file only needs to implement:
|
||||||
pm_init(), which calls various routines to register the
|
pm_init(), which calls various routines to register the
|
||||||
available midi devices,
|
available midi devices,
|
||||||
Pm_GetDefaultInputDeviceID(), and
|
Pm_GetDefaultInputDeviceID(), and
|
||||||
Pm_GetDefaultOutputDeviceID().
|
Pm_GetDefaultOutputDeviceID().
|
||||||
This file must
|
This file must
|
||||||
be separate from the main portmidi.c file because it is system
|
be separate from the main portmidi.c file because it is system
|
||||||
dependent, and it is separate from, say, pmwinmm.c, because it
|
dependent, and it is separate from, say, pmwinmm.c, because it
|
||||||
might need to register devices for winmm, directx, and others.
|
might need to register devices for winmm, directx, and others.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "stdlib.h"
|
#include "stdlib.h"
|
||||||
#include "portmidi.h"
|
#include "portmidi.h"
|
||||||
#include "pmutil.h"
|
#include "pmutil.h"
|
||||||
#include "pminternal.h"
|
#include "pminternal.h"
|
||||||
#include "pmwinmm.h"
|
#include "pmwinmm.h"
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#endif
|
#endif
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
/* pm_exit is called when the program exits.
|
/* pm_exit is called when the program exits.
|
||||||
It calls pm_term to make sure PortMidi is properly closed.
|
It calls pm_term to make sure PortMidi is properly closed.
|
||||||
If DEBUG is on, we prompt for input to avoid losing error messages.
|
If DEBUG is on, we prompt for input to avoid losing error messages.
|
||||||
*/
|
*/
|
||||||
static void pm_exit(void) {
|
static void pm_exit(void) {
|
||||||
pm_term();
|
pm_term();
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define STRING_MAX 80
|
#define STRING_MAX 80
|
||||||
{
|
{
|
||||||
char line[STRING_MAX];
|
char line[STRING_MAX];
|
||||||
printf("Type ENTER...\n");
|
printf("Type ENTER...\n");
|
||||||
/* note, w/o this prompting, client console application can not see one
|
/* note, w/o this prompting, client console application can not see one
|
||||||
of its errors before closing. */
|
of its errors before closing. */
|
||||||
fgets(line, STRING_MAX, stdin);
|
fgets(line, STRING_MAX, stdin);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* pm_init is the windows-dependent initialization.*/
|
/* pm_init is the windows-dependent initialization.*/
|
||||||
void pm_init(void)
|
void pm_init(void)
|
||||||
{
|
{
|
||||||
atexit(pm_exit);
|
atexit(pm_exit);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("registered pm_exit with atexit()\n");
|
printf("registered pm_exit with atexit()\n");
|
||||||
#endif
|
#endif
|
||||||
pm_winmm_init();
|
pm_winmm_init();
|
||||||
/* initialize other APIs (DirectX?) here */
|
/* initialize other APIs (DirectX?) here */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void pm_term(void) {
|
void pm_term(void) {
|
||||||
pm_winmm_term();
|
pm_winmm_term();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static PmDeviceID pm_get_default_device_id(int is_input, char *key) {
|
static PmDeviceID pm_get_default_device_id(int is_input, char *key) {
|
||||||
HKEY hkey;
|
HKEY hkey;
|
||||||
#define PATTERN_MAX 256
|
#define PATTERN_MAX 256
|
||||||
char pattern[PATTERN_MAX];
|
char pattern[PATTERN_MAX];
|
||||||
long pattern_max = PATTERN_MAX;
|
long pattern_max = PATTERN_MAX;
|
||||||
DWORD dwType;
|
DWORD dwType;
|
||||||
/* Find first input or device -- this is the default. */
|
/* Find first input or device -- this is the default. */
|
||||||
PmDeviceID id = pmNoDevice;
|
PmDeviceID id = pmNoDevice;
|
||||||
int i, j;
|
int i, j;
|
||||||
Pm_Initialize(); /* make sure descriptors exist! */
|
Pm_Initialize(); /* make sure descriptors exist! */
|
||||||
for (i = 0; i < pm_descriptor_index; i++) {
|
for (i = 0; i < pm_descriptor_index; i++) {
|
||||||
if (descriptors[i].pub.input == is_input) {
|
if (descriptors[i].pub.input == is_input) {
|
||||||
id = i;
|
id = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Look in registry for a default device name pattern. */
|
/* Look in registry for a default device name pattern. */
|
||||||
if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey) !=
|
if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey) !=
|
||||||
ERROR_SUCCESS) {
|
ERROR_SUCCESS) {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
if (RegOpenKeyEx(hkey, "JavaSoft", 0, KEY_READ, &hkey) !=
|
if (RegOpenKeyEx(hkey, "JavaSoft", 0, KEY_READ, &hkey) !=
|
||||||
ERROR_SUCCESS) {
|
ERROR_SUCCESS) {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
if (RegOpenKeyEx(hkey, "Prefs", 0, KEY_READ, &hkey) !=
|
if (RegOpenKeyEx(hkey, "Prefs", 0, KEY_READ, &hkey) !=
|
||||||
ERROR_SUCCESS) {
|
ERROR_SUCCESS) {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
if (RegOpenKeyEx(hkey, "/Port/Midi", 0, KEY_READ, &hkey) !=
|
if (RegOpenKeyEx(hkey, "/Port/Midi", 0, KEY_READ, &hkey) !=
|
||||||
ERROR_SUCCESS) {
|
ERROR_SUCCESS) {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
if (RegQueryValueEx(hkey, key, NULL, &dwType, pattern, &pattern_max) !=
|
if (RegQueryValueEx(hkey, key, NULL, &dwType, pattern, &pattern_max) !=
|
||||||
ERROR_SUCCESS) {
|
ERROR_SUCCESS) {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* decode pattern: upper case encoded with "/" prefix */
|
/* decode pattern: upper case encoded with "/" prefix */
|
||||||
i = j = 0;
|
i = j = 0;
|
||||||
while (pattern[i]) {
|
while (pattern[i]) {
|
||||||
if (pattern[i] == '/' && pattern[i + 1]) {
|
if (pattern[i] == '/' && pattern[i + 1]) {
|
||||||
pattern[j++] = toupper(pattern[++i]);
|
pattern[j++] = toupper(pattern[++i]);
|
||||||
} else {
|
} else {
|
||||||
pattern[j++] = tolower(pattern[i]);
|
pattern[j++] = tolower(pattern[i]);
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
pattern[j] = 0; /* end of string */
|
pattern[j] = 0; /* end of string */
|
||||||
|
|
||||||
/* now pattern is the string from the registry; search for match */
|
/* now pattern is the string from the registry; search for match */
|
||||||
i = pm_find_default_device(pattern, is_input);
|
i = pm_find_default_device(pattern, is_input);
|
||||||
if (i != pmNoDevice) {
|
if (i != pmNoDevice) {
|
||||||
id = i;
|
id = i;
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PmDeviceID Pm_GetDefaultInputDeviceID() {
|
PmDeviceID Pm_GetDefaultInputDeviceID() {
|
||||||
return pm_get_default_device_id(TRUE,
|
return pm_get_default_device_id(TRUE,
|
||||||
"/P/M_/R/E/C/O/M/M/E/N/D/E/D_/I/N/P/U/T_/D/E/V/I/C/E");
|
"/P/M_/R/E/C/O/M/M/E/N/D/E/D_/I/N/P/U/T_/D/E/V/I/C/E");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PmDeviceID Pm_GetDefaultOutputDeviceID() {
|
PmDeviceID Pm_GetDefaultOutputDeviceID() {
|
||||||
return pm_get_default_device_id(FALSE,
|
return pm_get_default_device_id(FALSE,
|
||||||
"/P/M_/R/E/C/O/M/M/E/N/D/E/D_/O/U/T/P/U/T_/D/E/V/I/C/E");
|
"/P/M_/R/E/C/O/M/M/E/N/D/E/D_/O/U/T/P/U/T_/D/E/V/I/C/E");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
|
|
||||||
void *pm_alloc(size_t s) {
|
void *pm_alloc(size_t s) {
|
||||||
return malloc(s);
|
return malloc(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void pm_free(void *ptr) {
|
void pm_free(void *ptr) {
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
||||||
/* midiwin32.h -- system-specific definitions */
|
/* midiwin32.h -- system-specific definitions */
|
||||||
|
|
||||||
void pm_winmm_init( void );
|
void pm_winmm_init( void );
|
||||||
void pm_winmm_term( void );
|
void pm_winmm_term( void );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,131 +1,131 @@
|
||||||
/* ptmacosx.c -- portable timer implementation for mac os x */
|
/* ptmacosx.c -- portable timer implementation for mac os x */
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <CoreAudio/HostTime.h>
|
#include <CoreAudio/HostTime.h>
|
||||||
|
|
||||||
#import <mach/mach.h>
|
#import <mach/mach.h>
|
||||||
#import <mach/mach_error.h>
|
#import <mach/mach_error.h>
|
||||||
#import <mach/mach_time.h>
|
#import <mach/mach_time.h>
|
||||||
#import <mach/clock.h>
|
#import <mach/clock.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "porttime.h"
|
#include "porttime.h"
|
||||||
#include "sys/time.h"
|
#include "sys/time.h"
|
||||||
#include "pthread.h"
|
#include "pthread.h"
|
||||||
|
|
||||||
#define NSEC_PER_MSEC 1000000
|
#define NSEC_PER_MSEC 1000000
|
||||||
#define THREAD_IMPORTANCE 30
|
#define THREAD_IMPORTANCE 30
|
||||||
|
|
||||||
static int time_started_flag = FALSE;
|
static int time_started_flag = FALSE;
|
||||||
static UInt64 start_time;
|
static UInt64 start_time;
|
||||||
static pthread_t pt_thread_pid;
|
static pthread_t pt_thread_pid;
|
||||||
|
|
||||||
/* note that this is static data -- we only need one copy */
|
/* note that this is static data -- we only need one copy */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int id;
|
int id;
|
||||||
int resolution;
|
int resolution;
|
||||||
PtCallback *callback;
|
PtCallback *callback;
|
||||||
void *userData;
|
void *userData;
|
||||||
} pt_callback_parameters;
|
} pt_callback_parameters;
|
||||||
|
|
||||||
static int pt_callback_proc_id = 0;
|
static int pt_callback_proc_id = 0;
|
||||||
|
|
||||||
static void *Pt_CallbackProc(void *p)
|
static void *Pt_CallbackProc(void *p)
|
||||||
{
|
{
|
||||||
pt_callback_parameters *parameters = (pt_callback_parameters *) p;
|
pt_callback_parameters *parameters = (pt_callback_parameters *) p;
|
||||||
int mytime = 1;
|
int mytime = 1;
|
||||||
|
|
||||||
kern_return_t error;
|
kern_return_t error;
|
||||||
thread_extended_policy_data_t extendedPolicy;
|
thread_extended_policy_data_t extendedPolicy;
|
||||||
thread_precedence_policy_data_t precedencePolicy;
|
thread_precedence_policy_data_t precedencePolicy;
|
||||||
|
|
||||||
extendedPolicy.timeshare = 0;
|
extendedPolicy.timeshare = 0;
|
||||||
error = thread_policy_set(mach_thread_self(), THREAD_EXTENDED_POLICY,
|
error = thread_policy_set(mach_thread_self(), THREAD_EXTENDED_POLICY,
|
||||||
(thread_policy_t)&extendedPolicy,
|
(thread_policy_t)&extendedPolicy,
|
||||||
THREAD_EXTENDED_POLICY_COUNT);
|
THREAD_EXTENDED_POLICY_COUNT);
|
||||||
if (error != KERN_SUCCESS) {
|
if (error != KERN_SUCCESS) {
|
||||||
mach_error("Couldn't set thread timeshare policy", error);
|
mach_error("Couldn't set thread timeshare policy", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
precedencePolicy.importance = THREAD_IMPORTANCE;
|
precedencePolicy.importance = THREAD_IMPORTANCE;
|
||||||
error = thread_policy_set(mach_thread_self(), THREAD_PRECEDENCE_POLICY,
|
error = thread_policy_set(mach_thread_self(), THREAD_PRECEDENCE_POLICY,
|
||||||
(thread_policy_t)&precedencePolicy,
|
(thread_policy_t)&precedencePolicy,
|
||||||
THREAD_PRECEDENCE_POLICY_COUNT);
|
THREAD_PRECEDENCE_POLICY_COUNT);
|
||||||
if (error != KERN_SUCCESS) {
|
if (error != KERN_SUCCESS) {
|
||||||
mach_error("Couldn't set thread precedence policy", error);
|
mach_error("Couldn't set thread precedence policy", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* to kill a process, just increment the pt_callback_proc_id */
|
/* to kill a process, just increment the pt_callback_proc_id */
|
||||||
/* printf("pt_callback_proc_id %d, id %d\n", pt_callback_proc_id, parameters->id); */
|
/* printf("pt_callback_proc_id %d, id %d\n", pt_callback_proc_id, parameters->id); */
|
||||||
while (pt_callback_proc_id == parameters->id) {
|
while (pt_callback_proc_id == parameters->id) {
|
||||||
/* wait for a multiple of resolution ms */
|
/* wait for a multiple of resolution ms */
|
||||||
UInt64 wait_time;
|
UInt64 wait_time;
|
||||||
int delay = mytime++ * parameters->resolution - Pt_Time();
|
int delay = mytime++ * parameters->resolution - Pt_Time();
|
||||||
PtTimestamp timestamp;
|
PtTimestamp timestamp;
|
||||||
if (delay < 0) delay = 0;
|
if (delay < 0) delay = 0;
|
||||||
wait_time = AudioConvertNanosToHostTime((UInt64)delay * NSEC_PER_MSEC);
|
wait_time = AudioConvertNanosToHostTime((UInt64)delay * NSEC_PER_MSEC);
|
||||||
wait_time += AudioGetCurrentHostTime();
|
wait_time += AudioGetCurrentHostTime();
|
||||||
error = mach_wait_until(wait_time);
|
error = mach_wait_until(wait_time);
|
||||||
timestamp = Pt_Time();
|
timestamp = Pt_Time();
|
||||||
(*(parameters->callback))(timestamp, parameters->userData);
|
(*(parameters->callback))(timestamp, parameters->userData);
|
||||||
}
|
}
|
||||||
free(parameters);
|
free(parameters);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PtError Pt_Start(int resolution, PtCallback *callback, void *userData)
|
PtError Pt_Start(int resolution, PtCallback *callback, void *userData)
|
||||||
{
|
{
|
||||||
if (time_started_flag) return ptAlreadyStarted;
|
if (time_started_flag) return ptAlreadyStarted;
|
||||||
start_time = AudioGetCurrentHostTime();
|
start_time = AudioGetCurrentHostTime();
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
int res;
|
int res;
|
||||||
pt_callback_parameters *parms;
|
pt_callback_parameters *parms;
|
||||||
|
|
||||||
parms = (pt_callback_parameters *) malloc(sizeof(pt_callback_parameters));
|
parms = (pt_callback_parameters *) malloc(sizeof(pt_callback_parameters));
|
||||||
if (!parms) return ptInsufficientMemory;
|
if (!parms) return ptInsufficientMemory;
|
||||||
parms->id = pt_callback_proc_id;
|
parms->id = pt_callback_proc_id;
|
||||||
parms->resolution = resolution;
|
parms->resolution = resolution;
|
||||||
parms->callback = callback;
|
parms->callback = callback;
|
||||||
parms->userData = userData;
|
parms->userData = userData;
|
||||||
res = pthread_create(&pt_thread_pid, NULL, Pt_CallbackProc, parms);
|
res = pthread_create(&pt_thread_pid, NULL, Pt_CallbackProc, parms);
|
||||||
if (res != 0) return ptHostError;
|
if (res != 0) return ptHostError;
|
||||||
}
|
}
|
||||||
|
|
||||||
time_started_flag = TRUE;
|
time_started_flag = TRUE;
|
||||||
return ptNoError;
|
return ptNoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PtError Pt_Stop()
|
PtError Pt_Stop()
|
||||||
{
|
{
|
||||||
/* printf("Pt_Stop called\n"); */
|
/* printf("Pt_Stop called\n"); */
|
||||||
pt_callback_proc_id++;
|
pt_callback_proc_id++;
|
||||||
pthread_join(pt_thread_pid, NULL);
|
pthread_join(pt_thread_pid, NULL);
|
||||||
time_started_flag = FALSE;
|
time_started_flag = FALSE;
|
||||||
return ptNoError;
|
return ptNoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Pt_Started()
|
int Pt_Started()
|
||||||
{
|
{
|
||||||
return time_started_flag;
|
return time_started_flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PtTimestamp Pt_Time()
|
PtTimestamp Pt_Time()
|
||||||
{
|
{
|
||||||
UInt64 clock_time, nsec_time;
|
UInt64 clock_time, nsec_time;
|
||||||
clock_time = AudioGetCurrentHostTime() - start_time;
|
clock_time = AudioGetCurrentHostTime() - start_time;
|
||||||
nsec_time = AudioConvertHostTimeToNanos(clock_time);
|
nsec_time = AudioConvertHostTimeToNanos(clock_time);
|
||||||
return (PtTimestamp)(nsec_time / NSEC_PER_MSEC);
|
return (PtTimestamp)(nsec_time / NSEC_PER_MSEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Pt_Sleep(int32_t duration)
|
void Pt_Sleep(int32_t duration)
|
||||||
{
|
{
|
||||||
usleep(duration * 1000);
|
usleep(duration * 1000);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2014 Waves Audio Ltd.
|
Copyright (C) 2013 Valeriy Kamyshniy
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -41,7 +41,7 @@
|
||||||
class ArdourAudioDeviceManager : public WCMRCoreAudioDeviceManager
|
class ArdourAudioDeviceManager : public WCMRCoreAudioDeviceManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ArdourAudioDeviceManager (WCMRAudioDeviceManagerClient *client) : WCMRCoreAudioDeviceManager (client, eFullDuplexDevices, true, eCABS_Simple, false) {};
|
ArdourAudioDeviceManager (WCMRAudioDeviceManagerClient *client) : WCMRCoreAudioDeviceManager (client, eAllDevices) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif defined (_WINDOWS)
|
#elif defined (_WINDOWS)
|
||||||
|
|
@ -51,7 +51,7 @@ class ArdourAudioDeviceManager : public WCMRCoreAudioDeviceManager
|
||||||
class ArdourAudioDeviceManager : public WCMRPortAudioDeviceManager
|
class ArdourAudioDeviceManager : public WCMRPortAudioDeviceManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ArdourAudioDeviceManager (WCMRAudioDeviceManagerClient *client) : WCMRPortAudioDeviceManager (client, eFullDuplexDevices, paASIO) {};
|
ArdourAudioDeviceManager (WCMRAudioDeviceManagerClient *client) : WCMRPortAudioDeviceManager (client, eAllDevices) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -103,10 +103,14 @@ class WavesMidiPort;
|
||||||
|
|
||||||
virtual int set_device_name (const std::string& name);
|
virtual int set_device_name (const std::string& name);
|
||||||
|
|
||||||
|
virtual int drop_device();
|
||||||
|
|
||||||
virtual int set_sample_rate (float);
|
virtual int set_sample_rate (float);
|
||||||
|
|
||||||
virtual int set_buffer_size (uint32_t);
|
virtual int set_buffer_size (uint32_t);
|
||||||
|
|
||||||
|
virtual int set_sample_format (SampleFormat);
|
||||||
|
|
||||||
virtual int set_interleaved (bool yn);
|
virtual int set_interleaved (bool yn);
|
||||||
|
|
||||||
virtual int set_input_channels (uint32_t);
|
virtual int set_input_channels (uint32_t);
|
||||||
|
|
@ -123,6 +127,8 @@ class WavesMidiPort;
|
||||||
|
|
||||||
virtual uint32_t buffer_size () const;
|
virtual uint32_t buffer_size () const;
|
||||||
|
|
||||||
|
virtual SampleFormat sample_format () const;
|
||||||
|
|
||||||
virtual bool interleaved () const;
|
virtual bool interleaved () const;
|
||||||
|
|
||||||
virtual uint32_t input_channels () const;
|
virtual uint32_t input_channels () const;
|
||||||
|
|
@ -275,6 +281,7 @@ class WavesMidiPort;
|
||||||
WavesMidiDeviceManager _midi_device_manager;
|
WavesMidiDeviceManager _midi_device_manager;
|
||||||
|
|
||||||
WCMRAudioDevice *_device;
|
WCMRAudioDevice *_device;
|
||||||
|
SampleFormat _sample_format;
|
||||||
bool _interleaved;
|
bool _interleaved;
|
||||||
static std::string __instantiated_name;
|
static std::string __instantiated_name;
|
||||||
uint32_t _input_channels;
|
uint32_t _input_channels;
|
||||||
|
|
@ -317,8 +324,15 @@ class WavesMidiPort;
|
||||||
pframes_t sample_time,
|
pframes_t sample_time,
|
||||||
uint64_t cycle_start_time_nanos);
|
uint64_t cycle_start_time_nanos);
|
||||||
|
|
||||||
|
int _reset_device (uint32_t buffer_size, float sample_rate);
|
||||||
void _changed_midi_devices ();
|
void _changed_midi_devices ();
|
||||||
|
|
||||||
|
// DO change sample rate and buffer size
|
||||||
|
int _buffer_size_change(uint32_t new_buffer_size);
|
||||||
|
int _sample_rate_change(float new_sample_rate);
|
||||||
|
|
||||||
|
int _device_list_change();
|
||||||
|
|
||||||
int _register_system_audio_ports ();
|
int _register_system_audio_ports ();
|
||||||
int _register_system_midi_ports ();
|
int _register_system_midi_ports ();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,90 +1,90 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2014 Waves Audio Ltd.
|
Copyright (C) 2013 Valeriy Kamyshniy
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "waves_dataport.h"
|
#include "waves_dataport.h"
|
||||||
#include "waves_audiobackend.h"
|
#include "waves_audiobackend.h"
|
||||||
|
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
WavesAudioBackend::set_systemic_input_latency (uint32_t systemic_input_latency)
|
WavesAudioBackend::set_systemic_input_latency (uint32_t systemic_input_latency)
|
||||||
{
|
{
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_systemic_input_latency (): " << systemic_input_latency << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_systemic_input_latency (): " << systemic_input_latency << std::endl;
|
||||||
|
|
||||||
_systemic_input_latency = systemic_input_latency;
|
_systemic_input_latency = systemic_input_latency;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
WavesAudioBackend::set_systemic_output_latency (uint32_t systemic_output_latency)
|
WavesAudioBackend::set_systemic_output_latency (uint32_t systemic_output_latency)
|
||||||
{
|
{
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_systemic_output_latency (): " << systemic_output_latency << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_systemic_output_latency (): " << systemic_output_latency << std::endl;
|
||||||
|
|
||||||
_systemic_output_latency = systemic_output_latency;
|
_systemic_output_latency = systemic_output_latency;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
WavesAudioBackend::systemic_input_latency () const
|
WavesAudioBackend::systemic_input_latency () const
|
||||||
{
|
{
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::systemic_input_latency ()" << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::systemic_input_latency ()" << std::endl;
|
||||||
|
|
||||||
return _systemic_input_latency;
|
return _systemic_input_latency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
WavesAudioBackend::systemic_output_latency () const
|
WavesAudioBackend::systemic_output_latency () const
|
||||||
{
|
{
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::systemic_output_latency ()" << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::systemic_output_latency ()" << std::endl;
|
||||||
|
|
||||||
return _systemic_output_latency;
|
return _systemic_output_latency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
WavesAudioBackend::update_latencies ()
|
WavesAudioBackend::update_latencies ()
|
||||||
{
|
{
|
||||||
// COMMENTED DBG LOGS */ std::cout << "update_latencies:" << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "update_latencies:" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
WavesAudioBackend::set_latency_range (PortHandle port_handle, bool for_playback, LatencyRange latency_range)
|
WavesAudioBackend::set_latency_range (PortHandle port_handle, bool for_playback, LatencyRange latency_range)
|
||||||
{
|
{
|
||||||
if (!_registered (port_handle)) {
|
if (!_registered (port_handle)) {
|
||||||
std::cerr << "WavesAudioBackend::set_latency_range (): Failed to find port [" << std::hex << port_handle << std::dec << "]!" << std::endl;
|
std::cerr << "WavesAudioBackend::set_latency_range (): Failed to find port [" << std::hex << port_handle << std::dec << "]!" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
((WavesDataPort*)port_handle)->set_latency_range (latency_range, for_playback);
|
((WavesDataPort*)port_handle)->set_latency_range (latency_range, for_playback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LatencyRange
|
LatencyRange
|
||||||
WavesAudioBackend::get_latency_range (PortHandle port_handle, bool for_playback)
|
WavesAudioBackend::get_latency_range (PortHandle port_handle, bool for_playback)
|
||||||
{
|
{
|
||||||
if (!_registered (port_handle)) {
|
if (!_registered (port_handle)) {
|
||||||
std::cerr << "WavesAudioBackend::get_latency_range (): Failed to find port [" << std::hex << port_handle << std::dec << "]!" << std::endl;
|
std::cerr << "WavesAudioBackend::get_latency_range (): Failed to find port [" << std::hex << port_handle << std::dec << "]!" << std::endl;
|
||||||
LatencyRange lr = {0,0};
|
LatencyRange lr = {0,0};
|
||||||
return lr;
|
return lr;
|
||||||
}
|
}
|
||||||
return ((WavesDataPort*)port_handle)->latency_range (for_playback);
|
return ((WavesDataPort*)port_handle)->latency_range (for_playback);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,354 +1,353 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2014 Waves Audio Ltd.
|
Copyright (C) 2013 Valeriy Kamyshniy
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
#include <boost/assign/list_of.hpp>
|
||||||
#include <boost/assign/list_of.hpp>
|
|
||||||
|
#include "waves_audiobackend.h"
|
||||||
#include "waves_audiobackend.h"
|
#include "waves_midiport.h"
|
||||||
#include "waves_midiport.h"
|
#include "waves_midi_event.h"
|
||||||
#include "waves_midi_event.h"
|
#include "waves_midi_buffer.h"
|
||||||
#include "waves_midi_buffer.h"
|
|
||||||
|
using namespace ARDOUR;
|
||||||
using namespace ARDOUR;
|
|
||||||
|
#ifdef __MACOS__
|
||||||
#ifdef __MACOS__
|
|
||||||
|
const std::vector<std::string> WavesAudioBackend::__available_midi_options = boost::assign::list_of ("None") ("CoreMIDI");
|
||||||
const std::vector<std::string> WavesAudioBackend::__available_midi_options = boost::assign::list_of ("None") ("CoreMIDI");
|
|
||||||
|
#elif _WINDOWS
|
||||||
#elif _WINDOWS
|
|
||||||
|
const std::vector<std::string> WavesAudioBackend::__available_midi_options = boost::assign::list_of ("None") ("Multimedia Extensions");
|
||||||
const std::vector<std::string> WavesAudioBackend::__available_midi_options = boost::assign::list_of ("None") ("Multimedia Extensions");
|
|
||||||
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
|
std::vector<std::string>
|
||||||
std::vector<std::string>
|
WavesAudioBackend::enumerate_midi_options () const
|
||||||
WavesAudioBackend::enumerate_midi_options () const
|
{
|
||||||
{
|
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::enumerate_midi_options ()" << std::endl;
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::enumerate_midi_options ()" << std::endl;
|
return __available_midi_options;
|
||||||
return __available_midi_options;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
int
|
||||||
int
|
WavesAudioBackend::set_midi_option (const std::string& option)
|
||||||
WavesAudioBackend::set_midi_option (const std::string& option)
|
{
|
||||||
{
|
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_midi_option ( " << option << " )" << std::endl;
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_midi_option ( " << option << " )" << std::endl;
|
if (option == __available_midi_options[0]) {
|
||||||
if (option == __available_midi_options[0]) {
|
_use_midi = false;
|
||||||
_use_midi = false;
|
// COMMENTED DBG LOGS */ std::cout << "\tNO MIDI system used)" << std::endl;
|
||||||
// COMMENTED DBG LOGS */ std::cout << "\tNO MIDI system used)" << std::endl;
|
}
|
||||||
}
|
else if (option == __available_midi_options[1]) {
|
||||||
else if (option == __available_midi_options[1]) {
|
_use_midi = true;
|
||||||
_use_midi = true;
|
// COMMENTED DBG LOGS */ std::cout << "\tNO MIDI system used)" << std::endl;
|
||||||
// COMMENTED DBG LOGS */ std::cout << "\tNO MIDI system used)" << std::endl;
|
}
|
||||||
}
|
else {
|
||||||
else {
|
std::cerr << "WavesAudioBackend::set_midi_option (): Invalid MIDI option!" << std::endl;
|
||||||
std::cerr << "WavesAudioBackend::set_midi_option (): Invalid MIDI option!" << std::endl;
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
return 0;
|
||||||
return 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
std::string
|
||||||
std::string
|
WavesAudioBackend::midi_option () const
|
||||||
WavesAudioBackend::midi_option () const
|
{
|
||||||
{
|
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::midi_option ():" << std::endl;
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::midi_option ():" << std::endl;
|
return * (__available_midi_options.begin () + (_use_midi?1:0));
|
||||||
return * (__available_midi_options.begin () + (_use_midi?1:0));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
int
|
||||||
int
|
WavesAudioBackend::midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buffer, void* port_buffer, uint32_t event_index)
|
||||||
WavesAudioBackend::midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buffer, void* port_buffer, uint32_t event_index)
|
{
|
||||||
{
|
// COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::midi_event_get ():" << std::endl;
|
||||||
// COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::midi_event_get ():" << std::endl;
|
|
||||||
|
if (buffer == NULL) {
|
||||||
if (buffer == NULL) {
|
std::cerr << "WavesAudioBackend::midi_event_get () : NULL in the 'buffer' argument!\n";
|
||||||
std::cerr << "WavesAudioBackend::midi_event_get () : NULL in the 'buffer' argument!\n";
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
if (port_buffer == NULL) {
|
||||||
if (port_buffer == NULL) {
|
std::cerr << "WavesAudioBackend::midi_event_get () : NULL in the 'port_buffer' argument!\n";
|
||||||
std::cerr << "WavesAudioBackend::midi_event_get () : NULL in the 'port_buffer' argument!\n";
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
WavesMidiBuffer& source = * (WavesMidiBuffer*)port_buffer;
|
||||||
WavesMidiBuffer& source = * (WavesMidiBuffer*)port_buffer;
|
|
||||||
|
if (event_index >= source.size ()) {
|
||||||
if (event_index >= source.size ()) {
|
std::cerr << "WavesAudioBackend::midi_event_get () : 'event_index' is out of the number of events stored in 'port_buffer'!\n";
|
||||||
std::cerr << "WavesAudioBackend::midi_event_get () : 'event_index' is out of the number of events stored in 'port_buffer'!\n";
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
WavesMidiEvent* waves_midi_event = source[event_index];
|
||||||
WavesMidiEvent* waves_midi_event = source[event_index];
|
|
||||||
|
timestamp = waves_midi_event->timestamp ();
|
||||||
timestamp = waves_midi_event->timestamp ();
|
size = waves_midi_event->size ();
|
||||||
size = waves_midi_event->size ();
|
*buffer = waves_midi_event->data ();
|
||||||
*buffer = waves_midi_event->data ();
|
|
||||||
|
return 0;
|
||||||
return 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
int
|
||||||
int
|
WavesAudioBackend::midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size)
|
||||||
WavesAudioBackend::midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size)
|
{
|
||||||
{
|
// COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::midi_event_put ():" << std::endl;
|
||||||
// COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::midi_event_put ():" << std::endl;
|
if (buffer == NULL) {
|
||||||
if (buffer == NULL) {
|
std::cerr << "WavesAudioBackend::midi_event_put () : NULL in the 'buffer' argument!\n";
|
||||||
std::cerr << "WavesAudioBackend::midi_event_put () : NULL in the 'buffer' argument!\n";
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
if (port_buffer == NULL) {
|
||||||
if (port_buffer == NULL) {
|
std::cerr << "WavesAudioBackend::midi_event_put () : NULL in the 'port_buffer' argument!\n";
|
||||||
std::cerr << "WavesAudioBackend::midi_event_put () : NULL in the 'port_buffer' argument!\n";
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
WavesMidiBuffer& target = * (WavesMidiBuffer*)port_buffer;
|
||||||
WavesMidiBuffer& target = * (WavesMidiBuffer*)port_buffer;
|
// COMMENTED FREQUENT DBG LOGS */ std::cout << "\t [" << target.name () << "]"<< std::endl;
|
||||||
// COMMENTED FREQUENT DBG LOGS */ std::cout << "\t [" << target.name () << "]"<< std::endl;
|
|
||||||
|
if (target.size () && (pframes_t)target.back ()->timestamp () > timestamp) {
|
||||||
if (target.size () && (pframes_t)target.back ()->timestamp () > timestamp) {
|
std::cerr << "WavesAudioBackend::midi_event_put (): The MIDI Event to put is a bit late!" << std::endl;
|
||||||
std::cerr << "WavesAudioBackend::midi_event_put (): The MIDI Event to put is a bit late!" << std::endl;
|
std::cerr << "\tprev timestamp is " << (pframes_t)target.back ()->timestamp () << " as the current one is " << timestamp << std::endl;
|
||||||
std::cerr << "\tprev timestamp is " << (pframes_t)target.back ()->timestamp () << " as the current one is " << timestamp << std::endl;
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
target.push_back (new WavesMidiEvent (timestamp, buffer, size));
|
||||||
target.push_back (new WavesMidiEvent (timestamp, buffer, size));
|
return 0;
|
||||||
return 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
uint32_t
|
||||||
uint32_t
|
WavesAudioBackend::get_midi_event_count (void* port_buffer)
|
||||||
WavesAudioBackend::get_midi_event_count (void* port_buffer)
|
{
|
||||||
{
|
// COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::get_midi_event_count (): " << std::endl;
|
||||||
// COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::get_midi_event_count (): " << std::endl;
|
|
||||||
|
if (port_buffer == NULL) {
|
||||||
if (port_buffer == NULL) {
|
std::cerr << "WavesAudioBackend::get_midi_event_count () : NULL in the 'port_buffer' argument!\n";
|
||||||
std::cerr << "WavesAudioBackend::get_midi_event_count () : NULL in the 'port_buffer' argument!\n";
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
// COMMENTED FREQUENT DBG LOGS */ std::cout << "\tcount = " << (* (WavesMidiBuffer*)port_buffer).size () << std::endl;
|
||||||
// COMMENTED FREQUENT DBG LOGS */ std::cout << "\tcount = " << (* (WavesMidiBuffer*)port_buffer).size () << std::endl;
|
|
||||||
|
return (* (WavesMidiBuffer*)port_buffer).size ();
|
||||||
return (* (WavesMidiBuffer*)port_buffer).size ();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
void
|
||||||
void
|
WavesAudioBackend::midi_clear (void* port_buffer)
|
||||||
WavesAudioBackend::midi_clear (void* port_buffer)
|
{
|
||||||
{
|
// COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::midi_clear (): " << std::endl;
|
||||||
// COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::midi_clear (): " << std::endl;
|
if (port_buffer == NULL) {
|
||||||
if (port_buffer == NULL) {
|
std::cerr << "WavesAudioBackend::midi_clear () : NULL in the 'port_buffer' argument!\n";
|
||||||
std::cerr << "WavesAudioBackend::midi_clear () : NULL in the 'port_buffer' argument!\n";
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
(* (WavesMidiBuffer*)port_buffer).clear ();
|
||||||
(* (WavesMidiBuffer*)port_buffer).clear ();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
void
|
||||||
void
|
WavesAudioBackend::_changed_midi_devices ()
|
||||||
WavesAudioBackend::_changed_midi_devices ()
|
{
|
||||||
{
|
if (_midi_device_manager.stream (false)) {
|
||||||
if (_midi_device_manager.stream (false)) {
|
std::cerr << "WavesAudioBackend::_changed_midi_devices (): _midi_device_manager.stream (false) failed!" << std::endl;
|
||||||
std::cerr << "WavesAudioBackend::_changed_midi_devices (): _midi_device_manager.stream (false) failed!" << std::endl;
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
_midi_device_manager.stop ();
|
||||||
_midi_device_manager.stop ();
|
|
||||||
|
if (_midi_device_manager.start () != 0) {
|
||||||
if (_midi_device_manager.start () != 0) {
|
std::cerr << "WavesAudioBackend::_changed_midi_devices (): _midi_device_manager.start () failed!" << std::endl;
|
||||||
std::cerr << "WavesAudioBackend::_changed_midi_devices (): _midi_device_manager.start () failed!" << std::endl;
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
if (_register_system_midi_ports () != 0) {
|
||||||
if (_register_system_midi_ports () != 0) {
|
std::cerr << "WavesAudioBackend::_changed_midi_devices (): _register_system_midi_ports () failed!" << std::endl;
|
||||||
std::cerr << "WavesAudioBackend::_changed_midi_devices (): _register_system_midi_ports () failed!" << std::endl;
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
manager.registration_callback ();
|
||||||
manager.registration_callback ();
|
|
||||||
|
if (_midi_device_manager.stream (true)) {
|
||||||
if (_midi_device_manager.stream (true)) {
|
std::cerr << "WavesAudioBackend::_changed_midi_devices (): _midi_device_manager.stream (true) failed!" << std::endl;
|
||||||
std::cerr << "WavesAudioBackend::_changed_midi_devices (): _midi_device_manager.stream (true) failed!" << std::endl;
|
return;
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
void
|
||||||
void
|
WavesAudioBackend::_unregister_system_midi_ports ()
|
||||||
WavesAudioBackend::_unregister_system_midi_ports ()
|
{
|
||||||
{
|
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_unregister_system_midi_ports ()" << std::endl;
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_unregister_system_midi_ports ()" << std::endl;
|
std::vector<WavesMidiPort*> physical_midi_ports = _physical_midi_inputs;
|
||||||
std::vector<WavesMidiPort*> physical_midi_ports = _physical_midi_inputs;
|
physical_midi_ports.insert (physical_midi_ports.begin (), _physical_midi_outputs.begin (), _physical_midi_outputs.end ());
|
||||||
physical_midi_ports.insert (physical_midi_ports.begin (), _physical_midi_outputs.begin (), _physical_midi_outputs.end ());
|
|
||||||
|
for (std::vector<WavesMidiPort*>::const_iterator it = physical_midi_ports.begin (); it != physical_midi_ports.end (); ++it) {
|
||||||
for (std::vector<WavesMidiPort*>::const_iterator it = physical_midi_ports.begin (); it != physical_midi_ports.end (); ++it) {
|
std::vector<WavesDataPort*>::iterator port_iterator = std::find (_ports.begin (), _ports.end (), *it);
|
||||||
std::vector<WavesDataPort*>::iterator port_iterator = std::find (_ports.begin (), _ports.end (), *it);
|
if (port_iterator == _ports.end ()) {
|
||||||
if (port_iterator == _ports.end ()) {
|
std::cerr << "WavesAudioBackend::_unregister_system_midi_ports (): Failed to find port [" << (*it)->name () << "]!" << std::endl;
|
||||||
std::cerr << "WavesAudioBackend::_unregister_system_midi_ports (): Failed to find port [" << (*it)->name () << "]!" << std::endl;
|
}
|
||||||
}
|
else
|
||||||
else
|
_ports.erase (port_iterator);
|
||||||
_ports.erase (port_iterator);
|
delete *it;
|
||||||
delete *it;
|
}
|
||||||
}
|
_physical_midi_inputs.clear ();
|
||||||
_physical_midi_inputs.clear ();
|
_physical_midi_outputs.clear ();
|
||||||
_physical_midi_outputs.clear ();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
int
|
||||||
int
|
WavesAudioBackend::_register_system_midi_ports ()
|
||||||
WavesAudioBackend::_register_system_midi_ports ()
|
{
|
||||||
{
|
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_register_system_midi_ports ()" << std::endl;
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_register_system_midi_ports ()" << std::endl;
|
|
||||||
|
LatencyRange lr = {0,0};
|
||||||
LatencyRange lr = {0,0};
|
lr.min = lr.max = _buffer_size;
|
||||||
lr.min = lr.max = _buffer_size;
|
|
||||||
|
for (size_t i = 0; i<_ports.size ();) {
|
||||||
for (size_t i = 0; i<_ports.size ();) {
|
WavesMidiPort* midi_port = dynamic_cast<WavesMidiPort*> (_ports[i]);
|
||||||
WavesMidiPort* midi_port = dynamic_cast<WavesMidiPort*> (_ports[i]);
|
if (!midi_port || !midi_port->is_physical () || !midi_port->is_terminal ()) {
|
||||||
if (!midi_port || !midi_port->is_physical () || !midi_port->is_terminal ()) {
|
++i;
|
||||||
++i;
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
|
||||||
|
if ((midi_port->is_input () && !midi_port->midi_device ()->is_output ()) ||
|
||||||
if ((midi_port->is_input () && !midi_port->midi_device ()->is_output ()) ||
|
(midi_port->is_output () && !midi_port->midi_device ()->is_input ())) {
|
||||||
(midi_port->is_output () && !midi_port->midi_device ()->is_input ())) {
|
disconnect_all (midi_port);
|
||||||
disconnect_all (midi_port);
|
unregister_port (midi_port);
|
||||||
unregister_port (midi_port);
|
continue; // to be here for further additions in the end of this loop
|
||||||
continue; // to be here for further additions in the end of this loop
|
}
|
||||||
}
|
|
||||||
|
++i;
|
||||||
++i;
|
}
|
||||||
}
|
|
||||||
|
const std::vector<WavesMidiDevice *>& devices = _midi_device_manager.devices ();
|
||||||
const std::vector<WavesMidiDevice *>& devices = _midi_device_manager.devices ();
|
|
||||||
|
for (std::vector<WavesMidiDevice*>::const_iterator it = devices.begin (); it != devices.end (); ++it) {
|
||||||
for (std::vector<WavesMidiDevice*>::const_iterator it = devices.begin (); it != devices.end (); ++it) {
|
if ((*it)->is_input ()) {
|
||||||
if ((*it)->is_input ()) {
|
std::string port_name = "system_midi:" + (*it)->name () + " capture";
|
||||||
std::string port_name = "system_midi:" + (*it)->name () + " capture";
|
WavesDataPort* port = _find_port (port_name);
|
||||||
WavesDataPort* port = _find_port (port_name);
|
WavesMidiPort* midi_port = dynamic_cast<WavesMidiPort*> (port);
|
||||||
WavesMidiPort* midi_port = dynamic_cast<WavesMidiPort*> (port);
|
if (midi_port && (midi_port->type () != DataType::MIDI ||
|
||||||
if (midi_port && (midi_port->type () != DataType::MIDI ||
|
midi_port->midi_device () != *it ||
|
||||||
midi_port->midi_device () != *it ||
|
!midi_port->is_output () ||
|
||||||
!midi_port->is_output () ||
|
!midi_port->is_physical () ||
|
||||||
!midi_port->is_physical () ||
|
!midi_port->is_terminal ())) {
|
||||||
!midi_port->is_terminal ())) {
|
std::cerr << "WavesAudioBackend::_register_system_midi_ports (): the port [" << midi_port->name () << "] is inconsystently constructed!" << std::endl;
|
||||||
std::cerr << "WavesAudioBackend::_register_system_midi_ports (): the port [" << midi_port->name () << "] is inconsystently constructed!" << std::endl;
|
disconnect_all (midi_port);
|
||||||
disconnect_all (midi_port);
|
unregister_port (midi_port);
|
||||||
unregister_port (midi_port);
|
port = NULL;
|
||||||
port = NULL;
|
}
|
||||||
}
|
|
||||||
|
if (port == NULL) {
|
||||||
if (port == NULL) {
|
port = _register_port ( port_name, DataType::MIDI , static_cast<ARDOUR::PortFlags> (IsOutput | IsPhysical | IsTerminal));
|
||||||
port = _register_port ( port_name, DataType::MIDI , static_cast<ARDOUR::PortFlags> (IsOutput | IsPhysical | IsTerminal));
|
if (port == NULL) {
|
||||||
if (port == NULL) {
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
((WavesMidiPort*)port)->set_midi_device (*it);
|
||||||
((WavesMidiPort*)port)->set_midi_device (*it);
|
}
|
||||||
}
|
port->set_latency_range (lr, false);
|
||||||
port->set_latency_range (lr, false);
|
}
|
||||||
}
|
|
||||||
|
if ((*it)->is_output ()) {
|
||||||
if ((*it)->is_output ()) {
|
std::string port_name = "system_midi:" + (*it)->name () + " playback";
|
||||||
std::string port_name = "system_midi:" + (*it)->name () + " playback";
|
WavesDataPort* port = _find_port (port_name);
|
||||||
WavesDataPort* port = _find_port (port_name);
|
WavesMidiPort* midi_port = dynamic_cast<WavesMidiPort*> (port);
|
||||||
WavesMidiPort* midi_port = dynamic_cast<WavesMidiPort*> (port);
|
if (midi_port && (midi_port->type () != DataType::MIDI ||
|
||||||
if (midi_port && (midi_port->type () != DataType::MIDI ||
|
midi_port->midi_device () != *it ||
|
||||||
midi_port->midi_device () != *it ||
|
!midi_port->is_input () ||
|
||||||
!midi_port->is_input () ||
|
!midi_port->is_physical () ||
|
||||||
!midi_port->is_physical () ||
|
!midi_port->is_terminal ())) {
|
||||||
!midi_port->is_terminal ())) {
|
std::cerr << "WavesAudioBackend::_register_system_midi_ports (): the port [" << midi_port->name () << "] is inconsystently constructed!" << std::endl;
|
||||||
std::cerr << "WavesAudioBackend::_register_system_midi_ports (): the port [" << midi_port->name () << "] is inconsystently constructed!" << std::endl;
|
disconnect_all (midi_port);
|
||||||
disconnect_all (midi_port);
|
unregister_port (midi_port);
|
||||||
unregister_port (midi_port);
|
}
|
||||||
}
|
|
||||||
|
if (port == NULL) {
|
||||||
if (port == NULL) {
|
port = _register_port (port_name,
|
||||||
port = _register_port (port_name,
|
DataType::MIDI,
|
||||||
DataType::MIDI,
|
static_cast<ARDOUR::PortFlags> (IsInput | IsPhysical | IsTerminal));
|
||||||
static_cast<ARDOUR::PortFlags> (IsInput | IsPhysical | IsTerminal));
|
if (port == NULL) {
|
||||||
if (port == NULL) {
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
((WavesMidiPort*)port)->set_midi_device ((*it));
|
||||||
((WavesMidiPort*)port)->set_midi_device ((*it));
|
port->set_latency_range (lr, true);
|
||||||
port->set_latency_range (lr, true);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
return 0;
|
||||||
return 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
int
|
||||||
int
|
WavesAudioBackend::_read_midi_data_from_devices ()
|
||||||
WavesAudioBackend::_read_midi_data_from_devices ()
|
{
|
||||||
{
|
// COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::_read_midi_data_from_devices ():" << std::endl;
|
||||||
// COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::_read_midi_data_from_devices ():" << std::endl;
|
if (!_midi_device_manager.is_streaming ())
|
||||||
if (!_midi_device_manager.is_streaming ())
|
return 0;
|
||||||
return 0;
|
|
||||||
|
_midi_device_manager.do_read ();
|
||||||
_midi_device_manager.do_read ();
|
|
||||||
|
for (std::vector<WavesMidiPort*>::iterator it = _physical_midi_inputs.begin (); it != _physical_midi_inputs.end (); ++it) {
|
||||||
for (std::vector<WavesMidiPort*>::iterator it = _physical_midi_inputs.begin (); it != _physical_midi_inputs.end (); ++it) {
|
WavesMidiDevice* midi_device = (*it)->midi_device ();
|
||||||
WavesMidiDevice* midi_device = (*it)->midi_device ();
|
|
||||||
|
WavesMidiBuffer& waves_midi_buffer = (*it)->buffer ();
|
||||||
WavesMidiBuffer& waves_midi_buffer = (*it)->buffer ();
|
waves_midi_buffer.clear ();
|
||||||
waves_midi_buffer.clear ();
|
|
||||||
|
while (WavesMidiEvent *waves_midi_event = midi_device->dequeue_input_waves_midi_event ()) {
|
||||||
while (WavesMidiEvent *waves_midi_event = midi_device->dequeue_input_waves_midi_event ()) {
|
int32_t timestamp_st = _buffer_size - (_sample_time_at_cycle_start - waves_midi_event->timestamp ());
|
||||||
int32_t timestamp_st = _buffer_size - (_sample_time_at_cycle_start - waves_midi_event->timestamp ());
|
|
||||||
|
if (timestamp_st < 0) {
|
||||||
if (timestamp_st < 0) {
|
timestamp_st = 0;
|
||||||
timestamp_st = 0;
|
}
|
||||||
}
|
else if (timestamp_st >= (int32_t)_buffer_size) {
|
||||||
else if (timestamp_st >= (int32_t)_buffer_size) {
|
timestamp_st = _buffer_size - 1;
|
||||||
timestamp_st = _buffer_size - 1;
|
}
|
||||||
}
|
waves_midi_event->set_timestamp (timestamp_st);
|
||||||
waves_midi_event->set_timestamp (timestamp_st);
|
waves_midi_buffer.push_back (waves_midi_event);
|
||||||
waves_midi_buffer.push_back (waves_midi_event);
|
}
|
||||||
}
|
}
|
||||||
}
|
return 0;
|
||||||
return 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
int
|
||||||
int
|
WavesAudioBackend::_write_midi_data_to_devices (pframes_t nframes)
|
||||||
WavesAudioBackend::_write_midi_data_to_devices (pframes_t nframes)
|
{
|
||||||
{
|
if (!_midi_device_manager.is_streaming ())
|
||||||
if (!_midi_device_manager.is_streaming ())
|
return 0;
|
||||||
return 0;
|
|
||||||
|
for (std::vector<WavesMidiPort*>::iterator it = _physical_midi_outputs.begin (); it != _physical_midi_outputs.end (); ++it) {
|
||||||
for (std::vector<WavesMidiPort*>::iterator it = _physical_midi_outputs.begin (); it != _physical_midi_outputs.end (); ++it) {
|
WavesMidiDevice* midi_device = (*it)->midi_device ();
|
||||||
WavesMidiDevice* midi_device = (*it)->midi_device ();
|
WavesMidiBuffer &waves_midi_buffer = * (WavesMidiBuffer*) (*it)->get_buffer (nframes);
|
||||||
WavesMidiBuffer &waves_midi_buffer = * (WavesMidiBuffer*) (*it)->get_buffer (nframes);
|
|
||||||
|
for (WavesMidiBufferIterator it = waves_midi_buffer.begin (); it != waves_midi_buffer.end ();) {
|
||||||
for (WavesMidiBufferIterator it = waves_midi_buffer.begin (); it != waves_midi_buffer.end ();) {
|
WavesMidiEvent* waves_midi_event = *it;
|
||||||
WavesMidiEvent* waves_midi_event = *it;
|
|
||||||
|
waves_midi_buffer.erase (it);
|
||||||
waves_midi_buffer.erase (it);
|
|
||||||
|
waves_midi_event->set_timestamp (_sample_time_at_cycle_start + waves_midi_event->timestamp () + nframes);
|
||||||
waves_midi_event->set_timestamp (_sample_time_at_cycle_start + waves_midi_event->timestamp () + nframes);
|
midi_device->enqueue_output_waves_midi_event (waves_midi_event);
|
||||||
midi_device->enqueue_output_waves_midi_event (waves_midi_event);
|
}
|
||||||
}
|
}
|
||||||
}
|
_midi_device_manager.do_write ();
|
||||||
_midi_device_manager.do_write ();
|
return 0;
|
||||||
return 0;
|
}
|
||||||
}
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,62 +1,62 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2014 Waves Audio Ltd.
|
Copyright (C) 2013 Valeriy Kamyshniy
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "waves_audioport.h"
|
#include "waves_audioport.h"
|
||||||
|
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
||||||
WavesAudioPort::WavesAudioPort (const std::string& port_name, PortFlags flags)
|
WavesAudioPort::WavesAudioPort (const std::string& port_name, PortFlags flags)
|
||||||
: WavesDataPort (port_name, flags)
|
: WavesDataPort (port_name, flags)
|
||||||
{
|
{
|
||||||
memset (_buffer, 0, sizeof (_buffer));
|
memset (_buffer, 0, sizeof (_buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void* WavesAudioPort::get_buffer (pframes_t nframes)
|
void* WavesAudioPort::get_buffer (pframes_t nframes)
|
||||||
{
|
{
|
||||||
if (is_input ()) {
|
if (is_input ()) {
|
||||||
|
|
||||||
std::vector<WavesDataPort*>::const_iterator it = get_connections ().begin ();
|
std::vector<WavesDataPort*>::const_iterator it = get_connections ().begin ();
|
||||||
|
|
||||||
if (it != get_connections ().end ()) {
|
if (it != get_connections ().end ()) {
|
||||||
/* In fact, the static casting to (const WavesAudioPort*) is not that safe.
|
/* In fact, the static casting to (const WavesAudioPort*) is not that safe.
|
||||||
* However, mixing the buffers is assumed in the time critical conditions.
|
* However, mixing the buffers is assumed in the time critical conditions.
|
||||||
* Base class WavesDataPort takes is supposed to provide enough consistentcy
|
* Base class WavesDataPort takes is supposed to provide enough consistentcy
|
||||||
* of the connections.
|
* of the connections.
|
||||||
*/
|
*/
|
||||||
for (memcpy (_buffer, ((const WavesAudioPort*)*it)->const_buffer (), nframes * sizeof (Sample)), ++it;
|
for (memcpy (_buffer, ((const WavesAudioPort*)*it)->const_buffer (), nframes * sizeof (Sample)), ++it;
|
||||||
it != get_connections ().end ();
|
it != get_connections ().end ();
|
||||||
++it) {
|
++it) {
|
||||||
Sample* tgt = buffer ();
|
Sample* tgt = buffer ();
|
||||||
const Sample* src = ((const WavesAudioPort*)*it)->const_buffer ();
|
const Sample* src = ((const WavesAudioPort*)*it)->const_buffer ();
|
||||||
for (uint32_t frame = 0; frame < nframes; ++frame, ++tgt, ++src) {
|
for (uint32_t frame = 0; frame < nframes; ++frame, ++tgt, ++src) {
|
||||||
*tgt += *src;
|
*tgt += *src;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _buffer;
|
return _buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
WavesAudioPort::_wipe_buffer()
|
WavesAudioPort::_wipe_buffer()
|
||||||
{
|
{
|
||||||
memset (_buffer, 0, sizeof (_buffer));
|
memset (_buffer, 0, sizeof (_buffer));
|
||||||
}
|
}
|
||||||
|
|
@ -1,58 +1,58 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2014 Waves Audio Ltd.
|
Copyright (C) 2013 Paul Davis
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __libardour_waves_audioport_h__
|
#ifndef __libardour_waves_audioport_h__
|
||||||
#define __libardour_waves_audioport_h__
|
#define __libardour_waves_audioport_h__
|
||||||
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "waves_dataport.h"
|
#include "waves_dataport.h"
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
class WavesAudioPort : public WavesDataPort {
|
class WavesAudioPort : public WavesDataPort {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum BufferSize {
|
enum BufferSize {
|
||||||
MAX_BUFFER_SIZE_SAMPLES = 8192,
|
MAX_BUFFER_SIZE_SAMPLES = 8192,
|
||||||
MAX_BUFFER_SIZE_BYTES = sizeof (Sample) * MAX_BUFFER_SIZE_SAMPLES
|
MAX_BUFFER_SIZE_BYTES = sizeof (Sample) * MAX_BUFFER_SIZE_SAMPLES
|
||||||
};
|
};
|
||||||
|
|
||||||
WavesAudioPort (const std::string& port_name, PortFlags flags);
|
WavesAudioPort (const std::string& port_name, PortFlags flags);
|
||||||
|
|
||||||
virtual ~WavesAudioPort () { };
|
virtual ~WavesAudioPort () { };
|
||||||
|
|
||||||
virtual DataType type () const { return DataType::AUDIO; };
|
virtual DataType type () const { return DataType::AUDIO; };
|
||||||
|
|
||||||
inline Sample* buffer () { return _buffer; }
|
inline Sample* buffer () { return _buffer; }
|
||||||
inline const Sample* const_buffer () const { return _buffer; }
|
inline const Sample* const_buffer () const { return _buffer; }
|
||||||
|
|
||||||
virtual void* get_buffer (pframes_t nframes);
|
virtual void* get_buffer (pframes_t nframes);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _wipe_buffer();
|
virtual void _wipe_buffer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Sample _buffer[MAX_BUFFER_SIZE_SAMPLES];
|
Sample _buffer[MAX_BUFFER_SIZE_SAMPLES];
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#endif /* __libardour_waves_audioport_h__ */
|
#endif /* __libardour_waves_audioport_h__ */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,142 +1,142 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2014 Waves Audio Ltd.
|
Copyright (C) 2013 Valeriy Kamyshniy
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "waves_dataport.h"
|
#include "waves_dataport.h"
|
||||||
|
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
||||||
WavesDataPort::WavesDataPort (const std::string& inport_name, PortFlags inflags)
|
WavesDataPort::WavesDataPort (const std::string& inport_name, PortFlags inflags)
|
||||||
: _name (inport_name)
|
: _name (inport_name)
|
||||||
, _flags (inflags)
|
, _flags (inflags)
|
||||||
{
|
{
|
||||||
_capture_latency_range.min =
|
_capture_latency_range.min =
|
||||||
_capture_latency_range.max =
|
_capture_latency_range.max =
|
||||||
_playback_latency_range.min =
|
_playback_latency_range.min =
|
||||||
_playback_latency_range.max = 0;
|
_playback_latency_range.max = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WavesDataPort::~WavesDataPort ()
|
WavesDataPort::~WavesDataPort ()
|
||||||
{
|
{
|
||||||
disconnect_all ();
|
disconnect_all ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int WavesDataPort::connect (WavesDataPort *port)
|
int WavesDataPort::connect (WavesDataPort *port)
|
||||||
{
|
{
|
||||||
if (!port) {
|
if (!port) {
|
||||||
std::cerr << "WavesDataPort::connect (): invalid (null) port to connect to!" << std::endl;
|
std::cerr << "WavesDataPort::connect (): invalid (null) port to connect to!" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type () != port->type ()) {
|
if (type () != port->type ()) {
|
||||||
std::cerr << "WavesDataPort::connect (): wrong type of the port to connect to!" << std::endl;
|
std::cerr << "WavesDataPort::connect (): wrong type of the port to connect to!" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_output () && port->is_output ()) {
|
if (is_output () && port->is_output ()) {
|
||||||
std::cerr << "WavesDataPort::connect (): attempt to connect output port to output port!" << std::endl;
|
std::cerr << "WavesDataPort::connect (): attempt to connect output port to output port!" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_input () && port->is_input ()) {
|
if (is_input () && port->is_input ()) {
|
||||||
std::cerr << "WavesDataPort::connect (): attempt to connect input port to input port!" << std::endl;
|
std::cerr << "WavesDataPort::connect (): attempt to connect input port to input port!" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this == port) {
|
if (this == port) {
|
||||||
std::cerr << "WavesDataPort::connect (): attempt to connect port to itself!" << std::endl;
|
std::cerr << "WavesDataPort::connect (): attempt to connect port to itself!" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_connected (port)) {
|
if (is_connected (port)) {
|
||||||
std::cerr << "WavesDataPort::connect (): the ports are already connected!" << std::endl;
|
std::cerr << "WavesDataPort::connect (): the ports are already connected!" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_connect (port, true);
|
_connect (port, true);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WavesDataPort::_connect (WavesDataPort *port, bool api_call)
|
void WavesDataPort::_connect (WavesDataPort *port, bool api_call)
|
||||||
{
|
{
|
||||||
_connections.push_back (port);
|
_connections.push_back (port);
|
||||||
if (api_call) {
|
if (api_call) {
|
||||||
port->_connect (this, false);
|
port->_connect (this, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int WavesDataPort::disconnect (WavesDataPort *port)
|
int WavesDataPort::disconnect (WavesDataPort *port)
|
||||||
{
|
{
|
||||||
if (port == NULL) {
|
if (port == NULL) {
|
||||||
std::cerr << "WavesDataPort::disconnect (): invalid (null) port to disconnect from!" << std::endl;
|
std::cerr << "WavesDataPort::disconnect (): invalid (null) port to disconnect from!" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_connected (port)) {
|
if (!is_connected (port)) {
|
||||||
std::cerr << "WavesDataPort::disconnect (): the ports are not connected!" << std::endl;
|
std::cerr << "WavesDataPort::disconnect (): the ports are not connected!" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_disconnect (port, true);
|
_disconnect (port, true);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WavesDataPort::_disconnect (WavesDataPort *port, bool api_call)
|
void WavesDataPort::_disconnect (WavesDataPort *port, bool api_call)
|
||||||
{
|
{
|
||||||
std::vector<WavesDataPort*>::iterator it = std::find (_connections.begin (), _connections.end (), port);
|
std::vector<WavesDataPort*>::iterator it = std::find (_connections.begin (), _connections.end (), port);
|
||||||
|
|
||||||
if (it != _connections.end ()) { // actually, it's supposed to be always true.
|
if (it != _connections.end ()) { // actually, it's supposed to be always true.
|
||||||
_connections.erase (it);
|
_connections.erase (it);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (api_call) {
|
if (api_call) {
|
||||||
port->_disconnect (this, false);
|
port->_disconnect (this, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_input() && _connections.empty())
|
if (is_input() && _connections.empty())
|
||||||
{
|
{
|
||||||
_wipe_buffer();
|
_wipe_buffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WavesDataPort::disconnect_all ()
|
void WavesDataPort::disconnect_all ()
|
||||||
{
|
{
|
||||||
while (!_connections.empty ()) {
|
while (!_connections.empty ()) {
|
||||||
_connections.back ()->_disconnect (this, false);
|
_connections.back ()->_disconnect (this, false);
|
||||||
_connections.pop_back ();
|
_connections.pop_back ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool WavesDataPort::is_physically_connected () const
|
bool WavesDataPort::is_physically_connected () const
|
||||||
{
|
{
|
||||||
for (std::vector<WavesDataPort*>::const_iterator it = _connections.begin (); it != _connections.end (); ++it) {
|
for (std::vector<WavesDataPort*>::const_iterator it = _connections.begin (); it != _connections.end (); ++it) {
|
||||||
if ((*it)->is_physical ()) {
|
if ((*it)->is_physical ()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,115 +1,115 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2014 Waves Audio Ltd.
|
Copyright (C) 2013 Paul Davis
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __libardour_waves_dataport_h__
|
#ifndef __libardour_waves_dataport_h__
|
||||||
#define __libardour_waves_dataport_h__
|
#define __libardour_waves_dataport_h__
|
||||||
|
|
||||||
#include "ardour/types.h"
|
#include "ardour/types.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
class WavesDataPort {
|
class WavesDataPort {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual ~WavesDataPort ();
|
virtual ~WavesDataPort ();
|
||||||
|
|
||||||
inline const std::string& name () const
|
inline const std::string& name () const
|
||||||
{
|
{
|
||||||
return _name;
|
return _name;
|
||||||
}
|
}
|
||||||
|
|
||||||
int set_name (const std::string &name)
|
int set_name (const std::string &name)
|
||||||
{
|
{
|
||||||
_name = name;
|
_name = name;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual DataType type () const = 0;
|
virtual DataType type () const = 0;
|
||||||
|
|
||||||
inline PortFlags flags () const
|
inline PortFlags flags () const
|
||||||
{
|
{
|
||||||
return _flags;
|
return _flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_input () { return flags () & IsInput; }
|
inline bool is_input () { return flags () & IsInput; }
|
||||||
inline bool is_output () { return flags () & IsOutput; }
|
inline bool is_output () { return flags () & IsOutput; }
|
||||||
inline bool is_physical () { return flags () & IsPhysical; }
|
inline bool is_physical () { return flags () & IsPhysical; }
|
||||||
inline bool is_terminal () { return flags () & IsTerminal; }
|
inline bool is_terminal () { return flags () & IsTerminal; }
|
||||||
inline operator void* () { return (void*)this; }
|
inline operator void* () { return (void*)this; }
|
||||||
|
|
||||||
inline const LatencyRange& latency_range (bool for_playback) const
|
inline const LatencyRange& latency_range (bool for_playback) const
|
||||||
{
|
{
|
||||||
return for_playback ? _playback_latency_range : _capture_latency_range;
|
return for_playback ? _playback_latency_range : _capture_latency_range;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void set_latency_range (const LatencyRange &latency_range, bool for_playback)
|
inline void set_latency_range (const LatencyRange &latency_range, bool for_playback)
|
||||||
{
|
{
|
||||||
if (for_playback)
|
if (for_playback)
|
||||||
{
|
{
|
||||||
_playback_latency_range = latency_range;
|
_playback_latency_range = latency_range;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_capture_latency_range = latency_range;
|
_capture_latency_range = latency_range;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int connect (WavesDataPort *port);
|
int connect (WavesDataPort *port);
|
||||||
|
|
||||||
int disconnect (WavesDataPort *port);
|
int disconnect (WavesDataPort *port);
|
||||||
|
|
||||||
void disconnect_all ();
|
void disconnect_all ();
|
||||||
|
|
||||||
bool inline is_connected (const WavesDataPort *port) const
|
bool inline is_connected (const WavesDataPort *port) const
|
||||||
{
|
{
|
||||||
return std::find (_connections.begin (), _connections.end (), port) != _connections.end ();
|
return std::find (_connections.begin (), _connections.end (), port) != _connections.end ();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inline is_connected () const
|
bool inline is_connected () const
|
||||||
{
|
{
|
||||||
return _connections.size () != 0;
|
return _connections.size () != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_physically_connected () const;
|
bool is_physically_connected () const;
|
||||||
|
|
||||||
inline const std::vector<WavesDataPort *>& get_connections () const { return _connections; }
|
inline const std::vector<WavesDataPort *>& get_connections () const { return _connections; }
|
||||||
|
|
||||||
virtual void* get_buffer (pframes_t nframes) = 0;
|
virtual void* get_buffer (pframes_t nframes) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
WavesDataPort (const std::string& inport_name, PortFlags inflags);
|
WavesDataPort (const std::string& inport_name, PortFlags inflags);
|
||||||
virtual void _wipe_buffer() = 0;
|
virtual void _wipe_buffer() = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::string _name;
|
std::string _name;
|
||||||
const PortFlags _flags;
|
const PortFlags _flags;
|
||||||
LatencyRange _capture_latency_range;
|
LatencyRange _capture_latency_range;
|
||||||
LatencyRange _playback_latency_range;
|
LatencyRange _playback_latency_range;
|
||||||
std::vector<WavesDataPort*> _connections;
|
std::vector<WavesDataPort*> _connections;
|
||||||
|
|
||||||
void _connect (WavesDataPort* port, bool api_call);
|
void _connect (WavesDataPort* port, bool api_call);
|
||||||
void _disconnect (WavesDataPort* port, bool api_call);
|
void _disconnect (WavesDataPort* port, bool api_call);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#endif /* __libardour_waves_dataport_h__ */
|
#endif /* __libardour_waves_dataport_h__ */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,50 +1,49 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2014 Waves Audio Ltd.
|
Copyright (C) 2013 Valeriy amyshniy
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
#include "waves_midi_buffer.h"
|
||||||
#include "waves_midi_buffer.h"
|
#include "waves_midi_event.h"
|
||||||
#include "waves_midi_event.h"
|
|
||||||
|
using namespace ARDOUR;
|
||||||
using namespace ARDOUR;
|
|
||||||
|
WavesMidiBuffer::WavesMidiBuffer (std::string name)
|
||||||
WavesMidiBuffer::WavesMidiBuffer (std::string name)
|
: std::vector<WavesMidiEvent*> ()
|
||||||
: std::vector<WavesMidiEvent*> ()
|
, _name (name)
|
||||||
, _name (name)
|
{
|
||||||
{
|
}
|
||||||
}
|
|
||||||
|
WavesMidiBuffer::~WavesMidiBuffer ()
|
||||||
WavesMidiBuffer::~WavesMidiBuffer ()
|
{
|
||||||
{
|
clear ();
|
||||||
clear ();
|
}
|
||||||
}
|
|
||||||
|
void WavesMidiBuffer::clear ()
|
||||||
void WavesMidiBuffer::clear ()
|
{
|
||||||
{
|
for (WavesMidiBufferIterator it = begin (); it != end (); ++it)
|
||||||
for (WavesMidiBufferIterator it = begin (); it != end (); ++it)
|
delete *it;
|
||||||
delete *it;
|
|
||||||
|
std::vector<WavesMidiEvent*>::clear ();
|
||||||
std::vector<WavesMidiEvent*>::clear ();
|
}
|
||||||
}
|
|
||||||
|
WavesMidiBuffer& WavesMidiBuffer::operator += (const WavesMidiBuffer& source)
|
||||||
WavesMidiBuffer& WavesMidiBuffer::operator += (const WavesMidiBuffer& source)
|
{
|
||||||
{
|
for (WavesMidiBufferConstIterator it = source.begin (); it != source.end (); ++it) {
|
||||||
for (WavesMidiBufferConstIterator it = source.begin (); it != source.end (); ++it) {
|
push_back (new WavesMidiEvent (**it));
|
||||||
push_back (new WavesMidiEvent (**it));
|
}
|
||||||
}
|
return *this;
|
||||||
return *this;
|
}
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,48 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2014 Waves Audio Ltd.
|
Copyright (C) 2013 Valeriy amyshniy
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
#ifndef __libardour_waves_midi_buffer_h__
|
|
||||||
#define __libardour_waves_midi_buffer_h__
|
#ifndef __libardour_waves_midi_buffer_h__
|
||||||
|
#define __libardour_waves_midi_buffer_h__
|
||||||
#include "ardour/types.h"
|
|
||||||
|
#include "ardour/types.h"
|
||||||
namespace ARDOUR {
|
|
||||||
|
namespace ARDOUR {
|
||||||
class WavesMidiEvent;
|
|
||||||
|
class WavesMidiEvent;
|
||||||
class WavesMidiBuffer : public std::vector<WavesMidiEvent*>
|
|
||||||
{
|
class WavesMidiBuffer : public std::vector<WavesMidiEvent*>
|
||||||
public:
|
{
|
||||||
WavesMidiBuffer (std::string name);
|
public:
|
||||||
~WavesMidiBuffer ();
|
WavesMidiBuffer (std::string name);
|
||||||
void clear ();
|
~WavesMidiBuffer ();
|
||||||
WavesMidiBuffer& operator += (const WavesMidiBuffer& source);
|
void clear ();
|
||||||
|
WavesMidiBuffer& operator += (const WavesMidiBuffer& source);
|
||||||
inline const std::string name () { return _name; } // for DBG purpouses;
|
|
||||||
|
inline const std::string name () { return _name; } // for DBG purpouses;
|
||||||
private:
|
|
||||||
const std::string _name;
|
private:
|
||||||
};
|
const std::string _name;
|
||||||
|
};
|
||||||
typedef std::vector<WavesMidiEvent*>::iterator WavesMidiBufferIterator;
|
|
||||||
typedef std::vector<WavesMidiEvent*>::const_iterator WavesMidiBufferConstIterator;
|
typedef std::vector<WavesMidiEvent*>::iterator WavesMidiBufferIterator;
|
||||||
|
typedef std::vector<WavesMidiEvent*>::const_iterator WavesMidiBufferConstIterator;
|
||||||
} // namespace
|
|
||||||
|
} // namespace
|
||||||
#endif /* __libardour_waves_midi_buffer_h__ */
|
|
||||||
|
#endif /* __libardour_waves_midi_buffer_h__ */
|
||||||
|
|
|
||||||
|
|
@ -1,268 +1,268 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2014 Waves Audio Ltd.
|
Copyright (C) 2013 Gorobchenko Dmytro
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "waves_midi_device.h"
|
#include "waves_midi_device.h"
|
||||||
#include "waves_midi_event.h"
|
#include "waves_midi_event.h"
|
||||||
|
|
||||||
// use non-zero latency because we want output to be timestapmed
|
// use non-zero latency because we want output to be timestapmed
|
||||||
#define LATENCY 0
|
#define LATENCY 0
|
||||||
|
|
||||||
#define QUEUE_LENGTH 1024
|
#define QUEUE_LENGTH 1024
|
||||||
|
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
||||||
WavesMidiDevice::WavesMidiDevice (const std::string& device_name)
|
WavesMidiDevice::WavesMidiDevice (const std::string& device_name)
|
||||||
: _pm_input_id (pmNoDevice)
|
: _pm_input_id (pmNoDevice)
|
||||||
, _pm_output_id (pmNoDevice)
|
, _pm_output_id (pmNoDevice)
|
||||||
, _name (device_name)
|
, _name (device_name)
|
||||||
, _input_queue (NULL)
|
, _input_queue (NULL)
|
||||||
, _output_queue (NULL)
|
, _output_queue (NULL)
|
||||||
, _input_pm_stream (NULL)
|
, _input_pm_stream (NULL)
|
||||||
, _output_pm_stream (NULL)
|
, _output_pm_stream (NULL)
|
||||||
, _incomplete_waves_midi_event (NULL)
|
, _incomplete_waves_midi_event (NULL)
|
||||||
{
|
{
|
||||||
validate ();
|
validate ();
|
||||||
}
|
}
|
||||||
|
|
||||||
WavesMidiDevice::~WavesMidiDevice ()
|
WavesMidiDevice::~WavesMidiDevice ()
|
||||||
{
|
{
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::~WavesMidiDevice ():" << name () << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::~WavesMidiDevice ():" << name () << std::endl;
|
||||||
close ();
|
close ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WavesMidiDevice::validate ()
|
WavesMidiDevice::validate ()
|
||||||
{
|
{
|
||||||
_pm_input_id =
|
_pm_input_id =
|
||||||
_pm_output_id = pmNoDevice;
|
_pm_output_id = pmNoDevice;
|
||||||
int count = Pm_CountDevices ();
|
int count = Pm_CountDevices ();
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
|
|
||||||
const PmDeviceInfo* pm_device_info = Pm_GetDeviceInfo (i);
|
const PmDeviceInfo* pm_device_info = Pm_GetDeviceInfo (i);
|
||||||
|
|
||||||
if (pm_device_info == NULL) {
|
if (pm_device_info == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (name () == pm_device_info->name) {
|
if (name () == pm_device_info->name) {
|
||||||
if (pm_device_info->input){
|
if (pm_device_info->input){
|
||||||
_pm_input_id = i;
|
_pm_input_id = i;
|
||||||
}
|
}
|
||||||
if (pm_device_info->output){
|
if (pm_device_info->output){
|
||||||
_pm_output_id = i;
|
_pm_output_id = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
WavesMidiDevice::open (PmTimeProcPtr time_proc, void* time_info)
|
WavesMidiDevice::open (PmTimeProcPtr time_proc, void* time_info)
|
||||||
{
|
{
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::open ():" << name () << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::open ():" << name () << std::endl;
|
||||||
|
|
||||||
if (is_input () && !_input_pm_stream) {
|
if (is_input () && !_input_pm_stream) {
|
||||||
if (pmNoError != Pm_OpenInput (&_input_pm_stream,
|
if (pmNoError != Pm_OpenInput (&_input_pm_stream,
|
||||||
_pm_input_id,
|
_pm_input_id,
|
||||||
NULL,
|
NULL,
|
||||||
1024,
|
1024,
|
||||||
time_proc,
|
time_proc,
|
||||||
time_info)) {
|
time_info)) {
|
||||||
std::cerr << "WavesMidiDevice::open (): Pm_OpenInput () failed for " << _pm_input_id << "-[" << name () << "]!" << std::endl;
|
std::cerr << "WavesMidiDevice::open (): Pm_OpenInput () failed for " << _pm_input_id << "-[" << name () << "]!" << std::endl;
|
||||||
_input_pm_stream = NULL;
|
_input_pm_stream = NULL;
|
||||||
_pm_input_id = pmNoDevice;
|
_pm_input_id = pmNoDevice;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
_input_queue = Pm_QueueCreate (QUEUE_LENGTH, sizeof (const WavesMidiEvent*));
|
_input_queue = Pm_QueueCreate (QUEUE_LENGTH, sizeof (const WavesMidiEvent*));
|
||||||
if (NULL == _input_queue) {
|
if (NULL == _input_queue) {
|
||||||
std::cerr << "WavesMidiDevice::open (): _input_queue = Pm_QueueCreate () failed for " << _pm_input_id << "-[" << name () << "]!" << std::endl;
|
std::cerr << "WavesMidiDevice::open (): _input_queue = Pm_QueueCreate () failed for " << _pm_input_id << "-[" << name () << "]!" << std::endl;
|
||||||
close ();
|
close ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_output () && !_output_pm_stream) {
|
if (is_output () && !_output_pm_stream) {
|
||||||
if (pmNoError != Pm_OpenOutput (&_output_pm_stream,
|
if (pmNoError != Pm_OpenOutput (&_output_pm_stream,
|
||||||
_pm_output_id,
|
_pm_output_id,
|
||||||
NULL,
|
NULL,
|
||||||
1024,
|
1024,
|
||||||
time_proc,
|
time_proc,
|
||||||
time_info,
|
time_info,
|
||||||
LATENCY)) {
|
LATENCY)) {
|
||||||
std::cerr << "WavesMidiDevice::open (): Pm_OpenOutput () failed for " << _pm_output_id << "-[" << name () << "]!" << std::endl;
|
std::cerr << "WavesMidiDevice::open (): Pm_OpenOutput () failed for " << _pm_output_id << "-[" << name () << "]!" << std::endl;
|
||||||
_output_pm_stream = NULL;
|
_output_pm_stream = NULL;
|
||||||
_pm_output_id = pmNoDevice;
|
_pm_output_id = pmNoDevice;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
_output_queue = Pm_QueueCreate (QUEUE_LENGTH, sizeof (const WavesMidiEvent*));
|
_output_queue = Pm_QueueCreate (QUEUE_LENGTH, sizeof (const WavesMidiEvent*));
|
||||||
if (NULL == _output_queue) {
|
if (NULL == _output_queue) {
|
||||||
std::cerr << "WavesMidiDevice::open (): _output_queue = Pm_QueueCreate () failed for " << _pm_output_id << "-[" << name () << "]!" << std::endl;
|
std::cerr << "WavesMidiDevice::open (): _output_queue = Pm_QueueCreate () failed for " << _pm_output_id << "-[" << name () << "]!" << std::endl;
|
||||||
close ();
|
close ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
WavesMidiDevice::close ()
|
WavesMidiDevice::close ()
|
||||||
{
|
{
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::close ():" << name () << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::close ():" << name () << std::endl;
|
||||||
WavesMidiEvent *waves_midi_event;
|
WavesMidiEvent *waves_midi_event;
|
||||||
|
|
||||||
if (_input_pm_stream) {
|
if (_input_pm_stream) {
|
||||||
Pm_Close (_input_pm_stream);
|
Pm_Close (_input_pm_stream);
|
||||||
while (1 == Pm_Dequeue (_input_queue, &waves_midi_event)) {
|
while (1 == Pm_Dequeue (_input_queue, &waves_midi_event)) {
|
||||||
delete waves_midi_event;
|
delete waves_midi_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pm_QueueDestroy (_input_queue);
|
Pm_QueueDestroy (_input_queue);
|
||||||
_input_queue = NULL;
|
_input_queue = NULL;
|
||||||
_input_pm_stream = NULL;
|
_input_pm_stream = NULL;
|
||||||
_pm_input_id = pmNoDevice;
|
_pm_input_id = pmNoDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( _output_pm_stream ) {
|
if ( _output_pm_stream ) {
|
||||||
Pm_Close (_output_pm_stream);
|
Pm_Close (_output_pm_stream);
|
||||||
while (1 == Pm_Dequeue (_output_queue, &waves_midi_event)) {
|
while (1 == Pm_Dequeue (_output_queue, &waves_midi_event)) {
|
||||||
delete waves_midi_event;
|
delete waves_midi_event;
|
||||||
}
|
}
|
||||||
Pm_QueueDestroy (_output_queue);
|
Pm_QueueDestroy (_output_queue);
|
||||||
_output_queue = NULL;
|
_output_queue = NULL;
|
||||||
_output_pm_stream = NULL;
|
_output_pm_stream = NULL;
|
||||||
_pm_output_id = pmNoDevice;
|
_pm_output_id = pmNoDevice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WavesMidiDevice::do_io ()
|
WavesMidiDevice::do_io ()
|
||||||
{
|
{
|
||||||
read_midi ();
|
read_midi ();
|
||||||
write_midi ();
|
write_midi ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WavesMidiDevice::read_midi ()
|
WavesMidiDevice::read_midi ()
|
||||||
{
|
{
|
||||||
if (NULL == _input_pm_stream) {
|
if (NULL == _input_pm_stream) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "]" << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "]" << std::endl;
|
||||||
|
|
||||||
while (Pm_Poll (_input_pm_stream) > 0) {
|
while (Pm_Poll (_input_pm_stream) > 0) {
|
||||||
PmEvent pm_event; // just one message at a time
|
PmEvent pm_event; // just one message at a time
|
||||||
int result = Pm_Read (_input_pm_stream, &pm_event, 1);
|
int result = Pm_Read (_input_pm_stream, &pm_event, 1);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
std::cerr << "WavesMidiDevice::_read_midi (): Pm_Read () failed (" << result << ") for [" << name () << "]!" << std::endl;
|
std::cerr << "WavesMidiDevice::_read_midi (): Pm_Read () failed (" << result << ") for [" << name () << "]!" << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "] evt-tm:" << pm_event.timestamp << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "] evt-tm:" << pm_event.timestamp << std::endl;
|
||||||
if (_incomplete_waves_midi_event == NULL ) {
|
if (_incomplete_waves_midi_event == NULL ) {
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "] : new _incomplete_waves_midi_event" << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "] : new _incomplete_waves_midi_event" << std::endl;
|
||||||
_incomplete_waves_midi_event = new WavesMidiEvent (pm_event.timestamp);
|
_incomplete_waves_midi_event = new WavesMidiEvent (pm_event.timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
WavesMidiEvent *nested_pm_event = _incomplete_waves_midi_event->append_data (pm_event);
|
WavesMidiEvent *nested_pm_event = _incomplete_waves_midi_event->append_data (pm_event);
|
||||||
if (nested_pm_event) {
|
if (nested_pm_event) {
|
||||||
Pm_Enqueue (_input_queue, &nested_pm_event);
|
Pm_Enqueue (_input_queue, &nested_pm_event);
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "] : Pm_Enqueue (_input_queue, nested_pm_event)" << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "] : Pm_Enqueue (_input_queue, nested_pm_event)" << std::endl;
|
||||||
}
|
}
|
||||||
switch ( _incomplete_waves_midi_event->state ()) {
|
switch ( _incomplete_waves_midi_event->state ()) {
|
||||||
case WavesMidiEvent::BROKEN:
|
case WavesMidiEvent::BROKEN:
|
||||||
delete _incomplete_waves_midi_event;
|
delete _incomplete_waves_midi_event;
|
||||||
_incomplete_waves_midi_event = NULL;
|
_incomplete_waves_midi_event = NULL;
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "] : case WavesMidiEvent::BROKEN:" << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "] : case WavesMidiEvent::BROKEN:" << std::endl;
|
||||||
break;
|
break;
|
||||||
case WavesMidiEvent::COMPLETE:
|
case WavesMidiEvent::COMPLETE:
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "] : Pm_Enqueue (_input_queue, _incomplete_waves_midi_event); " << std::hex << (void*)_incomplete_waves_midi_event << std::dec << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_read_midi (): " << _pm_device_id << "-[" << name () << "] : Pm_Enqueue (_input_queue, _incomplete_waves_midi_event); " << std::hex << (void*)_incomplete_waves_midi_event << std::dec << std::endl;
|
||||||
Pm_Enqueue (_input_queue, &_incomplete_waves_midi_event);
|
Pm_Enqueue (_input_queue, &_incomplete_waves_midi_event);
|
||||||
_incomplete_waves_midi_event = NULL;
|
_incomplete_waves_midi_event = NULL;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
WavesMidiDevice::write_midi ()
|
WavesMidiDevice::write_midi ()
|
||||||
{
|
{
|
||||||
if (NULL == _output_pm_stream) {
|
if (NULL == _output_pm_stream) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_write_midi (): " << _pm_device_id << "-[" << name () << "]" << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_write_midi (): " << _pm_device_id << "-[" << name () << "]" << std::endl;
|
||||||
|
|
||||||
PmError err;
|
PmError err;
|
||||||
WavesMidiEvent *waves_midi_event;
|
WavesMidiEvent *waves_midi_event;
|
||||||
|
|
||||||
while (1 == Pm_Dequeue (_output_queue, &waves_midi_event)) {
|
while (1 == Pm_Dequeue (_output_queue, &waves_midi_event)) {
|
||||||
if (waves_midi_event->sysex ()) {
|
if (waves_midi_event->sysex ()) {
|
||||||
// LATENCY compensation
|
// LATENCY compensation
|
||||||
err = Pm_WriteSysEx (_output_pm_stream, waves_midi_event->timestamp () - LATENCY, waves_midi_event->data ());
|
err = Pm_WriteSysEx (_output_pm_stream, waves_midi_event->timestamp () - LATENCY, waves_midi_event->data ());
|
||||||
if (0 > err) {
|
if (0 > err) {
|
||||||
std::cout << "WavesMidiDevice::write_event_to_device (): [" << name () << "] Pm_WriteSysEx () failed (" << err << ")!" << std::endl;
|
std::cout << "WavesMidiDevice::write_event_to_device (): [" << name () << "] Pm_WriteSysEx () failed (" << err << ")!" << std::endl;
|
||||||
};
|
};
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_write_midi (): SYSEX used, ev->tm:" << waves_midi_event->timestamp () - LATENCY << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_write_midi (): SYSEX used, ev->tm:" << waves_midi_event->timestamp () - LATENCY << std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
err = Pm_WriteShort (_output_pm_stream, waves_midi_event->timestamp () - LATENCY, * (PmMessage*)waves_midi_event->data ());
|
err = Pm_WriteShort (_output_pm_stream, waves_midi_event->timestamp () - LATENCY, * (PmMessage*)waves_midi_event->data ());
|
||||||
if (0 > err) {
|
if (0 > err) {
|
||||||
std::cout << "WavesMidiDevice::write_event_to_device (): [" << name () << "] Pm_WriteShort () failed (" << err << ")!" << std::endl;
|
std::cout << "WavesMidiDevice::write_event_to_device (): [" << name () << "] Pm_WriteShort () failed (" << err << ")!" << std::endl;
|
||||||
}
|
}
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_write_midi (): SHORTMSG used, ev->tm:" << waves_midi_event->timestamp () - LATENCY << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::_write_midi (): SHORTMSG used, ev->tm:" << waves_midi_event->timestamp () - LATENCY << std::endl;
|
||||||
}
|
}
|
||||||
delete waves_midi_event;
|
delete waves_midi_event;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
WavesMidiDevice::enqueue_output_waves_midi_event (const WavesMidiEvent* waves_midi_event)
|
WavesMidiDevice::enqueue_output_waves_midi_event (const WavesMidiEvent* waves_midi_event)
|
||||||
{
|
{
|
||||||
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::enqueue_output_waves_midi_event (): " << _pm_device_id << "-[" << name () << "]" << std::endl;
|
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::enqueue_output_waves_midi_event (): " << _pm_device_id << "-[" << name () << "]" << std::endl;
|
||||||
|
|
||||||
if (waves_midi_event == NULL) {
|
if (waves_midi_event == NULL) {
|
||||||
std::cerr << "WavesMidiDevice::put_event_to_callback (): 'waves_midi_event' is NULL!" << std::endl;
|
std::cerr << "WavesMidiDevice::put_event_to_callback (): 'waves_midi_event' is NULL!" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PmError err = Pm_Enqueue (_output_queue, &waves_midi_event);
|
PmError err = Pm_Enqueue (_output_queue, &waves_midi_event);
|
||||||
|
|
||||||
if (0 > err) {
|
if (0 > err) {
|
||||||
std::cerr << "WavesMidiDevice::put_event_to_callback (): Pm_Enqueue () failed (" << err << ")!" << std::endl;
|
std::cerr << "WavesMidiDevice::put_event_to_callback (): Pm_Enqueue () failed (" << err << ")!" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WavesMidiEvent*
|
WavesMidiEvent*
|
||||||
WavesMidiDevice::dequeue_input_waves_midi_event ()
|
WavesMidiDevice::dequeue_input_waves_midi_event ()
|
||||||
{
|
{
|
||||||
WavesMidiEvent* waves_midi_event;
|
WavesMidiEvent* waves_midi_event;
|
||||||
if (Pm_Dequeue (_input_queue, &waves_midi_event) == 1) {
|
if (Pm_Dequeue (_input_queue, &waves_midi_event) == 1) {
|
||||||
return waves_midi_event;
|
return waves_midi_event;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2014 Waves Audio Ltd.
|
Copyright (C) 2013 Gorobchenko Dmytro
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2014 Waves Audio Ltd.
|
Copyright (C) 2013 Paul Davis
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2014 Waves Audio Ltd.
|
Copyright (C) 2013 Gorobchenko Dmytro
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2014 Waves Audio Ltd.
|
Copyright (C) 2013 Valeriy amyshniy
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "waves_midi_event.h"
|
#include "waves_midi_event.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,75 +1,75 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2014 Waves Audio Ltd.
|
Copyright (C) 2013 Valeriy amyshniy
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __libardour_waves_midi_event_h__
|
#ifndef __libardour_waves_midi_event_h__
|
||||||
#define __libardour_waves_midi_event_h__
|
#define __libardour_waves_midi_event_h__
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <portmidi/portmidi.h>
|
#include <portmidi/portmidi.h>
|
||||||
#include "ardour/types.h"
|
#include "ardour/types.h"
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
class WavesMidiEvent
|
class WavesMidiEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum State {
|
enum State {
|
||||||
INCOMPLETE,
|
INCOMPLETE,
|
||||||
BROKEN,
|
BROKEN,
|
||||||
COMPLETE
|
COMPLETE
|
||||||
};
|
};
|
||||||
|
|
||||||
WavesMidiEvent (PmTimestamp timestamp);
|
WavesMidiEvent (PmTimestamp timestamp);
|
||||||
WavesMidiEvent (PmTimestamp timestamp, const uint8_t* data, size_t datalen);
|
WavesMidiEvent (PmTimestamp timestamp, const uint8_t* data, size_t datalen);
|
||||||
WavesMidiEvent (const WavesMidiEvent& source);
|
WavesMidiEvent (const WavesMidiEvent& source);
|
||||||
~WavesMidiEvent ();
|
~WavesMidiEvent ();
|
||||||
|
|
||||||
WavesMidiEvent *append_data (const PmEvent &midi_event);
|
WavesMidiEvent *append_data (const PmEvent &midi_event);
|
||||||
|
|
||||||
inline State state () const { return _state; };
|
inline State state () const { return _state; };
|
||||||
inline size_t size () const { return _size; };
|
inline size_t size () const { return _size; };
|
||||||
inline PmTimestamp timestamp () const { return _timestamp; };
|
inline PmTimestamp timestamp () const { return _timestamp; };
|
||||||
inline void set_timestamp (PmTimestamp time_stamp) { _timestamp = time_stamp; };
|
inline void set_timestamp (PmTimestamp time_stamp) { _timestamp = time_stamp; };
|
||||||
inline const unsigned char* const_data () const { return _data; };
|
inline const unsigned char* const_data () const { return _data; };
|
||||||
inline unsigned char* data () { return _data; };
|
inline unsigned char* data () { return _data; };
|
||||||
inline bool operator< (const WavesMidiEvent &other) const { return timestamp () < other.timestamp (); };
|
inline bool operator< (const WavesMidiEvent &other) const { return timestamp () < other.timestamp (); };
|
||||||
inline bool sysex () const { return _data && (*_data == SYSEX); };
|
inline bool sysex () const { return _data && (*_data == SYSEX); };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SYSEX = 0xF0,
|
SYSEX = 0xF0,
|
||||||
EOX = 0xF7,
|
EOX = 0xF7,
|
||||||
REAL_TIME_FIRST = 0xF8,
|
REAL_TIME_FIRST = 0xF8,
|
||||||
STATUS_FIRST = 0x80
|
STATUS_FIRST = 0x80
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t _size;
|
size_t _size;
|
||||||
PmTimestamp _timestamp;
|
PmTimestamp _timestamp;
|
||||||
uint8_t *_data;
|
uint8_t *_data;
|
||||||
State _state;
|
State _state;
|
||||||
|
|
||||||
static size_t _midi_message_size (PmMessage midi_message);
|
static size_t _midi_message_size (PmMessage midi_message);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#endif /* __libardour_waves_midi_event_h__ */
|
#endif /* __libardour_waves_midi_event_h__ */
|
||||||
|
|
|
||||||
|
|
@ -1,61 +1,61 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2014 Waves Audio Ltd.
|
Copyright (C) 2013 Gorobchenko Dmytro
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "waves_midiport.h"
|
#include "waves_midiport.h"
|
||||||
#include "waves_midi_event.h"
|
#include "waves_midi_event.h"
|
||||||
|
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
||||||
WavesMidiPort::WavesMidiPort (const std::string& port_name, PortFlags flags)
|
WavesMidiPort::WavesMidiPort (const std::string& port_name, PortFlags flags)
|
||||||
: WavesDataPort (port_name, flags)
|
: WavesDataPort (port_name, flags)
|
||||||
, _midi_device (NULL)
|
, _midi_device (NULL)
|
||||||
, _waves_midi_buffer (port_name)
|
, _waves_midi_buffer (port_name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void*
|
void*
|
||||||
WavesMidiPort::get_buffer (pframes_t nframes)
|
WavesMidiPort::get_buffer (pframes_t nframes)
|
||||||
{
|
{
|
||||||
if (is_input ()) {
|
if (is_input ()) {
|
||||||
std::vector<WavesDataPort*>::const_iterator cit = get_connections ().begin ();
|
std::vector<WavesDataPort*>::const_iterator cit = get_connections ().begin ();
|
||||||
if (cit != get_connections ().end ()) {
|
if (cit != get_connections ().end ()) {
|
||||||
_waves_midi_buffer.clear ();
|
_waves_midi_buffer.clear ();
|
||||||
WavesMidiBuffer& target = _waves_midi_buffer;
|
WavesMidiBuffer& target = _waves_midi_buffer;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* In fact, the static casting to (const WavesMidiPort*) is not that safe.
|
/* In fact, the static casting to (const WavesMidiPort*) is not that safe.
|
||||||
* However, mixing the buffers is assumed in the time critical conditions.
|
* However, mixing the buffers is assumed in the time critical conditions.
|
||||||
* Base class WavesDataPort is supposed to provide enough consistentcy
|
* Base class WavesDataPort is supposed to provide enough consistentcy
|
||||||
* of the connections.
|
* of the connections.
|
||||||
*/
|
*/
|
||||||
target += ((const WavesMidiPort*)*cit)->const_buffer ();
|
target += ((const WavesMidiPort*)*cit)->const_buffer ();
|
||||||
}while((++cit) != get_connections ().end ());
|
}while((++cit) != get_connections ().end ());
|
||||||
|
|
||||||
std::sort (target.begin (), target.end ());
|
std::sort (target.begin (), target.end ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &_waves_midi_buffer;
|
return &_waves_midi_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WavesMidiPort::_wipe_buffer()
|
WavesMidiPort::_wipe_buffer()
|
||||||
{
|
{
|
||||||
_waves_midi_buffer.clear ();
|
_waves_midi_buffer.clear ();
|
||||||
}
|
}
|
||||||
|
|
@ -1,64 +1,64 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2014 Waves Audio Ltd.
|
Copyright (C) 2013 Gorobchenko Dmytro
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __libardour_waves_midiport_h__
|
#ifndef __libardour_waves_midiport_h__
|
||||||
#define __libardour_waves_midiport_h__
|
#define __libardour_waves_midiport_h__
|
||||||
|
|
||||||
#include "waves_dataport.h"
|
#include "waves_dataport.h"
|
||||||
#include "waves_midi_buffer.h"
|
#include "waves_midi_buffer.h"
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
class WavesMidiEvent;
|
class WavesMidiEvent;
|
||||||
class WavesMidiDevice;
|
class WavesMidiDevice;
|
||||||
class WavesMidiEvent;
|
class WavesMidiEvent;
|
||||||
|
|
||||||
class WavesMidiPort : public WavesDataPort {
|
class WavesMidiPort : public WavesDataPort {
|
||||||
public:
|
public:
|
||||||
enum BufferSize {
|
enum BufferSize {
|
||||||
// This value has nothing to do with reality as buffer of MIDI Port is not a flat array.
|
// This value has nothing to do with reality as buffer of MIDI Port is not a flat array.
|
||||||
// It's an iterated list.
|
// It's an iterated list.
|
||||||
MAX_BUFFER_SIZE_BYTES = 8192
|
MAX_BUFFER_SIZE_BYTES = 8192
|
||||||
};
|
};
|
||||||
|
|
||||||
WavesMidiPort (const std::string& port_name, PortFlags flags);
|
WavesMidiPort (const std::string& port_name, PortFlags flags);
|
||||||
virtual ~WavesMidiPort (){};
|
virtual ~WavesMidiPort (){};
|
||||||
|
|
||||||
virtual DataType type () const { return DataType::MIDI; };
|
virtual DataType type () const { return DataType::MIDI; };
|
||||||
|
|
||||||
virtual void* get_buffer (pframes_t nframes);
|
virtual void* get_buffer (pframes_t nframes);
|
||||||
|
|
||||||
inline WavesMidiBuffer& buffer () { return _waves_midi_buffer; }
|
inline WavesMidiBuffer& buffer () { return _waves_midi_buffer; }
|
||||||
inline const WavesMidiBuffer& const_buffer () const { return _waves_midi_buffer; }
|
inline const WavesMidiBuffer& const_buffer () const { return _waves_midi_buffer; }
|
||||||
|
|
||||||
inline void set_midi_device (WavesMidiDevice* midi_device) { _midi_device = midi_device; };
|
inline void set_midi_device (WavesMidiDevice* midi_device) { _midi_device = midi_device; };
|
||||||
inline WavesMidiDevice* midi_device () const { return _midi_device; };
|
inline WavesMidiDevice* midi_device () const { return _midi_device; };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _wipe_buffer();
|
virtual void _wipe_buffer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WavesMidiDevice * _midi_device;
|
WavesMidiDevice * _midi_device;
|
||||||
WavesMidiBuffer _waves_midi_buffer;
|
WavesMidiBuffer _waves_midi_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#endif /* __libardour_waves_midiport_h__ */
|
#endif /* __libardour_waves_midiport_h__ */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifndef __WCFourCC_h__
|
#ifndef __WCFourCC_h__
|
||||||
#define __WCFourCC_h__
|
#define __WCFourCC_h__
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#if !defined(__WTByteOrder_h__)
|
#if !defined(__WTByteOrder_h__)
|
||||||
#define __WTByteOrder_h__
|
#define __WTByteOrder_h__
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifndef __WUComPtr_h__
|
#ifndef __WUComPtr_h__
|
||||||
#define __WUComPtr_h__
|
#define __WUComPtr_h__
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifndef __WUDefines_h__
|
#ifndef __WUDefines_h__
|
||||||
#define __WUDefines_h__
|
#define __WUDefines_h__
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifndef __WUMathConsts_h__
|
#ifndef __WUMathConsts_h__
|
||||||
#define __WUMathConsts_h__
|
#define __WUMathConsts_h__
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifndef __WUTypes_h__
|
#ifndef __WUTypes_h__
|
||||||
#define __WUTypes_h__
|
#define __WUTypes_h__
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,49 +1,31 @@
|
||||||
/*
|
#ifndef __IncludeWindows_h__
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
#define __IncludeWindows_h__
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
#ifdef _WINDOWS
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
|
/* Copy to include
|
||||||
|
#include "IncludeWindows.h"
|
||||||
*/
|
*/
|
||||||
#ifndef __IncludeWindows_h__
|
|
||||||
#define __IncludeWindows_h__
|
#ifndef _WIN32_WINNT
|
||||||
|
#define _WIN32_WINNT 0x0601 // Windows 7
|
||||||
#ifdef _WINDOWS
|
#endif
|
||||||
|
|
||||||
/* Copy to include
|
#ifndef WINVER
|
||||||
#include "IncludeWindows.h"
|
#define WINVER 0x0601 // Windows 7
|
||||||
*/
|
#endif
|
||||||
|
|
||||||
#ifndef _WIN32_WINNT
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
#define _WIN32_WINNT 0x0601 // Windows 7
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef WINVER
|
#ifndef NOMINMAX
|
||||||
#define WINVER 0x0601 // Windows 7
|
#define NOMINMAX // DO NOT REMOVE NOMINMAX - DOING SO CAUSES CONFLICTS WITH STD INCLUDES (<limits> ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#include <WinSock2.h>
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#include <Windows.h>
|
||||||
#endif
|
#include <objbase.h>
|
||||||
|
#endif // #if _WINDOWS
|
||||||
#ifndef NOMINMAX
|
#endif // #ifndef __IncludeWindows_h__
|
||||||
#define NOMINMAX // DO NOT REMOVE NOMINMAX - DOING SO CAUSES CONFLICTS WITH STD INCLUDES (<limits> ...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <WinSock2.h>
|
|
||||||
#include <Windows.h>
|
|
||||||
#include <objbase.h>
|
|
||||||
#endif // #if _WINDOWS
|
|
||||||
#endif // #ifndef __IncludeWindows_h__
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,6 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
// Copyright (c) 2008 Waves Audio Ltd. All rights reserved.
|
||||||
//
|
//
|
||||||
//! \file WCMRAudioDeviceManager.cpp
|
//! \file WCMRAudioDeviceManager.cpp
|
||||||
//!
|
//!
|
||||||
|
|
@ -27,10 +10,6 @@
|
||||||
#include "WCMRAudioDeviceManager.h"
|
#include "WCMRAudioDeviceManager.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//**********************************************************************************************
|
//**********************************************************************************************
|
||||||
// WCMRAudioDevice::WCMRAudioDevice
|
// WCMRAudioDevice::WCMRAudioDevice
|
||||||
//
|
//
|
||||||
|
|
@ -39,27 +18,21 @@
|
||||||
//! and streaming will also be provided by the derived implementations.
|
//! and streaming will also be provided by the derived implementations.
|
||||||
//!
|
//!
|
||||||
//! \param *pManager : The audio device manager that's managing this device.
|
//! \param *pManager : The audio device manager that's managing this device.
|
||||||
//!
|
|
||||||
//! \return Nothing.
|
//! \return Nothing.
|
||||||
//!
|
//!
|
||||||
//**********************************************************************************************
|
//**********************************************************************************************
|
||||||
WCMRAudioDevice::WCMRAudioDevice (WCMRAudioDeviceManager *pManager)
|
WCMRAudioDevice::WCMRAudioDevice (WCMRAudioDeviceManager *pManager) :
|
||||||
|
m_pMyManager (pManager)
|
||||||
|
, m_ConnectionStatus (DeviceDisconnected)
|
||||||
|
, m_IsActive (false)
|
||||||
|
, m_IsStreaming (false)
|
||||||
|
, m_CurrentSamplingRate (-1)
|
||||||
|
, m_CurrentBufferSize (0)
|
||||||
|
, m_LeftMonitorChannel (-1)
|
||||||
|
, m_RightMonitorChannel (-1)
|
||||||
|
, m_MonitorGain (1.0f)
|
||||||
{
|
{
|
||||||
m_pMyManager = pManager;
|
|
||||||
m_DeviceName = "Unknown";
|
m_DeviceName = "Unknown";
|
||||||
|
|
||||||
m_ConnectionStatus = DeviceDisconnected;
|
|
||||||
m_IsActive = false;
|
|
||||||
m_IsStreaming = false;
|
|
||||||
|
|
||||||
m_CurrentSamplingRate = -1;
|
|
||||||
m_CurrentBufferSize = 0;
|
|
||||||
|
|
||||||
m_LeftMonitorChannel = -1;
|
|
||||||
m_RightMonitorChannel = -1;
|
|
||||||
m_MonitorGain = 1.0f;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -565,6 +538,7 @@ uint32_t WCMRAudioDevice::GetLatency (bool isInput)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//**********************************************************************************************
|
//**********************************************************************************************
|
||||||
// WCMRAudioDeviceManager::WCMRAudioDeviceManager
|
// WCMRAudioDeviceManager::WCMRAudioDeviceManager
|
||||||
//
|
//
|
||||||
|
|
@ -576,15 +550,13 @@ uint32_t WCMRAudioDevice::GetLatency (bool isInput)
|
||||||
//!
|
//!
|
||||||
//**********************************************************************************************
|
//**********************************************************************************************
|
||||||
WCMRAudioDeviceManager::WCMRAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient, eAudioDeviceFilter eCurAudioDeviceFilter)
|
WCMRAudioDeviceManager::WCMRAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient, eAudioDeviceFilter eCurAudioDeviceFilter)
|
||||||
: m_pTheClient (pTheClient)
|
: m_eAudioDeviceFilter(eCurAudioDeviceFilter)
|
||||||
, m_eAudioDeviceFilter(eCurAudioDeviceFilter)
|
, m_CurrentDevice(0)
|
||||||
|
, m_pTheClient (pTheClient)
|
||||||
{
|
{
|
||||||
//The derived classes will do lot more init!
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//**********************************************************************************************
|
//**********************************************************************************************
|
||||||
// WCMRAudioDeviceManager::~WCMRAudioDeviceManager
|
// WCMRAudioDeviceManager::~WCMRAudioDeviceManager
|
||||||
//
|
//
|
||||||
|
|
@ -599,19 +571,21 @@ WCMRAudioDeviceManager::~WCMRAudioDeviceManager()
|
||||||
{
|
{
|
||||||
AUTO_FUNC_DEBUG;
|
AUTO_FUNC_DEBUG;
|
||||||
|
|
||||||
|
std::cout << "API::Destroying AudioDeviceManager " << std::endl;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//Need to call release on our devices, and erase them from list
|
// clean up device info list
|
||||||
std::vector<WCMRAudioDevice*>::iterator deviceIter;
|
{
|
||||||
while (m_Devices.size())
|
wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceInfoVecMutex);
|
||||||
{
|
while( m_DeviceInfoVec.size() )
|
||||||
WCMRAudioDevice *pDeviceToRelease = m_Devices.back();
|
{
|
||||||
m_Devices.pop_back();
|
DeviceInfo* devInfo = m_DeviceInfoVec.back();
|
||||||
if (pDeviceToRelease)
|
m_DeviceInfoVec.pop_back();
|
||||||
SAFE_RELEASE (pDeviceToRelease);
|
delete devInfo;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//The derived classes may want to do additional de-int!
|
delete m_CurrentDevice;
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
|
|
@ -621,109 +595,48 @@ WCMRAudioDeviceManager::~WCMRAudioDeviceManager()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WCMRAudioDevice* WCMRAudioDeviceManager::InitNewCurrentDevice(const std::string & deviceName)
|
||||||
|
|
||||||
//**********************************************************************************************
|
|
||||||
// WCMRAudioDeviceManager::DoIdle_Private
|
|
||||||
//
|
|
||||||
//! Used for idle time processing. This calls each device's DoIdle so that it can perform it's own idle processing.
|
|
||||||
//!
|
|
||||||
//! \param none
|
|
||||||
//!
|
|
||||||
//! \return noErr if no devices have returned an error. An error code if any of the devices returned error.
|
|
||||||
//!
|
|
||||||
//**********************************************************************************************
|
|
||||||
WTErr WCMRAudioDeviceManager::DoIdle_Private()
|
|
||||||
{
|
{
|
||||||
WTErr retVal = eNoErr;
|
return initNewCurrentDeviceImpl(deviceName);
|
||||||
|
}
|
||||||
//Need to call DoIdle of all our devices...
|
|
||||||
std::vector<WCMRAudioDevice*>::iterator deviceIter;
|
|
||||||
for (deviceIter = m_Devices.begin(); deviceIter != m_Devices.end(); deviceIter++)
|
void WCMRAudioDeviceManager::DestroyCurrentDevice()
|
||||||
|
{
|
||||||
|
return destroyCurrentDeviceImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const DeviceInfoVec WCMRAudioDeviceManager::DeviceInfoList() const
|
||||||
|
{
|
||||||
|
wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceInfoVecMutex);
|
||||||
|
return m_DeviceInfoVec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WTErr WCMRAudioDeviceManager::GetDeviceInfoByName(const std::string & nameToMatch, DeviceInfo & devInfo) const
|
||||||
|
{
|
||||||
|
wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceInfoVecMutex);
|
||||||
|
DeviceInfoVecConstIter iter = m_DeviceInfoVec.begin();
|
||||||
|
for (; iter != m_DeviceInfoVec.end(); ++iter)
|
||||||
{
|
{
|
||||||
WTErr thisDeviceErr = (*deviceIter)->DoIdle();
|
if (nameToMatch == (*iter)->m_DeviceName)
|
||||||
|
{
|
||||||
if (thisDeviceErr != eNoErr)
|
devInfo = *(*iter);
|
||||||
retVal = thisDeviceErr;
|
return eNoErr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (retVal);
|
return eRMResNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WTErr WCMRAudioDeviceManager::GetDeviceBufferSizes(const std::string & nameToMatch, std::vector<int>& bufferSizes) const
|
||||||
|
|
||||||
//**********************************************************************************************
|
|
||||||
// WCMRAudioDeviceManager::Devices_Private
|
|
||||||
//
|
|
||||||
//! Retrieve list of devices managed by this manager.
|
|
||||||
//!
|
|
||||||
//! \param none
|
|
||||||
//!
|
|
||||||
//! \return A vector containing the list of devices.
|
|
||||||
//!
|
|
||||||
//**********************************************************************************************
|
|
||||||
const WCMRAudioDeviceList& WCMRAudioDeviceManager::Devices_Private() const
|
|
||||||
{
|
{
|
||||||
return (m_Devices);
|
return getDeviceBufferSizesImpl(nameToMatch, bufferSizes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//**********************************************************************************************
|
|
||||||
// *WCMRAudioDeviceManager::GetDeviceByName_Private
|
|
||||||
//
|
|
||||||
//! Locates a device based on device name.
|
|
||||||
//!
|
|
||||||
//! \param nameToMatch : Device to look for.
|
|
||||||
//!
|
|
||||||
//! \return Pointer to the device object if found, NULL otherwise.
|
|
||||||
//!
|
|
||||||
//**********************************************************************************************
|
|
||||||
WCMRAudioDevice *WCMRAudioDeviceManager::GetDeviceByName_Private(const std::string& nameToMatch) const
|
|
||||||
{
|
|
||||||
//Need to check all our devices...
|
|
||||||
WCMRAudioDevice *pRetVal = NULL;
|
|
||||||
|
|
||||||
WCMRAudioDeviceListConstIter deviceIter;
|
|
||||||
for (deviceIter = m_Devices.begin(); deviceIter != m_Devices.end(); deviceIter++)
|
|
||||||
{
|
|
||||||
if ((*deviceIter)->DeviceName() == nameToMatch)
|
|
||||||
{
|
|
||||||
pRetVal = *deviceIter;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (pRetVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
//**********************************************************************************************
|
|
||||||
// *WCMRAudioDeviceManager::GetDefaultDevice
|
|
||||||
//
|
|
||||||
//! Locates a device based on device name.
|
|
||||||
//!
|
|
||||||
//! \param nameToMatch : Device to look for.
|
|
||||||
//!
|
|
||||||
//! \return Pointer to the device object if found, NULL otherwise.
|
|
||||||
//!
|
|
||||||
//**********************************************************************************************
|
|
||||||
WCMRAudioDevice *WCMRAudioDeviceManager::GetDefaultDevice_Private()
|
|
||||||
{
|
|
||||||
//Need to check all our devices...
|
|
||||||
WCMRAudioDevice *pRetVal = NULL;
|
|
||||||
|
|
||||||
WCMRAudioDeviceListIter deviceIter = m_Devices.begin();
|
|
||||||
if(deviceIter != m_Devices.end())
|
|
||||||
{
|
|
||||||
pRetVal = *deviceIter;
|
|
||||||
}
|
|
||||||
return (pRetVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//**********************************************************************************************
|
//**********************************************************************************************
|
||||||
// WCMRAudioDeviceManager::NotifyClient
|
// WCMRAudioDeviceManager::NotifyClient
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,6 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
// Copyright (c) 2008 Waves Audio Ltd. All rights reserved.
|
||||||
//
|
//
|
||||||
//! \file WCMRAudioDeviceManager.h
|
//! \file WCMRAudioDeviceManager.h
|
||||||
//!
|
//!
|
||||||
|
|
@ -42,19 +25,35 @@
|
||||||
#include "WCRefManager.h"
|
#include "WCRefManager.h"
|
||||||
#include "BasicTypes/WUTypes.h"
|
#include "BasicTypes/WUTypes.h"
|
||||||
#include "WUErrors.h"
|
#include "WUErrors.h"
|
||||||
|
#include "WCThreadSafe.h"
|
||||||
|
|
||||||
#define WCUNUSEDPARAM(a)
|
#define WCUNUSEDPARAM(a)
|
||||||
|
|
||||||
//forward decl.
|
|
||||||
class WCMRAudioConnection;
|
|
||||||
class WCMRAudioDevice;
|
class WCMRAudioDevice;
|
||||||
class WCMRAudioDeviceManager;
|
class WCMRAudioDeviceManager;
|
||||||
|
|
||||||
typedef std::vector<WCMRAudioDevice *> WCMRAudioDeviceList; ///< Vector for audio devices
|
typedef unsigned int DeviceID;
|
||||||
typedef std::vector<WCMRAudioDevice *>::iterator WCMRAudioDeviceListIter; ///< Vector iterator for audio devices
|
|
||||||
typedef std::vector<WCMRAudioDevice *>::const_iterator WCMRAudioDeviceListConstIter; ///< Vector iterator for audio devices
|
|
||||||
typedef std::vector<WCMRAudioConnection *> WCMRAudioConnectionsList; ///< Vector for audio devices
|
|
||||||
|
|
||||||
|
struct DeviceInfo
|
||||||
|
{
|
||||||
|
DeviceID m_DeviceId;
|
||||||
|
std::string m_DeviceName;
|
||||||
|
std::vector<int> m_AvailableSampleRates;
|
||||||
|
unsigned int m_MaxInputChannels;
|
||||||
|
unsigned int m_MaxOutputChannels;
|
||||||
|
|
||||||
|
DeviceInfo():
|
||||||
|
m_DeviceId(-1), m_DeviceName("Unknown"), m_MaxInputChannels(0), m_MaxOutputChannels(0)
|
||||||
|
{};
|
||||||
|
|
||||||
|
DeviceInfo(unsigned int deviceID, const std::string & deviceName):
|
||||||
|
m_DeviceId(deviceID), m_DeviceName(deviceName), m_MaxInputChannels(0), m_MaxOutputChannels(0)
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<DeviceInfo*> DeviceInfoVec;
|
||||||
|
typedef DeviceInfoVec::iterator DeviceInfoVecIter;
|
||||||
|
typedef DeviceInfoVec::const_iterator DeviceInfoVecConstIter;
|
||||||
|
|
||||||
/// for notification... A client must derive it's class from us.
|
/// for notification... A client must derive it's class from us.
|
||||||
class WCMRAudioDeviceManagerClient
|
class WCMRAudioDeviceManagerClient
|
||||||
|
|
@ -71,6 +70,7 @@ class WCMRAudioDeviceManagerClient
|
||||||
BufferSizeChanged,
|
BufferSizeChanged,
|
||||||
ClockSourceChanged,
|
ClockSourceChanged,
|
||||||
DeviceStoppedStreaming,
|
DeviceStoppedStreaming,
|
||||||
|
DeviceStartsStreaming,
|
||||||
DeviceDroppedSamples,
|
DeviceDroppedSamples,
|
||||||
DeviceConnectionLost,
|
DeviceConnectionLost,
|
||||||
DeviceGenericError,
|
DeviceGenericError,
|
||||||
|
|
@ -123,7 +123,7 @@ public:
|
||||||
{
|
{
|
||||||
DeviceAvailable,
|
DeviceAvailable,
|
||||||
DeviceDisconnected,
|
DeviceDisconnected,
|
||||||
DeviceError
|
DeviceErrors
|
||||||
};
|
};
|
||||||
|
|
||||||
WCMRAudioDevice (WCMRAudioDeviceManager *pManager);///<Constructor
|
WCMRAudioDevice (WCMRAudioDeviceManager *pManager);///<Constructor
|
||||||
|
|
@ -167,6 +167,8 @@ public:
|
||||||
virtual WTErr SendCustomCommand (int customCommand, void *pCommandParam); ///< Send a custom command to the audiodevice...
|
virtual WTErr SendCustomCommand (int customCommand, void *pCommandParam); ///< Send a custom command to the audiodevice...
|
||||||
|
|
||||||
virtual uint32_t GetLatency (bool isInput); ///Get latency.
|
virtual uint32_t GetLatency (bool isInput); ///Get latency.
|
||||||
|
|
||||||
|
virtual WTErr UpdateDeviceInfo () = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
WCMRAudioDeviceManager *m_pMyManager; ///< The manager who's managing this device, can be used for sending notifications!
|
WCMRAudioDeviceManager *m_pMyManager; ///< The manager who's managing this device, can be used for sending notifications!
|
||||||
|
|
@ -191,6 +193,7 @@ protected:
|
||||||
float m_MonitorGain; ///< Amount of gain to apply for monitoring signal.
|
float m_MonitorGain; ///< Amount of gain to apply for monitoring signal.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// This enum is for choosing filter for audio devices scan
|
// This enum is for choosing filter for audio devices scan
|
||||||
typedef enum eAudioDeviceFilter
|
typedef enum eAudioDeviceFilter
|
||||||
{
|
{
|
||||||
|
|
@ -202,65 +205,44 @@ typedef enum eAudioDeviceFilter
|
||||||
eAudioDeviceFilterNum // Number of enums
|
eAudioDeviceFilterNum // Number of enums
|
||||||
} eAudioDeviceFilter;
|
} eAudioDeviceFilter;
|
||||||
|
|
||||||
//! WCMRAudioDeviceManager
|
|
||||||
/*! The Audio Device Manager class */
|
|
||||||
class WCMRAudioDeviceManager : public WCRefManager
|
class WCMRAudioDeviceManager : public WCRefManager
|
||||||
{
|
{
|
||||||
private://< Private version of class functions which will be called by class's public function after mutex lock acquistion.
|
|
||||||
WCMRAudioDevice* GetDefaultDevice_Private();
|
|
||||||
WTErr DoIdle_Private();
|
|
||||||
const WCMRAudioDeviceList& Devices_Private() const;
|
|
||||||
WCMRAudioDevice* GetDeviceByName_Private(const std::string & nameToMatch) const;
|
|
||||||
|
|
||||||
public://< Public functions for the class.
|
public://< Public functions for the class.
|
||||||
WCMRAudioDevice* GetDefaultDevice()
|
|
||||||
{
|
WCMRAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient, eAudioDeviceFilter eCurAudioDeviceFilter); ///< constructor
|
||||||
//wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceManagerMutex);
|
virtual ~WCMRAudioDeviceManager(void); ///< Destructor
|
||||||
return GetDefaultDevice_Private();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual WTErr DoIdle()
|
//interfaces
|
||||||
{
|
WCMRAudioDevice* InitNewCurrentDevice(const std::string & deviceName);
|
||||||
//wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceManagerMutex);
|
void DestroyCurrentDevice();
|
||||||
return DoIdle_Private();
|
const DeviceInfoVec DeviceInfoList () const;
|
||||||
}
|
WTErr GetDeviceInfoByName(const std::string & nameToMatch, DeviceInfo & devInfo) const;
|
||||||
|
WTErr GetDeviceBufferSizes(const std::string & nameToMatch, std::vector<int>& bufferSizes) const;
|
||||||
|
|
||||||
const WCMRAudioDeviceList& Devices() const
|
//virtual void EnableVerboseLogging(bool /*bEnable*/, const std::string& /*logFilePath*/) { };
|
||||||
{
|
|
||||||
//wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceManagerMutex);
|
|
||||||
return Devices_Private();
|
|
||||||
}
|
|
||||||
|
|
||||||
WCMRAudioDevice* GetDeviceByName(const std::string & nameToMatch) const
|
//notify backend
|
||||||
{
|
void NotifyClient (WCMRAudioDeviceManagerClient::NotificationReason forReason, void *pParam = NULL);
|
||||||
//wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceManagerMutex);
|
|
||||||
return GetDeviceByName_Private(nameToMatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
WCMRAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient, eAudioDeviceFilter eCurAudioDeviceFilter
|
|
||||||
); ///< constructor
|
|
||||||
virtual ~WCMRAudioDeviceManager(void); ///< Destructor
|
|
||||||
|
|
||||||
virtual WTErr UpdateDeviceList () = 0; //has to be overridden!
|
|
||||||
|
|
||||||
|
|
||||||
//This is primarily for use by WCMRAudioDevice and it's descendants... We could have made it
|
|
||||||
//protected and made WCMRAudioDevice a friend, and then in some way found a way to extend
|
|
||||||
//the friendship to WCMRAudioDevice's descendants, but that would require a lot of extra
|
|
||||||
//effort!
|
|
||||||
void NotifyClient (WCMRAudioDeviceManagerClient::NotificationReason forReason, void *pParam = NULL);
|
|
||||||
virtual void EnableVerboseLogging(bool /*bEnable*/, const std::string& /*logFilePath*/) { };
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
//< NOTE : Mutex protection is commented, but wrapper classes are still there, in case they are required in future.
|
mutable wvNS::wvThread::ThreadMutex m_AudioDeviceInfoVecMutex; // mutex to lock device info list
|
||||||
//wvNS::wvThread::ThreadMutex m_AudioDeviceManagerMutex; ///< Mutex for Audio device manager class function access.
|
DeviceInfoVec m_DeviceInfoVec;
|
||||||
WCMRAudioDeviceManagerClient *m_pTheClient; ///< The device manager's client, used to send notifications.
|
|
||||||
|
|
||||||
WCMRAudioDeviceList m_Devices; ///< List of all relevant devices devices
|
eAudioDeviceFilter m_eAudioDeviceFilter;
|
||||||
eAudioDeviceFilter m_eAudioDeviceFilter; // filter of 'm_Devices'
|
WCMRAudioDevice* m_CurrentDevice;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// override in derived classes
|
||||||
|
// made private to avoid pure virtual function call
|
||||||
|
virtual WCMRAudioDevice* initNewCurrentDeviceImpl(const std::string & deviceName) = 0;
|
||||||
|
virtual void destroyCurrentDeviceImpl() = 0;
|
||||||
|
virtual WTErr getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& bufferSizes) const = 0;
|
||||||
|
virtual WTErr generateDeviceListImpl() = 0;
|
||||||
|
virtual WTErr updateDeviceListImpl() = 0;
|
||||||
|
|
||||||
|
WCMRAudioDeviceManagerClient *m_pTheClient; ///< The device manager's client, used to send notifications.
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //#ifndef __WCMRAudioDeviceManager_h_
|
#endif //#ifndef __WCMRAudioDeviceManager_h_
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,6 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
// Copyright (c) 2008 Waves Audio Ltd. All rights reserved.
|
||||||
//
|
//
|
||||||
//! \file WCMRCoreAudioDeviceManager.cpp
|
//! \file WCMRCoreAudioDeviceManager.cpp
|
||||||
//!
|
//!
|
||||||
|
|
@ -58,6 +41,8 @@ static const int DEFAULT_SR = 44100;
|
||||||
///< The default buffer size.
|
///< The default buffer size.
|
||||||
static const int DEFAULT_BUFFERSIZE = 128;
|
static const int DEFAULT_BUFFERSIZE = 128;
|
||||||
|
|
||||||
|
static const int NONE_DEVICE_ID = -1;
|
||||||
|
|
||||||
///< Number of stalls to wait before notifying user...
|
///< Number of stalls to wait before notifying user...
|
||||||
static const int NUM_STALLS_FOR_NOTIFICATION = 2 * 50; // 2*50 corresponds to 2 * 50 x 42 ms idle timer - about 4 seconds.
|
static const int NUM_STALLS_FOR_NOTIFICATION = 2 * 50; // 2*50 corresponds to 2 * 50 x 42 ms idle timer - about 4 seconds.
|
||||||
static const int CHANGE_CHECK_COUNTER_PERIOD = 100; // 120 corresponds to 120 x 42 ms idle timer - about 4 seconds.
|
static const int CHANGE_CHECK_COUNTER_PERIOD = 100; // 120 corresponds to 120 x 42 ms idle timer - about 4 seconds.
|
||||||
|
|
@ -166,7 +151,7 @@ WCMRCoreAudioDevice::WCMRCoreAudioDevice (WCMRCoreAudioDeviceManager *pManager,
|
||||||
m_CurrentBufferSize = (int)bufferSize;
|
m_CurrentBufferSize = (int)bufferSize;
|
||||||
|
|
||||||
|
|
||||||
UpdateDeviceInfo(true /*updateSRSupported*/, true /* updateBufferSizes */);
|
UpdateDeviceInfo();
|
||||||
|
|
||||||
//should use a valid current SR...
|
//should use a valid current SR...
|
||||||
if (m_SamplingRates.size())
|
if (m_SamplingRates.size())
|
||||||
|
|
@ -252,14 +237,11 @@ WCMRCoreAudioDevice::~WCMRCoreAudioDevice ()
|
||||||
// WCMRCoreAudioDevice::UpdateDeviceInfo
|
// WCMRCoreAudioDevice::UpdateDeviceInfo
|
||||||
//
|
//
|
||||||
//! Updates Device Information about channels, sampling rates, buffer sizes.
|
//! Updates Device Information about channels, sampling rates, buffer sizes.
|
||||||
//!
|
|
||||||
//! \param updateSRSupported : Is Sampling Rate support needs to be updated.
|
|
||||||
//! \param updateBufferSizes : Is buffer size support needs to be updated.
|
|
||||||
//!
|
//!
|
||||||
//! \return WTErr.
|
//! \return WTErr.
|
||||||
//!
|
//!
|
||||||
//**********************************************************************************************
|
//**********************************************************************************************
|
||||||
WTErr WCMRCoreAudioDevice::UpdateDeviceInfo (bool updateSRSupported, bool updateBufferSizes)
|
WTErr WCMRCoreAudioDevice::UpdateDeviceInfo ()
|
||||||
{
|
{
|
||||||
AUTO_FUNC_DEBUG;
|
AUTO_FUNC_DEBUG;
|
||||||
|
|
||||||
|
|
@ -272,17 +254,8 @@ WTErr WCMRCoreAudioDevice::UpdateDeviceInfo (bool updateSRSupported, bool update
|
||||||
WTErr errSR = eNoErr;
|
WTErr errSR = eNoErr;
|
||||||
WTErr errBS = eNoErr;
|
WTErr errBS = eNoErr;
|
||||||
|
|
||||||
if (updateSRSupported)
|
errSR = UpdateDeviceSampleRates();
|
||||||
{
|
errBS = UpdateDeviceBufferSizes();
|
||||||
errSR = UpdateDeviceSampleRates();
|
|
||||||
}
|
|
||||||
|
|
||||||
//update SR list... This is done conditionally, because some devices may not like
|
|
||||||
//changing the SR later on, just to check on things.
|
|
||||||
if (updateBufferSizes)
|
|
||||||
{
|
|
||||||
errBS = UpdateDeviceBufferSizes();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(errName != eNoErr || errIn != eNoErr || errOut != eNoErr || errSR != eNoErr || errBS != eNoErr)
|
if(errName != eNoErr || errIn != eNoErr || errOut != eNoErr || errSR != eNoErr || errBS != eNoErr)
|
||||||
{
|
{
|
||||||
|
|
@ -786,7 +759,7 @@ WTErr WCMRCoreAudioDevice::SetCurrentSamplingRate (int newRate)
|
||||||
retVal = SetAndCheckCurrentSamplingRate (newRate);
|
retVal = SetAndCheckCurrentSamplingRate (newRate);
|
||||||
if(retVal == eNoErr)
|
if(retVal == eNoErr)
|
||||||
{
|
{
|
||||||
retVal = UpdateDeviceInfo (false/*updateSRSupported*/, true/*updateBufferSizes*/);
|
retVal = UpdateDeviceInfo ();
|
||||||
}
|
}
|
||||||
|
|
||||||
//reactivate it.
|
//reactivate it.
|
||||||
|
|
@ -1759,7 +1732,7 @@ WTErr WCMRCoreAudioDevice::SetActive (bool newState)
|
||||||
m_DropsReported = 0;
|
m_DropsReported = 0;
|
||||||
m_IgnoreThisDrop = true;
|
m_IgnoreThisDrop = true;
|
||||||
|
|
||||||
UpdateDeviceInfo(true /*updateSRSupported */, true /* updateBufferSizes#*/);
|
UpdateDeviceInfo();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2317,14 +2290,10 @@ OSStatus WCMRCoreAudioDevice::GetStreamLatency(AudioDeviceID device, bool isInpu
|
||||||
//! \return Nothing.
|
//! \return Nothing.
|
||||||
//!
|
//!
|
||||||
//**********************************************************************************************
|
//**********************************************************************************************
|
||||||
WCMRCoreAudioDeviceManager::WCMRCoreAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient, eAudioDeviceFilter eCurAudioDeviceFilter
|
WCMRCoreAudioDeviceManager::WCMRCoreAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient,
|
||||||
, bool useMultithreading, eCABS_Method eCABS_method, bool bNocopy)
|
eAudioDeviceFilter eCurAudioDeviceFilter, bool useMultithreading, bool bNocopy)
|
||||||
: WCMRAudioDeviceManager (pTheClient, eCurAudioDeviceFilter
|
: WCMRAudioDeviceManager (pTheClient, eCurAudioDeviceFilter)
|
||||||
)
|
|
||||||
, m_UpdateDeviceListRequested(0)
|
|
||||||
, m_UpdateDeviceListProcessed(0)
|
|
||||||
, m_UseMultithreading (useMultithreading)
|
, m_UseMultithreading (useMultithreading)
|
||||||
, m_eCABS_Method(eCABS_method)
|
|
||||||
, m_bNoCopyAudioBuffer(bNocopy)
|
, m_bNoCopyAudioBuffer(bNocopy)
|
||||||
{
|
{
|
||||||
AUTO_FUNC_DEBUG;
|
AUTO_FUNC_DEBUG;
|
||||||
|
|
@ -2347,13 +2316,13 @@ WCMRCoreAudioDeviceManager::WCMRCoreAudioDeviceManager(WCMRAudioDeviceManagerCli
|
||||||
}
|
}
|
||||||
|
|
||||||
//add a listener to find out when devices change...
|
//add a listener to find out when devices change...
|
||||||
AudioHardwareAddPropertyListener (kAudioHardwarePropertyDevices, StaticPropertyChangeProc, this);
|
AudioHardwareAddPropertyListener (kAudioHardwarePropertyDevices, DevicePropertyChangeCallback, this);
|
||||||
|
|
||||||
//Always add the None device first...
|
//Always add the None device first...
|
||||||
m_Devices.push_back (new WCMRNativeAudioNoneDevice(this));
|
m_NoneDevice = new WCMRNativeAudioNoneDevice(this);
|
||||||
|
|
||||||
//prepare our initial list...
|
//prepare our initial list...
|
||||||
UpdateDeviceList_Private();
|
generateDeviceListImpl();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -2376,25 +2345,7 @@ WCMRCoreAudioDeviceManager::~WCMRCoreAudioDeviceManager()
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
AudioHardwareRemovePropertyListener (kAudioHardwarePropertyDevices, StaticPropertyChangeProc);
|
delete m_NoneDevice;
|
||||||
|
|
||||||
//Note: We purposely release the device list here, instead of
|
|
||||||
//depending on the superclass to do it, as by the time the superclass'
|
|
||||||
//destructor executes, we will have called Pa_Terminate()!
|
|
||||||
|
|
||||||
//Need to call release on our devices, and erase them from list
|
|
||||||
std::vector<WCMRAudioDevice*>::iterator deviceIter;
|
|
||||||
while (m_Devices.size())
|
|
||||||
{
|
|
||||||
WCMRAudioDevice *pDeviceToRelease = m_Devices.back();
|
|
||||||
m_Devices.pop_back();
|
|
||||||
|
|
||||||
SAFE_RELEASE (pDeviceToRelease);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//The derived classes may want to do additional de-int!
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
|
|
@ -2405,313 +2356,511 @@ WCMRCoreAudioDeviceManager::~WCMRCoreAudioDeviceManager()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//**********************************************************************************************
|
WCMRAudioDevice* WCMRCoreAudioDeviceManager::initNewCurrentDeviceImpl(const std::string & deviceName)
|
||||||
// WCMRCoreAudioDeviceManager::StaticPropertyChangeProc
|
|
||||||
//
|
|
||||||
//! The property change listener for the Audio Device Manager. It calls upon (non-static) PropertyChangeProc
|
|
||||||
//! to do the actual work.
|
|
||||||
//!
|
|
||||||
//! \param iPropertyID : the property that has changed.
|
|
||||||
//! \param inClientData : What was supplied at init time.
|
|
||||||
//!
|
|
||||||
//! \return if parameters are incorrect, or the value returned by PropertyChangeProc.
|
|
||||||
//!
|
|
||||||
//**********************************************************************************************
|
|
||||||
OSStatus WCMRCoreAudioDeviceManager::StaticPropertyChangeProc (AudioHardwarePropertyID inPropertyID, void* inClientData)
|
|
||||||
{
|
{
|
||||||
WCMRCoreAudioDeviceManager *pMyManager = (WCMRCoreAudioDeviceManager *)inClientData;
|
destroyCurrentDeviceImpl();
|
||||||
|
|
||||||
if (pMyManager)
|
std::cout << "API::PortAudioDeviceManager::initNewCurrentDevice " << deviceName << std::endl;
|
||||||
return pMyManager->PropertyChangeProc (inPropertyID);
|
if (deviceName == m_NoneDevice->DeviceName() )
|
||||||
|
{
|
||||||
return 0;
|
m_CurrentDevice = m_NoneDevice;
|
||||||
|
return m_CurrentDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceInfo devInfo;
|
||||||
|
WTErr err = GetDeviceInfoByName(deviceName, devInfo);
|
||||||
|
|
||||||
|
if (eNoErr == err)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::cout << "API::PortAudioDeviceManager::Creating PA device: " << devInfo.m_DeviceId << ", Device Name: " << devInfo.m_DeviceName << std::endl;
|
||||||
|
TRACE_MSG ("API::PortAudioDeviceManager::Creating PA device: " << devInfo.m_DeviceId << ", Device Name: " << devInfo.m_DeviceName);
|
||||||
|
|
||||||
|
m_CurrentDevice = new WCMRCoreAudioDevice (this, devInfo.m_DeviceId, m_UseMultithreading, m_bNoCopyAudioBuffer);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
std::cout << "Unabled to create PA Device: " << devInfo.m_DeviceId << std::endl;
|
||||||
|
DEBUG_MSG ("Unabled to create PA Device: " << devInfo.m_DeviceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_CurrentDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WCMRCoreAudioDeviceManager::destroyCurrentDeviceImpl()
|
||||||
//**********************************************************************************************
|
|
||||||
// WCMRCoreAudioDeviceManager::PropertyChangeProc
|
|
||||||
//
|
|
||||||
//! The property change listener for the Audio Device Manager. Currently we only listen for the
|
|
||||||
//! device list change (device arrival/removal, and accordingly cause an update to the device list.
|
|
||||||
//! Note that the actual update happens from the DoIdle() call to prevent multi-threading related issues.
|
|
||||||
//!
|
|
||||||
//! \param
|
|
||||||
//!
|
|
||||||
//! \return Nothing.
|
|
||||||
//!
|
|
||||||
//**********************************************************************************************
|
|
||||||
OSStatus WCMRCoreAudioDeviceManager::PropertyChangeProc (AudioHardwarePropertyID inPropertyID)
|
|
||||||
{
|
{
|
||||||
OSStatus retVal = 0;
|
if (m_CurrentDevice != m_NoneDevice)
|
||||||
switch (inPropertyID)
|
delete m_CurrentDevice;
|
||||||
|
|
||||||
|
m_CurrentDevice = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WTErr WCMRCoreAudioDeviceManager::getDeviceAvailableSampleRates(DeviceID deviceId, std::vector<int>& sampleRates)
|
||||||
|
{
|
||||||
|
AUTO_FUNC_DEBUG;
|
||||||
|
|
||||||
|
WTErr retVal = eNoErr;
|
||||||
|
OSStatus err = kAudioHardwareNoError;
|
||||||
|
UInt32 propSize = 0;
|
||||||
|
|
||||||
|
sampleRates.clear();
|
||||||
|
|
||||||
|
//! 1. Get sample rate property size.
|
||||||
|
err = AudioDeviceGetPropertyInfo(deviceId, 0, 0, kAudioDevicePropertyAvailableNominalSampleRates, &propSize, NULL);
|
||||||
|
if (err == kAudioHardwareNoError)
|
||||||
{
|
{
|
||||||
case kAudioHardwarePropertyDevices:
|
//! 2. Get property: cannels output.
|
||||||
m_UpdateDeviceListRequested++;
|
|
||||||
break;
|
// Allocate size accrding to the number of audio values
|
||||||
default:
|
int numRates = propSize / sizeof(AudioValueRange);
|
||||||
break;
|
AudioValueRange* supportedRates = new AudioValueRange[numRates];
|
||||||
|
|
||||||
|
// Get sampling rates from Audio device
|
||||||
|
err = AudioDeviceGetProperty(deviceId, 0, 0, kAudioDevicePropertyAvailableNominalSampleRates, &propSize, supportedRates);
|
||||||
|
if (err == kAudioHardwareNoError)
|
||||||
|
{
|
||||||
|
//! 3. Update sample rates
|
||||||
|
|
||||||
|
// now iterate through our standard SRs
|
||||||
|
for(int ourSR=0; gAllSampleRates[ourSR] > 0; ourSR++)
|
||||||
|
{
|
||||||
|
//check to see if our SR is in the supported rates...
|
||||||
|
for (int deviceSR = 0; deviceSR < numRates; deviceSR++)
|
||||||
|
{
|
||||||
|
if ((supportedRates[deviceSR].mMinimum <= gAllSampleRates[ourSR]) &&
|
||||||
|
(supportedRates[deviceSR].mMaximum >= gAllSampleRates[ourSR]))
|
||||||
|
{
|
||||||
|
sampleRates.push_back ((int)gAllSampleRates[ourSR]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retVal = eCoreAudioFailed;
|
||||||
|
DEBUG_MSG("Failed to get device Sample rates. Device Name: " << m_DeviceName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] supportedRates;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retVal = eCoreAudioFailed;
|
||||||
|
DEBUG_MSG("Failed to get device Sample rates property size. Device Name: " << m_DeviceName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
//**********************************************************************************************
|
|
||||||
// WCMRCoreAudioDeviceManager::remove_pattern
|
|
||||||
//
|
|
||||||
//! remove a substring from a given string
|
|
||||||
//!
|
|
||||||
//! \param original_str - original string
|
|
||||||
//! \param pattern_str - pattern to find
|
|
||||||
//! \param return_str - the return string - without the pattern substring
|
|
||||||
//!
|
|
||||||
//! \return Nothing.
|
|
||||||
//!
|
|
||||||
//**********************************************************************************************
|
|
||||||
void WCMRCoreAudioDeviceManager::remove_pattern(const std::string& original_str, const std::string& pattern_str, std::string& return_str)
|
|
||||||
{
|
|
||||||
char *orig_c_str = new char[original_str.size() + 1];
|
|
||||||
char* strSavePtr;
|
|
||||||
strcpy(orig_c_str, original_str.c_str());
|
|
||||||
char *p_splited_orig_str = strtok_r(orig_c_str," ", &strSavePtr);
|
|
||||||
|
|
||||||
std::ostringstream stream_str;
|
|
||||||
while (p_splited_orig_str != 0)
|
WTErr WCMRCoreAudioDeviceManager::getDeviceMaxInputChannels(DeviceID deviceId, unsigned int& inputChannels)
|
||||||
|
{
|
||||||
|
AUTO_FUNC_DEBUG;
|
||||||
|
WTErr retVal = eNoErr;
|
||||||
|
OSStatus err = kAudioHardwareNoError;
|
||||||
|
UInt32 propSize = 0;
|
||||||
|
inputChannels = 0;
|
||||||
|
|
||||||
|
// 1. Get property cannels input size.
|
||||||
|
err = AudioDeviceGetPropertyInfo (deviceId, 0, 1/* Input */, kAudioDevicePropertyStreamConfiguration, &propSize, NULL);
|
||||||
|
if (err == kAudioHardwareNoError)
|
||||||
{
|
{
|
||||||
int cmp_res = strcmp(p_splited_orig_str, pattern_str.c_str()); // might need Ignore case ( stricmp OR strcasecmp)
|
//! 2. Get property: cannels input.
|
||||||
if ( cmp_res != 0)
|
|
||||||
stream_str << p_splited_orig_str << " ";
|
// Allocate size according to the property size. Note that this is a variable sized struct...
|
||||||
p_splited_orig_str = strtok_r(NULL," ", &strSavePtr);
|
AudioBufferList *pStreamBuffers = (AudioBufferList *)malloc(propSize);
|
||||||
|
|
||||||
|
if (pStreamBuffers)
|
||||||
|
{
|
||||||
|
memset (pStreamBuffers, 0, propSize);
|
||||||
|
|
||||||
|
// Get the Input channels
|
||||||
|
err = AudioDeviceGetProperty (deviceId, 0, 1/* Input */, kAudioDevicePropertyStreamConfiguration, &propSize, pStreamBuffers);
|
||||||
|
if (err == kAudioHardwareNoError)
|
||||||
|
{
|
||||||
|
// Calculate the number of input channels
|
||||||
|
for (UInt32 streamIndex = 0; streamIndex < pStreamBuffers->mNumberBuffers; streamIndex++)
|
||||||
|
{
|
||||||
|
inputChannels += pStreamBuffers->mBuffers[streamIndex].mNumberChannels;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retVal = eCoreAudioFailed;
|
||||||
|
DEBUG_MSG("Failed to get device Input channels. Device Name: " << m_DeviceName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
free (pStreamBuffers);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retVal = eMemOutOfMemory;
|
||||||
|
DEBUG_MSG("Faild to allocate memory. Device Name: " << m_DeviceName.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
delete[] orig_c_str;
|
else
|
||||||
return_str = stream_str.str();
|
{
|
||||||
|
retVal = eCoreAudioFailed;
|
||||||
|
DEBUG_MSG("Failed to get device Input channels property size. Device Name: " << m_DeviceName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WTErr WCMRCoreAudioDeviceManager::getDeviceMaxOutputChannels(DeviceID deviceId, unsigned int& outputChannels)
|
||||||
//**********************************************************************************************
|
|
||||||
// WCMRCoreAudioDeviceManager::UpdateDeviceList_Private
|
|
||||||
//
|
|
||||||
//! Updates the list of devices maintained by the manager. If devices have gone away, they are removed
|
|
||||||
//! if new devices have been connected, they are added to the list.
|
|
||||||
//!
|
|
||||||
//! \param none
|
|
||||||
//!
|
|
||||||
//! \return eNoErr on success, an error code on failure.
|
|
||||||
//!
|
|
||||||
//**********************************************************************************************
|
|
||||||
WTErr WCMRCoreAudioDeviceManager::UpdateDeviceList_Private()
|
|
||||||
{
|
{
|
||||||
AUTO_FUNC_DEBUG;
|
AUTO_FUNC_DEBUG;
|
||||||
|
|
||||||
|
WTErr retVal = eNoErr;
|
||||||
|
OSStatus err = kAudioHardwareNoError;
|
||||||
|
UInt32 propSize = 0;
|
||||||
|
outputChannels = 0;
|
||||||
|
|
||||||
|
//! 1. Get property cannels output size.
|
||||||
|
err = AudioDeviceGetPropertyInfo (deviceId, 0, 0/* Output */, kAudioDevicePropertyStreamConfiguration, &propSize, NULL);
|
||||||
|
if (err == kAudioHardwareNoError)
|
||||||
|
{
|
||||||
|
//! 2. Get property: cannels output.
|
||||||
|
|
||||||
|
// Allocate size according to the property size. Note that this is a variable sized struct...
|
||||||
|
AudioBufferList *pStreamBuffers = (AudioBufferList *)malloc(propSize);
|
||||||
|
if (pStreamBuffers)
|
||||||
|
{
|
||||||
|
memset (pStreamBuffers, 0, propSize);
|
||||||
|
|
||||||
|
// Get the Output channels
|
||||||
|
err = AudioDeviceGetProperty (deviceId, 0, 0/* Output */, kAudioDevicePropertyStreamConfiguration, &propSize, pStreamBuffers);
|
||||||
|
if (err == kAudioHardwareNoError)
|
||||||
|
{
|
||||||
|
// Calculate the number of output channels
|
||||||
|
for (UInt32 streamIndex = 0; streamIndex < pStreamBuffers->mNumberBuffers; streamIndex++)
|
||||||
|
{
|
||||||
|
outputChannels += pStreamBuffers->mBuffers[streamIndex].mNumberChannels;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retVal = eCoreAudioFailed;
|
||||||
|
DEBUG_MSG("Failed to get device Output channels. Device Name: " << m_DeviceName.c_str());
|
||||||
|
}
|
||||||
|
free (pStreamBuffers);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retVal = eMemOutOfMemory;
|
||||||
|
DEBUG_MSG("Faild to allocate memory. Device Name: " << m_DeviceName.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retVal = eCoreAudioFailed;
|
||||||
|
DEBUG_MSG("Failed to get device Output channels property size. Device Name: " << m_DeviceName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WTErr WCMRCoreAudioDeviceManager::generateDeviceListImpl()
|
||||||
|
{
|
||||||
|
AUTO_FUNC_DEBUG;
|
||||||
|
|
||||||
|
// lock the list first
|
||||||
|
wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceInfoVecMutex);
|
||||||
|
m_DeviceInfoVec.clear();
|
||||||
|
|
||||||
|
//First, get info from None device which is always present
|
||||||
|
if (m_NoneDevice)
|
||||||
|
{
|
||||||
|
DeviceInfo *pDevInfo = new DeviceInfo(NONE_DEVICE_ID, m_NoneDevice->DeviceName() );
|
||||||
|
pDevInfo->m_AvailableSampleRates = m_NoneDevice->SamplingRates();
|
||||||
|
m_DeviceInfoVec.push_back(pDevInfo);
|
||||||
|
}
|
||||||
|
|
||||||
WTErr retVal = eNoErr;
|
WTErr retVal = eNoErr;
|
||||||
OSStatus osErr = noErr;
|
OSStatus osErr = noErr;
|
||||||
AudioDeviceID* deviceIDs = 0;
|
AudioDeviceID* deviceIDs = 0;
|
||||||
size_t reportedDeviceIndex = 0;
|
|
||||||
|
|
||||||
openlog("WCMRCoreAudioDeviceManager", LOG_PID | LOG_CONS, LOG_USER);
|
openlog("WCMRCoreAudioDeviceManager", LOG_PID | LOG_CONS, LOG_USER);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
// Define 2 vectors for input and output - only for eMatchedDuplexDevices case
|
|
||||||
WCMRAudioDeviceList adOnlyIn;
|
|
||||||
WCMRAudioDeviceList adOnlyOut;
|
|
||||||
|
|
||||||
//Get device count...
|
//Get device count...
|
||||||
UInt32 propSize = 0;
|
UInt32 propSize = 0;
|
||||||
osErr = AudioHardwareGetPropertyInfo (kAudioHardwarePropertyDevices, &propSize, NULL);
|
osErr = AudioHardwareGetPropertyInfo (kAudioHardwarePropertyDevices, &propSize, NULL);
|
||||||
ASSERT_ERROR(osErr, "AudioHardwareGetProperty 1");
|
ASSERT_ERROR(osErr, "AudioHardwareGetProperty 1");
|
||||||
if (WUIsError(osErr))
|
if (WUIsError(osErr))
|
||||||
throw osErr;
|
throw osErr;
|
||||||
|
|
||||||
size_t numDevices = propSize / sizeof (AudioDeviceID);
|
size_t numDevices = propSize / sizeof (AudioDeviceID);
|
||||||
deviceIDs = new AudioDeviceID[numDevices];
|
deviceIDs = new AudioDeviceID[numDevices];
|
||||||
|
|
||||||
//retrieve the device IDs
|
//retrieve the device IDs
|
||||||
propSize = numDevices * sizeof (AudioDeviceID);
|
propSize = numDevices * sizeof (AudioDeviceID);
|
||||||
osErr = AudioHardwareGetProperty (kAudioHardwarePropertyDevices, &propSize, deviceIDs);
|
osErr = AudioHardwareGetProperty (kAudioHardwarePropertyDevices, &propSize, deviceIDs);
|
||||||
ASSERT_ERROR(osErr, "Error while getting audio devices: AudioHardwareGetProperty 2");
|
ASSERT_ERROR(osErr, "Error while getting audio devices: AudioHardwareGetProperty 2");
|
||||||
if (WUIsError(osErr))
|
if (WUIsError(osErr))
|
||||||
throw osErr;
|
throw osErr;
|
||||||
|
|
||||||
//first go through our list of devices, remove the ones that are no longer present...
|
|
||||||
std::vector<WCMRAudioDevice*>::iterator deviceIter;
|
|
||||||
for (deviceIter = m_Devices.begin(); deviceIter != m_Devices.end(); /*This is purposefully blank*/)
|
|
||||||
{
|
|
||||||
WCMRCoreAudioDevice *pDeviceToWorkUpon = dynamic_cast<WCMRCoreAudioDevice *>(*deviceIter);
|
|
||||||
|
|
||||||
//it's possible that the device is actually not a core audio device - perhaps a none device...
|
|
||||||
if (!pDeviceToWorkUpon)
|
|
||||||
{
|
|
||||||
deviceIter++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioDeviceID myDeviceID = pDeviceToWorkUpon->DeviceID();
|
|
||||||
bool deviceFound = false;
|
|
||||||
for (reportedDeviceIndex = 0; reportedDeviceIndex < numDevices; reportedDeviceIndex++)
|
|
||||||
{
|
|
||||||
if (myDeviceID == deviceIDs[reportedDeviceIndex])
|
|
||||||
{
|
|
||||||
deviceFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!deviceFound)
|
//now add the ones that are not there...
|
||||||
|
for (size_t deviceIndex = 0; deviceIndex < numDevices; deviceIndex++)
|
||||||
|
{
|
||||||
|
DeviceInfo* pDevInfo = 0;
|
||||||
|
|
||||||
|
//Get device name and create new DeviceInfo entry
|
||||||
|
//Get property name size.
|
||||||
|
osErr = AudioDeviceGetPropertyInfo(deviceIDs[deviceIndex], 0, 0, kAudioDevicePropertyDeviceName, &propSize, NULL);
|
||||||
|
if (osErr == kAudioHardwareNoError)
|
||||||
{
|
{
|
||||||
//it's no longer there, need to remove it!
|
//Get property: name.
|
||||||
WCMRAudioDevice *pTheDeviceToErase = *deviceIter;
|
char* deviceName = new char[propSize];
|
||||||
deviceIter = m_Devices.erase (deviceIter);
|
osErr = AudioDeviceGetProperty(deviceIDs[deviceIndex], 0, 0, kAudioDevicePropertyDeviceName, &propSize, deviceName);
|
||||||
if (pTheDeviceToErase->Active())
|
if (osErr == kAudioHardwareNoError)
|
||||||
{
|
{
|
||||||
NotifyClient (WCMRAudioDeviceManagerClient::DeviceConnectionLost);
|
pDevInfo = new DeviceInfo(deviceIDs[deviceIndex], deviceName);
|
||||||
}
|
}
|
||||||
SAFE_RELEASE (pTheDeviceToErase);
|
else
|
||||||
|
{
|
||||||
|
retVal = eCoreAudioFailed;
|
||||||
|
DEBUG_MSG("Failed to get device name. Device ID: " << m_DeviceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] deviceName;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
deviceIter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
//now add the ones that are not there...
|
|
||||||
for (reportedDeviceIndex = 0; reportedDeviceIndex < numDevices; reportedDeviceIndex++)
|
|
||||||
{
|
|
||||||
bool deviceFound = false;
|
|
||||||
for (deviceIter = m_Devices.begin(); deviceIter != m_Devices.end(); deviceIter++)
|
|
||||||
{
|
{
|
||||||
WCMRCoreAudioDevice *pDeviceToWorkUpon = dynamic_cast<WCMRCoreAudioDevice *>(*deviceIter);
|
retVal = eCoreAudioFailed;
|
||||||
//it's possible that the device is actually not a core audio device - perhaps a none device...
|
DEBUG_MSG("Failed to get device name property size. Device ID: " << m_DeviceID);
|
||||||
if (!pDeviceToWorkUpon)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (pDeviceToWorkUpon->DeviceID() == deviceIDs[reportedDeviceIndex])
|
|
||||||
{
|
|
||||||
deviceFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!deviceFound)
|
if (pDevInfo)
|
||||||
{
|
{
|
||||||
//add it to our list...
|
//Retrieve all the information we need for the device
|
||||||
//build a device object...
|
WTErr wErr = eNoErr;
|
||||||
WCMRCoreAudioDevice *pNewDevice = new WCMRCoreAudioDevice (this, deviceIDs[reportedDeviceIndex], m_UseMultithreading, m_bNoCopyAudioBuffer);
|
|
||||||
bool bDeleteNewDevice = true;
|
|
||||||
|
|
||||||
if (pNewDevice)
|
//Get available sample rates for the device
|
||||||
|
std::vector<int> availableSampleRates;
|
||||||
|
wErr = getDeviceAvailableSampleRates(pDevInfo->m_DeviceId, availableSampleRates);
|
||||||
|
|
||||||
|
if (wErr != eNoErr)
|
||||||
|
{
|
||||||
|
DEBUG_MSG ("Failed to get device available sample rates. Device ID: " << m_DeviceID);
|
||||||
|
delete pDevInfo;
|
||||||
|
continue; //proceed to the next device
|
||||||
|
}
|
||||||
|
|
||||||
|
pDevInfo->m_AvailableSampleRates = availableSampleRates;
|
||||||
|
|
||||||
|
//Get max input channels
|
||||||
|
uint32 maxInputChannels;
|
||||||
|
wErr = getDeviceMaxInputChannels(pDevInfo->m_DeviceId, maxInputChannels);
|
||||||
|
|
||||||
|
if (wErr != eNoErr)
|
||||||
|
{
|
||||||
|
DEBUG_MSG ("Failed to get device max input channels count. Device ID: " << m_DeviceID);
|
||||||
|
delete pDevInfo;
|
||||||
|
continue; //proceed to the next device
|
||||||
|
}
|
||||||
|
|
||||||
|
pDevInfo->m_MaxInputChannels = maxInputChannels;
|
||||||
|
|
||||||
|
//Get max output channels
|
||||||
|
uint32 maxOutputChannels;
|
||||||
|
wErr = getDeviceMaxOutputChannels(pDevInfo->m_DeviceId, maxOutputChannels);
|
||||||
|
|
||||||
|
if (wErr != eNoErr)
|
||||||
|
{
|
||||||
|
DEBUG_MSG ("Failed to get device max output channels count. Device ID: " << m_DeviceID);
|
||||||
|
delete pDevInfo;
|
||||||
|
continue; //proceed to the next device
|
||||||
|
}
|
||||||
|
|
||||||
|
pDevInfo->m_MaxOutputChannels = maxOutputChannels;
|
||||||
|
|
||||||
|
//Now check if this device is acceptable according to current input/output settings
|
||||||
|
bool bRejectDevice = false;
|
||||||
|
switch(m_eAudioDeviceFilter)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Don't delete the new device by default, since most cases use it
|
|
||||||
bDeleteNewDevice = false;
|
|
||||||
|
|
||||||
// Insert the new device to the device list according to its enum
|
|
||||||
switch(m_eAudioDeviceFilter)
|
|
||||||
{
|
|
||||||
case eInputOnlyDevices:
|
case eInputOnlyDevices:
|
||||||
if ((int) pNewDevice->InputChannels().size() != 0)
|
if (pDevInfo->m_MaxInputChannels != 0)
|
||||||
{
|
{
|
||||||
m_Devices.push_back (pNewDevice);
|
m_DeviceInfoVec.push_back(pDevInfo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Delete unnecesarry device
|
// Delete unnecesarry device
|
||||||
bDeleteNewDevice = true;
|
bRejectDevice = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case eOutputOnlyDevices:
|
case eOutputOnlyDevices:
|
||||||
if ((int) pNewDevice->OutputChannels().size() != 0)
|
if (pDevInfo->m_MaxOutputChannels != 0)
|
||||||
{
|
{
|
||||||
m_Devices.push_back (pNewDevice);
|
m_DeviceInfoVec.push_back(pDevInfo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Delete unnecesarry device
|
// Delete unnecesarry device
|
||||||
bDeleteNewDevice = true;
|
bRejectDevice = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case eFullDuplexDevices:
|
case eFullDuplexDevices:
|
||||||
if ((int) pNewDevice->InputChannels().size() != 0 && (int) pNewDevice->OutputChannels().size() != 0)
|
if (pDevInfo->m_MaxInputChannels != 0 && pDevInfo->m_MaxOutputChannels != 0)
|
||||||
{
|
{
|
||||||
m_Devices.push_back (pNewDevice);
|
m_DeviceInfoVec.push_back(pDevInfo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Delete unnecesarry device
|
// Delete unnecesarry device
|
||||||
bDeleteNewDevice = true;
|
bRejectDevice = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case eAllDevices:
|
case eAllDevices:
|
||||||
default:
|
default:
|
||||||
m_Devices.push_back (pNewDevice);
|
m_DeviceInfoVec.push_back(pDevInfo);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bDeleteNewDevice)
|
if(bRejectDevice)
|
||||||
{
|
{
|
||||||
syslog (LOG_NOTICE, "%s rejected, In Channels = %d, Out Channels = %d\n",
|
syslog (LOG_NOTICE, "%s rejected, In Channels = %d, Out Channels = %d\n",
|
||||||
pNewDevice->DeviceName().c_str(), (int) pNewDevice->InputChannels().size(),
|
pDevInfo->m_DeviceName.c_str(), pDevInfo->m_MaxInputChannels, pDevInfo->m_MaxOutputChannels);
|
||||||
(int) pNewDevice->OutputChannels().size());
|
|
||||||
// In case of Input and Output both channels being Zero, we will release memory; since we created CoreAudioDevice but we are Not adding it in list.
|
// In case of Input and Output both channels being Zero, we will release memory; since we created CoreAudioDevice but we are Not adding it in list.
|
||||||
SAFE_RELEASE(pNewDevice);
|
delete pDevInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//If no devices were found, that's not a good thing!
|
//If no devices were found, that's not a good thing!
|
||||||
if (m_Devices.empty())
|
if (m_DeviceInfoVec.empty())
|
||||||
{
|
{
|
||||||
DEBUG_MSG ("No matching CoreAudio devices were found\n");
|
DEBUG_MSG ("No matching CoreAudio devices were found\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
m_UpdateDeviceListRequested = m_UpdateDeviceListProcessed = 0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
if (WUNoError(retVal))
|
if (WUNoError(retVal))
|
||||||
retVal = eCoreAudioFailed;
|
retVal = eCoreAudioFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
safe_delete_array(deviceIDs);
|
delete[] deviceIDs;
|
||||||
closelog();
|
closelog();
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WTErr WCMRCoreAudioDeviceManager::updateDeviceListImpl()
|
||||||
//**********************************************************************************************
|
|
||||||
// WCMRCoreAudioDeviceManager::DoIdle
|
|
||||||
//
|
|
||||||
//! Used for idle time processing. This calls each device's DoIdle so that it can perform it's own idle processing.
|
|
||||||
//! Also, if a device list change is detected, it updates the device list.
|
|
||||||
//!
|
|
||||||
//! \param none
|
|
||||||
//!
|
|
||||||
//! \return noErr if no devices have returned an error. An error code if any of the devices returned error.
|
|
||||||
//!
|
|
||||||
//**********************************************************************************************
|
|
||||||
WTErr WCMRCoreAudioDeviceManager::DoIdle()
|
|
||||||
{
|
{
|
||||||
//WTErr retVal = eNoErr;
|
wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceInfoVecMutex);
|
||||||
|
WTErr err = generateDeviceListImpl();
|
||||||
|
|
||||||
|
if (eNoErr != err)
|
||||||
{
|
{
|
||||||
//wvThread::ThreadMutex::lock theLock(m_AudioDeviceManagerMutex);
|
std::cout << "API::PortAudioDeviceManager::updateDeviceListImpl: Device list update error: "<< err << std::endl;
|
||||||
|
return err;
|
||||||
//If there's something specific to CoreAudio manager idle handling do it here...
|
}
|
||||||
if (m_UpdateDeviceListRequested != m_UpdateDeviceListProcessed)
|
|
||||||
|
if (m_CurrentDevice)
|
||||||
|
{
|
||||||
|
// if we have device initialized we should find out if this device is still connected
|
||||||
|
DeviceInfo devInfo;
|
||||||
|
WTErr deviceLookUpErr = GetDeviceInfoByName(m_CurrentDevice->DeviceName(), devInfo );
|
||||||
|
|
||||||
|
if (eNoErr != deviceLookUpErr)
|
||||||
{
|
{
|
||||||
m_UpdateDeviceListProcessed = m_UpdateDeviceListRequested;
|
NotifyClient (WCMRAudioDeviceManagerClient::IODeviceDisconnected);
|
||||||
UpdateDeviceList_Private();
|
return err;
|
||||||
NotifyClient (WCMRAudioDeviceManagerClient::DeviceListChanged);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Note that the superclass is going to call all the devices' DoIdle() anyway...
|
NotifyClient (WCMRAudioDeviceManagerClient::DeviceListChanged);
|
||||||
return (WCMRAudioDeviceManager::DoIdle());
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WTErr WCMRCoreAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& bufferSizes) const
|
||||||
|
{
|
||||||
|
AUTO_FUNC_DEBUG;
|
||||||
|
|
||||||
|
WTErr retVal = eNoErr;
|
||||||
|
OSStatus err = kAudioHardwareNoError;
|
||||||
|
UInt32 propSize = 0;
|
||||||
|
|
||||||
|
bufferSizes.clear();
|
||||||
|
|
||||||
|
//first check if the request has been made for None device
|
||||||
|
if (deviceName == m_NoneDevice->DeviceName() )
|
||||||
|
{
|
||||||
|
bufferSizes = m_NoneDevice->BufferSizes();
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceInfo devInfo;
|
||||||
|
retVal = GetDeviceInfoByName(deviceName, devInfo);
|
||||||
|
|
||||||
|
if (eNoErr == retVal)
|
||||||
|
{
|
||||||
|
// 1. Get buffer size range
|
||||||
|
AudioValueRange bufferSizesRange;
|
||||||
|
propSize = sizeof (AudioValueRange);
|
||||||
|
err = AudioDeviceGetProperty (devInfo.m_DeviceId, 0, 0, kAudioDevicePropertyBufferFrameSizeRange, &propSize, &bufferSizesRange);
|
||||||
|
if(err == kAudioHardwareNoError)
|
||||||
|
{
|
||||||
|
// 2. Run on all ranges and add them to the list
|
||||||
|
for(int bsize=0; gAllBufferSizes[bsize] > 0; bsize++)
|
||||||
|
{
|
||||||
|
if ((bufferSizesRange.mMinimum <= gAllBufferSizes[bsize]) && (bufferSizesRange.mMaximum >= gAllBufferSizes[bsize]))
|
||||||
|
{
|
||||||
|
bufferSizes.push_back (gAllBufferSizes[bsize]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if we didn't get a single hit, let's simply add the min. and the max...
|
||||||
|
if (bufferSizes.empty())
|
||||||
|
{
|
||||||
|
bufferSizes.push_back ((int)bufferSizesRange.mMinimum);
|
||||||
|
bufferSizes.push_back ((int)bufferSizesRange.mMaximum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retVal = eCoreAudioFailed;
|
||||||
|
DEBUG_MSG("Failed to get device buffer sizes range. Device Name: " << m_DeviceName.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retVal = eRMResNotFound;
|
||||||
|
std::cout << "API::PortAudioDeviceManager::GetBufferSizes: Device not found: "<< deviceName << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OSStatus WCMRCoreAudioDeviceManager::DevicePropertyChangeCallback (AudioHardwarePropertyID inPropertyID, void* inClientData)
|
||||||
|
{
|
||||||
|
switch (inPropertyID)
|
||||||
|
{
|
||||||
|
case kAudioHardwarePropertyDevices:
|
||||||
|
{
|
||||||
|
WCMRCoreAudioDeviceManager* pManager = (WCMRCoreAudioDeviceManager*)inClientData;
|
||||||
|
if (pManager)
|
||||||
|
pManager->updateDeviceListImpl();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,6 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
// Copyright (c) 2008 Waves Audio Ltd. All rights reserved.
|
||||||
//
|
//
|
||||||
//! \file WCMRCoreAudioDeviceManager.h
|
//! \file WCMRCoreAudioDeviceManager.h
|
||||||
//!
|
//!
|
||||||
|
|
@ -138,7 +121,7 @@ protected:
|
||||||
uint32_t m_NextSampleToUse;
|
uint32_t m_NextSampleToUse;
|
||||||
#endif //WV_USE_TONE_GEN
|
#endif //WV_USE_TONE_GEN
|
||||||
|
|
||||||
WTErr UpdateDeviceInfo (bool updateSRSupported, bool updateBufferSizes);
|
WTErr UpdateDeviceInfo ();
|
||||||
WTErr UpdateDeviceName();
|
WTErr UpdateDeviceName();
|
||||||
WTErr UpdateDeviceInputs();
|
WTErr UpdateDeviceInputs();
|
||||||
WTErr UpdateDeviceOutputs();
|
WTErr UpdateDeviceOutputs();
|
||||||
|
|
@ -181,40 +164,28 @@ class WCMRCoreAudioDeviceManager : public WCMRAudioDeviceManager
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WCMRCoreAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient, eAudioDeviceFilter eCurAudioDeviceFilter,
|
WCMRCoreAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient, eAudioDeviceFilter eCurAudioDeviceFilter,
|
||||||
bool useMultithreading = true, eCABS_Method eCABS_method = eCABS_Simple, bool bNocopy = false); ///< constructor
|
bool useMultithreading = true, bool bNocopy = false); ///< constructor
|
||||||
virtual ~WCMRCoreAudioDeviceManager(void); ///< Destructor
|
virtual ~WCMRCoreAudioDeviceManager(void); ///< Destructor
|
||||||
|
|
||||||
|
|
||||||
virtual WTErr UpdateDeviceList() //has to be overridden!
|
|
||||||
{
|
|
||||||
//wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceManagerMutex);
|
|
||||||
return UpdateDeviceList_Private();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual eCABS_Method GetBufferSizeMethod()
|
|
||||||
{
|
|
||||||
//wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceManagerMutex);
|
|
||||||
return GetBufferSizeMethod_Private();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual WTErr DoIdle();
|
|
||||||
|
|
||||||
private:
|
|
||||||
WTErr UpdateDeviceList_Private();
|
|
||||||
eCABS_Method GetBufferSizeMethod_Private() { return m_eCABS_Method; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static OSStatus DevicePropertyChangeCallback (AudioHardwarePropertyID inPropertyID, void* inClientData);
|
||||||
int m_UpdateDeviceListRequested; ///< Number of times device list change has been detected.
|
|
||||||
int m_UpdateDeviceListProcessed; ///< Number of times device list change has been processed.
|
virtual WCMRAudioDevice* initNewCurrentDeviceImpl(const std::string & deviceName);
|
||||||
|
virtual void destroyCurrentDeviceImpl();
|
||||||
|
virtual WTErr generateDeviceListImpl();
|
||||||
|
virtual WTErr updateDeviceListImpl();
|
||||||
|
virtual WTErr getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& bufferSizes) const;
|
||||||
|
|
||||||
bool m_UseMultithreading; ///< Flag indicates whether to use multi-threading for audio processing.
|
bool m_UseMultithreading; ///< Flag indicates whether to use multi-threading for audio processing.
|
||||||
bool m_bNoCopyAudioBuffer;
|
bool m_bNoCopyAudioBuffer;
|
||||||
eCABS_Method m_eCABS_Method; // Type of core audio buffer size list method
|
|
||||||
|
private:
|
||||||
static OSStatus StaticPropertyChangeProc (AudioHardwarePropertyID inPropertyID, void* inClientData);
|
// helper functions for this class only
|
||||||
OSStatus PropertyChangeProc (AudioHardwarePropertyID inPropertyID);
|
WTErr getDeviceAvailableSampleRates(DeviceID deviceId, std::vector<int>& sampleRates);
|
||||||
|
WTErr getDeviceMaxInputChannels(DeviceID deviceId, unsigned int& inputChannels);
|
||||||
void remove_pattern(const std::string& original_str, const std::string& pattern_str, std::string& return_str);
|
WTErr getDeviceMaxOutputChannels(DeviceID deviceId, unsigned int& outputChannels);
|
||||||
|
|
||||||
|
WCMRAudioDevice* m_NoneDevice;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //#ifndef __WCMRCoreAudioDeviceManager_h_
|
#endif //#ifndef __WCMRCoreAudioDeviceManager_h_
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,6 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
// Copyright (c) 2008 Waves Audio Ltd. All rights reserved.
|
||||||
//
|
//
|
||||||
//! \file WCMRNativeAudio.cpp
|
//! \file WCMRNativeAudio.cpp
|
||||||
//!
|
//!
|
||||||
|
|
@ -136,6 +119,12 @@ WTErr WCMRNativeAudioNoneDevice::SetCurrentBufferSize (int newSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WTErr WCMRNativeAudioNoneDevice::UpdateDeviceInfo ()
|
||||||
|
{
|
||||||
|
return eNoErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
WTErr WCMRNativeAudioNoneDevice::SetStreaming (bool newState)
|
WTErr WCMRNativeAudioNoneDevice::SetStreaming (bool newState)
|
||||||
{
|
{
|
||||||
if (Streaming() == newState)
|
if (Streaming() == newState)
|
||||||
|
|
@ -144,7 +133,8 @@ WTErr WCMRNativeAudioNoneDevice::SetStreaming (bool newState)
|
||||||
}
|
}
|
||||||
|
|
||||||
WCMRAudioDevice::SetStreaming(newState);
|
WCMRAudioDevice::SetStreaming(newState);
|
||||||
if(Streaming())
|
|
||||||
|
if (Streaming())
|
||||||
{
|
{
|
||||||
if (m_SilenceThread)
|
if (m_SilenceThread)
|
||||||
std::cerr << "\t\t\t\t\t !!!!!!!!!!!!!!! Warning: the inactive NONE-DEVICE was streaming!" << std::endl;
|
std::cerr << "\t\t\t\t\t !!!!!!!!!!!!!!! Warning: the inactive NONE-DEVICE was streaming!" << std::endl;
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,6 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
// Copyright (c) 2008 Waves Audio Ltd. All rights reserved.
|
||||||
//
|
//
|
||||||
//! \file WCMRNativeAudio.h
|
//! \file WCMRNativeAudio.h
|
||||||
//!
|
//!
|
||||||
|
|
@ -42,9 +25,10 @@ class WCMRNativeAudioDevice : public WCMRAudioDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WCMRNativeAudioDevice (WCMRAudioDeviceManager *pManager, bool useMultithreading = true, bool bNoCopy = false) : WCMRAudioDevice (pManager),
|
WCMRNativeAudioDevice (WCMRAudioDeviceManager *pManager, bool useMultithreading = true, bool bNoCopy = false) :
|
||||||
m_UseMultithreading (useMultithreading),
|
WCMRAudioDevice (pManager)
|
||||||
m_bNoCopyAudioBuffer(bNoCopy)
|
, m_UseMultithreading (useMultithreading)
|
||||||
|
, m_bNoCopyAudioBuffer(bNoCopy)
|
||||||
{}
|
{}
|
||||||
virtual ~WCMRNativeAudioDevice () {}
|
virtual ~WCMRNativeAudioDevice () {}
|
||||||
|
|
||||||
|
|
@ -52,7 +36,6 @@ protected:
|
||||||
bool m_UseMultithreading;
|
bool m_UseMultithreading;
|
||||||
bool m_bNoCopyAudioBuffer; ///< This flag determines whether the audio callback performs a copy of audio, or the source/sink perform the copy. It should be true to let source/sink do the copies.
|
bool m_bNoCopyAudioBuffer; ///< This flag determines whether the audio callback performs a copy of audio, or the source/sink perform the copy. It should be true to let source/sink do the copies.
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -65,6 +48,7 @@ public:
|
||||||
virtual WTErr SetActive (bool newState);///<Prepare/Activate device.
|
virtual WTErr SetActive (bool newState);///<Prepare/Activate device.
|
||||||
virtual WTErr SetStreaming (bool newState);///<Start/Stop Streaming - should reconnect connections when streaming starts!
|
virtual WTErr SetStreaming (bool newState);///<Start/Stop Streaming - should reconnect connections when streaming starts!
|
||||||
virtual WTErr SetCurrentBufferSize (int newSize);///<Change Current Buffer Size : This is a requset, might not be successful at run time!
|
virtual WTErr SetCurrentBufferSize (int newSize);///<Change Current Buffer Size : This is a requset, might not be successful at run time!
|
||||||
|
virtual WTErr UpdateDeviceInfo ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
@ -75,11 +59,11 @@ private:
|
||||||
#else
|
#else
|
||||||
inline void _usleep(uint64_t usec) { ::usleep(usec); }
|
inline void _usleep(uint64_t usec) { ::usleep(usec); }
|
||||||
#endif
|
#endif
|
||||||
static const size_t __m_NumInputChannels = 32;
|
static const size_t __m_NumInputChannels = 0;
|
||||||
static const size_t __m_NumOutputChannels = 32;
|
static const size_t __m_NumOutputChannels = 0;
|
||||||
pthread_t m_SilenceThread;
|
pthread_t m_SilenceThread;
|
||||||
float *_m_inputBuffer;
|
float *_m_inputBuffer;
|
||||||
float *_m_outputBuffer;
|
float *_m_outputBuffer;
|
||||||
static uint64_t __get_time_nanos ();
|
static uint64_t __get_time_nanos ();
|
||||||
#if defined (_WINDOWS)
|
#if defined (_WINDOWS)
|
||||||
HANDLE _waitableTimerForUsleep;
|
HANDLE _waitableTimerForUsleep;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,160 @@
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Copyright (c) 2008 Waves Audio Ltd. All rights reserved.
|
||||||
|
//
|
||||||
|
//! \file WCMRPortAudioDeviceManager.h
|
||||||
|
//!
|
||||||
|
//! WCMRPortAudioDeviceManager and related class declarations
|
||||||
|
//!
|
||||||
|
//---------------------------------------------------------------------------------*/
|
||||||
|
#ifndef __WCMRPortAudioDeviceManager_h_
|
||||||
|
#define __WCMRPortAudioDeviceManager_h_
|
||||||
|
|
||||||
|
#include "WCMRAudioDeviceManager.h"
|
||||||
|
#include "WCMRNativeAudio.h"
|
||||||
|
#include "portaudio.h"
|
||||||
|
|
||||||
|
//forward decl.
|
||||||
|
class WCMRPortAudioDeviceManager;
|
||||||
|
|
||||||
|
//! Manages a port audio device, providing information
|
||||||
|
//! about the device, and managing audio callbacks.
|
||||||
|
class WCMRPortAudioDevice : public WCMRNativeAudioDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
WCMRPortAudioDevice (WCMRPortAudioDeviceManager *pManager, unsigned int deviceID, bool useMultiThreading = true, bool bNoCopy = false);///<Constructor
|
||||||
|
virtual ~WCMRPortAudioDevice ();///<Destructor
|
||||||
|
|
||||||
|
virtual int CurrentSamplingRate(); ///<Current Sampling rate.?
|
||||||
|
virtual WTErr SetCurrentSamplingRate(int newRate);///<Change Current Sampling Rate : This is a requset, might not be successful at run time!
|
||||||
|
|
||||||
|
virtual int CurrentBufferSize();///<Current Buffer Size.? - note that this may change with change in sampling rate.
|
||||||
|
virtual WTErr SetCurrentBufferSize (int newSize);///<Change Current Buffer Size : This is a requset, might not be successful at run time!
|
||||||
|
|
||||||
|
virtual ConnectionStates ConnectionStatus();///< Connection Status - device available, gone, disconnected
|
||||||
|
|
||||||
|
virtual WTErr SetActive (bool newState);///<Prepare/Activate device.
|
||||||
|
|
||||||
|
virtual WTErr SetStreaming (bool newState);///<Start/Stop Streaming - should reconnect connections when streaming starts!
|
||||||
|
|
||||||
|
virtual WTErr SetMonitorChannels (int leftChannel, int rightChannel);///<Set monitor channels. - optional, will not be available with AG
|
||||||
|
virtual WTErr SetMonitorGain (float newGain);///<Set monitor gain. - optional, will not be available with AG
|
||||||
|
|
||||||
|
virtual WTErr ShowConfigPanel (void *pParam);///< Show Control Panel - in case of ASIO this will work only with Active device!
|
||||||
|
|
||||||
|
virtual int AudioCallback (const float *pInputBuffer, float *pOutputBuffer, unsigned long framesPerBuffe, bool dropsDetectedr);
|
||||||
|
|
||||||
|
virtual WTErr UpdateDeviceInfo ();
|
||||||
|
|
||||||
|
virtual WTErr ResetDevice();
|
||||||
|
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
static long StaticASIOMessageHook (void *pRefCon, long selector, long value, void* message, double* opt);
|
||||||
|
long ASIOMessageHook (long selector, long value, void* message, double* opt);
|
||||||
|
#endif //_WINDOWS
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static DWORD WINAPI __DoIdle__(LPVOID lpThreadParameter);
|
||||||
|
|
||||||
|
// Methods which are executed by device processing thread
|
||||||
|
WTErr DoIdle();///<Do Idle Processing
|
||||||
|
void initDevice();
|
||||||
|
void terminateDevice();
|
||||||
|
void updateDeviceInfo(bool callerIsWaiting = false);
|
||||||
|
void activateDevice(bool callerIsWaiting = false);
|
||||||
|
void deactivateDevice(bool callerIsWaiting = false);
|
||||||
|
void startStreaming(bool callerIsWaiting = false);
|
||||||
|
void stopStreaming(bool callerIsWaiting = false);
|
||||||
|
void resetDevice (bool callerIsWaiting = false);///<Reset device - close and reopen stream, update device information!
|
||||||
|
|
||||||
|
PaError testStateValidness(int sampleRate, int bufferSize);
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static int TheCallback (const void *pInputBuffer, void *pOutputBuffer, unsigned long framesPerBuffer,
|
||||||
|
const PaStreamCallbackTimeInfo* /*pTimeInfo*/, PaStreamCallbackFlags /*statusFlags*/, void *pUserData );
|
||||||
|
|
||||||
|
unsigned int m_DeviceID; ///< The PA device id
|
||||||
|
PaStream* m_PortAudioStream; ///< Port audio stream, when the device is active!
|
||||||
|
bool m_StopRequested; ///< should be set to true when want to stop, set to false otherwise.
|
||||||
|
const float *m_pInputData; ///< This is what came in with the most recent callback.
|
||||||
|
int m_SampleCounter; ///< The current running sample counter, updated by the audio callback.
|
||||||
|
int m_SampleCountAtLastIdle;
|
||||||
|
|
||||||
|
int m_DropsDetected; ///< Number of times audio drops have been detected so far.
|
||||||
|
int m_DropsReported; ///< Number of times audio drops have been reported so far to the client.
|
||||||
|
bool m_IgnoreThisDrop; ///< Allows disregarding the first drop
|
||||||
|
|
||||||
|
int m_BufferSizeChangeRequested;
|
||||||
|
int m_BufferSizeChangeReported;
|
||||||
|
int m_ResetRequested;
|
||||||
|
int m_ResetReported;
|
||||||
|
int m_ResyncRequested;
|
||||||
|
int m_ResyncReported;
|
||||||
|
|
||||||
|
HANDLE m_hDeviceProcessingThread;
|
||||||
|
DWORD m_DeviceProcessingThreadID;
|
||||||
|
|
||||||
|
///< Backend request events
|
||||||
|
HANDLE m_hResetRequestedEvent;
|
||||||
|
HANDLE m_hResetDone;
|
||||||
|
|
||||||
|
HANDLE m_hUpdateDeviceInfoRequestedEvent;
|
||||||
|
HANDLE m_hUpdateDeviceInfoDone;
|
||||||
|
|
||||||
|
HANDLE m_hActivateRequestedEvent;
|
||||||
|
HANDLE m_hActivationDone;
|
||||||
|
|
||||||
|
HANDLE m_hDeActivateRequestedEvent;
|
||||||
|
HANDLE m_hDeActivationDone;
|
||||||
|
|
||||||
|
HANDLE m_hStartStreamingRequestedEvent;
|
||||||
|
HANDLE m_hStartStreamingDone;
|
||||||
|
|
||||||
|
HANDLE m_hStopStreamingRequestedEvent;
|
||||||
|
HANDLE m_hStopStreamingDone;
|
||||||
|
/////////////////////////
|
||||||
|
|
||||||
|
///< Device request events
|
||||||
|
HANDLE m_hResetFromDevRequestedEvent;
|
||||||
|
HANDLE m_hBufferSizeChangedEvent;
|
||||||
|
HANDLE m_hSampleRateChangedEvent;
|
||||||
|
/////////////////////////////
|
||||||
|
|
||||||
|
///< Sync events
|
||||||
|
HANDLE m_hDeviceInitialized;
|
||||||
|
HANDLE m_hExitIdleThread;
|
||||||
|
|
||||||
|
//Should be set if the device connection status is "DeviceErrors"
|
||||||
|
WTErr m_lastErr;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! WCMRPortAudioDeviceManager
|
||||||
|
/*! The PortAudio Device Manager class */
|
||||||
|
class WCMRPortAudioDeviceManager : public WCMRAudioDeviceManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WCMRPortAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient, eAudioDeviceFilter eCurAudioDeviceFilter,
|
||||||
|
bool useMultithreading = true, bool bNocopy = false); ///< constructor
|
||||||
|
|
||||||
|
virtual ~WCMRPortAudioDeviceManager(void); ///< destructor
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual WCMRAudioDevice* initNewCurrentDeviceImpl(const std::string & deviceName);
|
||||||
|
virtual void destroyCurrentDeviceImpl();
|
||||||
|
virtual WTErr generateDeviceListImpl(); // use this in derived class to fill device list
|
||||||
|
virtual WTErr updateDeviceListImpl() {return eNoErr; } // not supported
|
||||||
|
virtual WTErr getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& buffers) const;
|
||||||
|
|
||||||
|
bool m_UseMultithreading; ///< Flag indicates whether to use multi-threading for audio processing.
|
||||||
|
bool m_bNoCopyAudioBuffer;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// helper functions for this class only
|
||||||
|
WTErr getDeviceAvailableSampleRates(DeviceID deviceId, std::vector<int>& sampleRates);
|
||||||
|
|
||||||
|
WCMRAudioDevice* m_NoneDevice;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //#ifndef __WCMRPortAudioDeviceManager_h_
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifndef __MinMaxUtilities_h__
|
#ifndef __MinMaxUtilities_h__
|
||||||
#define __MinMaxUtilities_h__
|
#define __MinMaxUtilities_h__
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,87 +1,69 @@
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
#include "IncludeWindows.h"
|
||||||
|
#endif
|
||||||
|
#if defined(__linux__) || defined(__MACOS__)
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "UMicroseconds.h"
|
||||||
|
|
||||||
|
namespace wvNS {
|
||||||
|
UMicroseconds& UMicroseconds::ReadTime()
|
||||||
|
{
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
LARGE_INTEGER Frequency, Count ;
|
||||||
|
|
||||||
|
QueryPerformanceFrequency(&Frequency) ;
|
||||||
|
QueryPerformanceCounter(&Count);
|
||||||
|
theTime = uint64_t((Count.QuadPart * 1000000.0 / Frequency.QuadPart));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__linux__) || defined(__MACOS__)
|
||||||
|
// Mac code replaced by posix calls, to reduce Carbon dependency.
|
||||||
|
timeval buf;
|
||||||
|
|
||||||
|
gettimeofday(&buf,NULL);
|
||||||
|
|
||||||
|
// micro sec
|
||||||
|
theTime = uint64_t(buf.tv_sec) * 1000*1000 + buf.tv_usec;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
Removed in favor of the posix implementation.
|
||||||
|
#ifdef __MACOS__
|
||||||
This program is free software; you can redistribute it and/or modify
|
uint32_t UMicroseconds::hi() {return reinterpret_cast<UnsignedWide*>(&theTime)->hi;}
|
||||||
it under the terms of the GNU General Public License as published by
|
uint32_t UMicroseconds::lo() {return reinterpret_cast<UnsignedWide*>(&theTime)->lo;}
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
#endif
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
#ifdef _WINDOWS
|
void UMicrosecondsAccumulator::Start()
|
||||||
#include "IncludeWindows.h"
|
{
|
||||||
#endif
|
m_start_time.ReadTime();
|
||||||
#if defined(__linux__) || defined(__MACOS__)
|
}
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
void UMicrosecondsAccumulator::Stop()
|
||||||
|
{
|
||||||
#include "UMicroseconds.h"
|
UMicroseconds stop_time;
|
||||||
|
|
||||||
namespace wvNS {
|
m_accumulator += stop_time.GetNativeTime() - m_start_time.GetNativeTime();
|
||||||
UMicroseconds& UMicroseconds::ReadTime()
|
}
|
||||||
{
|
|
||||||
#ifdef _WINDOWS
|
void UMicrosecondsAccumulator::Clear()
|
||||||
LARGE_INTEGER Frequency, Count ;
|
{
|
||||||
|
m_start_time = 0;
|
||||||
QueryPerformanceFrequency(&Frequency) ;
|
m_accumulator = 0;
|
||||||
QueryPerformanceCounter(&Count);
|
}
|
||||||
theTime = uint64_t((Count.QuadPart * 1000000.0 / Frequency.QuadPart));
|
|
||||||
#endif
|
UMicroseconds UMicrosecondsAccumulator::GetAccumulatedTime() const
|
||||||
|
{
|
||||||
#if defined(__linux__) || defined(__MACOS__)
|
return m_accumulator;
|
||||||
// Mac code replaced by posix calls, to reduce Carbon dependency.
|
}
|
||||||
timeval buf;
|
|
||||||
|
UMicrosecondsAccumulator& UMicrosecondsAccumulator::operator+=(const UMicrosecondsAccumulator& inaccum_to_add)
|
||||||
gettimeofday(&buf,NULL);
|
{
|
||||||
|
m_accumulator += inaccum_to_add.GetAccumulatedTime();
|
||||||
// micro sec
|
return *this;
|
||||||
theTime = uint64_t(buf.tv_sec) * 1000*1000 + buf.tv_usec;
|
}
|
||||||
#endif
|
|
||||||
|
} // namespace wvNS {
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
Removed in favor of the posix implementation.
|
|
||||||
#ifdef __MACOS__
|
|
||||||
uint32_t UMicroseconds::hi() {return reinterpret_cast<UnsignedWide*>(&theTime)->hi;}
|
|
||||||
uint32_t UMicroseconds::lo() {return reinterpret_cast<UnsignedWide*>(&theTime)->lo;}
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
void UMicrosecondsAccumulator::Start()
|
|
||||||
{
|
|
||||||
m_start_time.ReadTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
void UMicrosecondsAccumulator::Stop()
|
|
||||||
{
|
|
||||||
UMicroseconds stop_time;
|
|
||||||
|
|
||||||
m_accumulator += stop_time.GetNativeTime() - m_start_time.GetNativeTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
void UMicrosecondsAccumulator::Clear()
|
|
||||||
{
|
|
||||||
m_start_time = 0;
|
|
||||||
m_accumulator = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
UMicroseconds UMicrosecondsAccumulator::GetAccumulatedTime() const
|
|
||||||
{
|
|
||||||
return m_accumulator;
|
|
||||||
}
|
|
||||||
|
|
||||||
UMicrosecondsAccumulator& UMicrosecondsAccumulator::operator+=(const UMicrosecondsAccumulator& inaccum_to_add)
|
|
||||||
{
|
|
||||||
m_accumulator += inaccum_to_add.GetAccumulatedTime();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace wvNS {
|
|
||||||
|
|
|
||||||
|
|
@ -1,123 +1,105 @@
|
||||||
/*
|
#ifndef __UMicroseconds_h__
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
#define __UMicroseconds_h__
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
/* Copy to include
|
||||||
it under the terms of the GNU General Public License as published by
|
#include "UMicroseconds.h"
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
#ifndef __UMicroseconds_h__
|
|
||||||
#define __UMicroseconds_h__
|
|
||||||
|
|
||||||
/* Copy to include
|
#include "BasicTypes/WUDefines.h"
|
||||||
#include "UMicroseconds.h"
|
#include "BasicTypes/WUTypes.h"
|
||||||
*/
|
|
||||||
|
namespace wvNS {
|
||||||
|
// a wraper for Microseconds function from Timer.h
|
||||||
|
class DllExport UMicroseconds
|
||||||
#include "BasicTypes/WUDefines.h"
|
{
|
||||||
#include "BasicTypes/WUTypes.h"
|
public:
|
||||||
|
|
||||||
namespace wvNS {
|
#ifdef _WINDOWS
|
||||||
// a wraper for Microseconds function from Timer.h
|
typedef int64_t TimeKeeper;
|
||||||
class DllExport UMicroseconds
|
#endif
|
||||||
{
|
#ifdef __MACOS__
|
||||||
public:
|
typedef uint64_t TimeKeeper;
|
||||||
|
#endif
|
||||||
#ifdef _WINDOWS
|
#ifdef __linux__
|
||||||
typedef int64_t TimeKeeper;
|
typedef uint64_t TimeKeeper;
|
||||||
#endif
|
#endif
|
||||||
#ifdef __MACOS__
|
|
||||||
typedef uint64_t TimeKeeper;
|
private:
|
||||||
#endif
|
TimeKeeper theTime;
|
||||||
#ifdef __linux__
|
|
||||||
typedef uint64_t TimeKeeper;
|
public:
|
||||||
#endif
|
|
||||||
|
UMicroseconds()
|
||||||
private:
|
{
|
||||||
TimeKeeper theTime;
|
ReadTime();
|
||||||
|
}
|
||||||
public:
|
|
||||||
|
UMicroseconds(const TimeKeeper in_initVal) : theTime(in_initVal) {}
|
||||||
UMicroseconds()
|
|
||||||
{
|
UMicroseconds(const UMicroseconds& inUM) : theTime(inUM.theTime) {}
|
||||||
ReadTime();
|
UMicroseconds& operator=(const UMicroseconds& inUM) {theTime = inUM.theTime; return *this;}
|
||||||
}
|
UMicroseconds& operator+=(const TimeKeeper in_timeToAdd) {theTime += in_timeToAdd; return *this;}
|
||||||
|
|
||||||
UMicroseconds(const TimeKeeper in_initVal) : theTime(in_initVal) {}
|
UMicroseconds& ReadTime();
|
||||||
|
|
||||||
UMicroseconds(const UMicroseconds& inUM) : theTime(inUM.theTime) {}
|
TimeKeeper GetNativeTime() const {return theTime;}
|
||||||
UMicroseconds& operator=(const UMicroseconds& inUM) {theTime = inUM.theTime; return *this;}
|
operator uint64_t () {return static_cast<uint64_t>(theTime);}
|
||||||
UMicroseconds& operator+=(const TimeKeeper in_timeToAdd) {theTime += in_timeToAdd; return *this;}
|
operator double () const {return static_cast<const double>(theTime);}
|
||||||
|
|
||||||
UMicroseconds& ReadTime();
|
double Seconds() const {return static_cast<double>(theTime) / double(1000000);}
|
||||||
|
double MilliSeconds() const {return static_cast<double>(theTime) / double(1000);}
|
||||||
TimeKeeper GetNativeTime() const {return theTime;}
|
double MicroSeconds() const {return static_cast<double>(theTime);}
|
||||||
operator uint64_t () {return static_cast<uint64_t>(theTime);}
|
|
||||||
operator double () const {return static_cast<const double>(theTime);}
|
#ifdef __MACOS__
|
||||||
|
uint32_t hi();
|
||||||
double Seconds() const {return static_cast<double>(theTime) / double(1000000);}
|
uint32_t lo();
|
||||||
double MilliSeconds() const {return static_cast<double>(theTime) / double(1000);}
|
#endif
|
||||||
double MicroSeconds() const {return static_cast<double>(theTime);}
|
};
|
||||||
|
|
||||||
#ifdef __MACOS__
|
inline UMicroseconds operator-(const UMicroseconds& in_one, const UMicroseconds& in_two)
|
||||||
uint32_t hi();
|
{
|
||||||
uint32_t lo();
|
UMicroseconds retVal(in_one.GetNativeTime() - in_two.GetNativeTime());
|
||||||
#endif
|
return retVal;
|
||||||
};
|
}
|
||||||
|
|
||||||
inline UMicroseconds operator-(const UMicroseconds& in_one, const UMicroseconds& in_two)
|
class UMicrosecondsAccumulator
|
||||||
{
|
{
|
||||||
UMicroseconds retVal(in_one.GetNativeTime() - in_two.GetNativeTime());
|
public:
|
||||||
return retVal;
|
UMicrosecondsAccumulator() : m_start_time(0), m_accumulator(0) {}
|
||||||
}
|
|
||||||
|
void Start();
|
||||||
class UMicrosecondsAccumulator
|
void Stop();
|
||||||
{
|
void Clear();
|
||||||
public:
|
|
||||||
UMicrosecondsAccumulator() : m_start_time(0), m_accumulator(0) {}
|
UMicroseconds GetAccumulatedTime() const;
|
||||||
|
|
||||||
void Start();
|
UMicrosecondsAccumulator& operator+=(const UMicrosecondsAccumulator&);
|
||||||
void Stop();
|
|
||||||
void Clear();
|
protected:
|
||||||
|
UMicroseconds m_start_time;
|
||||||
UMicroseconds GetAccumulatedTime() const;
|
UMicroseconds m_accumulator;
|
||||||
|
};
|
||||||
UMicrosecondsAccumulator& operator+=(const UMicrosecondsAccumulator&);
|
|
||||||
|
inline UMicroseconds operator-(const UMicrosecondsAccumulator& in_one, const UMicrosecondsAccumulator& in_two)
|
||||||
protected:
|
{
|
||||||
UMicroseconds m_start_time;
|
UMicroseconds retVal(in_one.GetAccumulatedTime() - in_two.GetAccumulatedTime());
|
||||||
UMicroseconds m_accumulator;
|
return retVal;
|
||||||
};
|
}
|
||||||
|
|
||||||
inline UMicroseconds operator-(const UMicrosecondsAccumulator& in_one, const UMicrosecondsAccumulator& in_two)
|
//=========================================================================================//
|
||||||
{
|
inline void MicrosecondDelay(double amt)
|
||||||
UMicroseconds retVal(in_one.GetAccumulatedTime() - in_two.GetAccumulatedTime());
|
//=========================================================================================//
|
||||||
return retVal;
|
{
|
||||||
}
|
UMicroseconds than;
|
||||||
|
UMicroseconds now;
|
||||||
//=========================================================================================//
|
|
||||||
inline void MicrosecondDelay(double amt)
|
do
|
||||||
//=========================================================================================//
|
{
|
||||||
{
|
now.ReadTime();
|
||||||
UMicroseconds than;
|
} while ((now.MicroSeconds() - than.MicroSeconds()) < amt);
|
||||||
UMicroseconds now;
|
}
|
||||||
|
|
||||||
do
|
} // namespace wvNS {
|
||||||
{
|
#endif //#ifndef __UMicroseconds_h__
|
||||||
now.ReadTime();
|
|
||||||
} while ((now.MicroSeconds() - than.MicroSeconds()) < amt);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace wvNS {
|
|
||||||
#endif //#ifndef __UMicroseconds_h__
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifndef __WCFixedString_h__
|
#ifndef __WCFixedString_h__
|
||||||
#define __WCFixedString_h__
|
#define __WCFixedString_h__
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifndef __WUErrors_h__
|
#ifndef __WUErrors_h__
|
||||||
#define __WUErrors_h__
|
#define __WUErrors_h__
|
||||||
|
|
||||||
|
|
@ -53,6 +35,7 @@ const WTErr eAppTerminateFailed = -23; //!< failed to terminate an appl
|
||||||
const WTErr eAppReturnedError = -24; //!< Non zero exit code from application
|
const WTErr eAppReturnedError = -24; //!< Non zero exit code from application
|
||||||
const WTErr eNotImplemented = -25; //!< Function is not implmemented
|
const WTErr eNotImplemented = -25; //!< Function is not implmemented
|
||||||
const WTErr eNotEmpty = -26; //!< Something was expected to be empty but is not
|
const WTErr eNotEmpty = -26; //!< Something was expected to be empty but is not
|
||||||
|
const WTErr eAsioFailed = -27;
|
||||||
|
|
||||||
// File Manager errors
|
// File Manager errors
|
||||||
const WTErr eFMNoSuchVolume = -1001;
|
const WTErr eFMNoSuchVolume = -1001;
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifndef __safe_delete_h__
|
#ifndef __safe_delete_h__
|
||||||
#define __safe_delete_h__
|
#define __safe_delete_h__
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#include "WCRefManager.h"
|
#include "WCRefManager.h"
|
||||||
|
|
||||||
/// Construcotr.
|
/// Construcotr.
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifndef WCREFMANAGER_H
|
#ifndef WCREFMANAGER_H
|
||||||
#define WCREFMANAGER_H
|
#define WCREFMANAGER_H
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#include "Threads/WCThreadSafe.h"
|
#include "Threads/WCThreadSafe.h"
|
||||||
|
|
||||||
#if XPLATFORMTHREADS_WINDOWS
|
#if XPLATFORMTHREADS_WINDOWS
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifndef __WCThreadSafe_h_
|
#ifndef __WCThreadSafe_h_
|
||||||
#define __WCThreadSafe_h_
|
#define __WCThreadSafe_h_
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifndef __WavesPublicAPI_Defines_h__
|
#ifndef __WavesPublicAPI_Defines_h__
|
||||||
#define __WavesPublicAPI_Defines_h__
|
#define __WavesPublicAPI_Defines_h__
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,5 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (c) 2011 Waves Audio Ltd. All rights reserved.
|
||||||
// \file WTErr.h, defines basic error type and "No Error" code
|
// \file WTErr.h, defines basic error type and "No Error" code
|
||||||
// All users may use their own error codes with this type, as long as eNoErr remains defined here
|
// All users may use their own error codes with this type, as long as eNoErr remains defined here
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,3 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2013 Waves Audio Ltd.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifndef __stdint_h__
|
#ifndef __stdint_h__
|
||||||
#define __stdint_h__
|
#define __stdint_h__
|
||||||
|
|
||||||
|
|
|
||||||
82
libs/backends/wavesaudio/wscript
Normal file → Executable file
82
libs/backends/wavesaudio/wscript
Normal file → Executable file
|
|
@ -19,14 +19,18 @@ def options(opt):
|
||||||
autowaf.set_options(opt)
|
autowaf.set_options(opt)
|
||||||
|
|
||||||
def configure(conf):
|
def configure(conf):
|
||||||
|
if conf.options.dist_target == 'mingw':
|
||||||
|
autowaf.check_pkg(conf, 'portaudio-2.0', uselib_store='PORTAUDIO',
|
||||||
|
atleast_version='19')
|
||||||
autowaf.configure(conf)
|
autowaf.configure(conf)
|
||||||
|
|
||||||
def build(bld):
|
def build(bld):
|
||||||
obj = bld(features = 'c cxx cxxshlib')
|
|
||||||
if bld.env['build_target'] == 'mountain_lion':
|
if bld.env['build_target'] == 'mingw':
|
||||||
obj.framework = 'CoreMidi'
|
obj = bld(features = 'cxx cxxshlib')
|
||||||
else:
|
else:
|
||||||
obj.framework = 'CoreMIDI'
|
obj = bld(features = 'cxx cxxshlib', framework = ["CoreMidi"])
|
||||||
|
|
||||||
obj.source = [
|
obj.source = [
|
||||||
'waves_audiobackend.cc',
|
'waves_audiobackend.cc',
|
||||||
'waves_audiobackend.latency.cc',
|
'waves_audiobackend.latency.cc',
|
||||||
|
|
@ -41,34 +45,60 @@ def build(bld):
|
||||||
'waves_midi_buffer.cc',
|
'waves_midi_buffer.cc',
|
||||||
'wavesapi/refmanager/WCRefManager.cpp',
|
'wavesapi/refmanager/WCRefManager.cpp',
|
||||||
'wavesapi/devicemanager/WCMRAudioDeviceManager.cpp',
|
'wavesapi/devicemanager/WCMRAudioDeviceManager.cpp',
|
||||||
'wavesapi/devicemanager/WCMRCoreAudioDeviceManager.cpp',
|
|
||||||
'wavesapi/devicemanager/WCMRNativeAudio.cpp',
|
'wavesapi/devicemanager/WCMRNativeAudio.cpp',
|
||||||
'wavesapi/threads/WCThreadSafe.cpp',
|
'wavesapi/threads/WCThreadSafe.cpp',
|
||||||
'portmidi/src/pm_common/pmutil.c',
|
'portmidi/src/pm_common/pmutil.c',
|
||||||
'portmidi/src/pm_common/portmidi.c',
|
'portmidi/src/pm_common/portmidi.c'
|
||||||
'portmidi/src/pm_mac/pmmac.c',
|
|
||||||
'portmidi/src/pm_mac/pmmacosxcm.c',
|
|
||||||
'portmidi/src/pm_mac/finddefault.c',
|
|
||||||
'portmidi/src/pm_mac/readbinaryplist.c',
|
|
||||||
'portmidi/src/porttime/ptmacosx_mach.c'
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if bld.env['build_target'] == 'mingw':
|
||||||
|
platform_dependent = [
|
||||||
|
'wavesapi/miscutils/UMicroseconds.cpp',
|
||||||
|
'wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp',
|
||||||
|
'portmidi/src/pm_win/pmwin.c',
|
||||||
|
'portmidi/src/pm_win/pmwinmm.c',
|
||||||
|
'portmidi/src/porttime/ptwinmm.c'
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
platform_dependent = [
|
||||||
|
'wavesapi/devicemanager/WCMRCoreAudioDeviceManager.cpp',
|
||||||
|
'portmidi/src/pm_mac/pmmac.c',
|
||||||
|
'portmidi/src/pm_mac/pmmacosxcm.c',
|
||||||
|
'portmidi/src/pm_mac/finddefault.c',
|
||||||
|
'portmidi/src/pm_mac/readbinaryplist.c',
|
||||||
|
'portmidi/src/porttime/ptmacosx_mach.c'
|
||||||
|
]
|
||||||
|
|
||||||
|
obj.source.extend(platform_dependent)
|
||||||
|
|
||||||
obj.includes = ['.',
|
obj.includes = ['.',
|
||||||
'wavesapi',
|
'wavesapi',
|
||||||
'wavesapi/refmanager',
|
'wavesapi/refmanager',
|
||||||
'wavesapi/wavespublicapi',
|
'wavesapi/wavespublicapi',
|
||||||
'wavesapi/devicemanager',
|
'wavesapi/devicemanager',
|
||||||
'wavesapi/miscutils',
|
'wavesapi/miscutils',
|
||||||
'portmidi',
|
'wavesapi/threads',
|
||||||
'portmidi/src/pm_common'
|
'portmidi',
|
||||||
]
|
'portmidi/src/pm_common'
|
||||||
|
]
|
||||||
|
|
||||||
obj.cxxflags = [ '-fPIC' ]
|
obj.cxxflags = [ '-fPIC' ]
|
||||||
obj.cflags = [ '-fPIC', '-fms-extensions' ]
|
obj.cflags = [ '-fPIC', '-fms-extensions' ]
|
||||||
obj.name = 'waves_audiobackend'
|
obj.name = 'waves_audiobackend'
|
||||||
obj.target = 'waves_audiobackend'
|
obj.target = 'waves_audiobackend'
|
||||||
obj.use = [ 'libardour', 'libpbd' ]
|
obj.use = 'libardour libpbd'
|
||||||
|
if bld.env['build_target'] == 'mingw':
|
||||||
|
obj.uselib = ['PORTAUDIO']
|
||||||
obj.vnum = WAVESAUDIOBACKEND_VERSION
|
obj.vnum = WAVESAUDIOBACKEND_VERSION
|
||||||
obj.install_path = os.path.join(bld.env['LIBDIR'], 'backends')
|
obj.install_path = os.path.join(bld.env['LIBDIR'], 'ardour3', 'backends')
|
||||||
obj.defines = ['PACKAGE="' + I18N_PACKAGE + '"',
|
|
||||||
'__MACOS__',
|
if bld.env['build_target']== 'mingw':
|
||||||
'ARDOURBACKEND_DLL_EXPORTS'
|
obj.defines = ['PACKAGE="' + I18N_PACKAGE + '"',
|
||||||
]
|
'_WINDOWS',
|
||||||
|
'ARDOURBACKEND_DLL_EXPORTS'
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
obj.defines = ['PACKAGE="' + I18N_PACKAGE + '"',
|
||||||
|
'__MACOS__',
|
||||||
|
'ARDOURBACKEND_DLL_EXPORTS'
|
||||||
|
]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue