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:
Paul Davis 2014-04-30 13:46:41 -04:00
parent 1ac8815296
commit 19d21045af
58 changed files with 9353 additions and 7631 deletions

View file

@ -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 */

View file

@ -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

View file

@ -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); }

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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 );

View file

@ -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

View file

@ -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 ();

View file

@ -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);
} }

View file

@ -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

View file

@ -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));
} }

View file

@ -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__ */

View file

@ -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;
} }

View file

@ -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__ */

View file

@ -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; }
}

View file

@ -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__ */

View file

@ -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;
} }

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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"

View file

@ -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__ */

View file

@ -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 ();
} }

View file

@ -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__ */

View file

@ -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__

View file

@ -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__

View file

@ -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__

View file

@ -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__

View file

@ -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__

View file

@ -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__

View file

@ -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__

View file

@ -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
// //

View file

@ -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_

View file

@ -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;
}

View file

@ -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_

View file

@ -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;

View file

@ -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

View file

@ -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_

View file

@ -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__

View file

@ -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 {

View file

@ -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__

View file

@ -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__

View file

@ -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;

View file

@ -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__

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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_

View file

@ -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__

View file

@ -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
/////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////

View file

@ -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
View 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'
]