summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2008-05-23 04:30:24 +0000
committerDavid Robillard <d@drobilla.net>2008-05-23 04:30:24 +0000
commit0dbcca14bcbcb3aa7e7c0ae24934463a5973a651 (patch)
treed85dd8d74e4d5ea5c8b4400255c03adb79cda2c5
parent9cec63d68fef0e9fd5d3ee5b99a080dbd9180a88 (diff)
downloadingen-0dbcca14bcbcb3aa7e7c0ae24934463a5973a651.tar.gz
ingen-0dbcca14bcbcb3aa7e7c0ae24934463a5973a651.tar.bz2
ingen-0dbcca14bcbcb3aa7e7c0ae24934463a5973a651.zip
Fix crash when trying to add multiple objects with the same path.
Handle failed jack port registrations more gracefully. Don't assume all LADSPA plugins have minimum and maximum port range values. git-svn-id: http://svn.drobilla.net/lad/ingen@1230 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--src/libs/engine/JackAudioDriver.cpp43
-rw-r--r--src/libs/engine/JackAudioDriver.hpp2
-rw-r--r--src/libs/engine/JackMidiDriver.cpp6
-rw-r--r--src/libs/engine/LADSPANode.cpp50
-rw-r--r--src/libs/engine/LADSPANode.hpp6
-rw-r--r--src/libs/engine/ObjectStore.cpp6
6 files changed, 78 insertions, 35 deletions
diff --git a/src/libs/engine/JackAudioDriver.cpp b/src/libs/engine/JackAudioDriver.cpp
index 9d5a06b9..cd86f91f 100644
--- a/src/libs/engine/JackAudioDriver.cpp
+++ b/src/libs/engine/JackAudioDriver.cpp
@@ -48,11 +48,11 @@ namespace Ingen {
//// JackAudioPort ////
JackAudioPort::JackAudioPort(JackAudioDriver* driver, DuplexPort* patch_port)
-: DriverPort(patch_port),
- Raul::List<JackAudioPort*>::Node(this),
- _driver(driver),
- _jack_port(NULL),
- _jack_buffer(NULL)
+ : DriverPort(patch_port)
+ , Raul::List<JackAudioPort*>::Node(this)
+ , _driver(driver)
+ , _jack_port(NULL)
+ , _jack_buffer(NULL)
{
assert(patch_port->poly() == 1);
@@ -61,6 +61,11 @@ JackAudioPort::JackAudioPort(JackAudioDriver* driver, DuplexPort* patch_port)
(patch_port->is_input()) ? JackPortIsInput : JackPortIsOutput,
0);
+ if (_jack_port == NULL) {
+ cerr << "[JackAudioPort] ERROR: Failed to register port " << patch_port->path() << endl;
+ throw JackAudioDriver::PortRegistrationFailedException();
+ }
+
patch_port->buffer(0)->clear();
patch_port->fixed_buffers(true);
}
@@ -95,15 +100,15 @@ JackAudioPort::prepare_buffer(jack_nframes_t nframes)
JackAudioDriver::JackAudioDriver(Engine& engine,
std::string server_name,
jack_client_t* jack_client)
-: _engine(engine),
- _jack_thread(NULL),
- _client(jack_client),
- _buffer_size(jack_client ? jack_get_buffer_size(jack_client) : 0),
- _sample_rate(jack_client ? jack_get_sample_rate(jack_client) : 0),
- _is_activated(false),
- _local_client(true), // FIXME
- _process_context(engine),
- _root_patch(NULL)
+ : _engine(engine)
+ , _jack_thread(NULL)
+ , _client(jack_client)
+ , _buffer_size(jack_client ? jack_get_buffer_size(jack_client) : 0)
+ , _sample_rate(jack_client ? jack_get_sample_rate(jack_client) : 0)
+ , _is_activated(false)
+ , _local_client(true) // FIXME
+ , _process_context(engine)
+ , _root_patch(NULL)
{
if (!_client) {
// Try supplied server name
@@ -247,10 +252,14 @@ JackAudioDriver::port(const Path& path)
DriverPort*
JackAudioDriver::create_port(DuplexPort* patch_port)
{
- if (patch_port->buffer_size() == _buffer_size)
- return new JackAudioPort(this, patch_port);
- else
+ try {
+ if (patch_port->buffer_size() == _buffer_size)
+ return new JackAudioPort(this, patch_port);
+ else
+ return NULL;
+ } catch (...) {
return NULL;
+ }
}
diff --git a/src/libs/engine/JackAudioDriver.hpp b/src/libs/engine/JackAudioDriver.hpp
index f436f795..3beb775a 100644
--- a/src/libs/engine/JackAudioDriver.hpp
+++ b/src/libs/engine/JackAudioDriver.hpp
@@ -110,6 +110,8 @@ public:
inline SampleCount frame_time() const { return jack_frame_time(_client); }
+ class PortRegistrationFailedException : public std::exception {};
+
private:
friend class JackAudioPort;
diff --git a/src/libs/engine/JackMidiDriver.cpp b/src/libs/engine/JackMidiDriver.cpp
index 22db1d4b..7aba309a 100644
--- a/src/libs/engine/JackMidiDriver.cpp
+++ b/src/libs/engine/JackMidiDriver.cpp
@@ -22,6 +22,7 @@
#include <raul/midi_events.h>
#include "types.hpp"
#include "JackMidiDriver.hpp"
+#include "JackAudioDriver.hpp"
#include "ThreadManager.hpp"
#include "AudioDriver.hpp"
#include "EventBuffer.hpp"
@@ -50,6 +51,11 @@ JackMidiPort::JackMidiPort(JackMidiDriver* driver, DuplexPort* patch_port)
patch_port->path().c_str(), JACK_DEFAULT_MIDI_TYPE,
(patch_port->is_input()) ? JackPortIsInput : JackPortIsOutput,
0);
+
+ if (_jack_port == NULL) {
+ cerr << "[JackMidiPort] ERROR: Failed to register port " << patch_port->path() << endl;
+ throw JackAudioDriver::PortRegistrationFailedException();
+ }
patch_port->buffer(0)->clear();
}
diff --git a/src/libs/engine/LADSPANode.cpp b/src/libs/engine/LADSPANode.cpp
index 7e19a6b6..767c0cb4 100644
--- a/src/libs/engine/LADSPANode.cpp
+++ b/src/libs/engine/LADSPANode.cpp
@@ -20,6 +20,7 @@
#include <cmath>
#include <stdint.h>
#include <raul/Maid.hpp>
+#include <boost/optional.hpp>
#include "LADSPANode.hpp"
#include "AudioBuffer.hpp"
#include "InputPort.hpp"
@@ -172,14 +173,17 @@ LADSPANode::instantiate()
assert (LADSPA_IS_PORT_INPUT(_descriptor->PortDescriptors[j])
|| LADSPA_IS_PORT_OUTPUT(_descriptor->PortDescriptors[j]));
- Sample default_val, min, max;
+ boost::optional<Sample> default_val, min, max;
get_port_limits(j, default_val, min, max);
+ if (!default_val)
+ default_val = 0.0f;
+
if (LADSPA_IS_PORT_INPUT(_descriptor->PortDescriptors[j])) {
- port = new InputPort(this, port_name, j, _polyphony, type, default_val, port_buffer_size);
+ port = new InputPort(this, port_name, j, _polyphony, type, default_val.get(), port_buffer_size);
_ports->at(j) = port;
} else if (LADSPA_IS_PORT_OUTPUT(_descriptor->PortDescriptors[j])) {
- port = new OutputPort(this, port_name, j, _polyphony, type, default_val, port_buffer_size);
+ port = new OutputPort(this, port_name, j, _polyphony, type, default_val.get(), port_buffer_size);
_ports->at(j) = port;
}
@@ -202,12 +206,14 @@ LADSPANode::instantiate()
// Set default value
if (port->buffer_size() == 1) {
for (uint32_t i=0; i < _polyphony; ++i)
- ((AudioBuffer*)port->buffer(i))->set(default_val, 0);
+ ((AudioBuffer*)port->buffer(i))->set(default_val.get(), 0);
}
if (port->is_input() && port->buffer_size() == 1) {
- port->set_variable("ingen:minimum", min);
- port->set_variable("ingen:maximum", max);
+ if (min)
+ port->set_variable("ingen:minimum", min.get());
+ if (max)
+ port->set_variable("ingen:maximum", max.get());
}
}
@@ -272,7 +278,10 @@ LADSPANode::set_port_buffer(uint32_t voice, uint32_t port_num, Buffer* buf)
void
-LADSPANode::get_port_limits(unsigned long port_index, Sample& normal, Sample& lower, Sample& upper)
+LADSPANode::get_port_limits(unsigned long port_index,
+ boost::optional<Sample>& normal,
+ boost::optional<Sample>& lower,
+ boost::optional<Sample>& upper)
{
LADSPA_PortRangeHintDescriptor hint_descriptor = _descriptor->PortRangeHints[port_index].HintDescriptor;
@@ -299,25 +308,32 @@ LADSPANode::get_port_limits(unsigned long port_index, Sample& normal, Sample& lo
if (LADSPA_IS_HINT_DEFAULT_MINIMUM(hint_descriptor)) {
normal = lower;
} else if (LADSPA_IS_HINT_DEFAULT_LOW(hint_descriptor)) {
+ assert(lower);
+ assert(upper);
if (LADSPA_IS_HINT_LOGARITHMIC(hint_descriptor)) {
- normal = exp(log(lower) * 0.75 + log(upper) * 0.25);
+ normal = exp(log(lower.get()) * 0.75 + log(upper.get()) * 0.25);
} else {
- normal = lower * 0.75 + upper * 0.25;
+ normal = lower.get() * 0.75 + upper.get() * 0.25;
}
} else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(hint_descriptor)) {
+ assert(lower);
+ assert(upper);
if (LADSPA_IS_HINT_LOGARITHMIC(hint_descriptor)) {
- normal = exp(log(lower) * 0.5 + log(upper) * 0.5);
+ normal = exp(log(lower.get()) * 0.5 + log(upper.get()) * 0.5);
} else {
- normal = lower * 0.5 + upper * 0.5;
+ normal = lower.get() * 0.5 + upper.get() * 0.5;
}
} else if (LADSPA_IS_HINT_DEFAULT_HIGH(hint_descriptor)) {
+ assert(lower);
+ assert(upper);
if (LADSPA_IS_HINT_LOGARITHMIC(hint_descriptor)) {
- normal = exp(log(lower) * 0.25 + log(upper) * 0.75);
+ normal = exp(log(lower.get()) * 0.25 + log(upper.get()) * 0.75);
} else {
- normal = lower * 0.25 + upper * 0.75;
+ normal = lower.get() * 0.25 + upper.get() * 0.75;
}
} else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(hint_descriptor)) {
- normal = upper;
+ assert(upper);
+ normal = upper.get();
} else if (LADSPA_IS_HINT_DEFAULT_0(hint_descriptor)) {
normal = 0.0;
} else if (LADSPA_IS_HINT_DEFAULT_1(hint_descriptor)) {
@@ -329,9 +345,11 @@ LADSPANode::get_port_limits(unsigned long port_index, Sample& normal, Sample& lo
}
} else { // No default hint
if (LADSPA_IS_HINT_BOUNDED_BELOW(hint_descriptor)) {
- normal = lower;
+ assert(lower);
+ normal = lower.get();
} else if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint_descriptor)) {
- normal = upper;
+ assert(upper);
+ normal = upper.get();
}
}
}
diff --git a/src/libs/engine/LADSPANode.hpp b/src/libs/engine/LADSPANode.hpp
index abadcf9f..53d7ad9e 100644
--- a/src/libs/engine/LADSPANode.hpp
+++ b/src/libs/engine/LADSPANode.hpp
@@ -20,6 +20,7 @@
#include <string>
#include <ladspa.h>
+#include <boost/optional.hpp>
#include "types.hpp"
#include "NodeBase.hpp"
#include "PluginImpl.hpp"
@@ -57,7 +58,10 @@ public:
void set_port_buffer(uint32_t voice, uint32_t port_num, Buffer* buf);
protected:
- void get_port_limits(unsigned long port_index, Sample& default_value, Sample& lower_bound, Sample& upper_bound);
+ void get_port_limits(unsigned long port_index,
+ boost::optional<Sample>& default_value,
+ boost::optional<Sample>& lower_bound,
+ boost::optional<Sample>& upper_bound);
const LADSPA_Descriptor* _descriptor;
Raul::Array<LADSPA_Handle>* _instances;
diff --git a/src/libs/engine/ObjectStore.cpp b/src/libs/engine/ObjectStore.cpp
index 2df1965f..052200fd 100644
--- a/src/libs/engine/ObjectStore.cpp
+++ b/src/libs/engine/ObjectStore.cpp
@@ -79,7 +79,11 @@ ObjectStore::add(GraphObjectImpl* o)
{
assert(ThreadManager::current_thread_id() == THREAD_PRE_PROCESS);
- //cerr << "[ObjectStore] Adding " << o->path() << endl;
+ if (_objects.find(o->path()) != _objects.end()) {
+ cerr << "[ObjectStore] ERROR: Attempt to add duplicate object " << o->path() << endl;
+ return;
+ }
+
_objects.insert(make_pair(o->path(), o));
NodeImpl* node = dynamic_cast<NodeImpl*>(o);