diff options
author | Marcus Müller <mmueller@gnuradio.org> | 2019-08-07 21:45:12 +0200 |
---|---|---|
committer | Marcus Müller <marcus@hostalia.de> | 2019-08-09 23:04:28 +0200 |
commit | f7bbf2c1d8d780294f3e016aff239ca35eb6516e (patch) | |
tree | e09ab6112e02b2215b2d59ac24d3d6ea2edac745 /gr-audio/lib/osx | |
parent | 78431dc6941e3acc67c858277dfe4a0ed583643c (diff) |
Tree: clang-format without the include sorting
Diffstat (limited to 'gr-audio/lib/osx')
-rw-r--r-- | gr-audio/lib/osx/circular_buffer.h | 531 | ||||
-rw-r--r-- | gr-audio/lib/osx/osx_common.h | 46 | ||||
-rw-r--r-- | gr-audio/lib/osx/osx_impl.cc | 412 | ||||
-rw-r--r-- | gr-audio/lib/osx/osx_sink.cc | 1310 | ||||
-rw-r--r-- | gr-audio/lib/osx/osx_sink.h | 142 | ||||
-rw-r--r-- | gr-audio/lib/osx/osx_source.cc | 2002 | ||||
-rw-r--r-- | gr-audio/lib/osx/osx_source.h | 199 |
7 files changed, 2200 insertions, 2442 deletions
diff --git a/gr-audio/lib/osx/circular_buffer.h b/gr-audio/lib/osx/circular_buffer.h index 5193a982d3..c18f2464cb 100644 --- a/gr-audio/lib/osx/circular_buffer.h +++ b/gr-audio/lib/osx/circular_buffer.h @@ -32,291 +32,302 @@ #endif #if DO_DEBUG -#define DEBUG(X) do{X} while(0); +#define DEBUG(X) \ + do { \ + X \ + } while (0); #else -#define DEBUG(X) do{} while(0); +#define DEBUG(X) \ + do { \ + } while (0); #endif template <class T> class circular_buffer { private: -// the buffer to use - T* d_buffer; + // the buffer to use + T* d_buffer; -// the following are in Items (type T) - size_t d_bufLen_I, d_readNdx_I, d_writeNdx_I; - size_t d_n_avail_write_I, d_n_avail_read_I; + // the following are in Items (type T) + size_t d_bufLen_I, d_readNdx_I, d_writeNdx_I; + size_t d_n_avail_write_I, d_n_avail_read_I; -// stuff to control access to class internals - gr::thread::mutex* d_internal; - gr::thread::condition_variable* d_readBlock; - gr::thread::condition_variable* d_writeBlock; + // stuff to control access to class internals + gr::thread::mutex* d_internal; + gr::thread::condition_variable* d_readBlock; + gr::thread::condition_variable* d_writeBlock; -// booleans to decide how to control reading, writing, and aborting - bool d_doWriteBlock, d_doFullRead, d_doAbort; + // booleans to decide how to control reading, writing, and aborting + bool d_doWriteBlock, d_doFullRead, d_doAbort; - void delete_mutex_cond () { - if (d_internal) { - delete d_internal; - d_internal = NULL; - } - if (d_readBlock) { - delete d_readBlock; - d_readBlock = NULL; - } - if (d_writeBlock) { - delete d_writeBlock; - d_writeBlock = NULL; - } - }; + void delete_mutex_cond() + { + if (d_internal) { + delete d_internal; + d_internal = NULL; + } + if (d_readBlock) { + delete d_readBlock; + d_readBlock = NULL; + } + if (d_writeBlock) { + delete d_writeBlock; + d_writeBlock = NULL; + } + }; public: - circular_buffer (size_t bufLen_I, - bool doWriteBlock = true, bool doFullRead = false) { - if (bufLen_I == 0) - throw std::runtime_error ("circular_buffer(): " - "Number of items to buffer must be > 0.\n"); - d_bufLen_I = bufLen_I; - d_buffer = (T*) new T[d_bufLen_I]; - d_doWriteBlock = doWriteBlock; - d_doFullRead = doFullRead; - d_internal = NULL; - d_readBlock = d_writeBlock = NULL; - reset (); - DEBUG (std::cerr << "c_b(): buf len (items) = " << d_bufLen_ - << ", doWriteBlock = " << (d_doWriteBlock ? "true" : "false") - << ", doFullRead = " << (d_doFullRead ? "true" : "false") - << std::endl); - }; + circular_buffer(size_t bufLen_I, bool doWriteBlock = true, bool doFullRead = false) + { + if (bufLen_I == 0) + throw std::runtime_error("circular_buffer(): " + "Number of items to buffer must be > 0.\n"); + d_bufLen_I = bufLen_I; + d_buffer = (T*)new T[d_bufLen_I]; + d_doWriteBlock = doWriteBlock; + d_doFullRead = doFullRead; + d_internal = NULL; + d_readBlock = d_writeBlock = NULL; + reset(); + DEBUG(std::cerr << "c_b(): buf len (items) = " << d_bufLen_ + << ", doWriteBlock = " << (d_doWriteBlock ? "true" : "false") + << ", doFullRead = " << (d_doFullRead ? "true" : "false") + << std::endl); + }; - ~circular_buffer () { - delete_mutex_cond (); - delete [] d_buffer; - }; + ~circular_buffer() + { + delete_mutex_cond(); + delete[] d_buffer; + }; - inline size_t n_avail_write_items () { - gr::thread::scoped_lock l (*d_internal); - size_t retVal = d_n_avail_write_I; - return (retVal); - }; + inline size_t n_avail_write_items() + { + gr::thread::scoped_lock l(*d_internal); + size_t retVal = d_n_avail_write_I; + return (retVal); + }; - inline size_t n_avail_read_items () { - gr::thread::scoped_lock l (*d_internal); - size_t retVal = d_n_avail_read_I; - return (retVal); - }; + inline size_t n_avail_read_items() + { + gr::thread::scoped_lock l(*d_internal); + size_t retVal = d_n_avail_read_I; + return (retVal); + }; - inline size_t buffer_length_items () {return (d_bufLen_I);}; - inline bool do_write_block () {return (d_doWriteBlock);}; - inline bool do_full_read () {return (d_doFullRead);}; + inline size_t buffer_length_items() { return (d_bufLen_I); }; + inline bool do_write_block() { return (d_doWriteBlock); }; + inline bool do_full_read() { return (d_doFullRead); }; - void reset () { - d_doAbort = false; - bzero (d_buffer, d_bufLen_I * sizeof (T)); - d_readNdx_I = d_writeNdx_I = d_n_avail_read_I = 0; - d_n_avail_write_I = d_bufLen_I; - delete_mutex_cond (); - // create a mutex to handle contention of shared resources; - // any routine needed access to shared resources uses lock() - // before doing anything, then unlock() when finished. - d_internal = new gr::thread::mutex (); - // link the internal mutex to the read and write conditions; - // when wait() is called, the internal mutex will automatically - // be unlock()'ed. Upon return (from a notify_one() to the condition), - // the internal mutex will be lock()'ed. - d_readBlock = new gr::thread::condition_variable (); - d_writeBlock = new gr::thread::condition_variable (); - }; + void reset() + { + d_doAbort = false; + bzero(d_buffer, d_bufLen_I * sizeof(T)); + d_readNdx_I = d_writeNdx_I = d_n_avail_read_I = 0; + d_n_avail_write_I = d_bufLen_I; + delete_mutex_cond(); + // create a mutex to handle contention of shared resources; + // any routine needed access to shared resources uses lock() + // before doing anything, then unlock() when finished. + d_internal = new gr::thread::mutex(); + // link the internal mutex to the read and write conditions; + // when wait() is called, the internal mutex will automatically + // be unlock()'ed. Upon return (from a notify_one() to the condition), + // the internal mutex will be lock()'ed. + d_readBlock = new gr::thread::condition_variable(); + d_writeBlock = new gr::thread::condition_variable(); + }; -/* - * enqueue: add the given buffer of item-length to the queue, - * first-in-first-out (FIFO). - * - * inputs: - * buf: a pointer to the buffer holding the data - * - * bufLen_I: the buffer length in items (of the instantiated type) - * - * returns: - * -1: on overflow (write is not blocking, and data is being - * written faster than it is being read) - * 0: if nothing to do (0 length buffer) - * 1: if success - * 2: in the process of aborting, do doing nothing - * - * will throw runtime errors if inputs are improper: - * buffer pointer is NULL - * buffer length is larger than the instantiated buffer length - */ + /* + * enqueue: add the given buffer of item-length to the queue, + * first-in-first-out (FIFO). + * + * inputs: + * buf: a pointer to the buffer holding the data + * + * bufLen_I: the buffer length in items (of the instantiated type) + * + * returns: + * -1: on overflow (write is not blocking, and data is being + * written faster than it is being read) + * 0: if nothing to do (0 length buffer) + * 1: if success + * 2: in the process of aborting, do doing nothing + * + * will throw runtime errors if inputs are improper: + * buffer pointer is NULL + * buffer length is larger than the instantiated buffer length + */ - int enqueue (T* buf, size_t bufLen_I) { - DEBUG (std::cerr << "enqueue: buf = " << (void*) buf - << ", bufLen = " << bufLen_I - << ", #av_wr = " << d_n_avail_write_I - << ", #av_rd = " << d_n_avail_read_I << std::endl); - if (bufLen_I > d_bufLen_I) { - std::cerr << "ERROR: cannot add buffer longer (" - << bufLen_I << ") than instantiated length (" - << d_bufLen_I << ")." << std::endl; - throw std::runtime_error ("circular_buffer::enqueue()"); - } + int enqueue(T* buf, size_t bufLen_I) + { + DEBUG(std::cerr << "enqueue: buf = " << (void*)buf << ", bufLen = " << bufLen_I + << ", #av_wr = " << d_n_avail_write_I + << ", #av_rd = " << d_n_avail_read_I << std::endl); + if (bufLen_I > d_bufLen_I) { + std::cerr << "ERROR: cannot add buffer longer (" << bufLen_I + << ") than instantiated length (" << d_bufLen_I << ")." + << std::endl; + throw std::runtime_error("circular_buffer::enqueue()"); + } - if (bufLen_I == 0) - return (0); - if (!buf) - throw std::runtime_error ("circular_buffer::enqueue(): " - "input buffer is NULL.\n"); - gr::thread::scoped_lock l (*d_internal); - if (d_doAbort) { - return (2); - } - // set the return value to 1: success; change if needed - int retval = 1; - if (bufLen_I > d_n_avail_write_I) { - if (d_doWriteBlock) { - while (bufLen_I > d_n_avail_write_I) { - DEBUG (std::cerr << "enqueue: #len > #a, waiting." << std::endl); - // wait; will automatically unlock() the internal mutex via - // the scoped lock - d_writeBlock->wait (l); - // and auto re-lock() it here. - if (d_doAbort) { - DEBUG (std::cerr << "enqueue: #len > #a, aborting." << std::endl); - return (2); - } - DEBUG (std::cerr << "enqueue: #len > #a, done waiting." << std::endl); - } - } else { - d_n_avail_read_I = d_bufLen_I - bufLen_I; - d_n_avail_write_I = bufLen_I; - DEBUG (std::cerr << "circular_buffer::enqueue: overflow" << std::endl); - retval = -1; - } - } - size_t n_now_I = d_bufLen_I - d_writeNdx_I, n_start_I = 0; - if (n_now_I > bufLen_I) - n_now_I = bufLen_I; - else if (n_now_I < bufLen_I) - n_start_I = bufLen_I - n_now_I; - memcpy (&(d_buffer[d_writeNdx_I]), buf, n_now_I * sizeof (T)); - if (n_start_I) { - memcpy (d_buffer, &(buf[n_now_I]), n_start_I * sizeof (T)); - d_writeNdx_I = n_start_I; - } else - d_writeNdx_I += n_now_I; - d_n_avail_read_I += bufLen_I; - d_n_avail_write_I -= bufLen_I; - d_readBlock->notify_one (); - return (retval); - }; + if (bufLen_I == 0) + return (0); + if (!buf) + throw std::runtime_error("circular_buffer::enqueue(): " + "input buffer is NULL.\n"); + gr::thread::scoped_lock l(*d_internal); + if (d_doAbort) { + return (2); + } + // set the return value to 1: success; change if needed + int retval = 1; + if (bufLen_I > d_n_avail_write_I) { + if (d_doWriteBlock) { + while (bufLen_I > d_n_avail_write_I) { + DEBUG(std::cerr << "enqueue: #len > #a, waiting." << std::endl); + // wait; will automatically unlock() the internal mutex via + // the scoped lock + d_writeBlock->wait(l); + // and auto re-lock() it here. + if (d_doAbort) { + DEBUG(std::cerr << "enqueue: #len > #a, aborting." << std::endl); + return (2); + } + DEBUG(std::cerr << "enqueue: #len > #a, done waiting." << std::endl); + } + } else { + d_n_avail_read_I = d_bufLen_I - bufLen_I; + d_n_avail_write_I = bufLen_I; + DEBUG(std::cerr << "circular_buffer::enqueue: overflow" << std::endl); + retval = -1; + } + } + size_t n_now_I = d_bufLen_I - d_writeNdx_I, n_start_I = 0; + if (n_now_I > bufLen_I) + n_now_I = bufLen_I; + else if (n_now_I < bufLen_I) + n_start_I = bufLen_I - n_now_I; + memcpy(&(d_buffer[d_writeNdx_I]), buf, n_now_I * sizeof(T)); + if (n_start_I) { + memcpy(d_buffer, &(buf[n_now_I]), n_start_I * sizeof(T)); + d_writeNdx_I = n_start_I; + } else + d_writeNdx_I += n_now_I; + d_n_avail_read_I += bufLen_I; + d_n_avail_write_I -= bufLen_I; + d_readBlock->notify_one(); + return (retval); + }; -/* - * dequeue: removes from the queue the number of items requested, or - * available, into the given buffer on a FIFO basis. - * - * inputs: - * buf: a pointer to the buffer into which to copy the data - * - * bufLen_I: pointer to the requested number of items to remove - * - * outputs: - * bufLen_I: pointer to the actual number of items removed - * - * returns: - * 0: if nothing to do (0 length buffer) - * 1: if success - * 2: in the process of aborting, do doing nothing - * 3: if the number of requested items to remove is not the same - * as the actual number of items removed. - * - * will throw runtime errors if inputs are improper: - * buffer pointer is NULL - * buffer length pointer is NULL - * buffer length is larger than the instantiated buffer length - */ + /* + * dequeue: removes from the queue the number of items requested, or + * available, into the given buffer on a FIFO basis. + * + * inputs: + * buf: a pointer to the buffer into which to copy the data + * + * bufLen_I: pointer to the requested number of items to remove + * + * outputs: + * bufLen_I: pointer to the actual number of items removed + * + * returns: + * 0: if nothing to do (0 length buffer) + * 1: if success + * 2: in the process of aborting, do doing nothing + * 3: if the number of requested items to remove is not the same + * as the actual number of items removed. + * + * will throw runtime errors if inputs are improper: + * buffer pointer is NULL + * buffer length pointer is NULL + * buffer length is larger than the instantiated buffer length + */ - int dequeue (T* buf, size_t* bufLen_I) { - DEBUG (std::cerr << "dequeue: buf = " << ((void*) buf) - << ", *bufLen = " << (*bufLen_I) - << ", #av_wr = " << d_n_avail_write_I - << ", #av_rd = " << d_n_avail_read_I << std::endl); - if (!bufLen_I) - throw std::runtime_error ("circular_buffer::dequeue(): " - "input bufLen pointer is NULL.\n"); - if (!buf) - throw std::runtime_error ("circular_buffer::dequeue(): " - "input buffer pointer is NULL.\n"); - size_t l_bufLen_I = *bufLen_I; - if (l_bufLen_I == 0) - return (0); - if (l_bufLen_I > d_bufLen_I) { - std::cerr << "ERROR: cannot remove buffer longer (" - << l_bufLen_I << ") than instantiated length (" - << d_bufLen_I << ")." << std::endl; - throw std::runtime_error ("circular_buffer::dequeue()"); - } + int dequeue(T* buf, size_t* bufLen_I) + { + DEBUG(std::cerr << "dequeue: buf = " << ((void*)buf) << ", *bufLen = " + << (*bufLen_I) << ", #av_wr = " << d_n_avail_write_I + << ", #av_rd = " << d_n_avail_read_I << std::endl); + if (!bufLen_I) + throw std::runtime_error("circular_buffer::dequeue(): " + "input bufLen pointer is NULL.\n"); + if (!buf) + throw std::runtime_error("circular_buffer::dequeue(): " + "input buffer pointer is NULL.\n"); + size_t l_bufLen_I = *bufLen_I; + if (l_bufLen_I == 0) + return (0); + if (l_bufLen_I > d_bufLen_I) { + std::cerr << "ERROR: cannot remove buffer longer (" << l_bufLen_I + << ") than instantiated length (" << d_bufLen_I << ")." + << std::endl; + throw std::runtime_error("circular_buffer::dequeue()"); + } - gr::thread::scoped_lock l (*d_internal); - if (d_doAbort) { - return (2); - } - if (d_doFullRead) { - while (d_n_avail_read_I < l_bufLen_I) { - DEBUG (std::cerr << "dequeue: #a < #len, waiting." << std::endl); - // wait; will automatically unlock() the internal mutex via - // the scoped lock - d_readBlock->wait (l); - // and re-lock() it here. - if (d_doAbort) { - DEBUG (std::cerr << "dequeue: #a < #len, aborting." << std::endl); - return (2); - } - DEBUG (std::cerr << "dequeue: #a < #len, done waiting." << std::endl); - } - } else { - while (d_n_avail_read_I == 0) { - DEBUG (std::cerr << "dequeue: #a == 0, waiting." << std::endl); - // wait; will automatically unlock() the internal mutex via - // the scoped lock - d_readBlock->wait (l); - // and re-lock() it here. - if (d_doAbort) { - DEBUG (std::cerr << "dequeue: #a == 0, aborting." << std::endl); - return (2); - } - DEBUG (std::cerr << "dequeue: #a == 0, done waiting." << std::endl); - } - } - if (l_bufLen_I > d_n_avail_read_I) - l_bufLen_I = d_n_avail_read_I; - size_t n_now_I = d_bufLen_I - d_readNdx_I, n_start_I = 0; - if (n_now_I > l_bufLen_I) - n_now_I = l_bufLen_I; - else if (n_now_I < l_bufLen_I) - n_start_I = l_bufLen_I - n_now_I; - memcpy (buf, &(d_buffer[d_readNdx_I]), n_now_I * sizeof (T)); - if (n_start_I) { - memcpy (&(buf[n_now_I]), d_buffer, n_start_I * sizeof (T)); - d_readNdx_I = n_start_I; - } else - d_readNdx_I += n_now_I; - int rv = 1; - if (*bufLen_I != l_bufLen_I) - rv = 3; - *bufLen_I = l_bufLen_I; - d_n_avail_read_I -= l_bufLen_I; - d_n_avail_write_I += l_bufLen_I; - d_writeBlock->notify_one (); - return (rv); - }; + gr::thread::scoped_lock l(*d_internal); + if (d_doAbort) { + return (2); + } + if (d_doFullRead) { + while (d_n_avail_read_I < l_bufLen_I) { + DEBUG(std::cerr << "dequeue: #a < #len, waiting." << std::endl); + // wait; will automatically unlock() the internal mutex via + // the scoped lock + d_readBlock->wait(l); + // and re-lock() it here. + if (d_doAbort) { + DEBUG(std::cerr << "dequeue: #a < #len, aborting." << std::endl); + return (2); + } + DEBUG(std::cerr << "dequeue: #a < #len, done waiting." << std::endl); + } + } else { + while (d_n_avail_read_I == 0) { + DEBUG(std::cerr << "dequeue: #a == 0, waiting." << std::endl); + // wait; will automatically unlock() the internal mutex via + // the scoped lock + d_readBlock->wait(l); + // and re-lock() it here. + if (d_doAbort) { + DEBUG(std::cerr << "dequeue: #a == 0, aborting." << std::endl); + return (2); + } + DEBUG(std::cerr << "dequeue: #a == 0, done waiting." << std::endl); + } + } + if (l_bufLen_I > d_n_avail_read_I) + l_bufLen_I = d_n_avail_read_I; + size_t n_now_I = d_bufLen_I - d_readNdx_I, n_start_I = 0; + if (n_now_I > l_bufLen_I) + n_now_I = l_bufLen_I; + else if (n_now_I < l_bufLen_I) + n_start_I = l_bufLen_I - n_now_I; + memcpy(buf, &(d_buffer[d_readNdx_I]), n_now_I * sizeof(T)); + if (n_start_I) { + memcpy(&(buf[n_now_I]), d_buffer, n_start_I * sizeof(T)); + d_readNdx_I = n_start_I; + } else + d_readNdx_I += n_now_I; + int rv = 1; + if (*bufLen_I != l_bufLen_I) + rv = 3; + *bufLen_I = l_bufLen_I; + d_n_avail_read_I -= l_bufLen_I; + d_n_avail_write_I += l_bufLen_I; + d_writeBlock->notify_one(); + return (rv); + }; - void abort () { - gr::thread::scoped_lock l (*d_internal); - d_doAbort = true; - d_writeBlock->notify_one (); - d_readBlock->notify_one (); - }; + void abort() + { + gr::thread::scoped_lock l(*d_internal); + d_doAbort = true; + d_writeBlock->notify_one(); + d_readBlock->notify_one(); + }; }; #endif /* _CIRCULAR_BUFFER_H_ */ diff --git a/gr-audio/lib/osx/osx_common.h b/gr-audio/lib/osx/osx_common.h index 5d8a3800a5..3a578a4719 100644 --- a/gr-audio/lib/osx/osx_common.h +++ b/gr-audio/lib/osx/osx_common.h @@ -37,32 +37,28 @@ namespace osx { #define _OSX_AU_DEBUG_RENDER_ 0 #endif -#define check_error_and_throw(err,what,throw_str) \ - if(err) { \ - OSStatus error = static_cast<OSStatus>(err); \ - char err_str[sizeof(OSStatus)+1]; \ - memcpy((void*)(&err_str), (void*)(&error), sizeof(OSStatus)); \ - err_str[sizeof(OSStatus)] = 0; \ - GR_LOG_FATAL(d_logger, boost::format(what)); \ - GR_LOG_FATAL(d_logger, boost::format(" Error# %u ('%s')") \ - % error % err_str); \ - GR_LOG_FATAL(d_logger, boost::format(" %s:%d") \ - % __FILE__ %__LINE__); \ - throw std::runtime_error(throw_str); \ - } +#define check_error_and_throw(err, what, throw_str) \ + if (err) { \ + OSStatus error = static_cast<OSStatus>(err); \ + char err_str[sizeof(OSStatus) + 1]; \ + memcpy((void*)(&err_str), (void*)(&error), sizeof(OSStatus)); \ + err_str[sizeof(OSStatus)] = 0; \ + GR_LOG_FATAL(d_logger, boost::format(what)); \ + GR_LOG_FATAL(d_logger, boost::format(" Error# %u ('%s')") % error % err_str); \ + GR_LOG_FATAL(d_logger, boost::format(" %s:%d") % __FILE__ % __LINE__); \ + throw std::runtime_error(throw_str); \ + } -#define check_error(err,what) \ - if(err) { \ - OSStatus error = static_cast<OSStatus>(err); \ - char err_str[sizeof(OSStatus)+1]; \ - memcpy((void*)(&err_str), (void*)(&error), sizeof(OSStatus)); \ - err_str[sizeof(OSStatus)] = 0; \ - GR_LOG_WARN(d_logger, boost::format(what)); \ - GR_LOG_WARN(d_logger, boost::format(" Error# %u ('%s')") \ - % error % err_str); \ - GR_LOG_WARN(d_logger, boost::format(" %s:%d") \ - % __FILE__ %__LINE__); \ - } +#define check_error(err, what) \ + if (err) { \ + OSStatus error = static_cast<OSStatus>(err); \ + char err_str[sizeof(OSStatus) + 1]; \ + memcpy((void*)(&err_str), (void*)(&error), sizeof(OSStatus)); \ + err_str[sizeof(OSStatus)] = 0; \ + GR_LOG_WARN(d_logger, boost::format(what)); \ + GR_LOG_WARN(d_logger, boost::format(" Error# %u ('%s')") % error % err_str); \ + GR_LOG_WARN(d_logger, boost::format(" %s:%d") % __FILE__ % __LINE__); \ + } #include <boost/detail/endian.hpp> //BOOST_BIG_ENDIAN #ifdef BOOST_BIG_ENDIAN diff --git a/gr-audio/lib/osx/osx_impl.cc b/gr-audio/lib/osx/osx_impl.cc index 2a73375114..c3ef76ba8f 100644 --- a/gr-audio/lib/osx/osx_impl.cc +++ b/gr-audio/lib/osx/osx_impl.cc @@ -33,275 +33,253 @@ #include <locale> #include <stdexcept> -std::ostream& -operator<< -(std::ostream& s, - const AudioStreamBasicDescription& asbd) +std::ostream& operator<<(std::ostream& s, const AudioStreamBasicDescription& asbd) { - char format_id[sizeof(asbd.mFormatID)+1]; - memcpy(format_id, (void*)(&asbd.mFormatID), sizeof(asbd.mFormatID)); - format_id[sizeof(asbd.mFormatID)] = 0; - s << " Sample Rate : " << asbd.mSampleRate << std::endl; - s << " Format ID : " << format_id << std::endl; - s << " Format Flags : " << asbd.mFormatFlags << std::endl; - s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsFloat) != 0) - << " : Is Float" << std::endl; - s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0) - << " : Is Big Endian" << std::endl; - s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0) - << " : Is Signed Integer" << std::endl; - s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsPacked) != 0) - << " : Is Packed" << std::endl; - s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsAlignedHigh) != 0) - << " : Is Aligned High" << std::endl; - s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsNonInterleaved) != 0) - << " : Is Non-Interleaved" << std::endl; - s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsNonMixable) != 0) - << " : Is Non-Mixable" << std::endl; - s << " Bytes / Packet : " << asbd.mBytesPerPacket << std::endl; - s << " Frames / Packet : " << asbd.mFramesPerPacket << std::endl; - s << " Bytes / Frame : " << asbd.mBytesPerFrame << std::endl; - s << " Channels / Frame : " << asbd.mChannelsPerFrame << std::endl; - s << " Bits / Channel : " << asbd.mBitsPerChannel; - return(s); + char format_id[sizeof(asbd.mFormatID) + 1]; + memcpy(format_id, (void*)(&asbd.mFormatID), sizeof(asbd.mFormatID)); + format_id[sizeof(asbd.mFormatID)] = 0; + s << " Sample Rate : " << asbd.mSampleRate << std::endl; + s << " Format ID : " << format_id << std::endl; + s << " Format Flags : " << asbd.mFormatFlags << std::endl; + s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsFloat) != 0) << " : Is Float" + << std::endl; + s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0) + << " : Is Big Endian" << std::endl; + s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0) + << " : Is Signed Integer" << std::endl; + s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsPacked) != 0) << " : Is Packed" + << std::endl; + s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsAlignedHigh) != 0) + << " : Is Aligned High" << std::endl; + s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsNonInterleaved) != 0) + << " : Is Non-Interleaved" << std::endl; + s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsNonMixable) != 0) + << " : Is Non-Mixable" << std::endl; + s << " Bytes / Packet : " << asbd.mBytesPerPacket << std::endl; + s << " Frames / Packet : " << asbd.mFramesPerPacket << std::endl; + s << " Bytes / Frame : " << asbd.mBytesPerFrame << std::endl; + s << " Channels / Frame : " << asbd.mChannelsPerFrame << std::endl; + s << " Bits / Channel : " << asbd.mBitsPerChannel; + return (s); }; namespace gr { namespace audio { namespace osx { -static UInt32 -_get_num_channels -(AudioDeviceID ad_id, - AudioObjectPropertyScope scope) +static UInt32 _get_num_channels(AudioDeviceID ad_id, AudioObjectPropertyScope scope) { - // retrieve the AudioBufferList associated with this ID using - // the provided scope - - UInt32 num_channels = 0; - UInt32 prop_size = 0; - AudioObjectPropertyAddress ao_address = { - kAudioDevicePropertyStreamConfiguration, scope, 0 - }; - OSStatus err = noErr; - if ((err = AudioObjectGetPropertyDataSize - (ad_id, &ao_address, 0, NULL, - &prop_size)) == noErr) { - boost::scoped_array<AudioBufferList> buf_list - (reinterpret_cast<AudioBufferList*> - (new char[prop_size])); - if ((err = AudioObjectGetPropertyData - (ad_id, &ao_address, 0, NULL, - &prop_size, buf_list.get())) == noErr) { - for (UInt32 mm = 0; mm < buf_list.get()->mNumberBuffers; ++mm) { - num_channels += buf_list.get()->mBuffers[mm].mNumberChannels; - } - } - else { - // assume 2 channels - num_channels = 2; + // retrieve the AudioBufferList associated with this ID using + // the provided scope + + UInt32 num_channels = 0; + UInt32 prop_size = 0; + AudioObjectPropertyAddress ao_address = { kAudioDevicePropertyStreamConfiguration, + scope, + 0 }; + OSStatus err = noErr; + if ((err = AudioObjectGetPropertyDataSize(ad_id, &ao_address, 0, NULL, &prop_size)) == + noErr) { + boost::scoped_array<AudioBufferList> buf_list( + reinterpret_cast<AudioBufferList*>(new char[prop_size])); + if ((err = AudioObjectGetPropertyData( + ad_id, &ao_address, 0, NULL, &prop_size, buf_list.get())) == noErr) { + for (UInt32 mm = 0; mm < buf_list.get()->mNumberBuffers; ++mm) { + num_channels += buf_list.get()->mBuffers[mm].mNumberChannels; + } + } else { + // assume 2 channels + num_channels = 2; + } + } else { + // assume 2 channels + num_channels = 2; } - } - else { - // assume 2 channels - num_channels = 2; - } - return(num_channels); + return (num_channels); } // works with both char and wchar_t -template<typename charT> +template <typename charT> struct ci_equal { - ci_equal( const std::locale& loc ) : loc_(loc) {} - bool operator()(charT ch1, charT ch2) { - return std::tolower(ch1, loc_) == std::tolower(ch2, loc_); - } + ci_equal(const std::locale& loc) : loc_(loc) {} + bool operator()(charT ch1, charT ch2) + { + return std::tolower(ch1, loc_) == std::tolower(ch2, loc_); + } + private: - const std::locale& loc_; + const std::locale& loc_; }; // find substring (case insensitive) -static std::string::size_type ci_find_substr -(const std::string& str1, const std::string& str2, - const std::locale& loc = std::locale()) +static std::string::size_type ci_find_substr(const std::string& str1, + const std::string& str2, + const std::locale& loc = std::locale()) { - std::string::const_iterator it = std::search - (str1.begin(), str1.end(), - str2.begin(), str2.end(), - ci_equal<std::string::value_type>(loc)); - if (it != str1.end()) { - return(it - str1.begin()); - } - // not found - return(std::string::npos); + std::string::const_iterator it = std::search(str1.begin(), + str1.end(), + str2.begin(), + str2.end(), + ci_equal<std::string::value_type>(loc)); + if (it != str1.end()) { + return (it - str1.begin()); + } + // not found + return (std::string::npos); } -void -get_num_channels_for_audio_device_id -(AudioDeviceID ad_id, - UInt32* n_input, - UInt32* n_output) +void get_num_channels_for_audio_device_id(AudioDeviceID ad_id, + UInt32* n_input, + UInt32* n_output) { - if (n_input) { - *n_input = _get_num_channels - (ad_id, kAudioDevicePropertyScopeInput); - } - if (n_output) { - *n_output = _get_num_channels - (ad_id, kAudioDevicePropertyScopeOutput); - } + if (n_input) { + *n_input = _get_num_channels(ad_id, kAudioDevicePropertyScopeInput); + } + if (n_output) { + *n_output = _get_num_channels(ad_id, kAudioDevicePropertyScopeOutput); + } } -void -find_audio_devices -(const std::string& device_name, - bool is_input, - std::vector < AudioDeviceID >* all_ad_ids, - std::vector < std::string >* all_names) +void find_audio_devices(const std::string& device_name, + bool is_input, + std::vector<AudioDeviceID>* all_ad_ids, + std::vector<std::string>* all_names) { - if ((!all_ad_ids) && (!all_names)) { - // if nothing is requested, no point in doing anything! - return; - } + if ((!all_ad_ids) && (!all_names)) { + // if nothing is requested, no point in doing anything! + return; + } - OSStatus err = noErr; + OSStatus err = noErr; - // retrieve the size of the array of known audio device IDs + // retrieve the size of the array of known audio device IDs - UInt32 prop_size = 0; + UInt32 prop_size = 0; - AudioObjectPropertyAddress ao_address = { - kAudioHardwarePropertyDevices, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster - }; + AudioObjectPropertyAddress ao_address = { kAudioHardwarePropertyDevices, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster }; - if ((err = AudioObjectGetPropertyDataSize - (kAudioObjectSystemObject, &ao_address, - 0, NULL, &prop_size)) != noErr) { + if ((err = AudioObjectGetPropertyDataSize( + kAudioObjectSystemObject, &ao_address, 0, NULL, &prop_size)) != noErr) { #if _OSX_AU_DEBUG_ - std::cerr << "audio_osx::find_audio_devices: " - << "Unable to retrieve number of audio objects: " - << err << std::endl; + std::cerr << "audio_osx::find_audio_devices: " + << "Unable to retrieve number of audio objects: " << err << std::endl; #endif - return; - } + return; + } - // get the total number of audio devices (input and output) + // get the total number of audio devices (input and output) - UInt32 num_devices = prop_size / sizeof(AudioDeviceID); + UInt32 num_devices = prop_size / sizeof(AudioDeviceID); - // retrieve all audio device ids + // retrieve all audio device ids - boost::scoped_array < AudioDeviceID > all_dev_ids - (new AudioDeviceID[num_devices]); + boost::scoped_array<AudioDeviceID> all_dev_ids(new AudioDeviceID[num_devices]); - if ((err = AudioObjectGetPropertyData - (kAudioObjectSystemObject, &ao_address, - 0, NULL, &prop_size, all_dev_ids.get())) != noErr) { + if ((err = AudioObjectGetPropertyData(kAudioObjectSystemObject, + &ao_address, + 0, + NULL, + &prop_size, + all_dev_ids.get())) != noErr) { #if _OSX_AU_DEBUG_ - std::cerr << "audio_osx::find_audio_devices: " - << "Unable to retrieve audio object ids: " - << err << std::endl; + std::cerr << "audio_osx::find_audio_devices: " + << "Unable to retrieve audio object ids: " << err << std::endl; #endif - return; - } - - // success; loop over all retrieved output device ids, retrieving - // the name for each and comparing with the desired name. - - std::vector< std::string > valid_names(num_devices); - std::vector< UInt32 > valid_indices(num_devices); - UInt32 num_found_devices = 0; - AudioObjectPropertyScope scope = is_input ? - kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; - - for (UInt32 nn = 0; nn < num_devices; ++nn) { - - // make sure this device has input / output channels (it might - // also have output / input channels, too, but we do not care - // about that here) - - AudioDeviceID t_id = all_dev_ids[nn]; - - if (is_input) { - UInt32 n_input_channels = 0; - get_num_channels_for_audio_device_id - (t_id, &n_input_channels, NULL); - if (n_input_channels == 0) { - // no input channels; must be output device; just continue - // to the next audio device. - continue; - } - } else { - UInt32 n_output_channels = 0; - get_num_channels_for_audio_device_id - (t_id, NULL, &n_output_channels); - if (n_output_channels == 0) { - // no output channels; must be input device; just continue - // to the next audio device. - continue; - } + return; } - // retrieve the device name; max name length is 64 characters. - - prop_size = 65; - char c_name_buf[prop_size]; - bzero((void*)c_name_buf, prop_size); - --prop_size; - - AudioObjectPropertyAddress ao_address = { - kAudioDevicePropertyDeviceName, scope, 0 - }; - - if ((err = AudioObjectGetPropertyData - (t_id, &ao_address, 0, NULL, - &prop_size, (void*)c_name_buf)) != noErr) { + // success; loop over all retrieved output device ids, retrieving + // the name for each and comparing with the desired name. + + std::vector<std::string> valid_names(num_devices); + std::vector<UInt32> valid_indices(num_devices); + UInt32 num_found_devices = 0; + AudioObjectPropertyScope scope = + is_input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; + + for (UInt32 nn = 0; nn < num_devices; ++nn) { + + // make sure this device has input / output channels (it might + // also have output / input channels, too, but we do not care + // about that here) + + AudioDeviceID t_id = all_dev_ids[nn]; + + if (is_input) { + UInt32 n_input_channels = 0; + get_num_channels_for_audio_device_id(t_id, &n_input_channels, NULL); + if (n_input_channels == 0) { + // no input channels; must be output device; just continue + // to the next audio device. + continue; + } + } else { + UInt32 n_output_channels = 0; + get_num_channels_for_audio_device_id(t_id, NULL, &n_output_channels); + if (n_output_channels == 0) { + // no output channels; must be input device; just continue + // to the next audio device. + continue; + } + } + + // retrieve the device name; max name length is 64 characters. + + prop_size = 65; + char c_name_buf[prop_size]; + bzero((void*)c_name_buf, prop_size); + --prop_size; + + AudioObjectPropertyAddress ao_address = { kAudioDevicePropertyDeviceName, + scope, + 0 }; + + if ((err = AudioObjectGetPropertyData( + t_id, &ao_address, 0, NULL, &prop_size, (void*)c_name_buf)) != noErr) { #if _OSX_AU_DEBUG_ - std::cerr << "audio_osx::find_audio_devices: " - << "Unable to retrieve audio device name #" - << (nn+1) << ": " << err << std::endl; + std::cerr << "audio_osx::find_audio_devices: " + << "Unable to retrieve audio device name #" << (nn + 1) << ": " + << err << std::endl; #endif - continue; - } - std::string name_buf(c_name_buf); - - // compare the retrieved name with the desired one, if - // provided; case insensitive. + continue; + } + std::string name_buf(c_name_buf); - if (device_name.length() > 0) { + // compare the retrieved name with the desired one, if + // provided; case insensitive. - std::string::size_type found = - ci_find_substr(name_buf, device_name); - if (found == std::string::npos) { - // not found; continue to the next ID - continue; - } - } + if (device_name.length() > 0) { - // store this info + std::string::size_type found = ci_find_substr(name_buf, device_name); + if (found == std::string::npos) { + // not found; continue to the next ID + continue; + } + } - valid_names[nn] = name_buf; - valid_indices[num_found_devices++] = nn; + // store this info - } + valid_names[nn] = name_buf; + valid_indices[num_found_devices++] = nn; + } - // resize valid function arguments, then copy found values + // resize valid function arguments, then copy found values - if (all_ad_ids) { - all_ad_ids->resize(num_found_devices); - for (UInt32 nn = 0; nn < num_found_devices; ++nn) { - (*all_ad_ids)[nn] = all_dev_ids[valid_indices[nn]]; + if (all_ad_ids) { + all_ad_ids->resize(num_found_devices); + for (UInt32 nn = 0; nn < num_found_devices; ++nn) { + (*all_ad_ids)[nn] = all_dev_ids[valid_indices[nn]]; + } } - } - if (all_names) { - all_names->resize(num_found_devices); - for (UInt32 nn = 0; nn < num_found_devices; ++nn) { - (*all_names)[nn] = valid_names[valid_indices[nn]]; + if (all_names) { + all_names->resize(num_found_devices); + for (UInt32 nn = 0; nn < num_found_devices; ++nn) { + (*all_names)[nn] = valid_names[valid_indices[nn]]; + } } - } } } /* namespace osx */ diff --git a/gr-audio/lib/osx/osx_sink.cc b/gr-audio/lib/osx/osx_sink.cc index 80dc5fe5fa..88e6d72fc6 100644 --- a/gr-audio/lib/osx/osx_sink.cc +++ b/gr-audio/lib/osx/osx_sink.cc @@ -32,637 +32,595 @@ #include <stdexcept> namespace gr { - namespace audio { - - sink::sptr - osx_sink_fcn(int sampling_rate, - const std::string& device_name, - bool ok_to_block) - { - return sink::sptr - (new osx_sink(sampling_rate, device_name, ok_to_block)); - } - - static std::string - default_device_name() - { - return prefs::singleton()->get_string - ("audio_osx", "default_output_device", "built-in"); - } - - osx_sink::osx_sink(int sample_rate, - const std::string& device_name, - bool ok_to_block) - : sync_block("audio_osx_sink", - io_signature::make(0, 0, 0), - io_signature::make(0, 0, 0)), - d_input_sample_rate(0.0), d_n_user_channels(0), - d_n_dev_channels(0), d_queue_sample_count(0), - d_buffer_size_samples(0), d_ok_to_block(ok_to_block), - d_do_reset(false), d_hardware_changed(false), - d_using_default_device(false), d_waiting_for_data(false), - d_desired_name(device_name.empty() ? default_device_name() - : device_name), - d_output_au(0), d_output_ad_id(0) - { - if(sample_rate <= 0) { - GR_LOG_ERROR(d_logger, boost::format - ("Invalid Sample Rate: %d") - % sample_rate); +namespace audio { + +sink::sptr +osx_sink_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block) +{ + return sink::sptr(new osx_sink(sampling_rate, device_name, ok_to_block)); +} + +static std::string default_device_name() +{ + return prefs::singleton()->get_string( + "audio_osx", "default_output_device", "built-in"); +} + +osx_sink::osx_sink(int sample_rate, const std::string& device_name, bool ok_to_block) + : sync_block( + "audio_osx_sink", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)), + d_input_sample_rate(0.0), + d_n_user_channels(0), + d_n_dev_channels(0), + d_queue_sample_count(0), + d_buffer_size_samples(0), + d_ok_to_block(ok_to_block), + d_do_reset(false), + d_hardware_changed(false), + d_using_default_device(false), + d_waiting_for_data(false), + d_desired_name(device_name.empty() ? default_device_name() : device_name), + d_output_au(0), + d_output_ad_id(0) +{ + if (sample_rate <= 0) { + GR_LOG_ERROR(d_logger, boost::format("Invalid Sample Rate: %d") % sample_rate); throw std::invalid_argument("audio_osx_sink"); - } - else { + } else { d_input_sample_rate = (Float64)sample_rate; - } + } - // set up for audio output using the stored desired parameters + // set up for audio output using the stored desired parameters - setup(); - } + setup(); +} - void osx_sink::setup() - { - OSStatus err = noErr; +void osx_sink::setup() +{ + OSStatus err = noErr; - // set the default output audio device id to "unknown" + // set the default output audio device id to "unknown" - d_output_ad_id = kAudioDeviceUnknown; + d_output_ad_id = kAudioDeviceUnknown; - // try to find the output audio device, if specified + // try to find the output audio device, if specified - std::vector < AudioDeviceID > all_ad_ids; - std::vector < std::string > all_names; + std::vector<AudioDeviceID> all_ad_ids; + std::vector<std::string> all_names; - osx::find_audio_devices - (d_desired_name, false, - &all_ad_ids, &all_names); + osx::find_audio_devices(d_desired_name, false, &all_ad_ids, &all_names); - // check number of device(s) returned + // check number of device(s) returned - if (d_desired_name.length() != 0) { + if (d_desired_name.length() != 0) { if (all_ad_ids.size() == 1) { - // exactly 1 match was found; see if it was partial - - if (all_names[0].compare(d_desired_name) != 0) { + // exactly 1 match was found; see if it was partial - // yes: log the full device name - GR_LOG_INFO(d_logger, boost::format - ("Using output audio device '%s'.") - % all_names[0]); + if (all_names[0].compare(d_desired_name) != 0) { - } + // yes: log the full device name + GR_LOG_INFO(d_logger, + boost::format("Using output audio device '%s'.") % + all_names[0]); + } - // store info on this device + // store info on this device - d_output_ad_id = all_ad_ids[0]; - d_selected_name = all_names[0]; + d_output_ad_id = all_ad_ids[0]; + d_selected_name = all_names[0]; } else { - // either 0 or more than 1 device was found; get all output - // device names, print those, and error out. - - osx::find_audio_devices("", false, NULL, &all_names); + // either 0 or more than 1 device was found; get all output + // device names, print those, and error out. - std::string err_str("\n\nA unique output audio device name " - "matching the string '"); - err_str += d_desired_name; - err_str += "' was not found.\n\n"; - err_str += "The current known output audio device name"; - err_str += ((all_names.size() > 1) ? "s are" : " is"); - err_str += ":\n"; - for (UInt32 nn = 0; nn < all_names.size(); ++nn) { - err_str += " " + all_names[nn] + "\n"; - } - GR_LOG_ERROR(d_logger, boost::format(err_str)); - throw std::runtime_error("audio_osx_sink::setup"); + osx::find_audio_devices("", false, NULL, &all_names); + std::string err_str("\n\nA unique output audio device name " + "matching the string '"); + err_str += d_desired_name; + err_str += "' was not found.\n\n"; + err_str += "The current known output audio device name"; + err_str += ((all_names.size() > 1) ? "s are" : " is"); + err_str += ":\n"; + for (UInt32 nn = 0; nn < all_names.size(); ++nn) { + err_str += " " + all_names[nn] + "\n"; + } + GR_LOG_ERROR(d_logger, boost::format(err_str)); + throw std::runtime_error("audio_osx_sink::setup"); } - } + } - // if no output audio device id was found, use the default - // output audio device as set in System Preferences. + // if no output audio device id was found, use the default + // output audio device as set in System Preferences. - if (d_output_ad_id == kAudioDeviceUnknown) { + if (d_output_ad_id == kAudioDeviceUnknown) { UInt32 size = sizeof(AudioDeviceID); AudioObjectPropertyAddress ao_address = { - kAudioHardwarePropertyDefaultOutputDevice, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster + kAudioHardwarePropertyDefaultOutputDevice, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster }; - err = AudioObjectGetPropertyData - (kAudioObjectSystemObject, &ao_address, - 0, NULL, &size, &d_output_ad_id); - check_error_and_throw - (err, "Getting the default output audio device ID failed", - "audio_osx_sink::setup"); + err = AudioObjectGetPropertyData( + kAudioObjectSystemObject, &ao_address, 0, NULL, &size, &d_output_ad_id); + check_error_and_throw(err, + "Getting the default output audio device ID failed", + "audio_osx_sink::setup"); { - // retrieve the device name; max name length is 64 characters. - - UInt32 prop_size = 65; - char c_name_buf[prop_size]; - bzero((void*)c_name_buf, prop_size); - --prop_size; - - AudioObjectPropertyAddress ao_address = { - kAudioDevicePropertyDeviceName, - kAudioDevicePropertyScopeOutput, 0 - }; - - if ((err = AudioObjectGetPropertyData - (d_output_ad_id, &ao_address, 0, NULL, - &prop_size, (void*)c_name_buf)) != noErr) { - - check_error(err, "Unable to retrieve output audio device name"); - - } else { - - GR_LOG_INFO(d_logger, boost::format - ("\n\nUsing output audio device '%s'.\n ... " - "which is the current default output audio" - " device.\n Changing the default output" - " audio device in the System Preferences" - " will \n result in changing it here, too " - "(with an internal reconfiguration).\n") % - std::string(c_name_buf)); - - } - - d_selected_name = c_name_buf; + // retrieve the device name; max name length is 64 characters. + + UInt32 prop_size = 65; + char c_name_buf[prop_size]; + bzero((void*)c_name_buf, prop_size); + --prop_size; + + AudioObjectPropertyAddress ao_address = { kAudioDevicePropertyDeviceName, + kAudioDevicePropertyScopeOutput, + 0 }; + + if ((err = AudioObjectGetPropertyData(d_output_ad_id, + &ao_address, + 0, + NULL, + &prop_size, + (void*)c_name_buf)) != noErr) { + + check_error(err, "Unable to retrieve output audio device name"); + + } else { + + GR_LOG_INFO(d_logger, + boost::format("\n\nUsing output audio device '%s'.\n ... " + "which is the current default output audio" + " device.\n Changing the default output" + " audio device in the System Preferences" + " will \n result in changing it here, too " + "(with an internal reconfiguration).\n") % + std::string(c_name_buf)); + } + d_selected_name = c_name_buf; } d_using_default_device = true; + } - } - - // retrieve the total number of channels for the selected audio - // output device + // retrieve the total number of channels for the selected audio + // output device - osx::get_num_channels_for_audio_device_id - (d_output_ad_id, NULL, &d_n_dev_channels); + osx::get_num_channels_for_audio_device_id(d_output_ad_id, NULL, &d_n_dev_channels); - // set the block input signature, if not already set - // (d_n_user_channels is set in check_topology, which is called - // before the flow-graph is running) + // set the block input signature, if not already set + // (d_n_user_channels is set in check_topology, which is called + // before the flow-graph is running) - if (d_n_user_channels == 0) { - set_input_signature(io_signature::make - (1, d_n_dev_channels, sizeof(float))); - } + if (d_n_user_channels == 0) { + set_input_signature(io_signature::make(1, d_n_dev_channels, sizeof(float))); + } - // set the interim buffer size; to work with the GR scheduler, - // must be at least 16kB. Pick 50 kS since that's plenty yet - // not very much. + // set the interim buffer size; to work with the GR scheduler, + // must be at least 16kB. Pick 50 kS since that's plenty yet + // not very much. - d_buffer_size_samples = (d_input_sample_rate < 50000.0 ? - 50000 : (UInt32)d_input_sample_rate); + d_buffer_size_samples = + (d_input_sample_rate < 50000.0 ? 50000 : (UInt32)d_input_sample_rate); #if _OSX_AU_DEBUG_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink: max # samples = " - << d_buffer_size_samples << std::endl; + std::cerr << ((void*)(pthread_self())) + << " : audio_osx_sink: max # samples = " << d_buffer_size_samples + << std::endl; #endif - // create the default AudioUnit for output: + // create the default AudioUnit for output: - // Open the default output unit + // Open the default output unit #ifndef GR_USE_OLD_AUDIO_UNIT - AudioComponentDescription desc; + AudioComponentDescription desc; #else - ComponentDescription desc; + ComponentDescription desc; #endif - desc.componentType = kAudioUnitType_Output; - desc.componentSubType = kAudioUnitSubType_DefaultOutput; - desc.componentManufacturer = kAudioUnitManufacturer_Apple; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_DefaultOutput; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; #ifndef GR_USE_OLD_AUDIO_UNIT - AudioComponent comp = AudioComponentFindNext(NULL, &desc); - if(!comp) { - GR_LOG_FATAL(d_logger, boost::format - ("AudioComponentFindNext Failed")); + AudioComponent comp = AudioComponentFindNext(NULL, &desc); + if (!comp) { + GR_LOG_FATAL(d_logger, boost::format("AudioComponentFindNext Failed")); throw std::runtime_error("audio_osx_sink::setup"); - } - err = AudioComponentInstanceNew(comp, &d_output_au); - check_error_and_throw(err, "AudioComponentInstanceNew Failed", - "audio_osx_sink::setup"); + } + err = AudioComponentInstanceNew(comp, &d_output_au); + check_error_and_throw( + err, "AudioComponentInstanceNew Failed", "audio_osx_sink::setup"); #else - Component comp = FindNextComponent(NULL, &desc); - if(comp == NULL) { - GR_LOG_FATAL(d_logger, boost::format - ("FindNextComponent Failed")); + Component comp = FindNextComponent(NULL, &desc); + if (comp == NULL) { + GR_LOG_FATAL(d_logger, boost::format("FindNextComponent Failed")); throw std::runtime_error("audio_osx_sink::setup"); - } - err = OpenAComponent(comp, &d_output_au); - check_error_and_throw(err, "OpenAComponent Failed", - "audio_osx_sink::setup"); - -#endif + } + err = OpenAComponent(comp, &d_output_au); + check_error_and_throw(err, "OpenAComponent Failed", "audio_osx_sink::setup"); + +#endif + + // set the selected device ID as the current output device + + err = AudioUnitSetProperty(d_output_au, + kAudioOutputUnitProperty_CurrentDevice, + kAudioUnitScope_Global, + 0, + &d_output_ad_id, + sizeof(d_output_ad_id)); + check_error_and_throw( + err, "Setting selected output device as current failed", "audio_osx_sink::setup"); + + // Set up a callback function to generate output to the output unit + + AURenderCallbackStruct au_callback = { reinterpret_cast<AURenderCallback>( + &osx_sink::au_output_callback), + reinterpret_cast<void*>(this) }; + UInt32 prop_size = (UInt32)sizeof(au_callback); + + err = AudioUnitSetProperty(d_output_au, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &au_callback, + prop_size); + check_error_and_throw(err, "Set Render Callback", "audio_osx_sink::setup"); + + // create the stream format for the output unit, so that it + // handles any format conversions. Set number of channels in + // ::start, once the actual number of channels is known. + + memset((void*)(&d_stream_format), 0, sizeof(d_stream_format)); + d_stream_format.mSampleRate = d_input_sample_rate; + d_stream_format.mFormatID = kAudioFormatLinearPCM; + d_stream_format.mFormatFlags = + (kLinearPCMFormatFlagIsFloat | GR_PCM_ENDIANNESS | kLinearPCMFormatFlagIsPacked | + kAudioFormatFlagIsNonInterleaved); + d_stream_format.mBytesPerPacket = sizeof(float); + d_stream_format.mFramesPerPacket = 1; + d_stream_format.mBytesPerFrame = sizeof(float); + d_stream_format.mBitsPerChannel = 8 * sizeof(float); + + // set the render quality to maximum + + UInt32 render_quality = kRenderQuality_Max; + prop_size = (UInt32)sizeof(render_quality); + err = AudioUnitSetProperty(d_output_au, + kAudioUnitProperty_RenderQuality, + kAudioUnitScope_Global, + 0, + &render_quality, + prop_size); + check_error(err, "Setting render quality failed"); + + // clear the RunLoop (whatever that is); needed, for some + // reason, before a listener will work. - // set the selected device ID as the current output device - - err = AudioUnitSetProperty - (d_output_au, kAudioOutputUnitProperty_CurrentDevice, - kAudioUnitScope_Global, 0, - &d_output_ad_id, sizeof(d_output_ad_id)); - check_error_and_throw - (err, "Setting selected output device as current failed", - "audio_osx_sink::setup"); - - // Set up a callback function to generate output to the output unit - - AURenderCallbackStruct au_callback = { - reinterpret_cast<AURenderCallback> - (&osx_sink::au_output_callback), - reinterpret_cast<void*>(this) - }; - UInt32 prop_size = (UInt32)sizeof(au_callback); - - err = AudioUnitSetProperty - (d_output_au, - kAudioUnitProperty_SetRenderCallback, - kAudioUnitScope_Input, 0, - &au_callback, prop_size); - check_error_and_throw - (err, "Set Render Callback", - "audio_osx_sink::setup"); - - // create the stream format for the output unit, so that it - // handles any format conversions. Set number of channels in - // ::start, once the actual number of channels is known. - - memset((void*)(&d_stream_format), 0, sizeof(d_stream_format)); - d_stream_format.mSampleRate = d_input_sample_rate; - d_stream_format.mFormatID = kAudioFormatLinearPCM; - d_stream_format.mFormatFlags = (kLinearPCMFormatFlagIsFloat | - GR_PCM_ENDIANNESS | - kLinearPCMFormatFlagIsPacked | - kAudioFormatFlagIsNonInterleaved); - d_stream_format.mBytesPerPacket = sizeof(float); - d_stream_format.mFramesPerPacket = 1; - d_stream_format.mBytesPerFrame = sizeof(float); - d_stream_format.mBitsPerChannel = 8*sizeof(float); - - // set the render quality to maximum - - UInt32 render_quality = kRenderQuality_Max; - prop_size = (UInt32)sizeof(render_quality); - err = AudioUnitSetProperty - (d_output_au, - kAudioUnitProperty_RenderQuality, - kAudioUnitScope_Global, 0, - &render_quality, prop_size); - check_error(err, "Setting render quality failed"); - - // clear the RunLoop (whatever that is); needed, for some - // reason, before a listener will work. - - { + { CFRunLoopRef the_run_loop = NULL; - AudioObjectPropertyAddress property = { - kAudioHardwarePropertyRunLoop, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster - }; + AudioObjectPropertyAddress property = { kAudioHardwarePropertyRunLoop, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster }; prop_size = (UInt32)sizeof(the_run_loop); - err = AudioObjectSetPropertyData - (kAudioObjectSystemObject, &property, 0, NULL, - prop_size, &the_run_loop); - check_error(err, "Clearing RunLoop failed; " + err = AudioObjectSetPropertyData( + kAudioObjectSystemObject, &property, 0, NULL, prop_size, &the_run_loop); + check_error(err, + "Clearing RunLoop failed; " "Audio Output Device Listener might not work."); - } + } - // set up listeners + // set up listeners #ifndef GR_USE_OLD_AUDIO_UNIT - // 10.4 and newer + // 10.4 and newer - { + { // set up a listener if hardware changes (at all) - AudioObjectPropertyAddress property = { - kAudioHardwarePropertyDevices, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster - }; + AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster }; - err = AudioObjectAddPropertyListener - (kAudioObjectSystemObject, &property, - reinterpret_cast<AudioObjectPropertyListenerProc> - (&osx_sink::hardware_listener), - reinterpret_cast<void*>(this)); + err = AudioObjectAddPropertyListener( + kAudioObjectSystemObject, + &property, + reinterpret_cast<AudioObjectPropertyListenerProc>( + &osx_sink::hardware_listener), + reinterpret_cast<void*>(this)); check_error(err, "Adding Audio Hardware Listener failed"); - } + } - if (d_using_default_device) { + if (d_using_default_device) { // set up a listener for the default output device so that if // the device changes, this routine will be called and we can // internally handle this change (if/as necessary) { - AudioObjectPropertyAddress property = { - kAudioHardwarePropertyDefaultOutputDevice, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster - }; - err = AudioObjectAddPropertyListener - (kAudioObjectSystemObject, &property, - reinterpret_cast<AudioObjectPropertyListenerProc> - (&osx_sink::hardware_listener), - reinterpret_cast<void*>(this)); - check_error(err, "Adding Default Output Audio Listener failed"); + AudioObjectPropertyAddress property = { + kAudioHardwarePropertyDefaultOutputDevice, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster + }; + err = AudioObjectAddPropertyListener( + kAudioObjectSystemObject, + &property, + reinterpret_cast<AudioObjectPropertyListenerProc>( + &osx_sink::hardware_listener), + reinterpret_cast<void*>(this)); + check_error(err, "Adding Default Output Audio Listener failed"); } - } + } #else - // 10.5 and older + // 10.5 and older - err = AudioHardwareAddPropertyListener - (kAudioHardwarePropertyDevices, - reinterpret_cast<AudioHardwarePropertyListenerProc> - (&osx_sink::hardware_listener), - reinterpret_cast<void*>(this)); - check_error(err, "Adding Audio Hardware Listener failed"); + err = AudioHardwareAddPropertyListener( + kAudioHardwarePropertyDevices, + reinterpret_cast<AudioHardwarePropertyListenerProc>(&osx_sink::hardware_listener), + reinterpret_cast<void*>(this)); + check_error(err, "Adding Audio Hardware Listener failed"); - if (d_using_default_device) { + if (d_using_default_device) { - err = AudioHardwareAddPropertyListener - (kAudioHardwarePropertyDefaultOutputDevice, - reinterpret_cast<AudioHardwarePropertyListenerProc> - (&osx_sink::default_listener), - reinterpret_cast<void*>(this)); + err = AudioHardwareAddPropertyListener( + kAudioHardwarePropertyDefaultOutputDevice, + reinterpret_cast<AudioHardwarePropertyListenerProc>( + &osx_sink::default_listener), + reinterpret_cast<void*>(this)); check_error(err, "Adding Default Output Audio Listener failed"); - - } + } #endif - // initialize the AU for output, so that it is ready to be used + // initialize the AU for output, so that it is ready to be used - err = AudioUnitInitialize(d_output_au); - check_error_and_throw - (err, "AudioUnit Initialize Failed", - "audio_osx_sink::setup"); + err = AudioUnitInitialize(d_output_au); + check_error_and_throw(err, "AudioUnit Initialize Failed", "audio_osx_sink::setup"); #if _OSX_AU_DEBUG_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink Parameters:" << std::endl - << " Sample Rate is " << d_input_sample_rate << std::endl - << " Max # samples to store per channel is " - << d_buffer_size_samples << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink Parameters:" << std::endl + << " Sample Rate is " << d_input_sample_rate << std::endl + << " Max # samples to store per channel is " << d_buffer_size_samples + << std::endl; #endif - } +} - void osx_sink::teardown() - { +void osx_sink::teardown() +{ #if _OSX_AU_DEBUG_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink::teardown: starting" - << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::teardown: starting" + << std::endl; #endif - OSStatus err = noErr; + OSStatus err = noErr; - // stop the AudioUnit + // stop the AudioUnit - stop(); + stop(); - if (d_using_default_device) { + if (d_using_default_device) { // remove the listener OSStatus err = noErr; - AudioObjectPropertyAddress property = { - kAudioHardwarePropertyDefaultOutputDevice, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster - }; - err = AudioObjectRemovePropertyListener - (kAudioObjectSystemObject, &property, - reinterpret_cast<AudioObjectPropertyListenerProc> - (&osx_sink::hardware_listener), - reinterpret_cast<void*>(this)); + AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultOutputDevice, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster }; + err = AudioObjectRemovePropertyListener( + kAudioObjectSystemObject, + &property, + reinterpret_cast<AudioObjectPropertyListenerProc>( + &osx_sink::hardware_listener), + reinterpret_cast<void*>(this)); #if _OSX_AU_DEBUG_ - check_error(err, "teardown: AudioObjectRemovePropertyListener " + check_error(err, + "teardown: AudioObjectRemovePropertyListener " "hardware failed"); #endif - } + } - // uninitialize the AudioUnit + // uninitialize the AudioUnit - err = AudioUnitUninitialize(d_output_au); + err = AudioUnitUninitialize(d_output_au); #if _OSX_AU_DEBUG_ - check_error(err, "teardown: AudioUnitUninitialize failed"); + check_error(err, "teardown: AudioUnitUninitialize failed"); #endif - // dispose / close the AudioUnit + // dispose / close the AudioUnit #ifndef GR_USE_OLD_AUDIO_UNIT - err = AudioComponentInstanceDispose(d_output_au); + err = AudioComponentInstanceDispose(d_output_au); #if _OSX_AU_DEBUG_ - check_error(err, "teardown: AudioComponentInstanceDispose failed"); + check_error(err, "teardown: AudioComponentInstanceDispose failed"); #endif #else - CloseComponent(d_output_au); + CloseComponent(d_output_au); #if _OSX_AU_DEBUG_ - check_error(err, "teardown: CloseComponent failed"); + check_error(err, "teardown: CloseComponent failed"); #endif #endif - // delete buffers + // delete buffers - for(UInt32 nn = 0; nn < d_buffers.size(); ++nn) { + for (UInt32 nn = 0; nn < d_buffers.size(); ++nn) { delete d_buffers[nn]; d_buffers[nn] = 0; - } - d_buffers.resize(0); + } + d_buffers.resize(0); - // clear important variables; not # user channels + // clear important variables; not # user channels - d_n_dev_channels = d_n_buffer_channels = - d_queue_sample_count = d_buffer_size_samples = 0; - d_using_default_device = false; - d_output_au = 0; - d_output_ad_id = 0; + d_n_dev_channels = d_n_buffer_channels = d_queue_sample_count = + d_buffer_size_samples = 0; + d_using_default_device = false; + d_output_au = 0; + d_output_ad_id = 0; #if _OSX_AU_DEBUG_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink::teardown: finished" - << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::teardown: finished" + << std::endl; #endif - } +} - bool - osx_sink::is_running() - { - UInt32 au_running = 0; +bool osx_sink::is_running() +{ + UInt32 au_running = 0; - if (d_output_au) { + if (d_output_au) { UInt32 prop_size = (UInt32)sizeof(UInt32); - OSStatus err = AudioUnitGetProperty - (d_output_au, - kAudioOutputUnitProperty_IsRunning, - kAudioUnitScope_Global, 0, - &au_running, &prop_size); - check_error_and_throw - (err, "AudioUnitGetProperty IsRunning", - "audio_osx_sink::is_running"); - - } - - return(au_running != 0); + OSStatus err = AudioUnitGetProperty(d_output_au, + kAudioOutputUnitProperty_IsRunning, + kAudioUnitScope_Global, + 0, + &au_running, + &prop_size); + check_error_and_throw( + err, "AudioUnitGetProperty IsRunning", "audio_osx_sink::is_running"); } - bool - osx_sink::check_topology(int ninputs, int noutputs) - { - // check # output to make sure it's valid - if(noutputs != 0) { - - GR_LOG_FATAL(d_logger, boost::format - ("check_topology(): number of output " - "streams provided (%d) should be 0.") - % noutputs); - throw std::runtime_error - ("audio_osx_sink::check_topology"); - - } - - // check # outputs to make sure it's valid - if((ninputs < 1) | (ninputs > (int) d_n_dev_channels)) { - - GR_LOG_FATAL(d_logger, boost::format - ("check_topology(): number of input " - "streams provided (%d) should be in [1,%d] " - "for the selected output audio device.") - % ninputs % d_n_dev_channels); + return (au_running != 0); +} + +bool osx_sink::check_topology(int ninputs, int noutputs) +{ + // check # output to make sure it's valid + if (noutputs != 0) { + + GR_LOG_FATAL(d_logger, + boost::format("check_topology(): number of output " + "streams provided (%d) should be 0.") % + noutputs); throw std::runtime_error("audio_osx_sink::check_topology"); + } + + // check # outputs to make sure it's valid + if ((ninputs < 1) | (ninputs > (int)d_n_dev_channels)) { - } + GR_LOG_FATAL(d_logger, + boost::format("check_topology(): number of input " + "streams provided (%d) should be in [1,%d] " + "for the selected output audio device.") % + ninputs % d_n_dev_channels); + throw std::runtime_error("audio_osx_sink::check_topology"); + } - // save the actual number of input (user) channels + // save the actual number of input (user) channels - d_n_user_channels = ninputs; + d_n_user_channels = ninputs; #if _OSX_AU_DEBUG_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink::check_topology: " - << "Actual # user input channels = " - << d_n_user_channels << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::check_topology: " + << "Actual # user input channels = " << d_n_user_channels << std::endl; #endif - return (true); - } + return (true); +} - void - osx_sink::check_channels(bool force_reset) - { - if (d_buffers.size() == 0) { +void osx_sink::check_channels(bool force_reset) +{ + if (d_buffers.size() == 0) { // allocate the output circular buffer(s), one per user channel d_buffers.resize(d_n_user_channels); - for(UInt32 nn = 0; nn < d_n_user_channels; ++nn) { - d_buffers[nn] = new circular_buffer<float> - (d_buffer_size_samples, false, false); + for (UInt32 nn = 0; nn < d_n_user_channels; ++nn) { + d_buffers[nn] = + new circular_buffer<float>(d_buffer_size_samples, false, false); } - } - else { - if(d_buffers.size() == d_n_user_channels) { - if (force_reset) { - for(UInt32 nn = 0; nn < d_buffers.size(); ++nn) { - d_buffers[nn]->reset(); + } else { + if (d_buffers.size() == d_n_user_channels) { + if (force_reset) { + for (UInt32 nn = 0; nn < d_buffers.size(); ++nn) { + d_buffers[nn]->reset(); + } } - } - return; + return; } // reallocate the output circular buffer(s) if (d_n_user_channels < d_buffers.size()) { - // too many buffers; delete some + // too many buffers; delete some - for (UInt32 nn = d_n_user_channels; nn < d_buffers.size(); ++nn) { - delete d_buffers[nn]; - d_buffers[nn] = 0; - } - d_buffers.resize(d_n_user_channels); + for (UInt32 nn = d_n_user_channels; nn < d_buffers.size(); ++nn) { + delete d_buffers[nn]; + d_buffers[nn] = 0; + } + d_buffers.resize(d_n_user_channels); - // reset remaining buffers + // reset remaining buffers - for(UInt32 nn = 0; nn < d_buffers.size(); ++nn) { - d_buffers[nn]->reset(); - } - } - else { + for (UInt32 nn = 0; nn < d_buffers.size(); ++nn) { + d_buffers[nn]->reset(); + } + } else { - // too few buffers; create some more + // too few buffers; create some more - // reset old buffers first + // reset old buffers first - for(UInt32 nn = 0; nn < d_buffers.size(); ++nn) { - d_buffers[nn]->reset(); - } + for (UInt32 nn = 0; nn < d_buffers.size(); ++nn) { + d_buffers[nn]->reset(); + } - d_buffers.resize(d_n_user_channels); - for (UInt32 nn = d_buffers.size(); nn < d_n_user_channels; ++nn) { - d_buffers[nn] = new circular_buffer<float> - (d_buffer_size_samples, false, false); - } + d_buffers.resize(d_n_user_channels); + for (UInt32 nn = d_buffers.size(); nn < d_n_user_channels; ++nn) { + d_buffers[nn] = + new circular_buffer<float>(d_buffer_size_samples, false, false); + } } - } + } - // reset the output audio unit for the correct number of channels - // have to uninitialize, set, initialize. + // reset the output audio unit for the correct number of channels + // have to uninitialize, set, initialize. - OSStatus err = AudioUnitUninitialize(d_output_au); - check_error(err, "AudioUnitUninitialize"); + OSStatus err = AudioUnitUninitialize(d_output_au); + check_error(err, "AudioUnitUninitialize"); - d_stream_format.mChannelsPerFrame = d_n_user_channels; + d_stream_format.mChannelsPerFrame = d_n_user_channels; - err = AudioUnitSetProperty - (d_output_au, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, 0, - &d_stream_format, sizeof(d_stream_format)); - check_error_and_throw - (err, "AudioUnitSetProperty StreamFormat", - "audio_osx_sink::check_channels"); + err = AudioUnitSetProperty(d_output_au, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, + &d_stream_format, + sizeof(d_stream_format)); + check_error_and_throw( + err, "AudioUnitSetProperty StreamFormat", "audio_osx_sink::check_channels"); - // initialize the AU for output, so that it is ready to be used + // initialize the AU for output, so that it is ready to be used - err = AudioUnitInitialize(d_output_au); - check_error_and_throw - (err, "AudioUnitInitialize", - "audio_osx_sink::check_channels"); - } + err = AudioUnitInitialize(d_output_au); + check_error_and_throw(err, "AudioUnitInitialize", "audio_osx_sink::check_channels"); +} - bool - osx_sink::start() - { - if(!is_running() && d_output_au) { +bool osx_sink::start() +{ + if (!is_running() && d_output_au) { #if _OSX_AU_DEBUG_ std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink::start: starting Output AudioUnit." - << std::endl; + << " : audio_osx_sink::start: starting Output AudioUnit." << std::endl; #endif // check channels, (re)allocate and reset buffers if/as necessary @@ -672,302 +630,268 @@ namespace gr { // start the audio unit (should never fail) OSStatus err = AudioOutputUnitStart(d_output_au); - check_error_and_throw - (err, "AudioOutputUnitStart", - "audio_osx_sink::start"); - } + check_error_and_throw(err, "AudioOutputUnitStart", "audio_osx_sink::start"); + } #if _OSX_AU_DEBUG_ - else { - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink::start: " + else { + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::start: " << "already running." << std::endl; - } + } #endif - return (true); - } + return (true); +} - bool - osx_sink::stop() - { - if(is_running()) { +bool osx_sink::stop() +{ + if (is_running()) { #if _OSX_AU_DEBUG_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink::stop: " - << "stopping Output AudioUnit." - << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::stop: " + << "stopping Output AudioUnit." << std::endl; #endif // if waiting in ::work, signal to wake up if (d_waiting_for_data) { #if _OSX_AU_DEBUG_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink::stop: " - << "signaling waiting condition" << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::stop: " + << "signaling waiting condition" << std::endl; #endif - d_cond_data.notify_one(); + d_cond_data.notify_one(); } // stop the audio unit (should never fail) OSStatus err = AudioOutputUnitStop(d_output_au); - check_error_and_throw - (err, "AudioOutputUnitStop", - "audio_osx_sink::stop"); + check_error_and_throw(err, "AudioOutputUnitStop", "audio_osx_sink::stop"); // abort and reset all buffers - for(UInt32 nn = 0; nn < d_n_user_channels; ++nn) { - d_buffers[nn]->abort(); - d_buffers[nn]->reset(); + for (UInt32 nn = 0; nn < d_n_user_channels; ++nn) { + d_buffers[nn]->abort(); + d_buffers[nn]->reset(); } // reset local knowledge of amount of data in queues d_queue_sample_count = 0; - } + } #if _OSX_AU_DEBUG_ - else { - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink::stop: " + else { + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::stop: " << "already stopped." << std::endl; - } + } #endif - return(true); - } + return (true); +} - int - osx_sink::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { +int osx_sink::work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ #if _OSX_AU_DEBUG_RENDER_ - { + { gr::thread::scoped_lock l(d_internal); - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink::work: " - << "Starting: #OI = " - << noutput_items << ", reset = " - << (d_do_reset ? "true" : "false") << std::endl; - } + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::work: " + << "Starting: #OI = " << noutput_items + << ", reset = " << (d_do_reset ? "true" : "false") << std::endl; + } #endif - if (d_do_reset) { + if (d_do_reset) { if (d_hardware_changed) { - // see if the current AudioDeviceID is still available - - std::vector < AudioDeviceID > all_ad_ids; - osx::find_audio_devices - (d_desired_name, false, - &all_ad_ids, NULL); - bool found = false; - for (UInt32 nn = 0; (nn < all_ad_ids.size()) && (!found); - ++nn) { - found = (all_ad_ids[nn] == d_output_ad_id); - } - if (!found) { + // see if the current AudioDeviceID is still available - GR_LOG_FATAL(d_logger, boost::format - ("The selected output audio device ('%s') " - "is no longer available.\n") - % d_selected_name); - return(gr::block::WORK_DONE); + std::vector<AudioDeviceID> all_ad_ids; + osx::find_audio_devices(d_desired_name, false, &all_ad_ids, NULL); + bool found = false; + for (UInt32 nn = 0; (nn < all_ad_ids.size()) && (!found); ++nn) { + found = (all_ad_ids[nn] == d_output_ad_id); + } + if (!found) { - } + GR_LOG_FATAL(d_logger, + boost::format("The selected output audio device ('%s') " + "is no longer available.\n") % + d_selected_name); + return (gr::block::WORK_DONE); + } - d_do_reset = d_hardware_changed = false; + d_do_reset = d_hardware_changed = false; - } - else { + } else { #if _OSX_AU_DEBUG_RENDER_ - { - gr::thread::scoped_lock l(d_internal); - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink::work: " - << "doing reset." << std::endl; - } + { + gr::thread::scoped_lock l(d_internal); + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::work: " + << "doing reset." << std::endl; + } #endif - GR_LOG_WARN(d_logger, boost::format - ("\n\nThe default output audio device has " - "changed; resetting audio.\nThere may " - "be a sound glitch while resetting.\n")); + GR_LOG_WARN(d_logger, + boost::format("\n\nThe default output audio device has " + "changed; resetting audio.\nThere may " + "be a sound glitch while resetting.\n")); - // for any changes, just tear down the current - // configuration, then set it up again using the user's - // parameters to try to make selections. + // for any changes, just tear down the current + // configuration, then set it up again using the user's + // parameters to try to make selections. - teardown(); + teardown(); - gr::thread::scoped_lock l(d_internal); + gr::thread::scoped_lock l(d_internal); - setup(); - start(); + setup(); + start(); #if _OSX_AU_DEBUG_RENDER_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink: " - << "returning 0 after reset." - << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink: " + << "returning 0 after reset." << std::endl; #endif - return(0); + return (0); } - } + } - gr::thread::scoped_lock l(d_internal); + gr::thread::scoped_lock l(d_internal); - // take the input data, copy it, and push it to the bottom of - // the queue. mono input is pushed onto queue[0]; stereo input - // is pushed onto queue[1]. If the number of user/graph - // channels is less than the number of device channels, copy the - // data from the last / highest number channel to remaining - // device channels. + // take the input data, copy it, and push it to the bottom of + // the queue. mono input is pushed onto queue[0]; stereo input + // is pushed onto queue[1]. If the number of user/graph + // channels is less than the number of device channels, copy the + // data from the last / highest number channel to remaining + // device channels. - // find the maximum amount of buffer space available right now + // find the maximum amount of buffer space available right now - UInt32 l_max_count; - int diff_count = ((int)d_buffer_size_samples) - noutput_items; - if(diff_count < 0) { + UInt32 l_max_count; + int diff_count = ((int)d_buffer_size_samples) - noutput_items; + if (diff_count < 0) { l_max_count = 0; - } - else { + } else { l_max_count = (UInt32)diff_count; - } + } #if _OSX_AU_DEBUG_RENDER_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink::work: " - << "qSC = " << d_queue_sample_count - << ", lMC = "<< l_max_count - << ", dBSC = " << d_buffer_size_samples - << ", #OI = " << noutput_items << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::work: " + << "qSC = " << d_queue_sample_count << ", lMC = " << l_max_count + << ", dBSC = " << d_buffer_size_samples << ", #OI = " << noutput_items + << std::endl; #endif - if(d_queue_sample_count > l_max_count) { + if (d_queue_sample_count > l_max_count) { // data coming in too fast; ok_to_block decides what to do: if // ok to block, then wait until the render callback makes // enough space. If not blocking, detect overflow via writing // data to the circular buffer. - if(d_ok_to_block == true) { - // block until there is data to return, or on reset - while(d_queue_sample_count > l_max_count) { - // release control so-as to allow data to be retrieved; - // block until there is data to return + if (d_ok_to_block == true) { + // block until there is data to return, or on reset + while (d_queue_sample_count > l_max_count) { + // release control so-as to allow data to be retrieved; + // block until there is data to return #if _OSX_AU_DEBUG_RENDER_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink::work: " - << "waiting." << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::work: " + << "waiting." << std::endl; #endif - d_waiting_for_data = true; - d_cond_data.wait(l); - d_waiting_for_data = false; + d_waiting_for_data = true; + d_cond_data.wait(l); + d_waiting_for_data = false; #if _OSX_AU_DEBUG_RENDER_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink::work: " - << "done waiting." << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::work: " + << "done waiting." << std::endl; #endif - // the condition's 'notify' was called; acquire control to - // keep thread safe + // the condition's 'notify' was called; acquire control to + // keep thread safe - // if doing a reset, just return here; reset will pick - // up the next time this method is called. - if (d_do_reset) { + // if doing a reset, just return here; reset will pick + // up the next time this method is called. + if (d_do_reset) { #if _OSX_AU_DEBUG_RENDER_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink::work: " - << "returning 0 for reset." << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::work: " + << "returning 0 for reset." << std::endl; #endif - return(0); + return (0); + } } - } } - } + } - // not blocking and overflow is handled by the circular buffer, - // or enough data space is available + // not blocking and overflow is handled by the circular buffer, + // or enough data space is available - // add the input frames to the buffers' queue, checking for overflow + // add the input frames to the buffers' queue, checking for overflow - UInt32 nn; - int res = 0; - float* inBuffer = (float*)input_items[0]; - const UInt32 l_size = input_items.size(); - for(nn = 0; nn < l_size; ++nn) { + UInt32 nn; + int res = 0; + float* inBuffer = (float*)input_items[0]; + const UInt32 l_size = input_items.size(); + for (nn = 0; nn < l_size; ++nn) { inBuffer = (float*)input_items[nn]; int l_res = d_buffers[nn]->enqueue(inBuffer, noutput_items); - if(l_res == -1) { - res = -1; + if (l_res == -1) { + res = -1; } - } - while(nn < d_n_user_channels) { + } + while (nn < d_n_user_channels) { // for extra channels, copy the last input's data int l_res = d_buffers[nn++]->enqueue(inBuffer, noutput_items); - if(l_res == -1) { - res = -1; + if (l_res == -1) { + res = -1; } - } + } - // did overflow occur? + // did overflow occur? - if(res == -1) { + if (res == -1) { // yes: data coming in too fast; drop oldest data. fputs("aO", stderr); fflush(stderr); // set the local number of samples available to the max d_queue_sample_count = d_buffers[0]->buffer_length_items(); - } - else { + } else { // no: keep up the local sample count d_queue_sample_count += noutput_items; - } + } #if _OSX_AU_DEBUG_RENDER_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink::work: " - << "returning: #OI = " - << noutput_items << ", qSC = " - << d_queue_sample_count << ", bSS = " - << d_buffer_size_samples << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::work: " + << "returning: #OI = " << noutput_items + << ", qSC = " << d_queue_sample_count << ", bSS = " << d_buffer_size_samples + << std::endl; #endif - return (noutput_items); - } + return (noutput_items); +} - OSStatus - osx_sink::au_output_callback - (void* in_ref_con, - AudioUnitRenderActionFlags* io_action_flags, - const AudioTimeStamp* in_time_stamp, - UInt32 in_bus_number, - UInt32 in_number_frames, - AudioBufferList* io_data) - { - // NOTE: This is a callback from the OS, so throwing here does - // not work; return an error instead when something does not go - // as planned. +OSStatus osx_sink::au_output_callback(void* in_ref_con, + AudioUnitRenderActionFlags* io_action_flags, + const AudioTimeStamp* in_time_stamp, + UInt32 in_bus_number, + UInt32 in_number_frames, + AudioBufferList* io_data) +{ + // NOTE: This is a callback from the OS, so throwing here does + // not work; return an error instead when something does not go + // as planned. - osx_sink* This = reinterpret_cast<osx_sink*>(in_ref_con); - OSStatus err = noErr; + osx_sink* This = reinterpret_cast<osx_sink*>(in_ref_con); + OSStatus err = noErr; - gr::thread::scoped_lock l(This->d_internal); + gr::thread::scoped_lock l(This->d_internal); #if _OSX_AU_DEBUG_RENDER_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink::au_output_callback: " - << "starting: qSC = " - << This->d_queue_sample_count - << ", in#F = " << in_number_frames - << ", in#C = " << This->d_n_user_channels << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::au_output_callback: " + << "starting: qSC = " << This->d_queue_sample_count + << ", in#F = " << in_number_frames << ", in#C = " << This->d_n_user_channels + << std::endl; #endif - if(This->d_queue_sample_count < in_number_frames) { + if (This->d_queue_sample_count < in_number_frames) { // not enough data to fill request; probably happened on // start-up, where this callback was called before ::work was. @@ -976,101 +900,85 @@ namespace gr { fflush(stderr); err = kAudioUnitErr_Initialized; - } - else { + } else { // enough data; remove data from our buffers into the AU's buffers int nn = This->d_n_user_channels; - while(--nn >= 0) { - - size_t t_n_output_items = in_number_frames; - float* out_buffer = (float*)(io_data->mBuffers[nn].mData); - int rv = This->d_buffers[nn]->dequeue - (out_buffer, &t_n_output_items); + while (--nn >= 0) { - if((rv != 1) || (t_n_output_items != in_number_frames)) { + size_t t_n_output_items = in_number_frames; + float* out_buffer = (float*)(io_data->mBuffers[nn].mData); + int rv = This->d_buffers[nn]->dequeue(out_buffer, &t_n_output_items); - std::cerr << "audio_osx_sink::au_output_callback: " - << "number of available items changing " - << "unexpectedly (should never happen): was " - << in_number_frames << " now " - << t_n_output_items<< std::endl; - err = kAudioUnitErr_TooManyFramesToProcess; + if ((rv != 1) || (t_n_output_items != in_number_frames)) { - } + std::cerr << "audio_osx_sink::au_output_callback: " + << "number of available items changing " + << "unexpectedly (should never happen): was " + << in_number_frames << " now " << t_n_output_items << std::endl; + err = kAudioUnitErr_TooManyFramesToProcess; + } } This->d_queue_sample_count -= in_number_frames; - } + } - // signal that data is available, if appropriate + // signal that data is available, if appropriate - if (This->d_waiting_for_data) { + if (This->d_waiting_for_data) { #if _OSX_AU_DEBUG_RENDER_ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::au_output_callback: " << "signaling waiting condition" << std::endl; #endif This->d_cond_data.notify_one(); - } + } #if _OSX_AU_DEBUG_RENDER_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_sink::au_output_callback: " - << "returning: qSC = " - << This->d_queue_sample_count - << ", err = " << err << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::au_output_callback: " + << "returning: qSC = " << This->d_queue_sample_count << ", err = " << err + << std::endl; #endif - return (err); - } + return (err); +} #ifndef GR_USE_OLD_AUDIO_UNIT - OSStatus - osx_sink::hardware_listener - (AudioObjectID in_object_id, - UInt32 in_num_addresses, - const AudioObjectPropertyAddress in_addresses[], - void* in_client_data) +OSStatus osx_sink::hardware_listener(AudioObjectID in_object_id, + UInt32 in_num_addresses, + const AudioObjectPropertyAddress in_addresses[], + void* in_client_data) #else - OSStatus - osx_sink::hardware_listener - (AudioHardwarePropertyID in_property_id, - void* in_client_data) +OSStatus osx_sink::hardware_listener(AudioHardwarePropertyID in_property_id, + void* in_client_data) #endif - { - osx_sink* This = static_cast - <osx_sink*>(in_client_data); - This->reset(true); - return(noErr); - } +{ + osx_sink* This = static_cast<osx_sink*>(in_client_data); + This->reset(true); + return (noErr); +} #ifndef GR_USE_OLD_AUDIO_UNIT - OSStatus - osx_sink::default_listener - (AudioObjectID in_object_id, - UInt32 in_num_addresses, - const AudioObjectPropertyAddress in_addresses[], - void* in_client_data) +OSStatus osx_sink::default_listener(AudioObjectID in_object_id, + UInt32 in_num_addresses, + const AudioObjectPropertyAddress in_addresses[], + void* in_client_data) #else - OSStatus - osx_sink::default_listener - (AudioHardwarePropertyID in_property_id, - void* in_client_data) +OSStatus osx_sink::default_listener(AudioHardwarePropertyID in_property_id, + void* in_client_data) #endif - { - osx_sink* This = reinterpret_cast - <osx_sink*>(in_client_data); - This->reset(false); - return(noErr); - } +{ + osx_sink* This = reinterpret_cast<osx_sink*>(in_client_data); + This->reset(false); + return (noErr); +} - } /* namespace audio */ +} /* namespace audio */ } /* namespace gr */ diff --git a/gr-audio/lib/osx/osx_sink.h b/gr-audio/lib/osx/osx_sink.h index 127f243495..db7763e188 100644 --- a/gr-audio/lib/osx/osx_sink.h +++ b/gr-audio/lib/osx/osx_sink.h @@ -29,109 +29,97 @@ #include "circular_buffer.h" namespace gr { - namespace audio { +namespace audio { - /*! - * \brief audio sink using OSX - * \ingroup audio_blk - * - * input signature is one or two streams of floats. - * Input samples must be in the range [-1,1]. - */ - - class osx_sink : public sink - { - protected: - - Float64 d_input_sample_rate; - UInt32 d_n_user_channels, d_n_dev_channels, d_n_buffer_channels; - UInt32 d_queue_sample_count, d_buffer_size_samples; - bool d_ok_to_block, d_do_reset, d_hardware_changed; - bool d_using_default_device, d_waiting_for_data; - gr::thread::mutex d_internal; - gr::thread::condition_variable d_cond_data; - std::vector < circular_buffer < float > *> d_buffers; - std::string d_desired_name, d_selected_name; - - // AudioUnits and Such +/*! + * \brief audio sink using OSX + * \ingroup audio_blk + * + * input signature is one or two streams of floats. + * Input samples must be in the range [-1,1]. + */ - AudioUnit d_output_au; - AudioDeviceID d_output_ad_id; - AudioStreamBasicDescription d_stream_format; +class osx_sink : public sink +{ +protected: + Float64 d_input_sample_rate; + UInt32 d_n_user_channels, d_n_dev_channels, d_n_buffer_channels; + UInt32 d_queue_sample_count, d_buffer_size_samples; + bool d_ok_to_block, d_do_reset, d_hardware_changed; + bool d_using_default_device, d_waiting_for_data; + gr::thread::mutex d_internal; + gr::thread::condition_variable d_cond_data; + std::vector<circular_buffer<float>*> d_buffers; + std::string d_desired_name, d_selected_name; - public: + // AudioUnits and Such - osx_sink(int sample_rate, - const std::string& device_name, - bool ok_to_block); + AudioUnit d_output_au; + AudioDeviceID d_output_ad_id; + AudioStreamBasicDescription d_stream_format; - inline virtual ~osx_sink() { - teardown(); - } +public: + osx_sink(int sample_rate, const std::string& device_name, bool ok_to_block); - virtual bool check_topology(int ninputs, int noutputs); - virtual bool start(); - virtual bool stop(); + inline virtual ~osx_sink() { teardown(); } - virtual int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + virtual bool check_topology(int ninputs, int noutputs); + virtual bool start(); + virtual bool stop(); - inline void reset(bool hardware_changed) { - d_hardware_changed = hardware_changed; - d_do_reset = true; - } + virtual int work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); - private: + inline void reset(bool hardware_changed) + { + d_hardware_changed = hardware_changed; + d_do_reset = true; + } - bool is_running(); +private: + bool is_running(); - void setup(); + void setup(); - void teardown(); + void teardown(); - void check_channels(bool force_reset); + void check_channels(bool force_reset); - static OSStatus au_output_callback - (void* in_ref_con, - AudioUnitRenderActionFlags* io_action_flags, - const AudioTimeStamp* in_time_stamp, - UInt32 in_bus_number, - UInt32 in_number_frames, - AudioBufferList* io_data); + static OSStatus au_output_callback(void* in_ref_con, + AudioUnitRenderActionFlags* io_action_flags, + const AudioTimeStamp* in_time_stamp, + UInt32 in_bus_number, + UInt32 in_number_frames, + AudioBufferList* io_data); #ifndef GR_USE_OLD_AUDIO_UNIT - // OSX 10.4 and newer + // OSX 10.4 and newer - static OSStatus hardware_listener - (AudioObjectID in_object_id, - UInt32 in_num_addresses, - const AudioObjectPropertyAddress in_addresses[], - void* in_client_data); + static OSStatus hardware_listener(AudioObjectID in_object_id, + UInt32 in_num_addresses, + const AudioObjectPropertyAddress in_addresses[], + void* in_client_data); - static OSStatus default_listener - (AudioObjectID in_object_id, - UInt32 in_num_addresses, - const AudioObjectPropertyAddress in_addresses[], - void* in_client_data); + static OSStatus default_listener(AudioObjectID in_object_id, + UInt32 in_num_addresses, + const AudioObjectPropertyAddress in_addresses[], + void* in_client_data); #else - // OSX 10.6 and older; removed as of 10.7 + // OSX 10.6 and older; removed as of 10.7 - static OSStatus hardware_listener - (AudioHardwarePropertyID in_property_id, - void* in_client_data); + static OSStatus hardware_listener(AudioHardwarePropertyID in_property_id, + void* in_client_data); - static OSStatus default_listener - (AudioHardwarePropertyID in_property_id, - void* in_client_data); + static OSStatus default_listener(AudioHardwarePropertyID in_property_id, + void* in_client_data); #endif - - }; - } /* namespace audio */ +}; +} /* namespace audio */ } /* namespace gr */ #endif /* INCLUDED_AUDIO_OSX_SINK_H */ diff --git a/gr-audio/lib/osx/osx_source.cc b/gr-audio/lib/osx/osx_source.cc index 48001e2638..5dfd2b8390 100644 --- a/gr-audio/lib/osx/osx_source.cc +++ b/gr-audio/lib/osx/osx_source.cc @@ -32,477 +32,466 @@ #include <stdexcept> namespace gr { - namespace audio { - - source::sptr - osx_source_fcn(int sampling_rate, - const std::string& device_name, - bool ok_to_block) - { - return source::sptr - (new osx_source(sampling_rate, device_name, ok_to_block)); - } - - static std::string - default_device_name() - { - return prefs::singleton()->get_string - ("audio_osx", "default_input_device", "built-in"); - } - - osx_source::osx_source - (int sample_rate, - const std::string& device_name, - bool ok_to_block) - : sync_block("audio_osx_source", - io_signature::make(0, 0, 0), - io_signature::make(0, 0, 0)), - d_device_sample_rate(0.0), d_output_sample_rate(0.0), - d_input_buffer_size_frames(0), d_input_buffer_size_bytes(0), - d_output_buffer_size_frames(0), d_output_buffer_size_bytes(0), - d_device_buffer_size_frames(0), d_device_buffer_size_bytes(0), - d_lead_size_frames(0), d_lead_size_bytes(0), - d_trail_size_frames(0), d_trail_size_bytes(0), - d_extra_buffer_size_frames(0), d_extra_buffer_size_bytes(0), - d_queue_sample_count(0), d_buffer_sample_count(0), - d_n_available_input_frames(0), d_n_actual_input_frames(0), - d_n_user_channels(0), d_n_dev_channels(0), - d_ok_to_block(ok_to_block), d_pass_through(false), - d_waiting_for_data(false), d_do_reset(false), - d_hardware_changed(false), d_using_default_device(false), - d_desired_name(device_name.empty() ? default_device_name() - : device_name), - d_input_ad_id(0), d_input_au(0), d_input_buffer(0), - d_output_buffer(0), d_audio_converter(0) - { - // set the desired output sample rate - - if(sample_rate <= 0) { - GR_LOG_ERROR(d_logger, boost::format - ("Invalid Sample Rate: %d") - % sample_rate); +namespace audio { + +source::sptr +osx_source_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block) +{ + return source::sptr(new osx_source(sampling_rate, device_name, ok_to_block)); +} + +static std::string default_device_name() +{ + return prefs::singleton()->get_string( + "audio_osx", "default_input_device", "built-in"); +} + +osx_source::osx_source(int sample_rate, const std::string& device_name, bool ok_to_block) + : sync_block( + "audio_osx_source", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)), + d_device_sample_rate(0.0), + d_output_sample_rate(0.0), + d_input_buffer_size_frames(0), + d_input_buffer_size_bytes(0), + d_output_buffer_size_frames(0), + d_output_buffer_size_bytes(0), + d_device_buffer_size_frames(0), + d_device_buffer_size_bytes(0), + d_lead_size_frames(0), + d_lead_size_bytes(0), + d_trail_size_frames(0), + d_trail_size_bytes(0), + d_extra_buffer_size_frames(0), + d_extra_buffer_size_bytes(0), + d_queue_sample_count(0), + d_buffer_sample_count(0), + d_n_available_input_frames(0), + d_n_actual_input_frames(0), + d_n_user_channels(0), + d_n_dev_channels(0), + d_ok_to_block(ok_to_block), + d_pass_through(false), + d_waiting_for_data(false), + d_do_reset(false), + d_hardware_changed(false), + d_using_default_device(false), + d_desired_name(device_name.empty() ? default_device_name() : device_name), + d_input_ad_id(0), + d_input_au(0), + d_input_buffer(0), + d_output_buffer(0), + d_audio_converter(0) +{ + // set the desired output sample rate + + if (sample_rate <= 0) { + GR_LOG_ERROR(d_logger, boost::format("Invalid Sample Rate: %d") % sample_rate); throw std::invalid_argument("audio_osx_source"); - } - else { + } else { d_output_sample_rate = (Float64)sample_rate; - } - - // set up for audio input using the stored desired parameters - - setup(); } - void osx_source::setup() - { - OSStatus err = noErr; + // set up for audio input using the stored desired parameters - // set the default input audio device id to "unknown" + setup(); +} - d_input_ad_id = kAudioDeviceUnknown; +void osx_source::setup() +{ + OSStatus err = noErr; - // try to find the input audio device, if specified + // set the default input audio device id to "unknown" - std::vector < AudioDeviceID > all_ad_ids; - std::vector < std::string > all_names; + d_input_ad_id = kAudioDeviceUnknown; - osx::find_audio_devices - (d_desired_name, true, - &all_ad_ids, &all_names); + // try to find the input audio device, if specified - // check number of device(s) returned + std::vector<AudioDeviceID> all_ad_ids; + std::vector<std::string> all_names; - if (d_desired_name.length() != 0) { - if (all_ad_ids.size() == 1) { + osx::find_audio_devices(d_desired_name, true, &all_ad_ids, &all_names); - // exactly 1 match was found; see if it was partial + // check number of device(s) returned - if (all_names[0].compare(d_desired_name) != 0) { + if (d_desired_name.length() != 0) { + if (all_ad_ids.size() == 1) { - // yes: log the full device name - GR_LOG_INFO(d_logger, boost::format - ("Using input audio device '%s'.") - % all_names[0]); + // exactly 1 match was found; see if it was partial - } + if (all_names[0].compare(d_desired_name) != 0) { - // store info on this device + // yes: log the full device name + GR_LOG_INFO(d_logger, + boost::format("Using input audio device '%s'.") % + all_names[0]); + } - d_input_ad_id = all_ad_ids[0]; - d_selected_name = all_names[0]; + // store info on this device - } else { + d_input_ad_id = all_ad_ids[0]; + d_selected_name = all_names[0]; - // either 0 or more than 1 device was found; get all input - // device names, print those, and error out. + } else { - osx::find_audio_devices("", true, NULL, &all_names); + // either 0 or more than 1 device was found; get all input + // device names, print those, and error out. - std::string err_str("\n\nA unique input audio device name " - "matching the string '"); - err_str += d_desired_name; - err_str += "' was not found.\n\n"; - err_str += "The current known input audio device name"; - err_str += ((all_names.size() > 1) ? "s are" : " is"); - err_str += ":\n"; - for (UInt32 nn = 0; nn < all_names.size(); ++nn) { - err_str += " " + all_names[nn] + "\n"; - } - GR_LOG_ERROR(d_logger, boost::format(err_str)); - throw std::runtime_error("audio_osx_source::setup"); + osx::find_audio_devices("", true, NULL, &all_names); - } - } + std::string err_str("\n\nA unique input audio device name " + "matching the string '"); + err_str += d_desired_name; + err_str += "' was not found.\n\n"; + err_str += "The current known input audio device name"; + err_str += ((all_names.size() > 1) ? "s are" : " is"); + err_str += ":\n"; + for (UInt32 nn = 0; nn < all_names.size(); ++nn) { + err_str += " " + all_names[nn] + "\n"; + } + GR_LOG_ERROR(d_logger, boost::format(err_str)); + throw std::runtime_error("audio_osx_source::setup"); + } + } - // if no input audio device id was found or no specific device - // name was provided, use the default input audio device id as - // set in System Preferences. + // if no input audio device id was found or no specific device + // name was provided, use the default input audio device id as + // set in System Preferences. - if (d_input_ad_id == kAudioDeviceUnknown) { + if (d_input_ad_id == kAudioDeviceUnknown) { UInt32 prop_size = (UInt32)sizeof(AudioDeviceID); AudioObjectPropertyAddress ao_address = { - kAudioHardwarePropertyDefaultInputDevice, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster + kAudioHardwarePropertyDefaultInputDevice, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster }; - err = AudioObjectGetPropertyData - (kAudioObjectSystemObject, &ao_address, - 0, NULL, &prop_size, &d_input_ad_id); - check_error_and_throw - (err, "Getting the default input audio device ID failed", - "audio_osx_source::setup"); - - { - // retrieve the device name; max name length is 64 characters. - - UInt32 prop_size = 65; - char c_name_buf[prop_size]; - memset((void*)c_name_buf, 0, (size_t)prop_size); - --prop_size; - - AudioObjectPropertyAddress ao_address = { - kAudioDevicePropertyDeviceName, - kAudioDevicePropertyScopeInput, 0 - }; - - if ((err = AudioObjectGetPropertyData - (d_input_ad_id, &ao_address, 0, NULL, - &prop_size, (void*)c_name_buf)) != noErr) { - - check_error(err, "Unable to retrieve input audio device name"); - - } else { - - GR_LOG_INFO(d_logger, boost::format - ("\n\nUsing input audio device '%s'.\n ... " - "which is the current default input audio" - " device.\n Changing the default input" - " audio device in the System Preferences" - " will \n result in changing it here, too " - "(with an internal reconfiguration).\n") % - std::string(c_name_buf)); - - } - - d_selected_name = c_name_buf; - - } + err = AudioObjectGetPropertyData( + kAudioObjectSystemObject, &ao_address, 0, NULL, &prop_size, &d_input_ad_id); + check_error_and_throw(err, + "Getting the default input audio device ID failed", + "audio_osx_source::setup"); + + { + // retrieve the device name; max name length is 64 characters. + + UInt32 prop_size = 65; + char c_name_buf[prop_size]; + memset((void*)c_name_buf, 0, (size_t)prop_size); + --prop_size; + + AudioObjectPropertyAddress ao_address = { kAudioDevicePropertyDeviceName, + kAudioDevicePropertyScopeInput, + 0 }; + + if ((err = AudioObjectGetPropertyData(d_input_ad_id, + &ao_address, + 0, + NULL, + &prop_size, + (void*)c_name_buf)) != noErr) { + + check_error(err, "Unable to retrieve input audio device name"); + + } else { + + GR_LOG_INFO(d_logger, + boost::format("\n\nUsing input audio device '%s'.\n ... " + "which is the current default input audio" + " device.\n Changing the default input" + " audio device in the System Preferences" + " will \n result in changing it here, too " + "(with an internal reconfiguration).\n") % + std::string(c_name_buf)); + } - d_using_default_device = true; + d_selected_name = c_name_buf; + } - } + d_using_default_device = true; + } - // retrieve the total number of channels for the selected input - // audio device + // retrieve the total number of channels for the selected input + // audio device - osx::get_num_channels_for_audio_device_id - (d_input_ad_id, &d_n_dev_channels, NULL); + osx::get_num_channels_for_audio_device_id(d_input_ad_id, &d_n_dev_channels, NULL); - // set the block output signature, if not already set - // (d_n_user_channels is set in check_topology, which is called - // before the flow-graph is running) + // set the block output signature, if not already set + // (d_n_user_channels is set in check_topology, which is called + // before the flow-graph is running) - if (d_n_user_channels == 0) { - set_output_signature(io_signature::make - (1, d_n_dev_channels, sizeof(float))); - } + if (d_n_user_channels == 0) { + set_output_signature(io_signature::make(1, d_n_dev_channels, sizeof(float))); + } - // set the interim buffer size; to work with the GR scheduler, - // must be at least 16kB. Pick 50 kB since that's plenty yet - // not very much. + // set the interim buffer size; to work with the GR scheduler, + // must be at least 16kB. Pick 50 kB since that's plenty yet + // not very much. - d_buffer_sample_count = (d_output_sample_rate < 50000.0 ? - 50000 : (UInt32)d_output_sample_rate); + d_buffer_sample_count = + (d_output_sample_rate < 50000.0 ? 50000 : (UInt32)d_output_sample_rate); #if _OSX_AU_DEBUG_ - std::cerr << "source(): max # samples = " - << d_buffer_sample_count << std::endl; + std::cerr << "source(): max # samples = " << d_buffer_sample_count << std::endl; #endif - // create the default AudioUnit for input + // create the default AudioUnit for input - // Open the default input unit + // Open the default input unit #ifndef GR_USE_OLD_AUDIO_UNIT - AudioComponentDescription desc; + AudioComponentDescription desc; #else - ComponentDescription desc; + ComponentDescription desc; #endif - desc.componentType = kAudioUnitType_Output; - desc.componentSubType = kAudioUnitSubType_HALOutput; - desc.componentManufacturer = kAudioUnitManufacturer_Apple; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_HALOutput; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; #ifndef GR_USE_OLD_AUDIO_UNIT - AudioComponent comp = AudioComponentFindNext(NULL, &desc); - if(!comp) { - GR_LOG_FATAL(d_logger, boost::format - ("AudioComponentFindNext Failed")); + AudioComponent comp = AudioComponentFindNext(NULL, &desc); + if (!comp) { + GR_LOG_FATAL(d_logger, boost::format("AudioComponentFindNext Failed")); throw std::runtime_error("audio_osx_source::setup"); - } - err = AudioComponentInstanceNew(comp, &d_input_au); - check_error_and_throw(err, "AudioComponentInstanceNew Failed", - "audio_osx_source::setup"); + } + err = AudioComponentInstanceNew(comp, &d_input_au); + check_error_and_throw( + err, "AudioComponentInstanceNew Failed", "audio_osx_source::setup"); #else - Component comp = FindNextComponent(NULL, &desc); - if(!comp) { - GR_LOG_FATAL(d_logger, boost::format - ("FindNextComponent Failed")); + Component comp = FindNextComponent(NULL, &desc); + if (!comp) { + GR_LOG_FATAL(d_logger, boost::format("FindNextComponent Failed")); throw std::runtime_error("audio_osx_source::setup"); - } - err = OpenAComponent(comp, &d_input_au); - check_error_and_throw(err, "OpenAComponent Failed", - "audio_osx_source::setup"); + } + err = OpenAComponent(comp, &d_input_au); + check_error_and_throw(err, "OpenAComponent Failed", "audio_osx_source::setup"); #endif - // must enable the AUHAL for input and disable output - // before setting the AUHAL's current device - - // Enable input on the AUHAL - - UInt32 enable_io = 1; - err = AudioUnitSetProperty - (d_input_au, - kAudioOutputUnitProperty_EnableIO, - kAudioUnitScope_Input, 1, // input element - &enable_io, sizeof(enable_io)); - check_error_and_throw - (err, "AudioUnitSetProperty Input Enable", - "audio_osx_source::setup"); - - // Disable output on the AUHAL - - enable_io = 0; - err = AudioUnitSetProperty - (d_input_au, - kAudioOutputUnitProperty_EnableIO, - kAudioUnitScope_Output, 0, // output element - &enable_io, sizeof(enable_io)); - check_error_and_throw - (err, "AudioUnitSetProperty Output Disable", - "audio_osx_source::setup"); - - // set the selected device ID as the current input device - - err = AudioUnitSetProperty - (d_input_au, kAudioOutputUnitProperty_CurrentDevice, - kAudioUnitScope_Global, 0, - &d_input_ad_id, sizeof(d_input_ad_id)); - check_error_and_throw - (err, "Setting selected input device as current failed", - "audio_osx_source::setup"); - - // Set up a callback function to retrieve input from the Audio Device - - AURenderCallbackStruct au_callback = { - reinterpret_cast<AURenderCallback> - (&osx_source::au_input_callback), - reinterpret_cast<void*>(this) - }; - UInt32 prop_size = (UInt32)sizeof(au_callback); - - err = AudioUnitSetProperty - (d_input_au, - kAudioOutputUnitProperty_SetInputCallback, - kAudioUnitScope_Global, 0, - &au_callback, prop_size); - check_error_and_throw - (err, "Set Input Callback", - "audio_osx_source::setup"); - - // Get the Stream Format (device side; cannot generally be changed) - - prop_size = (UInt32)sizeof(d_asbd_device); - memset((void*)(&d_asbd_device), 0, (size_t)prop_size); - err = AudioUnitGetProperty - (d_input_au, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, 1, - &d_asbd_device, &prop_size); - check_error_and_throw - (err, "Get Device Input Stream Format (before) failed", - "audio_osx_source::setup"); + // must enable the AUHAL for input and disable output + // before setting the AUHAL's current device + + // Enable input on the AUHAL + + UInt32 enable_io = 1; + err = AudioUnitSetProperty(d_input_au, + kAudioOutputUnitProperty_EnableIO, + kAudioUnitScope_Input, + 1, // input element + &enable_io, + sizeof(enable_io)); + check_error_and_throw( + err, "AudioUnitSetProperty Input Enable", "audio_osx_source::setup"); + + // Disable output on the AUHAL + + enable_io = 0; + err = AudioUnitSetProperty(d_input_au, + kAudioOutputUnitProperty_EnableIO, + kAudioUnitScope_Output, + 0, // output element + &enable_io, + sizeof(enable_io)); + check_error_and_throw( + err, "AudioUnitSetProperty Output Disable", "audio_osx_source::setup"); + + // set the selected device ID as the current input device + + err = AudioUnitSetProperty(d_input_au, + kAudioOutputUnitProperty_CurrentDevice, + kAudioUnitScope_Global, + 0, + &d_input_ad_id, + sizeof(d_input_ad_id)); + check_error_and_throw(err, + "Setting selected input device as current failed", + "audio_osx_source::setup"); + + // Set up a callback function to retrieve input from the Audio Device + + AURenderCallbackStruct au_callback = { reinterpret_cast<AURenderCallback>( + &osx_source::au_input_callback), + reinterpret_cast<void*>(this) }; + UInt32 prop_size = (UInt32)sizeof(au_callback); + + err = AudioUnitSetProperty(d_input_au, + kAudioOutputUnitProperty_SetInputCallback, + kAudioUnitScope_Global, + 0, + &au_callback, + prop_size); + check_error_and_throw(err, "Set Input Callback", "audio_osx_source::setup"); + + // Get the Stream Format (device side; cannot generally be changed) + + prop_size = (UInt32)sizeof(d_asbd_device); + memset((void*)(&d_asbd_device), 0, (size_t)prop_size); + err = AudioUnitGetProperty(d_input_au, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 1, + &d_asbd_device, + &prop_size); + check_error_and_throw( + err, "Get Device Input Stream Format (before) failed", "audio_osx_source::setup"); #if _OSX_AU_DEBUG_ - std::cerr << std::endl << "---- Device Stream Format (before) ----" - << std::endl << d_asbd_device << std::endl << std::endl; + std::cerr << std::endl + << "---- Device Stream Format (before) ----" << std::endl + << d_asbd_device << std::endl + << std::endl; #endif - // try to set the device (input) side of the audio device to the - // sample rate of this source. This will likely fail, and - // that's OK; just ignore the error since we can accomplish - // audio input in other ways. - - prop_size = (UInt32)sizeof(d_asbd_device); - d_asbd_device.mSampleRate = d_output_sample_rate; - err = AudioUnitSetProperty - (d_input_au, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, 1, - &d_asbd_device, prop_size); + // try to set the device (input) side of the audio device to the + // sample rate of this source. This will likely fail, and + // that's OK; just ignore the error since we can accomplish + // audio input in other ways. + + prop_size = (UInt32)sizeof(d_asbd_device); + d_asbd_device.mSampleRate = d_output_sample_rate; + err = AudioUnitSetProperty(d_input_au, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 1, + &d_asbd_device, + prop_size); #if _OSX_AU_DEBUG_ - check_error - (err, "Set Device Input Stream Format failed (expected)"); + check_error(err, "Set Device Input Stream Format failed (expected)"); #endif - memset((void*)(&d_asbd_device), 0, (size_t)prop_size); - err = AudioUnitGetProperty - (d_input_au, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, 1, - &d_asbd_device, &prop_size); - check_error_and_throw - (err, "Get Device Input Stream Format (after) failed", - "audio_osx_source::setup"); + memset((void*)(&d_asbd_device), 0, (size_t)prop_size); + err = AudioUnitGetProperty(d_input_au, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 1, + &d_asbd_device, + &prop_size); + check_error_and_throw( + err, "Get Device Input Stream Format (after) failed", "audio_osx_source::setup"); #if _OSX_AU_DEBUG_ - std::cerr << std::endl << "---- Device Stream Format (after) ----" - << std::endl << d_asbd_device << std::endl << std::endl; + std::cerr << std::endl + << "---- Device Stream Format (after) ----" << std::endl + << d_asbd_device << std::endl + << std::endl; #endif - d_device_sample_rate = d_asbd_device.mSampleRate; + d_device_sample_rate = d_asbd_device.mSampleRate; - // Get the Stream Format (client side; might be changeable) + // Get the Stream Format (client side; might be changeable) - prop_size = (UInt32)sizeof(d_asbd_client); - memset((void*)(&d_asbd_client), 0, (size_t)prop_size); - err = AudioUnitGetProperty - (d_input_au, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Output, 1, - &d_asbd_client, &prop_size); - check_error_and_throw - (err, "Get Device Output Stream Format (before) failed", - "audio_osx_source::setup"); + prop_size = (UInt32)sizeof(d_asbd_client); + memset((void*)(&d_asbd_client), 0, (size_t)prop_size); + err = AudioUnitGetProperty(d_input_au, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Output, + 1, + &d_asbd_client, + &prop_size); + check_error_and_throw(err, + "Get Device Output Stream Format (before) failed", + "audio_osx_source::setup"); #if _OSX_AU_DEBUG_ - std::cerr << "---- Client Stream Format (Before) ----" - << std::endl << d_asbd_client << std::endl << std::endl; + std::cerr << "---- Client Stream Format (Before) ----" << std::endl + << d_asbd_client << std::endl + << std::endl; #endif - // Set the format of all the AUs to the - // input/output devices channel count + // Set the format of all the AUs to the + // input/output devices channel count - d_asbd_client.mFormatID = kAudioFormatLinearPCM; - d_asbd_client.mFormatFlags = (kAudioFormatFlagIsFloat | - kAudioFormatFlagIsPacked | + d_asbd_client.mFormatID = kAudioFormatLinearPCM; + d_asbd_client.mFormatFlags = (kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved); - if((d_asbd_client.mFormatID == kAudioFormatLinearPCM) && - (d_n_dev_channels == 1)) { + if ((d_asbd_client.mFormatID == kAudioFormatLinearPCM) && (d_n_dev_channels == 1)) { d_asbd_client.mFormatFlags &= ~kLinearPCMFormatFlagIsNonInterleaved; - } - d_asbd_client.mBytesPerFrame = (UInt32)sizeof(float); - d_asbd_client.mFramesPerPacket = 1; - d_asbd_client.mBitsPerChannel = d_asbd_client.mBytesPerFrame * 8; - d_asbd_client.mChannelsPerFrame = d_n_dev_channels; - d_asbd_client.mBytesPerPacket = d_asbd_client.mBytesPerFrame; - - // according to Apple docs [see, e.g., Apple Technical Note - // TN2091 "Device input using the HAL Output Audio Unit"], the - // device input and output sample rate must be the same; do - // sample rate conversion elsewhere. - - d_asbd_client.mSampleRate = d_asbd_device.mSampleRate; - err = AudioUnitSetProperty - (d_input_au, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Output, 1, - &d_asbd_client, prop_size); - check_error_and_throw - (err, "Set Device Output Stream Format failed", - "audio_osx_source::setup"); - - // Get the Stream Format (client side), again - - prop_size = (UInt32)sizeof(d_asbd_client); - memset((void*)(&d_asbd_client), 0, (size_t)prop_size); - err = AudioUnitGetProperty - (d_input_au, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Output, 1, - &d_asbd_client, &prop_size); - check_error_and_throw - (err, "Get Device Output Stream Format (after) failed", - "audio_osx_source::setup"); + } + d_asbd_client.mBytesPerFrame = (UInt32)sizeof(float); + d_asbd_client.mFramesPerPacket = 1; + d_asbd_client.mBitsPerChannel = d_asbd_client.mBytesPerFrame * 8; + d_asbd_client.mChannelsPerFrame = d_n_dev_channels; + d_asbd_client.mBytesPerPacket = d_asbd_client.mBytesPerFrame; + + // according to Apple docs [see, e.g., Apple Technical Note + // TN2091 "Device input using the HAL Output Audio Unit"], the + // device input and output sample rate must be the same; do + // sample rate conversion elsewhere. + + d_asbd_client.mSampleRate = d_asbd_device.mSampleRate; + err = AudioUnitSetProperty(d_input_au, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Output, + 1, + &d_asbd_client, + prop_size); + check_error_and_throw( + err, "Set Device Output Stream Format failed", "audio_osx_source::setup"); + + // Get the Stream Format (client side), again + + prop_size = (UInt32)sizeof(d_asbd_client); + memset((void*)(&d_asbd_client), 0, (size_t)prop_size); + err = AudioUnitGetProperty(d_input_au, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Output, + 1, + &d_asbd_client, + &prop_size); + check_error_and_throw( + err, "Get Device Output Stream Format (after) failed", "audio_osx_source::setup"); #if _OSX_AU_DEBUG_ - std::cerr << "---- Client Stream Format (After) ----" - << std::endl << d_asbd_client << std::endl << std::endl; + std::cerr << "---- Client Stream Format (After) ----" << std::endl + << d_asbd_client << std::endl + << std::endl; #endif - d_pass_through = (d_asbd_client.mSampleRate == d_output_sample_rate); + d_pass_through = (d_asbd_client.mSampleRate == d_output_sample_rate); - if (d_pass_through) { + if (d_pass_through) { // no need to do conversion if d_asbd_client matches user wants d_lead_size_frames = d_trail_size_frames = 0L; - } - else { + } else { - // create an ASBD for the user's wants + // create an ASBD for the user's wants - memset((void*)(&d_asbd_user), 0, sizeof(d_asbd_user)); - d_asbd_user.mSampleRate = d_output_sample_rate; - d_asbd_user.mFormatID = kAudioFormatLinearPCM; - d_asbd_user.mFormatFlags = (kLinearPCMFormatFlagIsFloat | - GR_PCM_ENDIANNESS | - kLinearPCMFormatFlagIsPacked | - kAudioFormatFlagIsNonInterleaved); - d_asbd_user.mBytesPerPacket = (UInt32)sizeof(float); - d_asbd_user.mFramesPerPacket = 1; - d_asbd_user.mBytesPerFrame = d_asbd_user.mBytesPerPacket; - d_asbd_user.mChannelsPerFrame = d_n_dev_channels; - d_asbd_user.mBitsPerChannel = d_asbd_user.mBytesPerPacket * 8; + memset((void*)(&d_asbd_user), 0, sizeof(d_asbd_user)); + d_asbd_user.mSampleRate = d_output_sample_rate; + d_asbd_user.mFormatID = kAudioFormatLinearPCM; + d_asbd_user.mFormatFlags = + (kLinearPCMFormatFlagIsFloat | GR_PCM_ENDIANNESS | + kLinearPCMFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved); + d_asbd_user.mBytesPerPacket = (UInt32)sizeof(float); + d_asbd_user.mFramesPerPacket = 1; + d_asbd_user.mBytesPerFrame = d_asbd_user.mBytesPerPacket; + d_asbd_user.mChannelsPerFrame = d_n_dev_channels; + d_asbd_user.mBitsPerChannel = d_asbd_user.mBytesPerPacket * 8; // Create the audio converter - err = AudioConverterNew(&d_asbd_client, - &d_asbd_user, - &d_audio_converter); - check_error_and_throw - (err, "AudioConverterNew failed", - "audio_osx_source::setup"); + err = AudioConverterNew(&d_asbd_client, &d_asbd_user, &d_audio_converter); + check_error_and_throw(err, "AudioConverterNew failed", "audio_osx_source::setup"); // Set the audio converter sample rate quality to "max" ... // requires more samples, but should sound nicer UInt32 ac_quality = kAudioConverterQuality_Max; prop_size = (UInt32)sizeof(ac_quality); - err = AudioConverterSetProperty - (d_audio_converter, - kAudioConverterSampleRateConverterQuality, - prop_size, &ac_quality); - check_error_and_throw - (err, "Set Sample Rate Converter Quality failed", - "audio_osx_source::setup"); + err = AudioConverterSetProperty(d_audio_converter, + kAudioConverterSampleRateConverterQuality, + prop_size, + &ac_quality); + check_error_and_throw( + err, "Set Sample Rate Converter Quality failed", "audio_osx_source::setup"); // set the audio converter's prime method to "pre", // which uses both leading and trailing frames @@ -512,850 +501,767 @@ namespace gr { UInt32 ac_prime_method = kConverterPrimeMethod_Pre; prop_size = (UInt32)sizeof(ac_prime_method); - err = AudioConverterSetProperty - (d_audio_converter, - kAudioConverterPrimeMethod, - prop_size, &ac_prime_method); - check_error_and_throw - (err, "Set Prime Method failed", - "audio_osx_source::setup"); + err = AudioConverterSetProperty( + d_audio_converter, kAudioConverterPrimeMethod, prop_size, &ac_prime_method); + check_error_and_throw(err, "Set Prime Method failed", "audio_osx_source::setup"); // Get the size of the priming I/O buffer space to allow for // pre-allocated buffers - AudioConverterPrimeInfo ac_prime_info = {0, 0}; + AudioConverterPrimeInfo ac_prime_info = { 0, 0 }; prop_size = (UInt32)sizeof(ac_prime_info); - err = AudioConverterGetProperty - (d_audio_converter, - kAudioConverterPrimeInfo, - &prop_size, &ac_prime_info); - check_error_and_throw - (err, "Get Prime Info failed", - "audio_osx_source::setup"); - - d_lead_size_frames = ac_prime_info.leadingFrames; - d_trail_size_frames = ac_prime_info.trailingFrames; - } - - d_lead_size_bytes = d_lead_size_frames * sizeof(float); - d_trail_size_bytes = d_trail_size_frames * sizeof(float); - - prop_size = (UInt32)sizeof(d_device_buffer_size_frames); - err = AudioUnitGetProperty - (d_input_au, - kAudioDevicePropertyBufferFrameSize, - kAudioUnitScope_Global, 0, - &d_device_buffer_size_frames, &prop_size); - check_error_and_throw - (err, "Get Buffer Frame Size failed", - "audio_osx_source::setup"); - - d_device_buffer_size_bytes = (d_device_buffer_size_frames * - sizeof(float)); - d_input_buffer_size_bytes = (d_device_buffer_size_bytes + - d_lead_size_bytes); - d_input_buffer_size_frames = (d_device_buffer_size_frames + - d_lead_size_frames); - - // outBufSizeBytes = floor (inBufSizeBytes * rate_out / rate_in) - // since this is rarely exact, we need another buffer to hold - // "extra" samples not processed at any given sampling period - // this buffer must be at least 4 floats in size, but generally - // follows the rule that - // extraBufSize = ceil (rate_in / rate_out)*sizeof(float) - - d_extra_buffer_size_frames = - ((UInt32)ceil(d_device_sample_rate / - d_output_sample_rate) * - sizeof(float)); - if(d_extra_buffer_size_frames < 4) + err = AudioConverterGetProperty( + d_audio_converter, kAudioConverterPrimeInfo, &prop_size, &ac_prime_info); + check_error_and_throw(err, "Get Prime Info failed", "audio_osx_source::setup"); + + d_lead_size_frames = ac_prime_info.leadingFrames; + d_trail_size_frames = ac_prime_info.trailingFrames; + } + + d_lead_size_bytes = d_lead_size_frames * sizeof(float); + d_trail_size_bytes = d_trail_size_frames * sizeof(float); + + prop_size = (UInt32)sizeof(d_device_buffer_size_frames); + err = AudioUnitGetProperty(d_input_au, + kAudioDevicePropertyBufferFrameSize, + kAudioUnitScope_Global, + 0, + &d_device_buffer_size_frames, + &prop_size); + check_error_and_throw(err, "Get Buffer Frame Size failed", "audio_osx_source::setup"); + + d_device_buffer_size_bytes = (d_device_buffer_size_frames * sizeof(float)); + d_input_buffer_size_bytes = (d_device_buffer_size_bytes + d_lead_size_bytes); + d_input_buffer_size_frames = (d_device_buffer_size_frames + d_lead_size_frames); + + // outBufSizeBytes = floor (inBufSizeBytes * rate_out / rate_in) + // since this is rarely exact, we need another buffer to hold + // "extra" samples not processed at any given sampling period + // this buffer must be at least 4 floats in size, but generally + // follows the rule that + // extraBufSize = ceil (rate_in / rate_out)*sizeof(float) + + d_extra_buffer_size_frames = + ((UInt32)ceil(d_device_sample_rate / d_output_sample_rate) * sizeof(float)); + if (d_extra_buffer_size_frames < 4) d_extra_buffer_size_frames = 4; - d_extra_buffer_size_bytes = - d_extra_buffer_size_frames * sizeof(float); - - d_output_buffer_size_frames = - (UInt32)ceil(((Float64)d_input_buffer_size_frames) * - d_output_sample_rate / d_device_sample_rate); - d_output_buffer_size_bytes = - d_output_buffer_size_frames * sizeof(float); - d_input_buffer_size_frames += d_extra_buffer_size_frames; - - // pre-alloc all CoreAudio buffers - - alloc_audio_buffer_list - (&d_input_buffer, d_n_dev_channels, - d_input_buffer_size_bytes); - if(!d_pass_through) { - alloc_audio_buffer_list - (&d_output_buffer, d_n_dev_channels, - d_output_buffer_size_bytes); - } - else { + d_extra_buffer_size_bytes = d_extra_buffer_size_frames * sizeof(float); + + d_output_buffer_size_frames = + (UInt32)ceil(((Float64)d_input_buffer_size_frames) * d_output_sample_rate / + d_device_sample_rate); + d_output_buffer_size_bytes = d_output_buffer_size_frames * sizeof(float); + d_input_buffer_size_frames += d_extra_buffer_size_frames; + + // pre-alloc all CoreAudio buffers + + alloc_audio_buffer_list(&d_input_buffer, d_n_dev_channels, d_input_buffer_size_bytes); + if (!d_pass_through) { + alloc_audio_buffer_list( + &d_output_buffer, d_n_dev_channels, d_output_buffer_size_bytes); + } else { d_output_buffer = d_input_buffer; - } - - // allocate the output circular buffer(s), one per device - // channel (the user may select fewer channels; those buffers - // just won't get used). - - d_buffers.resize(d_n_dev_channels); - for(UInt32 nn = 0; nn < d_n_dev_channels; ++nn) { - d_buffers[nn] = new circular_buffer<float> - (d_buffer_sample_count, false, false); - } - - // clear the RunLoop (whatever that is); needed, for some - // reason, before a listener will work. - - { - CFRunLoopRef the_run_loop = NULL; - AudioObjectPropertyAddress property = { - kAudioHardwarePropertyRunLoop, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster - }; - prop_size = (UInt32)sizeof(the_run_loop); - err = AudioObjectSetPropertyData - (kAudioObjectSystemObject, &property, 0, NULL, - prop_size, &the_run_loop); - check_error(err, "Clearing RunLoop failed; " - "Audio Input Device Listener might not work."); - } - - // set up listeners + } -#ifndef GR_USE_OLD_AUDIO_UNIT + // allocate the output circular buffer(s), one per device + // channel (the user may select fewer channels; those buffers + // just won't get used). - // 10.4 and newer + d_buffers.resize(d_n_dev_channels); + for (UInt32 nn = 0; nn < d_n_dev_channels; ++nn) { + d_buffers[nn] = new circular_buffer<float>(d_buffer_sample_count, false, false); + } - { + // clear the RunLoop (whatever that is); needed, for some + // reason, before a listener will work. - // set up a listener if hardware changes (at all) + { + CFRunLoopRef the_run_loop = NULL; + AudioObjectPropertyAddress property = { kAudioHardwarePropertyRunLoop, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster }; + prop_size = (UInt32)sizeof(the_run_loop); + err = AudioObjectSetPropertyData( + kAudioObjectSystemObject, &property, 0, NULL, prop_size, &the_run_loop); + check_error(err, + "Clearing RunLoop failed; " + "Audio Input Device Listener might not work."); + } - AudioObjectPropertyAddress property = { - kAudioHardwarePropertyDevices, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster - }; + // set up listeners - err = AudioObjectAddPropertyListener - (kAudioObjectSystemObject, &property, - reinterpret_cast<AudioObjectPropertyListenerProc> - (&osx_source::hardware_listener), - reinterpret_cast<void*>(this)); - check_error(err, "Adding Audio Hardware Listener failed"); - } +#ifndef GR_USE_OLD_AUDIO_UNIT - if (d_using_default_device) { + // 10.4 and newer - // set up a listener if default hardware input device changes + { + + // set up a listener if hardware changes (at all) - AudioObjectPropertyAddress property = { - kAudioHardwarePropertyDefaultInputDevice, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster - }; + AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster }; - err = AudioObjectAddPropertyListener - (kAudioObjectSystemObject, &property, - reinterpret_cast<AudioObjectPropertyListenerProc> - (&osx_source::default_listener), - reinterpret_cast<void*>(this)); - check_error(err, "Adding Default Input Audio Listener failed"); + err = AudioObjectAddPropertyListener( + kAudioObjectSystemObject, + &property, + reinterpret_cast<AudioObjectPropertyListenerProc>( + &osx_source::hardware_listener), + reinterpret_cast<void*>(this)); + check_error(err, "Adding Audio Hardware Listener failed"); + } - } + if (d_using_default_device) { -#else + // set up a listener if default hardware input device changes - // 10.5 and older + AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster }; + + err = AudioObjectAddPropertyListener( + kAudioObjectSystemObject, + &property, + reinterpret_cast<AudioObjectPropertyListenerProc>( + &osx_source::default_listener), + reinterpret_cast<void*>(this)); + check_error(err, "Adding Default Input Audio Listener failed"); + } + +#else - err = AudioHardwareAddPropertyListener - (kAudioHardwarePropertyDevices, - reinterpret_cast<AudioHardwarePropertyListenerProc> - (&osx_source::hardware_listener), - reinterpret_cast<void*>(this)); - check_error(err, "Adding Audio Hardware Listener failed"); + // 10.5 and older - if (d_using_default_device) { + err = AudioHardwareAddPropertyListener( + kAudioHardwarePropertyDevices, + reinterpret_cast<AudioHardwarePropertyListenerProc>( + &osx_source::hardware_listener), + reinterpret_cast<void*>(this)); + check_error(err, "Adding Audio Hardware Listener failed"); - err = AudioHardwareAddPropertyListener - (kAudioHardwarePropertyDefaultInputDevice, - reinterpret_cast<AudioHardwarePropertyListenerProc> - (&osx_source::default_listener), - reinterpret_cast<void*>(this)); - check_error(err, "Adding Default Input Audio Listener failed"); + if (d_using_default_device) { - } + err = AudioHardwareAddPropertyListener( + kAudioHardwarePropertyDefaultInputDevice, + reinterpret_cast<AudioHardwarePropertyListenerProc>( + &osx_source::default_listener), + reinterpret_cast<void*>(this)); + check_error(err, "Adding Default Input Audio Listener failed"); + } #endif - // initialize the AU for input, so that it is ready to be used + // initialize the AU for input, so that it is ready to be used - err = AudioUnitInitialize(d_input_au); - check_error_and_throw - (err, "AudioUnitInitialize", - "audio_osx_source::check_channels"); + err = AudioUnitInitialize(d_input_au); + check_error_and_throw(err, "AudioUnitInitialize", "audio_osx_source::check_channels"); #if _OSX_AU_DEBUG_ - std::cerr << std::endl << "audio_osx_source Parameters:" - << std::endl << " Device Sample Rate is " - << d_device_sample_rate << std::endl - << " Client Sample Rate is " - << (d_pass_through ? d_output_sample_rate : - d_device_sample_rate) << std::endl - << " User Sample Rate is " - << d_output_sample_rate << std::endl - << " Do Passthrough is " - << (d_pass_through ? "true" : "false") << std::endl - << " Max Sample Count is " - << d_buffer_sample_count << std::endl - << " # Device Channels is " - << d_n_dev_channels << std::endl - << " Device Buffer Size in Frames = " - << d_device_buffer_size_frames << std::endl - << " Lead Size in Frames = " - << d_lead_size_frames << std::endl - << " Trail Size in Frames = " - << d_trail_size_frames << std::endl - << " Input Buffer Size in Frames = " - << d_input_buffer_size_frames << std::endl - << " Output Buffer Size in Frames = " - << d_output_buffer_size_frames << std::endl - << std::endl; + std::cerr << std::endl + << "audio_osx_source Parameters:" << std::endl + << " Device Sample Rate is " << d_device_sample_rate << std::endl + << " Client Sample Rate is " + << (d_pass_through ? d_output_sample_rate : d_device_sample_rate) + << std::endl + << " User Sample Rate is " << d_output_sample_rate << std::endl + << " Do Passthrough is " << (d_pass_through ? "true" : "false") + << std::endl + << " Max Sample Count is " << d_buffer_sample_count << std::endl + << " # Device Channels is " << d_n_dev_channels << std::endl + << " Device Buffer Size in Frames = " << d_device_buffer_size_frames + << std::endl + << " Lead Size in Frames = " << d_lead_size_frames << std::endl + << " Trail Size in Frames = " << d_trail_size_frames << std::endl + << " Input Buffer Size in Frames = " << d_input_buffer_size_frames + << std::endl + << " Output Buffer Size in Frames = " << d_output_buffer_size_frames + << std::endl + << std::endl; #endif - } +} - void - osx_source::alloc_audio_buffer_list - (AudioBufferList** t_abl, - UInt32 n_channels, - UInt32 input_buffer_size_bytes) - { - free_audio_buffer_list(t_abl); - UInt32 prop_size = (offsetof(AudioBufferList, mBuffers[0]) + - (sizeof(AudioBuffer) * n_channels)); - *t_abl = (AudioBufferList*)calloc(1, prop_size); - (*t_abl)->mNumberBuffers = n_channels; +void osx_source::alloc_audio_buffer_list(AudioBufferList** t_abl, + UInt32 n_channels, + UInt32 input_buffer_size_bytes) +{ + free_audio_buffer_list(t_abl); + UInt32 prop_size = + (offsetof(AudioBufferList, mBuffers[0]) + (sizeof(AudioBuffer) * n_channels)); + *t_abl = (AudioBufferList*)calloc(1, prop_size); + (*t_abl)->mNumberBuffers = n_channels; - int counter = n_channels; + int counter = n_channels; #if _OSX_AU_DEBUG_ - std::cerr << "alloc_audio_buffer_list: (#chan, #bytes) == (" - << n_channels << ", " << input_buffer_size_bytes - << ")" << std::endl; + std::cerr << "alloc_audio_buffer_list: (#chan, #bytes) == (" << n_channels << ", " + << input_buffer_size_bytes << ")" << std::endl; #endif - while(--counter >= 0) { - AudioBuffer* t_ab = &((*t_abl)->mBuffers[counter]); - t_ab->mNumberChannels = 1; - t_ab->mDataByteSize = input_buffer_size_bytes; - t_ab->mData = calloc(1, input_buffer_size_bytes); - } + while (--counter >= 0) { + AudioBuffer* t_ab = &((*t_abl)->mBuffers[counter]); + t_ab->mNumberChannels = 1; + t_ab->mDataByteSize = input_buffer_size_bytes; + t_ab->mData = calloc(1, input_buffer_size_bytes); } +} - void - osx_source::free_audio_buffer_list(AudioBufferList** t_abl) - { - // free pre-allocated audio buffer, if it exists - if(*t_abl) { +void osx_source::free_audio_buffer_list(AudioBufferList** t_abl) +{ + // free pre-allocated audio buffer, if it exists + if (*t_abl) { int counter = (*t_abl)->mNumberBuffers; - while(--counter >= 0) { - AudioBuffer* t_ab = &((*t_abl)->mBuffers[counter]); - free(t_ab->mData); - t_ab->mData = 0; - } + while (--counter >= 0) { + AudioBuffer* t_ab = &((*t_abl)->mBuffers[counter]); + free(t_ab->mData); + t_ab->mData = 0; + } free(*t_abl); (*t_abl) = 0; - } } - - bool - osx_source::is_running() - { - UInt32 au_running = 0; - if (d_input_au) { - - UInt32 prop_size = (UInt32)sizeof(au_running); - OSStatus err = AudioUnitGetProperty - (d_input_au, - kAudioOutputUnitProperty_IsRunning, - kAudioUnitScope_Global, 0, - &au_running, &prop_size); - check_error_and_throw - (err, "AudioUnitGetProperty IsRunning", - "audio_osx_source::is_running"); - } - - return(au_running != 0); +} + +bool osx_source::is_running() +{ + UInt32 au_running = 0; + if (d_input_au) { + + UInt32 prop_size = (UInt32)sizeof(au_running); + OSStatus err = AudioUnitGetProperty(d_input_au, + kAudioOutputUnitProperty_IsRunning, + kAudioUnitScope_Global, + 0, + &au_running, + &prop_size); + check_error_and_throw( + err, "AudioUnitGetProperty IsRunning", "audio_osx_source::is_running"); } - bool - osx_source::start() - { + return (au_running != 0); +} + +bool osx_source::start() +{ #if _OSX_AU_DEBUG_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_source::start: Starting." << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_source::start: Starting." + << std::endl; #endif - if((!is_running ()) && d_input_au) { + if ((!is_running()) && d_input_au) { #if _OSX_AU_DEBUG_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_source::start: Starting Audio Unit." - << std::endl; + std::cerr << ((void*)(pthread_self())) + << " : audio_osx_source::start: Starting Audio Unit." << std::endl; #endif - // reset buffers before starting + // reset buffers before starting - for(UInt32 nn = 0; nn < d_buffers.size(); ++nn) { - d_buffers[nn]->reset(); - } + for (UInt32 nn = 0; nn < d_buffers.size(); ++nn) { + d_buffers[nn]->reset(); + } - // start the audio unit + // start the audio unit OSStatus err = AudioOutputUnitStart(d_input_au); - check_error_and_throw(err, "AudioOutputUnitStart", - "audio_osx_source::start"); + check_error_and_throw(err, "AudioOutputUnitStart", "audio_osx_source::start"); - // clear reset (will sometimes be necessary, and it has to - // happen after AudioOutputUnitStart) + // clear reset (will sometimes be necessary, and it has to + // happen after AudioOutputUnitStart) - d_do_reset = false; - - } + d_do_reset = false; + } #if _OSX_AU_DEBUG_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_source::start: Returning." << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_source::start: Returning." + << std::endl; #endif - return (true); - } + return (true); +} - bool - osx_source::stop() - { +bool osx_source::stop() +{ #if _OSX_AU_DEBUG_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_source::stop: Starting." << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_source::stop: Starting." + << std::endl; #endif - if(is_running ()) { + if (is_running()) { #if _OSX_AU_DEBUG_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_source::stop: stopping audio unit." - << std::endl; + std::cerr << ((void*)(pthread_self())) + << " : audio_osx_source::stop: stopping audio unit." << std::endl; #endif - // stop the audio unit + // stop the audio unit OSStatus err = AudioOutputUnitStop(d_input_au); - check_error_and_throw(err, "AudioOutputUnitStart", - "audio_osx_source::stop"); + check_error_and_throw(err, "AudioOutputUnitStart", "audio_osx_source::stop"); - // abort all buffers + // abort all buffers - for(UInt32 nn = 0; nn < d_n_user_channels; ++nn) { - d_buffers[nn]->abort (); + for (UInt32 nn = 0; nn < d_n_user_channels; ++nn) { + d_buffers[nn]->abort(); } - } + } #if _OSX_AU_DEBUG_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_source::stop: Returning." << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_source::stop: Returning." + << std::endl; #endif - return (true); - } + return (true); +} - void - osx_source::teardown() - { +void osx_source::teardown() +{ #if _OSX_AU_DEBUG_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_source::teardown: Starting." << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_source::teardown: Starting." + << std::endl; #endif - OSStatus err = noErr; + OSStatus err = noErr; - // stop the AudioUnit + // stop the AudioUnit - stop(); + stop(); - // remove the listeners + // remove the listeners #ifndef GR_USE_OLD_AUDIO_UNIT - // 10.4 and newer - { - AudioObjectPropertyAddress property = { - kAudioHardwarePropertyDevices, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster - }; - - err = AudioObjectRemovePropertyListener - (kAudioObjectSystemObject, &property, - reinterpret_cast<AudioObjectPropertyListenerProc> - (&osx_source::hardware_listener), - reinterpret_cast<void*>(this)); + // 10.4 and newer + { + AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster }; + + err = AudioObjectRemovePropertyListener( + kAudioObjectSystemObject, + &property, + reinterpret_cast<AudioObjectPropertyListenerProc>( + &osx_source::hardware_listener), + reinterpret_cast<void*>(this)); #if _OSX_AU_DEBUG_ - check_error(err, "teardown: AudioObjectRemovePropertyListener " - "hardware failed"); + check_error(err, + "teardown: AudioObjectRemovePropertyListener " + "hardware failed"); #endif + } - } - - if (d_using_default_device) { + if (d_using_default_device) { - AudioObjectPropertyAddress property = { - kAudioHardwarePropertyDefaultInputDevice, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster - }; + AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster }; - err = AudioObjectRemovePropertyListener - (kAudioObjectSystemObject, &property, - reinterpret_cast<AudioObjectPropertyListenerProc> - (&osx_source::default_listener), - reinterpret_cast<void*>(this)); + err = AudioObjectRemovePropertyListener( + kAudioObjectSystemObject, + &property, + reinterpret_cast<AudioObjectPropertyListenerProc>( + &osx_source::default_listener), + reinterpret_cast<void*>(this)); #if _OSX_AU_DEBUG_ - check_error(err, "AudioObjectRemovePropertyListener default"); + check_error(err, "AudioObjectRemovePropertyListener default"); #endif - d_using_default_device = false; - - } + d_using_default_device = false; + } #else - // 10.5 and older + // 10.5 and older - err = AudioHardwareRemovePropertyListener - (kAudioHardwarePropertyDevices, - reinterpret_cast<AudioHardwarePropertyListenerProc> - (&osx_source::hardware_listener)); + err = AudioHardwareRemovePropertyListener( + kAudioHardwarePropertyDevices, + reinterpret_cast<AudioHardwarePropertyListenerProc>( + &osx_source::hardware_listener)); #if _OSX_AU_DEBUG_ - check_error(err, "AudioObjectRemovePropertyListener hardware"); + check_error(err, "AudioObjectRemovePropertyListener hardware"); #endif - if (d_using_default_device) { - err = AudioHardwareRemovePropertyListener - (kAudioHardwarePropertyDefaultInputDevice, - reinterpret_cast<AudioHardwarePropertyListenerProc> - (&osx_source::default_listener)); + if (d_using_default_device) { + err = AudioHardwareRemovePropertyListener( + kAudioHardwarePropertyDefaultInputDevice, + reinterpret_cast<AudioHardwarePropertyListenerProc>( + &osx_source::default_listener)); #if _OSX_AU_DEBUG_ - check_error(err, "AudioObjectRemovePropertyListener default"); + check_error(err, "AudioObjectRemovePropertyListener default"); #endif - d_using_default_device = false; - - } + d_using_default_device = false; + } #endif // GR_USE_OLD_AUDIO_UNIT - // free pre-allocated audio buffers - free_audio_buffer_list(&d_input_buffer); + // free pre-allocated audio buffers + free_audio_buffer_list(&d_input_buffer); - if(!d_pass_through) { + if (!d_pass_through) { err = AudioConverterDispose(d_audio_converter); #if _OSX_AU_DEBUG_ check_error(err, "~audio_osx_source: AudioConverterDispose"); #endif free_audio_buffer_list(&d_output_buffer); - } + } - // remove the audio unit - err = AudioUnitUninitialize(d_input_au); + // remove the audio unit + err = AudioUnitUninitialize(d_input_au); #if _OSX_AU_DEBUG_ - check_error(err, "~audio_osx_source: AudioUnitUninitialize"); + check_error(err, "~audio_osx_source: AudioUnitUninitialize"); #endif #ifndef GR_USE_OLD_AUDIO_UNIT - err = AudioComponentInstanceDispose(d_input_au); + err = AudioComponentInstanceDispose(d_input_au); #if _OSX_AU_DEBUG_ - check_error(err, "~audio_osx_source: AudioComponentInstanceDispose"); + check_error(err, "~audio_osx_source: AudioComponentInstanceDispose"); #endif #else - err = CloseComponent(d_input_au); + err = CloseComponent(d_input_au); #if _OSX_AU_DEBUG_ - check_error(err, "~audio_osx_source: CloseComponent"); + check_error(err, "~audio_osx_source: CloseComponent"); #endif #endif - // empty and delete the queues + // empty and delete the queues - for(UInt32 nn = 0; nn < d_buffers.size(); ++nn) { + for (UInt32 nn = 0; nn < d_buffers.size(); ++nn) { delete d_buffers[nn]; d_buffers[nn] = 0; - } - d_buffers.resize(0); + } + d_buffers.resize(0); - // clear important variables; not # user channels + // clear important variables; not # user channels - d_queue_sample_count = 0; - d_device_sample_rate = 0; - d_n_dev_channels = 0; - d_input_ad_id = 0; - d_input_au = 0; - d_input_buffer = d_output_buffer = 0; - d_audio_converter = 0; - d_using_default_device = false; + d_queue_sample_count = 0; + d_device_sample_rate = 0; + d_n_dev_channels = 0; + d_input_ad_id = 0; + d_input_au = 0; + d_input_buffer = d_output_buffer = 0; + d_audio_converter = 0; + d_using_default_device = false; #if _OSX_AU_DEBUG_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_source::teardown: Returning." << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_source::teardown: Returning." + << std::endl; #endif +} + +bool osx_source::check_topology(int ninputs, int noutputs) +{ + // check # inputs to make sure it's valid + if (ninputs != 0) { + + GR_LOG_FATAL(d_logger, + boost::format("check_topology(): number of input " + "streams provided (%d) should be 0.") % + ninputs); + throw std::runtime_error("audio_osx_source::check_topology"); } - bool - osx_source::check_topology(int ninputs, int noutputs) - { - // check # inputs to make sure it's valid - if(ninputs != 0) { - - GR_LOG_FATAL(d_logger, boost::format - ("check_topology(): number of input " - "streams provided (%d) should be 0.") - % ninputs); - throw std::runtime_error - ("audio_osx_source::check_topology"); + // check # outputs to make sure it's valid + if ((noutputs < 1) | (noutputs > (int)d_n_dev_channels)) { - } - - // check # outputs to make sure it's valid - if((noutputs < 1) | (noutputs > (int) d_n_dev_channels)) { - - GR_LOG_FATAL(d_logger, boost::format - ("check_topology(): number of output " - "streams provided (%d) should be in [1,%d] " - "for the selected input audio device.") - % noutputs % d_n_dev_channels); - throw std::runtime_error - ("audio_osx_source::check_topology"); - } + GR_LOG_FATAL(d_logger, + boost::format("check_topology(): number of output " + "streams provided (%d) should be in [1,%d] " + "for the selected input audio device.") % + noutputs % d_n_dev_channels); + throw std::runtime_error("audio_osx_source::check_topology"); + } - // save the actual number of output (user) channels + // save the actual number of output (user) channels - d_n_user_channels = noutputs; + d_n_user_channels = noutputs; #if _OSX_AU_DEBUG_ - std::cerr << "chk_topo: Actual # user output channels = " - << noutputs << std::endl; + std::cerr << "chk_topo: Actual # user output channels = " << noutputs << std::endl; #endif - return(true); - } + return (true); +} - int - osx_source::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { +int osx_source::work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ #if _OSX_AU_DEBUG_RENDER_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_source::work: Starting." << std::endl; + std::cerr << ((void*)(pthread_self())) << " : audio_osx_source::work: Starting." + << std::endl; #endif - if (d_do_reset) { - if (d_hardware_changed) { - - // see if the current AudioDeviceID is still available + if (d_do_reset) { + if (d_hardware_changed) { - std::vector < AudioDeviceID > all_ad_ids; - osx::find_audio_devices - (d_desired_name, true, - &all_ad_ids, NULL); - bool found = false; - for (UInt32 nn = 0; (nn < all_ad_ids.size()) && (!found); - ++nn) { - found = (all_ad_ids[nn] == d_input_ad_id); - } - if (!found) { + // see if the current AudioDeviceID is still available - GR_LOG_FATAL(d_logger, boost::format - ("The selected input audio device ('%s') " - "is no longer available.\n") - % d_selected_name); - return(gr::block::WORK_DONE); + std::vector<AudioDeviceID> all_ad_ids; + osx::find_audio_devices(d_desired_name, true, &all_ad_ids, NULL); + bool found = false; + for (UInt32 nn = 0; (nn < all_ad_ids.size()) && (!found); ++nn) { + found = (all_ad_ids[nn] == d_input_ad_id); + } + if (!found) { - } + GR_LOG_FATAL(d_logger, + boost::format("The selected input audio device ('%s') " + "is no longer available.\n") % + d_selected_name); + return (gr::block::WORK_DONE); + } - d_do_reset = d_hardware_changed = false; + d_do_reset = d_hardware_changed = false; - } else { + } else { #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "audio_osx_source::work: doing reset." - << std::endl; + std::cerr << "audio_osx_source::work: doing reset." << std::endl; #endif - GR_LOG_WARN(d_logger, boost::format - ("\n\nThe default input audio device has " - "changed; resetting audio.\nThere may " - "be a sound glitch while resetting.\n")); + GR_LOG_WARN(d_logger, + boost::format("\n\nThe default input audio device has " + "changed; resetting audio.\nThere may " + "be a sound glitch while resetting.\n")); - // for any changes, just tear down the current - // configuration, then set it up again using the user's - // parameters to try to make selections. + // for any changes, just tear down the current + // configuration, then set it up again using the user's + // parameters to try to make selections. - teardown(); + teardown(); - gr::thread::scoped_lock l(d_internal); + gr::thread::scoped_lock l(d_internal); #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "audio_osx_source::work: mutex locked." - << std::endl; + std::cerr << "audio_osx_source::work: mutex locked." << std::endl; #endif - setup(); - start(); + setup(); + start(); #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "audio_osx_source::work: returning after reset." - << std::endl; + std::cerr << "audio_osx_source::work: returning after reset." << std::endl; #endif - return(0); - } - } + return (0); + } + } - gr::thread::scoped_lock l(d_internal); + gr::thread::scoped_lock l(d_internal); #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "audio_osx_source::work: mutex locked." << std::endl; + std::cerr << "audio_osx_source::work: mutex locked." << std::endl; #endif #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "work1: SC = " << d_queue_sample_count - << ", #OI = " << noutput_items - << ", #Chan = " << output_items.size() << std::endl; + std::cerr << "work1: SC = " << d_queue_sample_count << ", #OI = " << noutput_items + << ", #Chan = " << output_items.size() << std::endl; #endif - // set the actual # of output items to the 'desired' amount then - // verify that data is available; if not enough data is - // available, either wait until it is (is "ok_to_block" is - // true), return (0) is no data is available and "ok_to_block" - // is false, or process the actual amount of available data. - - UInt32 actual_noutput_items = noutput_items; - - if(d_queue_sample_count < actual_noutput_items) { - if(d_queue_sample_count == 0) { - // no data; ok_to_block decides what to do - if(d_ok_to_block == true) { - // block until there is data to return, or on reset - while(d_queue_sample_count == 0) { - // release control so-as to allow data to be retrieved; - // block until there is data to return + // set the actual # of output items to the 'desired' amount then + // verify that data is available; if not enough data is + // available, either wait until it is (is "ok_to_block" is + // true), return (0) is no data is available and "ok_to_block" + // is false, or process the actual amount of available data. + + UInt32 actual_noutput_items = noutput_items; + + if (d_queue_sample_count < actual_noutput_items) { + if (d_queue_sample_count == 0) { + // no data; ok_to_block decides what to do + if (d_ok_to_block == true) { + // block until there is data to return, or on reset + while (d_queue_sample_count == 0) { + // release control so-as to allow data to be retrieved; + // block until there is data to return #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "audio_osx_source::work: waiting." - << std::endl; + std::cerr << "audio_osx_source::work: waiting." << std::endl; #endif - d_waiting_for_data = true; - d_cond_data.wait(l); - d_waiting_for_data = false; + d_waiting_for_data = true; + d_cond_data.wait(l); + d_waiting_for_data = false; #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "audio_osx_source::work: done waiting." - << std::endl; + std::cerr << "audio_osx_source::work: done waiting." << std::endl; #endif - // the condition's 'notify' was called; acquire control to - // keep thread safe + // the condition's 'notify' was called; acquire control to + // keep thread safe - // if doing a reset, just return here; reset will pick - // up the next time this method is called. - if (d_do_reset) { + // if doing a reset, just return here; reset will pick + // up the next time this method is called. + if (d_do_reset) { #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "audio_osx_source::work: " - "returning for reset." << std::endl; + std::cerr << "audio_osx_source::work: " + "returning for reset." + << std::endl; #endif - return(0); - } - } - } - else { - // no data & not blocking; return nothing + return (0); + } + } + } else { + // no data & not blocking; return nothing #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "audio_osx_source::work: no data " - "& not blocking; returning 0." << std::endl; + std::cerr << "audio_osx_source::work: no data " + "& not blocking; returning 0." + << std::endl; #endif - return (0); - } + return (0); + } } // use the actual amount of available data actual_noutput_items = d_queue_sample_count; - } + } #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "audio_osx_source::work: copying " - << actual_noutput_items << " items per channel" - << std::endl; + std::cerr << "audio_osx_source::work: copying " << actual_noutput_items + << " items per channel" << std::endl; #endif - // number of channels - int l_counter = (int)output_items.size(); + // number of channels + int l_counter = (int)output_items.size(); - // copy the items from the circular buffer(s) to 'work's output - // buffers; verify that the number copied out is as expected. + // copy the items from the circular buffer(s) to 'work's output + // buffers; verify that the number copied out is as expected. - while(--l_counter >= 0) { + while (--l_counter >= 0) { size_t t_n_output_items = actual_noutput_items; - d_buffers[l_counter]->dequeue - ((float*)output_items[l_counter], - &t_n_output_items); + d_buffers[l_counter]->dequeue((float*)output_items[l_counter], &t_n_output_items); - if(t_n_output_items != actual_noutput_items) { - - GR_LOG_FATAL(d_logger, boost::format - ("work(): ERROR: number of available " - "items changing unexpectedly; expecting %d" - ", got %d.") - % actual_noutput_items % t_n_output_items); - throw std::runtime_error("audio_osx_source::work()"); + if (t_n_output_items != actual_noutput_items) { + GR_LOG_FATAL(d_logger, + boost::format("work(): ERROR: number of available " + "items changing unexpectedly; expecting %d" + ", got %d.") % + actual_noutput_items % t_n_output_items); + throw std::runtime_error("audio_osx_source::work()"); } - } + } - // subtract the actual number of items removed from the buffer(s) - // from the local accounting of the number of available samples + // subtract the actual number of items removed from the buffer(s) + // from the local accounting of the number of available samples - d_queue_sample_count -= actual_noutput_items; + d_queue_sample_count -= actual_noutput_items; #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "work2: SC = " << d_queue_sample_count - << ", act#OI = " << actual_noutput_items << std::endl - << "Returning." << std::endl; + std::cerr << "work2: SC = " << d_queue_sample_count + << ", act#OI = " << actual_noutput_items << std::endl + << "Returning." << std::endl; #endif #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "audio_osx_source::work: returning." << std::endl; + std::cerr << "audio_osx_source::work: returning." << std::endl; #endif - return (actual_noutput_items); - } - - OSStatus - osx_source::converter_callback - (AudioConverterRef in_audio_converter, - UInt32* io_number_data_packets, - AudioBufferList* io_data, - AudioStreamPacketDescription** out_aspd, - void* in_user_data) - { - // This callback is for us to provide the buffers to CoreAudio - // for conversion. We need to set the buffers in the provided - // buffer list (io_data) to the buffers we know about and use to - // do data input (d_input_buffers). - - osx_source* This = static_cast<osx_source*>(in_user_data); - AudioBufferList* l_input_abl = This->d_input_buffer; - UInt32 total_input_buffer_size_bytes = - ((*io_number_data_packets) * sizeof(float)); - int counter = This->d_n_dev_channels; - io_data->mNumberBuffers = This->d_n_dev_channels; - This->d_n_actual_input_frames = (*io_number_data_packets); + return (actual_noutput_items); +} + +OSStatus osx_source::converter_callback(AudioConverterRef in_audio_converter, + UInt32* io_number_data_packets, + AudioBufferList* io_data, + AudioStreamPacketDescription** out_aspd, + void* in_user_data) +{ + // This callback is for us to provide the buffers to CoreAudio + // for conversion. We need to set the buffers in the provided + // buffer list (io_data) to the buffers we know about and use to + // do data input (d_input_buffers). + + osx_source* This = static_cast<osx_source*>(in_user_data); + AudioBufferList* l_input_abl = This->d_input_buffer; + UInt32 total_input_buffer_size_bytes = ((*io_number_data_packets) * sizeof(float)); + int counter = This->d_n_dev_channels; + io_data->mNumberBuffers = This->d_n_dev_channels; + This->d_n_actual_input_frames = (*io_number_data_packets); #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "cc1: io#DP = " << (*io_number_data_packets) - << ", TIBSB = " << total_input_buffer_size_bytes - << ", #C = " << counter << std::endl; + std::cerr << "cc1: io#DP = " << (*io_number_data_packets) + << ", TIBSB = " << total_input_buffer_size_bytes << ", #C = " << counter + << std::endl; #endif - while(--counter >= 0) { + while (--counter >= 0) { AudioBuffer* t_ab = &(io_data->mBuffers[counter]); t_ab->mNumberChannels = 1; t_ab->mData = l_input_abl->mBuffers[counter].mData; t_ab->mDataByteSize = total_input_buffer_size_bytes; - } + } #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "cc2: Returning." << std::endl; + std::cerr << "cc2: Returning." << std::endl; #endif - return (noErr); - } + return (noErr); +} - OSStatus - osx_source::au_input_callback - (void *in_ref_con, - AudioUnitRenderActionFlags *io_action_flags, - const AudioTimeStamp *in_time_stamp, - UInt32 in_bus_number, - UInt32 in_number_frames, - AudioBufferList *io_data) - { +OSStatus osx_source::au_input_callback(void* in_ref_con, + AudioUnitRenderActionFlags* io_action_flags, + const AudioTimeStamp* in_time_stamp, + UInt32 in_bus_number, + UInt32 in_number_frames, + AudioBufferList* io_data) +{ #if _OSX_AU_DEBUG_RENDER_ - std::cerr << ((void*)(pthread_self())) - << " : audio_osx_source::au_input_callback: Starting." - << std::endl; + std::cerr << ((void*)(pthread_self())) + << " : audio_osx_source::au_input_callback: Starting." << std::endl; #endif - osx_source* This = reinterpret_cast - <osx_source*>(in_ref_con); - gr::thread::scoped_lock l(This->d_internal); - gr::logger_ptr d_logger = This->d_logger; + osx_source* This = reinterpret_cast<osx_source*>(in_ref_con); + gr::thread::scoped_lock l(This->d_internal); + gr::logger_ptr d_logger = This->d_logger; #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "audio_osx_source::au_input_callback: mutex locked." - << std::endl; + std::cerr << "audio_osx_source::au_input_callback: mutex locked." << std::endl; #endif - OSStatus err = noErr; + OSStatus err = noErr; #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "cb0: in#Fr = " << in_number_frames - << ", inBus# = " << in_bus_number - << ", idD = " << ((void*)io_data) - << ", d_ib = " << ((void*)(This->d_input_buffer)) - << ", d_ib#c = " << This->d_input_buffer->mNumberBuffers - << ", SC = " << This->d_queue_sample_count << std::endl; + std::cerr << "cb0: in#Fr = " << in_number_frames << ", inBus# = " << in_bus_number + << ", idD = " << ((void*)io_data) + << ", d_ib = " << ((void*)(This->d_input_buffer)) + << ", d_ib#c = " << This->d_input_buffer->mNumberBuffers + << ", SC = " << This->d_queue_sample_count << std::endl; #endif - if (This->d_do_reset) { - - // clear audio data; do not render since it will generate an error - - AudioBufferList* t_abl = This->d_input_buffer; - for (UInt32 nn = 0; nn < t_abl->mNumberBuffers; ++nn) { - AudioBuffer* t_ab = &(t_abl->mBuffers[nn]); - memset(t_ab->mData, 0, (size_t)((t_ab->mDataByteSize) * - (t_ab->mNumberChannels))); - } - } else { + if (This->d_do_reset) { - // Get the new audio data from the input device + // clear audio data; do not render since it will generate an error - err = AudioUnitRender - (This->d_input_au, io_action_flags, - in_time_stamp, 1, //inBusNumber, - in_number_frames, This->d_input_buffer); - check_error_and_throw - (err, "AudioUnitRender", - "audio_osx_source::au_input_callback"); - - } + AudioBufferList* t_abl = This->d_input_buffer; + for (UInt32 nn = 0; nn < t_abl->mNumberBuffers; ++nn) { + AudioBuffer* t_ab = &(t_abl->mBuffers[nn]); + memset(t_ab->mData, + 0, + (size_t)((t_ab->mDataByteSize) * (t_ab->mNumberChannels))); + } + } else { + + // Get the new audio data from the input device + + err = AudioUnitRender(This->d_input_au, + io_action_flags, + in_time_stamp, + 1, // inBusNumber, + in_number_frames, + This->d_input_buffer); + check_error_and_throw( + err, "AudioUnitRender", "audio_osx_source::au_input_callback"); + } - UInt32 available_input_frames = - This->d_n_available_input_frames = in_number_frames; + UInt32 available_input_frames = This->d_n_available_input_frames = in_number_frames; - // get the number of actual output frames, - // either via converting the buffer or not + // get the number of actual output frames, + // either via converting the buffer or not - UInt32 actual_output_frames = available_input_frames; + UInt32 actual_output_frames = available_input_frames; - if(!This->d_pass_through) { - UInt32 available_input_bytes = - available_input_frames * sizeof(float); + if (!This->d_pass_through) { + UInt32 available_input_bytes = available_input_frames * sizeof(float); UInt32 available_output_bytes = available_input_bytes; UInt32 prop_size = sizeof(available_output_bytes); - err = AudioConverterGetProperty - (This->d_audio_converter, - kAudioConverterPropertyCalculateOutputBufferSize, - &prop_size, - &available_output_bytes); - check_error_and_throw - (err, "Get Output Buffer Size failed", - "audio_osx_source::au_input_callback"); + err = AudioConverterGetProperty(This->d_audio_converter, + kAudioConverterPropertyCalculateOutputBufferSize, + &prop_size, + &available_output_bytes); + check_error_and_throw( + err, "Get Output Buffer Size failed", "audio_osx_source::au_input_callback"); - UInt32 available_output_frames = - available_output_bytes / sizeof(float); + UInt32 available_output_frames = available_output_bytes / sizeof(float); #if 0 // when decimating too much, the output sounds warbly due to @@ -1392,17 +1298,17 @@ namespace gr { // convert the data to the correct rate; on input, // actual_output_frames is the number of available output frames - err = AudioConverterFillComplexBuffer - (This->d_audio_converter, - reinterpret_cast<AudioConverterComplexInputDataProc> - (&(This->converter_callback)), - in_ref_con, - &actual_output_frames, - This->d_output_buffer, - NULL); - check_error_and_throw - (err, "AudioConverterFillComplexBuffer failed", - "audio_osx_source::au_input_callback"); + err = AudioConverterFillComplexBuffer( + This->d_audio_converter, + reinterpret_cast<AudioConverterComplexInputDataProc>( + &(This->converter_callback)), + in_ref_con, + &actual_output_frames, + This->d_output_buffer, + NULL); + check_error_and_throw(err, + "AudioConverterFillComplexBuffer failed", + "audio_osx_source::au_input_callback"); // on output, actual_output_frames is the actual number of // output frames @@ -1410,111 +1316,97 @@ namespace gr { #if _OSX_AU_DEBUG_RENDER_ std::cerr << "cb2: actual: #IF = " << This->d_n_actual_input_frames << ", #OF = " << actual_output_frames << std::endl; - if(This->d_n_actual_input_frames != available_input_frames) - std::cerr << "cb2.1: avail#IF = " << available_input_frames - << ", actual#IF = " << This->d_n_actual_input_frames << std::endl; + if (This->d_n_actual_input_frames != available_input_frames) + std::cerr << "cb2.1: avail#IF = " << available_input_frames + << ", actual#IF = " << This->d_n_actual_input_frames << std::endl; #endif - } + } - // add the output frames to the buffers' queue, checking for overflow + // add the output frames to the buffers' queue, checking for overflow - int counter = This->d_n_user_channels; - int res = 0; + int counter = This->d_n_user_channels; + int res = 0; - while(--counter >= 0) { - float* in_buffer = (float*) - This->d_output_buffer->mBuffers[counter].mData; + while (--counter >= 0) { + float* in_buffer = (float*)This->d_output_buffer->mBuffers[counter].mData; #if _OSX_AU_DEBUG_RENDER_ std::cerr << "cb3: enqueuing audio data." << std::endl; #endif - int l_res = This->d_buffers[counter]->enqueue - (in_buffer, actual_output_frames); - if(l_res == -1) - res = -1; - } + int l_res = This->d_buffers[counter]->enqueue(in_buffer, actual_output_frames); + if (l_res == -1) + res = -1; + } - if(res == -1) { + if (res == -1) { // data coming in too fast // drop oldest buffer fputs("aO", stderr); fflush(stderr); // set the local number of samples available to the max - This->d_queue_sample_count = - This->d_buffers[0]->buffer_length_items(); - } - else { + This->d_queue_sample_count = This->d_buffers[0]->buffer_length_items(); + } else { // keep up the local sample count This->d_queue_sample_count += actual_output_frames; - } + } #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "cb4: #OI = " << actual_output_frames - << ", #Cnt = " << This->d_queue_sample_count - << ", mSC = " << This->d_buffer_sample_count << std::endl; + std::cerr << "cb4: #OI = " << actual_output_frames + << ", #Cnt = " << This->d_queue_sample_count + << ", mSC = " << This->d_buffer_sample_count << std::endl; #endif - // signal that data is available, if appropriate + // signal that data is available, if appropriate - if (This->d_waiting_for_data) { - This->d_cond_data.notify_one(); - } + if (This->d_waiting_for_data) { + This->d_cond_data.notify_one(); + } #if _OSX_AU_DEBUG_RENDER_ - std::cerr << "cb5: returning." << std::endl; + std::cerr << "cb5: returning." << std::endl; #endif - return(err); - } + return (err); +} #ifndef GR_USE_OLD_AUDIO_UNIT - OSStatus - osx_source::hardware_listener - (AudioObjectID in_object_id, - UInt32 in_num_addresses, - const AudioObjectPropertyAddress in_addresses[], - void* in_client_data) +OSStatus osx_source::hardware_listener(AudioObjectID in_object_id, + UInt32 in_num_addresses, + const AudioObjectPropertyAddress in_addresses[], + void* in_client_data) #else - OSStatus - osx_source::hardware_listener - (AudioHardwarePropertyID in_property_id, - void* in_client_data) +OSStatus osx_source::hardware_listener(AudioHardwarePropertyID in_property_id, + void* in_client_data) #endif - { - osx_source* This = reinterpret_cast - <osx_source*>(in_client_data); - This->reset(true); - return(noErr); - } +{ + osx_source* This = reinterpret_cast<osx_source*>(in_client_data); + This->reset(true); + return (noErr); +} #ifndef GR_USE_OLD_AUDIO_UNIT - OSStatus - osx_source::default_listener - (AudioObjectID in_object_id, - UInt32 in_num_addresses, - const AudioObjectPropertyAddress in_addresses[], - void* in_client_data) +OSStatus osx_source::default_listener(AudioObjectID in_object_id, + UInt32 in_num_addresses, + const AudioObjectPropertyAddress in_addresses[], + void* in_client_data) #else - OSStatus - osx_source::default_listener - (AudioHardwarePropertyID in_property_id, - void* in_client_data) +OSStatus osx_source::default_listener(AudioHardwarePropertyID in_property_id, + void* in_client_data) #endif - { - osx_source* This = reinterpret_cast - <osx_source*>(in_client_data); - This->reset(false); - return(noErr); - } +{ + osx_source* This = reinterpret_cast<osx_source*>(in_client_data); + This->reset(false); + return (noErr); +} - } /* namespace audio */ +} /* namespace audio */ } /* namespace gr */ diff --git a/gr-audio/lib/osx/osx_source.h b/gr-audio/lib/osx/osx_source.h index 3c9147d26c..688ff3c32d 100644 --- a/gr-audio/lib/osx/osx_source.h +++ b/gr-audio/lib/osx/osx_source.h @@ -29,147 +29,132 @@ #include "circular_buffer.h" namespace gr { - namespace audio { - - /*! - * \brief audio source using OSX - * \ingroup audio_blk - * - * Input signature is one or two streams of floats. - * Samples must be in the range [-1,1]. - */ - class osx_source : public source - { - private: - - Float64 d_device_sample_rate, d_output_sample_rate; - UInt32 d_input_buffer_size_frames, d_input_buffer_size_bytes; - UInt32 d_output_buffer_size_frames, d_output_buffer_size_bytes; - UInt32 d_device_buffer_size_frames, d_device_buffer_size_bytes; - UInt32 d_lead_size_frames, d_lead_size_bytes; - UInt32 d_trail_size_frames, d_trail_size_bytes; - UInt32 d_extra_buffer_size_frames, d_extra_buffer_size_bytes; - UInt32 d_queue_sample_count, d_buffer_sample_count; - UInt32 d_n_available_input_frames, d_n_actual_input_frames; - UInt32 d_n_user_channels, d_n_dev_channels; - bool d_ok_to_block, d_pass_through; - bool d_waiting_for_data, d_do_reset, d_hardware_changed; - bool d_using_default_device; - gr::thread::mutex d_internal; - gr::thread::condition_variable d_cond_data; - std::vector < circular_buffer<float>* > d_buffers; - std::string d_desired_name, d_selected_name; +namespace audio { - // CoreAudio variables - - AudioDeviceID d_input_ad_id; - AudioUnit d_input_au; - AudioBufferList* d_input_buffer; - AudioBufferList* d_output_buffer; - AudioConverterRef d_audio_converter; +/*! + * \brief audio source using OSX + * \ingroup audio_blk + * + * Input signature is one or two streams of floats. + * Samples must be in the range [-1,1]. + */ +class osx_source : public source +{ +private: + Float64 d_device_sample_rate, d_output_sample_rate; + UInt32 d_input_buffer_size_frames, d_input_buffer_size_bytes; + UInt32 d_output_buffer_size_frames, d_output_buffer_size_bytes; + UInt32 d_device_buffer_size_frames, d_device_buffer_size_bytes; + UInt32 d_lead_size_frames, d_lead_size_bytes; + UInt32 d_trail_size_frames, d_trail_size_bytes; + UInt32 d_extra_buffer_size_frames, d_extra_buffer_size_bytes; + UInt32 d_queue_sample_count, d_buffer_sample_count; + UInt32 d_n_available_input_frames, d_n_actual_input_frames; + UInt32 d_n_user_channels, d_n_dev_channels; + bool d_ok_to_block, d_pass_through; + bool d_waiting_for_data, d_do_reset, d_hardware_changed; + bool d_using_default_device; + gr::thread::mutex d_internal; + gr::thread::condition_variable d_cond_data; + std::vector<circular_buffer<float>*> d_buffers; + std::string d_desired_name, d_selected_name; - // d_asbd_device: ASBD of the device that is creating the input - // data stream + // CoreAudio variables - AudioStreamBasicDescription d_asbd_device; + AudioDeviceID d_input_ad_id; + AudioUnit d_input_au; + AudioBufferList* d_input_buffer; + AudioBufferList* d_output_buffer; + AudioConverterRef d_audio_converter; - // d_asbd_client: ASBD of the client side (output) of the - // hardware device + // d_asbd_device: ASBD of the device that is creating the input + // data stream - AudioStreamBasicDescription d_asbd_client; + AudioStreamBasicDescription d_asbd_device; - // d_asbd_user: ASBD of the user's arguments, if an audio - // converter is needed outside that provided by the client side. + // d_asbd_client: ASBD of the client side (output) of the + // hardware device - AudioStreamBasicDescription d_asbd_user; + AudioStreamBasicDescription d_asbd_client; - public: + // d_asbd_user: ASBD of the user's arguments, if an audio + // converter is needed outside that provided by the client side. - osx_source(int sample_rate, - const std::string& device_name, - bool ok_to_block); + AudioStreamBasicDescription d_asbd_user; - virtual inline ~osx_source() { - teardown(); - } +public: + osx_source(int sample_rate, const std::string& device_name, bool ok_to_block); - virtual bool start(); - virtual bool stop(); + virtual inline ~osx_source() { teardown(); } - virtual bool check_topology(int ninputs, int noutputs); + virtual bool start(); + virtual bool stop(); - virtual int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + virtual bool check_topology(int ninputs, int noutputs); - inline void reset(bool hardware_changed) { - d_hardware_changed = hardware_changed; - d_do_reset = true; - } + virtual int work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); - private: + inline void reset(bool hardware_changed) + { + d_hardware_changed = hardware_changed; + d_do_reset = true; + } - bool is_running(); +private: + bool is_running(); - void setup(); + void setup(); - void teardown(); + void teardown(); - void alloc_audio_buffer_list - (AudioBufferList** t_abl, - UInt32 n_channels, - UInt32 input_buffer_size_bytes); + void alloc_audio_buffer_list(AudioBufferList** t_abl, + UInt32 n_channels, + UInt32 input_buffer_size_bytes); - void free_audio_buffer_list - (AudioBufferList** t_abl); + void free_audio_buffer_list(AudioBufferList** t_abl); - static OSStatus converter_callback - (AudioConverterRef in_audio_converter, - UInt32* io_number_data_packets, - AudioBufferList* io_data, - AudioStreamPacketDescription** out_aspd, - void* in_user_data); + static OSStatus converter_callback(AudioConverterRef in_audio_converter, + UInt32* io_number_data_packets, + AudioBufferList* io_data, + AudioStreamPacketDescription** out_aspd, + void* in_user_data); - static OSStatus au_input_callback - (void *in_ref_con, - AudioUnitRenderActionFlags *io_action_flags, - const AudioTimeStamp *in_time_stamp, - UInt32 in_bus_number, - UInt32 in_number_frames, - AudioBufferList *io_data); + static OSStatus au_input_callback(void* in_ref_con, + AudioUnitRenderActionFlags* io_action_flags, + const AudioTimeStamp* in_time_stamp, + UInt32 in_bus_number, + UInt32 in_number_frames, + AudioBufferList* io_data); #ifndef GR_USE_OLD_AUDIO_UNIT - // OSX 10.4 and newer + // OSX 10.4 and newer - static OSStatus hardware_listener - (AudioObjectID in_object_id, - UInt32 in_num_addresses, - const AudioObjectPropertyAddress in_addresses[], - void* in_client_data); + static OSStatus hardware_listener(AudioObjectID in_object_id, + UInt32 in_num_addresses, + const AudioObjectPropertyAddress in_addresses[], + void* in_client_data); - static OSStatus default_listener - (AudioObjectID in_object_id, - UInt32 in_num_addresses, - const AudioObjectPropertyAddress in_addresses[], - void* in_client_data); + static OSStatus default_listener(AudioObjectID in_object_id, + UInt32 in_num_addresses, + const AudioObjectPropertyAddress in_addresses[], + void* in_client_data); #else - // OSX 10.6 and older; removed as of 10.7 + // OSX 10.6 and older; removed as of 10.7 - static OSStatus hardware_listener - (AudioHardwarePropertyID in_property_id, - void* in_client_data); + static OSStatus hardware_listener(AudioHardwarePropertyID in_property_id, + void* in_client_data); - static OSStatus default_listener - (AudioHardwarePropertyID in_property_id, - void* in_client_data); + static OSStatus default_listener(AudioHardwarePropertyID in_property_id, + void* in_client_data); #endif - - }; - } /* namespace audio */ +}; +} /* namespace audio */ } /* namespace gr */ #endif /* INCLUDED_AUDIO_OSX_SOURCE_H */ |