@@ -207,7 +207,7 @@ $(rtmidi): | rtmidi-4.0.0 | |||||
$(MAKE) -C rtmidi-4.0.0 | $(MAKE) -C rtmidi-4.0.0 | ||||
$(MAKE) -C rtmidi-4.0.0 install | $(MAKE) -C rtmidi-4.0.0 install | ||||
RTAUDIO_FLAGS += -DRTAUDIO_BUILD_STATIC_LIBS=ON | |||||
RTAUDIO_FLAGS += -DRTAUDIO_BUILD_STATIC_LIBS=ON -DRTAUDIO_BUILD_TESTING=OFF | |||||
ifdef ARCH_LIN | ifdef ARCH_LIN | ||||
RTAUDIO_FLAGS += -DRTAUDIO_API_ALSA=ON -DRTAUDIO_API_JACK=ON -DRTAUDIO_API_PULSE=OFF -DRTAUDIO_API_OSS=OFF | RTAUDIO_FLAGS += -DRTAUDIO_API_ALSA=ON -DRTAUDIO_API_JACK=ON -DRTAUDIO_API_PULSE=OFF -DRTAUDIO_API_OSS=OFF | ||||
endif | endif | ||||
@@ -1 +1 @@ | |||||
Subproject commit 07b1c6228fec77a207afd5d5cccc36681e90d319 | |||||
Subproject commit e9915064859381a7a616b088dadbaee81bc0e0df |
@@ -22,30 +22,45 @@ namespace audio { | |||||
struct Device; | struct Device; | ||||
struct Port; | struct Port; | ||||
/** An audio driver API containing any number of audio devices. | |||||
*/ | |||||
struct Driver { | struct Driver { | ||||
virtual ~Driver() {} | virtual ~Driver() {} | ||||
/** Returns the name of the driver. E.g. "ALSA". */ | |||||
virtual std::string getName() { | virtual std::string getName() { | ||||
return ""; | return ""; | ||||
} | } | ||||
/** Returns a list of all device IDs that can be subscribed to. */ | |||||
virtual std::vector<int> getDeviceIds() { | virtual std::vector<int> getDeviceIds() { | ||||
return {}; | return {}; | ||||
} | } | ||||
/** Gets the name of a device without subscribing to it. */ | |||||
/** Returns the name of a device without obtaining it. */ | |||||
virtual std::string getDeviceName(int deviceId) { | virtual std::string getDeviceName(int deviceId) { | ||||
return ""; | return ""; | ||||
} | } | ||||
/** Returns the number of inputs of a device without obtaining it. */ | |||||
virtual int getDeviceNumInputs(int deviceId) { | virtual int getDeviceNumInputs(int deviceId) { | ||||
return 0; | return 0; | ||||
} | } | ||||
/** Returns the number of output of a device without obtaining it. */ | |||||
virtual int getDeviceNumOutputs(int deviceId) { | virtual int getDeviceNumOutputs(int deviceId) { | ||||
return 0; | return 0; | ||||
} | } | ||||
/** Returns a detailed description of the device without obtaining it. | |||||
`offset` specifies the first channel (zero-indexed). | |||||
E.g. "MySoundcard (1-2 in, 1-2 out)" | |||||
*/ | |||||
std::string getDeviceDetail(int deviceId, int offset, int maxChannels); | std::string getDeviceDetail(int deviceId, int offset, int maxChannels); | ||||
/** Adds the given port as a reference holder of a device and returns the it. | |||||
Creates the Device if no ports are subscribed before calling. | |||||
*/ | |||||
virtual Device* subscribe(int deviceId, Port* port) { | virtual Device* subscribe(int deviceId, Port* port) { | ||||
return NULL; | return NULL; | ||||
} | } | ||||
/** Removes the give port as a reference holder of a device. | |||||
Deletes the Device if no ports are subscribed after calling. | |||||
*/ | |||||
virtual void unsubscribe(int deviceId, Port* port) {} | virtual void unsubscribe(int deviceId, Port* port) {} | ||||
}; | }; | ||||
@@ -53,6 +68,12 @@ struct Driver { | |||||
// Device | // Device | ||||
//////////////////// | //////////////////// | ||||
/** A single audio device of a driver API. | |||||
Modules should | |||||
Methods throw `rack::Exception` if the driver API has an exception. | |||||
*/ | |||||
struct Device { | struct Device { | ||||
std::set<Port*> subscribed; | std::set<Port*> subscribed; | ||||
virtual ~Device() {} | virtual ~Device() {} | ||||
@@ -69,22 +90,36 @@ struct Device { | |||||
virtual int getNumOutputs() { | virtual int getNumOutputs() { | ||||
return 0; | return 0; | ||||
} | } | ||||
/** Returns a detailed description of the device. | |||||
`offset` specifies the first channel (zero-indexed). | |||||
E.g. "MySoundcard (1-2 in, 1-2 out)" | |||||
*/ | |||||
std::string getDetail(int offset, int maxChannels); | std::string getDetail(int offset, int maxChannels); | ||||
/** Returns a list of all valid (user-selectable) sample rates. | |||||
The device may accept sample rates not in this list, but it *must* accept sample rates in the list. | |||||
*/ | |||||
virtual std::vector<int> getSampleRates() { | virtual std::vector<int> getSampleRates() { | ||||
return {}; | return {}; | ||||
} | } | ||||
/** Returns the current sample rate. */ | |||||
virtual int getSampleRate() { | virtual int getSampleRate() { | ||||
return 0; | return 0; | ||||
} | } | ||||
/** Sets the sample rate of the device, re-opening it if needed. */ | |||||
virtual void setSampleRate(int sampleRate) {} | virtual void setSampleRate(int sampleRate) {} | ||||
/** Returns a list of all valid (user-selectable) block sizes. | |||||
The device may accept block sizes not in this list, but it *must* accept block sizes in the list. | |||||
*/ | |||||
virtual std::vector<int> getBlockSizes() { | virtual std::vector<int> getBlockSizes() { | ||||
return {}; | return {}; | ||||
} | } | ||||
/** Returns the current block size. */ | |||||
virtual int getBlockSize() { | virtual int getBlockSize() { | ||||
return 0; | return 0; | ||||
} | } | ||||
/** Sets the block size of the device, re-opening it if needed. */ | |||||
virtual void setBlockSize(int blockSize) {} | virtual void setBlockSize(int blockSize) {} | ||||
// Called by this Device class, forwards to subscribed Ports. | // Called by this Device class, forwards to subscribed Ports. | ||||
@@ -97,6 +132,11 @@ struct Device { | |||||
// Port | // Port | ||||
//////////////////// | //////////////////// | ||||
/** A handle to a Device, typically owned by modules to have shared access to a single Device. | |||||
All Port methods safely wrap Drivers methods. | |||||
That is, if the active Device thrown a `rack::Exception`, it is caught and logged inside all Port methods, so you can consider them nothrow. | |||||
*/ | |||||
struct Port { | struct Port { | ||||
/** The first channel index of the device to process. */ | /** The first channel index of the device to process. */ | ||||
int offset = 0; | int offset = 0; | ||||
@@ -115,51 +155,27 @@ struct Port { | |||||
virtual ~Port(); | virtual ~Port(); | ||||
void reset(); | void reset(); | ||||
Driver* getDriver() { | |||||
return driver; | |||||
} | |||||
int getDriverId() { | |||||
return driverId; | |||||
} | |||||
Driver* getDriver(); | |||||
int getDriverId(); | |||||
void setDriverId(int driverId); | void setDriverId(int driverId); | ||||
std::string getDriverName(); | |||||
Device* getDevice() { | |||||
return device; | |||||
} | |||||
int getDeviceId() { | |||||
return deviceId; | |||||
} | |||||
Device* getDevice(); | |||||
std::vector<int> getDeviceIds(); | |||||
int getDeviceId(); | |||||
void setDeviceId(int deviceId); | void setDeviceId(int deviceId); | ||||
std::vector<int> getSampleRates() { | |||||
if (!device) | |||||
return {}; | |||||
return device->getSampleRates(); | |||||
} | |||||
int getSampleRate() { | |||||
if (!device) | |||||
return 0; | |||||
return device->getSampleRate(); | |||||
} | |||||
void setSampleRate(int sampleRate) { | |||||
if (device) | |||||
device->setSampleRate(sampleRate); | |||||
} | |||||
std::vector<int> getBlockSizes() { | |||||
if (!device) | |||||
return {}; | |||||
return device->getBlockSizes(); | |||||
} | |||||
int getBlockSize() { | |||||
if (!device) | |||||
return 0; | |||||
return device->getBlockSize(); | |||||
} | |||||
void setBlockSize(int blockSize) { | |||||
if (device) | |||||
device->setBlockSize(blockSize); | |||||
} | |||||
int getDeviceNumInputs(int deviceId); | |||||
int getDeviceNumOutputs(int deviceId); | |||||
std::string getDeviceName(int deviceId); | |||||
std::string getDeviceDetail(int deviceId, int offset); | |||||
std::vector<int> getSampleRates(); | |||||
int getSampleRate(); | |||||
void setSampleRate(int sampleRate); | |||||
std::vector<int> getBlockSizes(); | |||||
int getBlockSize(); | |||||
void setBlockSize(int blockSize); | |||||
int getNumInputs(); | int getNumInputs(); | ||||
int getNumOutputs(); | int getNumOutputs(); | ||||
@@ -88,20 +88,31 @@ struct Output; | |||||
struct Driver { | struct Driver { | ||||
virtual ~Driver() {} | virtual ~Driver() {} | ||||
/** Returns the name of the driver. E.g. "ALSA". */ | |||||
virtual std::string getName() { | virtual std::string getName() { | ||||
return ""; | return ""; | ||||
} | } | ||||
/** Returns a list of all input device IDs that can be subscribed to. */ | |||||
virtual std::vector<int> getInputDeviceIds() { | virtual std::vector<int> getInputDeviceIds() { | ||||
return {}; | return {}; | ||||
} | } | ||||
/** Returns the name of an input device without obtaining it. */ | |||||
virtual std::string getInputDeviceName(int deviceId) { | virtual std::string getInputDeviceName(int deviceId) { | ||||
return ""; | return ""; | ||||
} | } | ||||
/** Adds the given port as a reference holder of a device and returns the it. | |||||
Creates the Device if no ports are subscribed before calling. | |||||
*/ | |||||
virtual InputDevice* subscribeInput(int deviceId, Input* input) { | virtual InputDevice* subscribeInput(int deviceId, Input* input) { | ||||
return NULL; | return NULL; | ||||
} | } | ||||
/** Removes the give port as a reference holder of a device. | |||||
Deletes the Device if no ports are subscribed after calling. | |||||
*/ | |||||
virtual void unsubscribeInput(int deviceId, Input* input) {} | virtual void unsubscribeInput(int deviceId, Input* input) {} | ||||
// The following behave identically as the above methods except for outputs. | |||||
virtual std::vector<int> getOutputDeviceIds() { | virtual std::vector<int> getOutputDeviceIds() { | ||||
return {}; | return {}; | ||||
} | } | ||||
@@ -127,15 +138,21 @@ struct Device { | |||||
struct InputDevice : Device { | struct InputDevice : Device { | ||||
std::set<Input*> subscribed; | std::set<Input*> subscribed; | ||||
/** Not public. Use Driver::subscribeInput(). */ | |||||
void subscribe(Input* input); | void subscribe(Input* input); | ||||
/** Not public. Use Driver::unsubscribeInput(). */ | |||||
void unsubscribe(Input* input); | void unsubscribe(Input* input); | ||||
/** Called when a MIDI message is received from the device. */ | |||||
void onMessage(const Message &message); | void onMessage(const Message &message); | ||||
}; | }; | ||||
struct OutputDevice : Device { | struct OutputDevice : Device { | ||||
std::set<Output*> subscribed; | std::set<Output*> subscribed; | ||||
void subscribe(Output* input); | |||||
void unsubscribe(Output* input); | |||||
/** Not public. Use Driver::subscribeOutput(). */ | |||||
void subscribe(Output* output); | |||||
/** Not public. Use Driver::unsubscribeOutput(). */ | |||||
void unsubscribe(Output* output); | |||||
/** Sends a MIDI message to the device. */ | |||||
virtual void sendMessage(const Message &message) {} | virtual void sendMessage(const Message &message) {} | ||||
}; | }; | ||||
@@ -40,7 +40,8 @@ struct AudioDriverChoice : LedDisplayChoice { | |||||
text = ""; | text = ""; | ||||
if (box.size.x >= 200.0) | if (box.size.x >= 200.0) | ||||
text += "Driver: "; | text += "Driver: "; | ||||
std::string driverName = (port && port->driver) ? port->getDriver()->getName() : ""; | |||||
audio::Driver* driver = port ? port->getDriver() : NULL; | |||||
std::string driverName = driver ? driver->getName() : ""; | |||||
if (driverName != "") { | if (driverName != "") { | ||||
text += driverName; | text += driverName; | ||||
color.a = 1.0; | color.a = 1.0; | ||||
@@ -73,7 +74,7 @@ struct AudioDeviceValueItem : ui::MenuItem { | |||||
}; | }; | ||||
static void appendAudioDeviceMenu(ui::Menu* menu, audio::Port* port) { | static void appendAudioDeviceMenu(ui::Menu* menu, audio::Port* port) { | ||||
if (!port || !port->driver) | |||||
if (!port) | |||||
return; | return; | ||||
{ | { | ||||
@@ -85,8 +86,8 @@ static void appendAudioDeviceMenu(ui::Menu* menu, audio::Port* port) { | |||||
menu->addChild(item); | menu->addChild(item); | ||||
} | } | ||||
for (int deviceId : port->driver->getDeviceIds()) { | |||||
int channels = std::max(port->driver->getDeviceNumInputs(deviceId), port->driver->getDeviceNumOutputs(deviceId)); | |||||
for (int deviceId : port->getDeviceIds()) { | |||||
int channels = std::max(port->getDeviceNumInputs(deviceId), port->getDeviceNumOutputs(deviceId)); | |||||
// Prevents devices with a ridiculous number of channels from being displayed | // Prevents devices with a ridiculous number of channels from being displayed | ||||
const int maxTotalChannels = port->maxChannels * 16; | const int maxTotalChannels = port->maxChannels * 16; | ||||
channels = std::min(maxTotalChannels, channels); | channels = std::min(maxTotalChannels, channels); | ||||
@@ -96,7 +97,7 @@ static void appendAudioDeviceMenu(ui::Menu* menu, audio::Port* port) { | |||||
item->port = port; | item->port = port; | ||||
item->deviceId = deviceId; | item->deviceId = deviceId; | ||||
item->offset = offset; | item->offset = offset; | ||||
item->text = port->driver->getDeviceDetail(deviceId, offset, port->maxChannels); | |||||
item->text = port->getDeviceDetail(deviceId, offset); | |||||
item->rightText = CHECKMARK(item->deviceId == port->getDeviceId() && item->offset == port->offset); | item->rightText = CHECKMARK(item->deviceId == port->getDeviceId() && item->offset == port->offset); | ||||
menu->addChild(item); | menu->addChild(item); | ||||
} | } | ||||
@@ -96,11 +96,27 @@ Port::~Port() { | |||||
} | } | ||||
void Port::reset() { | void Port::reset() { | ||||
setDriverId(-1); | |||||
// Get default driver | |||||
int firstDriverId = -1; | |||||
std::vector<int> driverIds = getDriverIds(); | |||||
if (!driverIds.empty()) | |||||
firstDriverId = driverIds[0]; | |||||
setDriverId(firstDriverId); | |||||
offset = 0; | offset = 0; | ||||
} | } | ||||
Driver* Port::getDriver() { | |||||
return driver; | |||||
} | |||||
int Port::getDriverId() { | |||||
return driverId; | |||||
} | |||||
void Port::setDriverId(int driverId) { | void Port::setDriverId(int driverId) { | ||||
if (driverId == this->driverId) | |||||
return; | |||||
// Unset device and driver | // Unset device and driver | ||||
setDeviceId(-1); | setDeviceId(-1); | ||||
driver = NULL; | driver = NULL; | ||||
@@ -118,31 +134,206 @@ void Port::setDriverId(int driverId) { | |||||
} | } | ||||
} | } | ||||
std::string Port::getDriverName() { | |||||
if (!driver) | |||||
return ""; | |||||
try { | |||||
return driver->getName(); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("Audio port could not get driver name: %s", e.what()); | |||||
return ""; | |||||
} | |||||
} | |||||
Device* Port::getDevice() { | |||||
return device; | |||||
} | |||||
std::vector<int> Port::getDeviceIds() { | |||||
if (!driver) | |||||
return {}; | |||||
try { | |||||
return driver->getDeviceIds(); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("Audio port could not get device IDs: %s", e.what()); | |||||
return {}; | |||||
} | |||||
} | |||||
int Port::getDeviceId() { | |||||
return deviceId; | |||||
} | |||||
void Port::setDeviceId(int deviceId) { | void Port::setDeviceId(int deviceId) { | ||||
if (deviceId == this->deviceId) | |||||
return; | |||||
// Destroy device | // Destroy device | ||||
if (driver && this->deviceId >= 0) { | if (driver && this->deviceId >= 0) { | ||||
driver->unsubscribe(this->deviceId, this); | |||||
try { | |||||
driver->unsubscribe(this->deviceId, this); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("Audio port could not unsubscribe from device: %s", e.what()); | |||||
} | |||||
} | } | ||||
device = NULL; | device = NULL; | ||||
this->deviceId = -1; | this->deviceId = -1; | ||||
// Create device | // Create device | ||||
if (driver && deviceId >= 0) { | if (driver && deviceId >= 0) { | ||||
device = driver->subscribe(deviceId, this); | |||||
this->deviceId = deviceId; | |||||
try { | |||||
device = driver->subscribe(deviceId, this); | |||||
this->deviceId = deviceId; | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("Audio port could not subscribe to device: %s", e.what()); | |||||
} | |||||
} | |||||
} | |||||
int Port::getDeviceNumInputs(int deviceId) { | |||||
if (!driver) | |||||
return 0; | |||||
try { | |||||
return driver->getDeviceNumInputs(deviceId); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("Audio port could not get device number of inputs: %s", e.what()); | |||||
return 0; | |||||
} | |||||
} | |||||
int Port::getDeviceNumOutputs(int deviceId) { | |||||
if (!driver) | |||||
return 0; | |||||
try { | |||||
return driver->getDeviceNumOutputs(deviceId); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("Audio port could not get device number of outputs: %s", e.what()); | |||||
return 0; | |||||
} | |||||
} | |||||
std::string Port::getDeviceName(int deviceId) { | |||||
if (!driver) | |||||
return ""; | |||||
try { | |||||
return driver->getDeviceName(deviceId); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("Audio port could not get device name: %s", e.what()); | |||||
return 0; | |||||
} | |||||
} | |||||
std::string Port::getDeviceDetail(int deviceId, int offset) { | |||||
if (!driver) | |||||
return ""; | |||||
try { | |||||
// Use maxChannels from Port. | |||||
return driver->getDeviceDetail(deviceId, offset, maxChannels); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("Audio port could not get device detail: %s", e.what()); | |||||
return 0; | |||||
} | |||||
} | |||||
std::vector<int> Port::getSampleRates() { | |||||
if (!device) | |||||
return {}; | |||||
try { | |||||
return device->getSampleRates(); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("Audio port could not get device sample rates: %s", e.what()); | |||||
return {}; | |||||
} | |||||
} | |||||
int Port::getSampleRate() { | |||||
if (!device) | |||||
return 0; | |||||
try { | |||||
return device->getSampleRate(); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("Audio port could not get device sample rate: %s", e.what()); | |||||
return 0; | |||||
} | |||||
} | |||||
void Port::setSampleRate(int sampleRate) { | |||||
if (!device) | |||||
return; | |||||
try { | |||||
device->setSampleRate(sampleRate); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("Audio port could not set device sample rate: %s", e.what()); | |||||
} | |||||
} | |||||
std::vector<int> Port::getBlockSizes() { | |||||
if (!device) | |||||
return {}; | |||||
try { | |||||
return device->getBlockSizes(); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("Audio port could not get device block sizes: %s", e.what()); | |||||
return {}; | |||||
} | |||||
} | |||||
int Port::getBlockSize() { | |||||
if (!device) | |||||
return 0; | |||||
try { | |||||
return device->getBlockSize(); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("Audio port could not get device block size: %s", e.what()); | |||||
return 0; | |||||
} | |||||
} | |||||
void Port::setBlockSize(int blockSize) { | |||||
if (!device) | |||||
return; | |||||
try { | |||||
device->setBlockSize(blockSize); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("Audio port could not set device block size: %s", e.what()); | |||||
} | } | ||||
} | } | ||||
int Port::getNumInputs() { | int Port::getNumInputs() { | ||||
if (!device) | if (!device) | ||||
return 0; | return 0; | ||||
return std::min(device->getNumInputs() - offset, maxChannels); | |||||
try { | |||||
return std::min(device->getNumInputs() - offset, maxChannels); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("Audio port could not get device number of inputs: %s", e.what()); | |||||
return 0; | |||||
} | |||||
} | } | ||||
int Port::getNumOutputs() { | int Port::getNumOutputs() { | ||||
if (!device) | if (!device) | ||||
return 0; | return 0; | ||||
return std::min(device->getNumOutputs() - offset, maxChannels); | |||||
try { | |||||
return std::min(device->getNumOutputs() - offset, maxChannels); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("Audio port could not get device number of outputs: %s", e.what()); | |||||
return 0; | |||||
} | |||||
} | } | ||||
json_t* Port::toJson() { | json_t* Port::toJson() { | ||||
@@ -172,8 +363,11 @@ void Port::fromJson(json_t* rootJ) { | |||||
if (deviceNameJ) { | if (deviceNameJ) { | ||||
std::string deviceName = json_string_value(deviceNameJ); | std::string deviceName = json_string_value(deviceNameJ); | ||||
// Search for device ID with equal name | // Search for device ID with equal name | ||||
for (int deviceId : driver->getDeviceIds()) { | |||||
if (driver->getDeviceName(deviceId) == deviceName) { | |||||
for (int deviceId : getDeviceIds()) { | |||||
std::string deviceNameCurr = getDeviceName(deviceId); | |||||
if (deviceNameCurr == "") | |||||
continue; | |||||
if (deviceNameCurr == deviceName) { | |||||
setDeviceId(deviceId); | setDeviceId(deviceId); | ||||
break; | break; | ||||
} | } | ||||
@@ -194,7 +388,6 @@ void Port::fromJson(json_t* rootJ) { | |||||
offset = json_integer_value(offsetJ); | offset = json_integer_value(offsetJ); | ||||
} | } | ||||
//////////////////// | //////////////////// | ||||
// audio | // audio | ||||
//////////////////// | //////////////////// | ||||
@@ -223,6 +416,7 @@ std::vector<int> getDriverIds() { | |||||
} | } | ||||
Driver* getDriver(int driverId) { | Driver* getDriver(int driverId) { | ||||
// Search for driver by ID | |||||
for (auto& pair : drivers) { | for (auto& pair : drivers) { | ||||
if (pair.first == driverId) | if (pair.first == driverId) | ||||
return pair.second; | return pair.second; | ||||
@@ -39,7 +39,6 @@ struct RtAudioDevice : audio::Device { | |||||
deviceInfo = rtAudio->getDeviceInfo(deviceId); | deviceInfo = rtAudio->getDeviceInfo(deviceId); | ||||
} | } | ||||
catch (RtAudioError& e) { | catch (RtAudioError& e) { | ||||
WARN("Failed to query RtAudio device: %s", e.what()); | |||||
throw Exception(string::f("Failed to query RtAudio device: %s", e.what())); | throw Exception(string::f("Failed to query RtAudio device: %s", e.what())); | ||||
} | } | ||||
@@ -55,8 +54,7 @@ struct RtAudioDevice : audio::Device { | |||||
void openStream() { | void openStream() { | ||||
// Open new device | // Open new device | ||||
if (deviceInfo.outputChannels == 0 && deviceInfo.inputChannels == 0) { | if (deviceInfo.outputChannels == 0 && deviceInfo.inputChannels == 0) { | ||||
WARN("RtAudio device %d has 0 inputs and 0 outputs", deviceId); | |||||
return; | |||||
throw Exception(string::f("RtAudio device %d has 0 inputs and 0 outputs", deviceId)); | |||||
} | } | ||||
inputParameters = RtAudio::StreamParameters(); | inputParameters = RtAudio::StreamParameters(); | ||||
@@ -98,8 +96,7 @@ struct RtAudioDevice : audio::Device { | |||||
&rtAudioCallback, this, &options, NULL); | &rtAudioCallback, this, &options, NULL); | ||||
} | } | ||||
catch (RtAudioError& e) { | catch (RtAudioError& e) { | ||||
WARN("Failed to open RtAudio stream: %s", e.what()); | |||||
return; | |||||
throw Exception(string::f("Failed to open RtAudio stream: %s", e.what())); | |||||
} | } | ||||
INFO("Starting RtAudio stream %d", deviceId); | INFO("Starting RtAudio stream %d", deviceId); | ||||
@@ -107,8 +104,7 @@ struct RtAudioDevice : audio::Device { | |||||
rtAudio->startStream(); | rtAudio->startStream(); | ||||
} | } | ||||
catch (RtAudioError& e) { | catch (RtAudioError& e) { | ||||
WARN("Failed to start RtAudio stream: %s", e.what()); | |||||
return; | |||||
throw Exception(string::f("Failed to start RtAudio stream: %s", e.what())); | |||||
} | } | ||||
// Update sample rate to actual value | // Update sample rate to actual value | ||||
@@ -124,7 +120,7 @@ struct RtAudioDevice : audio::Device { | |||||
rtAudio->stopStream(); | rtAudio->stopStream(); | ||||
} | } | ||||
catch (RtAudioError& e) { | catch (RtAudioError& e) { | ||||
WARN("Failed to stop RtAudio stream %s", e.what()); | |||||
throw Exception(string::f("Failed to stop RtAudio stream %s", e.what())); | |||||
} | } | ||||
} | } | ||||
if (rtAudio->isStreamOpen()) { | if (rtAudio->isStreamOpen()) { | ||||
@@ -133,7 +129,7 @@ struct RtAudioDevice : audio::Device { | |||||
rtAudio->closeStream(); | rtAudio->closeStream(); | ||||
} | } | ||||
catch (RtAudioError& e) { | catch (RtAudioError& e) { | ||||
WARN("Failed to close RtAudio stream %s", e.what()); | |||||
throw Exception(string::f("Failed to close RtAudio stream %s", e.what())); | |||||
} | } | ||||
} | } | ||||
INFO("Closed RtAudio stream"); | INFO("Closed RtAudio stream"); | ||||