diff --git a/libs/backends/coreaudio/coreaudio_backend.cc b/libs/backends/coreaudio/coreaudio_backend.cc index 0b2ca5ba66..0f1b637026 100644 --- a/libs/backends/coreaudio/coreaudio_backend.cc +++ b/libs/backends/coreaudio/coreaudio_backend.cc @@ -60,6 +60,12 @@ static void error_callback_ptr (void *arg) d->error_callback(); } +static void halted_callback_ptr (void *arg) +{ + CoreAudioBackend *d = static_cast (arg); + d->halted_callback(); +} + static void xrun_callback_ptr (void *arg) { CoreAudioBackend *d = static_cast (arg); @@ -544,6 +550,7 @@ CoreAudioBackend::_start (bool for_latency_measurement) _last_process_start = 0; _pcmio->set_error_callback (error_callback_ptr, this); + _pcmio->set_halted_callback (halted_callback_ptr, this); _pcmio->set_buffer_size_callback (buffer_size_callback_ptr, this); _pcmio->set_sample_rate_callback (sample_rate_callback_ptr, this); @@ -1521,16 +1528,31 @@ CoreAudioBackend::process_callback (const uint32_t n_samples, const uint64_t hos } void -CoreAudioBackend::error_callback () +CoreAudioBackend::unset_callbacks () { _pcmio->set_error_callback (NULL, NULL); + _pcmio->set_halted_callback (NULL, NULL); _pcmio->set_sample_rate_callback (NULL, NULL); _pcmio->set_xrun_callback (NULL, NULL); _midiio->set_port_changed_callback(NULL, NULL); +} + +void +CoreAudioBackend::error_callback () +{ + unset_callbacks (); engine.halted_callback("CoreAudio Process aborted."); _active_ca = false; } +void +CoreAudioBackend::halted_callback () +{ + unset_callbacks (); + engine.halted_callback("Audio device was disconnected or shut down."); + stop (); +} + void CoreAudioBackend::xrun_callback () { @@ -1558,10 +1580,7 @@ CoreAudioBackend::sample_rate_callback () #endif return; } - _pcmio->set_error_callback (NULL, NULL); - _pcmio->set_sample_rate_callback (NULL, NULL); - _pcmio->set_xrun_callback (NULL, NULL); - _midiio->set_port_changed_callback(NULL, NULL); + unset_callbacks (); engine.halted_callback("Sample Rate Changed."); stop(); } diff --git a/libs/backends/coreaudio/coreaudio_backend.h b/libs/backends/coreaudio/coreaudio_backend.h index a5060bb617..05cff39d6d 100644 --- a/libs/backends/coreaudio/coreaudio_backend.h +++ b/libs/backends/coreaudio/coreaudio_backend.h @@ -234,6 +234,7 @@ class CoreAudioBackend : public AudioBackend, public PortEngineSharedImpl { // really private, but needing static access: int process_callback(uint32_t, uint64_t); void error_callback(); + void halted_callback(); void xrun_callback(); void buffer_size_callback(); void sample_rate_callback(); @@ -371,6 +372,8 @@ class CoreAudioBackend : public AudioBackend, public PortEngineSharedImpl { enum DeviceFilter { All, Input, Output, Duplex }; uint32_t name_to_id(std::string, DeviceFilter filter = All) const; + void unset_callbacks (); + /* processing */ float _dsp_load; ARDOUR::DSPLoadCalculator _dsp_load_calc; diff --git a/libs/backends/coreaudio/coreaudio_pcmio.cc b/libs/backends/coreaudio/coreaudio_pcmio.cc index 1b2714dfd2..19c277d2cc 100644 --- a/libs/backends/coreaudio/coreaudio_pcmio.cc +++ b/libs/backends/coreaudio/coreaudio_pcmio.cc @@ -139,6 +139,9 @@ static OSStatus property_callback_ptr (AudioObjectID inObjectID, UInt32 inNumber case kAudioDevicePropertyNominalSampleRate: self->sample_rate_callback(); break; + case kAudioDevicePropertyDeviceIsAlive: + self->halted_callback(); + break; default: break; } @@ -222,6 +225,7 @@ CoreAudioPCM::CoreAudioPCM () , _n_devices (0) , _process_callback (0) , _error_callback (0) + , _halted_callback (0) , _hw_changed_callback (0) , _xrun_callback (0) , _buffer_size_callback (0) @@ -266,7 +270,6 @@ CoreAudioPCM::~CoreAudioPCM () pthread_mutex_destroy (&_discovery_lock); } - void CoreAudioPCM::hw_changed_callback() { #ifndef NDEBUG @@ -278,6 +281,15 @@ CoreAudioPCM::hw_changed_callback() { } } +void +CoreAudioPCM::halted_callback() { +#ifndef NDEBUG + printf("CoreAudio halted callback..\n"); +#endif + if (_halted_callback) { + _halted_callback(_halted_arg); + } +} int CoreAudioPCM::available_sample_rates(uint32_t device_id, std::vector& sampleRates) @@ -711,12 +723,15 @@ CoreAudioPCM::pcm_stop () AudioObjectRemovePropertyListener(_active_device_id, &prop, &property_callback_ptr, this); prop.mSelector = kAudioDevicePropertyNominalSampleRate; AudioObjectRemovePropertyListener(_active_device_id, &prop, &property_callback_ptr, this); + prop.mSelector = kAudioDevicePropertyDeviceIsAlive; + AudioObjectRemovePropertyListener(_active_device_id, &prop, &property_callback_ptr, this); } #else if (_active_device_id > 0) { AudioDeviceRemovePropertyListener(_active_device_id, 0, true, kAudioDeviceProcessorOverload, property_callback_ptr); AudioDeviceRemovePropertyListener(_active_device_id, 0, true, kAudioDevicePropertyBufferFrameSize, property_callback_ptr); AudioDeviceRemovePropertyListener(_active_device_id, 0, true, kAudioDevicePropertyNominalSampleRate, property_callback_ptr); + AudioDeviceRemovePropertyListener(_active_device_id, 0, true, kAudioDevicePropertyDeviceIsAlive, property_callback_ptr); } #endif } @@ -746,6 +761,7 @@ CoreAudioPCM::pcm_stop () _output_names.clear(); _error_callback = 0; + _halted_callback = 0; _process_callback = 0; _xrun_callback = 0; } @@ -973,6 +989,10 @@ CoreAudioPCM::pcm_start ( err = add_listener (_active_device_id, kAudioDevicePropertyNominalSampleRate, this); if (err != noErr) { errorMsg="kAudioDevicePropertyNominalSampleRate, Listen"; _state = -9; goto error; } + err = add_listener (_active_device_id, kAudioDevicePropertyDeviceIsAlive, this); + if (err != noErr) { errorMsg="kAudioDevicePropertyNominalSampleRate, Listen"; _state = -9; goto error; } + + _samples_per_period = current_buffer_size_id(_active_device_id); // Setup callback diff --git a/libs/backends/coreaudio/coreaudio_pcmio.h b/libs/backends/coreaudio/coreaudio_pcmio.h index 765b42ddc9..76aa260624 100644 --- a/libs/backends/coreaudio/coreaudio_pcmio.h +++ b/libs/backends/coreaudio/coreaudio_pcmio.h @@ -101,6 +101,14 @@ public: _error_arg = error_arg; } + void set_halted_callback ( + void ( halted_callback (void*)), + void * halted_arg + ) { + _halted_callback = halted_callback; + _halted_arg = halted_arg; + } + void set_hw_changed_callback ( void ( callback (void*)), void * arg @@ -148,6 +156,7 @@ public: void buffer_size_callback (); void sample_rate_callback (); void hw_changed_callback (); + void halted_callback (); private: float current_sample_rate_id (AudioDeviceID id, bool input); @@ -192,6 +201,9 @@ private: void (* _error_callback) (void*); void * _error_arg; + void (* _halted_callback) (void*); + void * _halted_arg; + void (* _hw_changed_callback) (void*); void * _hw_changed_arg;