diff options
| author | Bent Bisballe Nyeng <deva@aasimon.org> | 2017-10-29 10:33:50 +0100 | 
|---|---|---|
| committer | Bent Bisballe Nyeng <deva@aasimon.org> | 2019-04-12 19:22:46 +0200 | 
| commit | f190cd111e15222258435ae7a1560f7da8e3a576 (patch) | |
| tree | 71c838263c480a1deebce27336f5beba0676bddd | |
| parent | 03eaf1a9b3e0538a77a9fc07322d939e937a3bc9 (diff) | |
Add coreaudio helper functions for iterating devices and readibng their names and UIDs.
| -rw-r--r-- | drumgizmo/output/coreaudio.cc | 223 | ||||
| -rw-r--r-- | drumgizmo/output/coreaudio.h | 5 | 
2 files changed, 216 insertions, 12 deletions
| diff --git a/drumgizmo/output/coreaudio.cc b/drumgizmo/output/coreaudio.cc index 7cae44a..d54bdd1 100644 --- a/drumgizmo/output/coreaudio.cc +++ b/drumgizmo/output/coreaudio.cc @@ -26,12 +26,15 @@   */  #include "coreaudio.h" +#include <iostream> +  #include <hugin.hpp>  static const char* errorString(OSStatus err)  {  	const char* err_string = "unknown"; -	switch (err) { +	switch(err) +	{  	case kAudioHardwareNoError:  		err_string = "kAudioHardwareNoError";  		break; @@ -69,24 +72,52 @@ static const char* errorString(OSStatus err)  	return err_string;  } - -CoreAudioOutputEngine::CoreAudioOutputEngine() +static std::vector<AudioDeviceID> getDeviceList()  {  	OSStatus err; -	std::uint32_t size; +	Boolean is_writable; -	size = sizeof(AudioDeviceID); -	err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, -	                               &size, &device_id); +	// Get number of devices in device list +	UInt32 size; +	err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, +	                                   &size, &is_writable); +	if(err != noErr) +	{ +		ERR(coreaudio, "Error kAudioHardwarePropertyDevices: %s", +		    errorString(err)); +		return {}; +	} + +	if(size == 0) +	{ +		return {}; +	} + +	std::size_t number_of_devices = size / sizeof(AudioDeviceID); + +	// Allocate vector for devices. +	std::vector<AudioDeviceID> devices; +	devices.resize(number_of_devices); + +	err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, +	                               devices.data());  	if(err != noErr)  	{ -		ERR(coreaudio, "Error kAudioHardwarePropertyDefaultOutputDevice: %s", +		ERR(coreaudio, "Error kAudioHardwarePropertyDevices: %s",  		    errorString(err)); +		return {};  	} +	return devices; +} + +static std::string getDeviceName(AudioDeviceID device_id) +{ +	OSStatus err; +  	char device_name[256];  	memset(device_name, 0, sizeof(device_name)); -	size = sizeof(device_name) - 1; // leave space for terminating zero +	UInt32 size = sizeof(device_name) - 1; // leave space for terminating zero  	err = AudioDeviceGetProperty(device_id, 0, false,  	                             kAudioDevicePropertyDeviceName,  	                             &size, device_name); @@ -94,9 +125,49 @@ CoreAudioOutputEngine::CoreAudioOutputEngine()  	{  		ERR(coreaudio, "Error kAudioDevicePropertyDeviceName: %s",  		    errorString(err)); +		return ""; +	} + +	return std::string(device_name); +} + +static std::string getDeviceUID(AudioDeviceID device_id) +{ +	OSStatus err; +	CFStringRef ui_name = nullptr; +	UInt32 size = sizeof(CFStringRef); +	err = AudioDeviceGetProperty(device_id, 0, false, +	                             kAudioDevicePropertyDeviceUID, +	                             &size, &ui_name); +	if(err != noErr) +	{ +		ERR(coreaudio, "Error kAudioDevicePropertyDeviceUID: %s", +		    errorString(err)); + +		if(ui_name != nullptr) +		{ +			CFRelease(ui_name); +		} + +		return ""; +	} + +	char internal_name[256]; +	memset(internal_name, 0, sizeof(internal_name)); +	size = sizeof(internal_name) - 1; // leave space for terminating zero +	CFStringGetCString(ui_name, internal_name, size, +	                   CFStringGetSystemEncoding()); + +	if(ui_name != nullptr) +	{ +		CFRelease(ui_name);  	} -	DEBUG(coreaudio, "default device id: %d (%s)", device_id, device_name); +	return std::string(internal_name); +} + +CoreAudioOutputEngine::CoreAudioOutputEngine() +{  }  CoreAudioOutputEngine::~CoreAudioOutputEngine() @@ -105,12 +176,142 @@ CoreAudioOutputEngine::~CoreAudioOutputEngine()  bool CoreAudioOutputEngine::init(const Channels& channels)  { +	OSStatus err; +	std::uint32_t size; + +	if(uid == "list") +	{ +		// Dump device list +		auto device_list = getDeviceList(); +		std::cout  << "[CoreAudioOutputEngine] Device list (" << +			device_list.size() << " devices):\n"; +		for(auto device_id : device_list) +		{ +			auto device_name = getDeviceName(device_id); +			auto device_uid = getDeviceUID(device_id); +			std::cout  << "[CoreAudioOutputEngine] - Device: '" << device_name << +				"' (uid: '" << device_uid  << "')\n"; +		} + +		// Do not proceed +		return false; +	} + +	if(uid != "") +	{ +		// Get device id from UID +		size = sizeof(AudioValueTranslation); +		CFStringRef in_uid = +			CFStringCreateWithCString(nullptr, uid.data(), +			                          CFStringGetSystemEncoding()); +		AudioValueTranslation value = +			{ +				&in_uid, sizeof(CFStringRef), &device_id, sizeof(AudioDeviceID) +			}; + +		err = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, +		                               &size, &value); +		CFRelease(in_uid); + +		if(err != noErr) +		{ +			ERR(coreaudio, "Error kAudioHardwarePropertyDeviceForUID: %s", +			    errorString(err)); +		} + +		DEBUG(coreaudio, "get_device_id_from_uid '%s' %d", +		      uid.data(), device_id); +	} +	else +	{ +		// Use default device id +		size = sizeof(AudioDeviceID); +		err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, +	                               &size, &device_id); +		if(err != noErr) +		{ +			ERR(coreaudio, "Error kAudioHardwarePropertyDefaultOutputDevice: %s", +			    errorString(err)); +		} +	} + +	auto device_name = getDeviceName(device_id); + +	DEBUG(coreaudio, "default device id: %d (%s)", +	      device_id, device_name.data()); + +	// TODO: Setting buffer size +	//outSize = sizeof(UInt32); +	//err = AudioDeviceSetProperty (driver->device_id, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &nframes); +	//if (err != noErr) { +	//	jack_error ("Cannot set buffer size %ld", nframes); +	//	printError (err); +	//	goto error; +	//} + +	// https://github.com/jackaudio/jack1/blob/master/drivers/coreaudio/coreaudio_driver.c#L796 +	// TODO: Set samplerate +	//// Get sample rate +	//outSize =  sizeof(Float64); +	//err = AudioDeviceGetProperty (driver->device_id, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate); +	//if (err != noErr) { +	//	jack_error ("Cannot get current sample rate"); +	//	printError (err); +	//	goto error; +	//} +	// +	// Then; if samplerate doesn't match - set it. +	//err = AudioDeviceSetProperty (driver->device_id, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate); +	//if (err != noErr) { +	//	jack_error ("Cannot set sample rate = %ld", samplerate); +	//	printError (err); +	//	return -1; +	//} + + +  	return true;  }  void CoreAudioOutputEngine::setParm(const std::string& parm,                                      const std::string& value)  { +	if(parm == "uid") +	{ +		// Use the device pointed to by this UID. +		uid = value; +	} +	else if(parm == "frames") +	{ +		// try to apply hardware buffer size +		try +		{ +			frames = std::stoi(value); +		} +		catch(...) +		{ +			std::cerr << "[CoreAudioOutputEngine] Invalid buffer size " << value +			          << "\n"; +		} +	} +	else if(parm == "srate") +	{ +		try +		{ +			samplerate = std::stoi(value); +		} +		catch(...) +		{ +			std::cerr << "[CoreAudioOutputEngine] Invalid samplerate " << value +			          << "\n"; +		} +	} +	else +	{ +		std::cerr << "[CoreAudioOutputEngine] Unsupported parameter '" << parm +		          << "'\n"; +	} +  }  bool CoreAudioOutputEngine::start() @@ -138,7 +339,7 @@ void CoreAudioOutputEngine::post(size_t nsamples)  size_t CoreAudioOutputEngine::getSamplerate() const  { -	return 0; +	return samplerate;  }  bool CoreAudioOutputEngine::isFreewheeling() const diff --git a/drumgizmo/output/coreaudio.h b/drumgizmo/output/coreaudio.h index 44df0a0..3e3b728 100644 --- a/drumgizmo/output/coreaudio.h +++ b/drumgizmo/output/coreaudio.h @@ -51,5 +51,8 @@ public:  	bool isFreewheeling() const override;  private: -	AudioDeviceID device_id; +	AudioDeviceID device_id{kAudioDeviceUnknown}; +	std::string uid; +	std::uint32_t frames{1024u}; +	std::uint32_t samplerate{44100u};  }; | 
