summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2011-09-14 22:49:22 +0000
committerDavid Robillard <d@drobilla.net>2011-09-14 22:49:22 +0000
commit728f510e8c542db2907dcd439a9ab99d07282220 (patch)
tree6aa01740b1def7a1fa0a32e22fef929bdc231a62
parente18380569bdbe1926be7540f3e2f9ebdf49a8e70 (diff)
downloadingen-728f510e8c542db2907dcd439a9ab99d07282220.tar.gz
ingen-728f510e8c542db2907dcd439a9ab99d07282220.tar.bz2
ingen-728f510e8c542db2907dcd439a9ab99d07282220.zip
Support lv2:sampleRate controls (mostly) correctly.
Fix initial control port values (was always 0.0). Fix numeric values in control window. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@3460 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--include/ingen/client/NodeModel.hpp5
-rw-r--r--include/ingen/client/PortModel.hpp2
-rw-r--r--src/client/ClientStore.cpp4
-rw-r--r--src/client/NodeModel.cpp15
-rw-r--r--src/client/ObjectModel.cpp6
-rw-r--r--src/client/PortModel.cpp4
-rw-r--r--src/gui/App.cpp28
-rw-r--r--src/gui/App.hpp8
-rw-r--r--src/gui/Controls.cpp10
-rw-r--r--src/gui/NodeMenu.cpp2
-rw-r--r--src/gui/Port.cpp22
-rw-r--r--src/gui/PortPropertiesWindow.cpp3
-rw-r--r--src/server/events/RegisterClient.cpp16
-rw-r--r--src/shared/LV2URIMap.cpp3
-rw-r--r--src/shared/LV2URIMap.hpp3
-rw-r--r--src/shared/ResourceImpl.cpp8
16 files changed, 108 insertions, 31 deletions
diff --git a/include/ingen/client/NodeModel.hpp b/include/ingen/client/NodeModel.hpp
index efc8514a..c874e6fb 100644
--- a/include/ingen/client/NodeModel.hpp
+++ b/include/ingen/client/NodeModel.hpp
@@ -66,9 +66,10 @@ public:
const Ports& ports() const { return _ports; }
void default_port_value_range(SharedPtr<const PortModel> port,
- float& min, float& max) const;
+ float& min, float& max, uint32_t srate=1) const;
+
void port_value_range(SharedPtr<const PortModel> port,
- float& min, float& max) const;
+ float& min, float& max, uint32_t srate=1) const;
std::string port_label(SharedPtr<const PortModel> port) const;
diff --git a/include/ingen/client/PortModel.hpp b/include/ingen/client/PortModel.hpp
index e8e74f8a..36ab847f 100644
--- a/include/ingen/client/PortModel.hpp
+++ b/include/ingen/client/PortModel.hpp
@@ -51,7 +51,7 @@ public:
inline bool is_input() const { return (_direction == INPUT); }
inline bool is_output() const { return (_direction == OUTPUT); }
- bool port_property(const std::string& uri) const;
+ bool port_property(const Raul::URI& uri) const;
bool is_numeric() const { return is_a(PortType::CONTROL); }
bool is_logarithmic() const { return port_property("http://drobilla.net/ns/ingen#logarithmic"); }
diff --git a/src/client/ClientStore.cpp b/src/client/ClientStore.cpp
index 2d7f0a4b..e1ebd97c 100644
--- a/src/client/ClientStore.cpp
+++ b/src/client/ClientStore.cpp
@@ -401,6 +401,10 @@ ClientStore::delta(const URI& uri,
void
ClientStore::set_property(const URI& subject_uri, const URI& predicate, const Atom& value)
{
+ if (subject_uri == _uris->ingen_engine) {
+ LOG(info) << "Engine property " << predicate << " = " << value << endl;
+ return;
+ }
SharedPtr<Resource> subject = _resource(subject_uri);
if (subject) {
subject->set_property(predicate, value);
diff --git a/src/client/NodeModel.cpp b/src/client/NodeModel.cpp
index 73ee5a5a..09350448 100644
--- a/src/client/NodeModel.cpp
+++ b/src/client/NodeModel.cpp
@@ -165,7 +165,7 @@ NodeModel::port(uint32_t index) const
void
NodeModel::default_port_value_range(SharedPtr<const PortModel> port,
- float& min, float& max) const
+ float& min, float& max, uint32_t srate) const
{
// Default control values
min = 0.0;
@@ -186,10 +186,16 @@ NodeModel::default_port_value_range(SharedPtr<const PortModel> port,
if (!std::isnan(_max_values[port->index()]))
max = _max_values[port->index()];
}
+
+ if (port->port_property(_uris.lv2_sampleRate)) {
+ min *= srate;
+ max *= srate;
+ }
}
void
-NodeModel::port_value_range(SharedPtr<const PortModel> port, float& min, float& max) const
+NodeModel::port_value_range(SharedPtr<const PortModel> port,
+ float& min, float& max, uint32_t srate) const
{
assert(port->parent().get() == this);
@@ -205,6 +211,11 @@ NodeModel::port_value_range(SharedPtr<const PortModel> port, float& min, float&
if (max <= min)
max = min + 1.0;
+
+ if (port->port_property(_uris.lv2_sampleRate)) {
+ min *= srate;
+ max *= srate;
+ }
}
std::string
diff --git a/src/client/ObjectModel.cpp b/src/client/ObjectModel.cpp
index 69b40154..03b21247 100644
--- a/src/client/ObjectModel.cpp
+++ b/src/client/ObjectModel.cpp
@@ -50,8 +50,9 @@ ObjectModel::~ObjectModel()
Raul::Atom&
ObjectModel::set_property(const Raul::URI& key, const Raul::Atom& value)
{
- _signal_property.emit(key, value);
- return ResourceImpl::set_property(key, value);
+ Raul::Atom& my_value = ResourceImpl::set_property(key, value);
+ _signal_property.emit(key, my_value);
+ return my_value;
}
void
@@ -69,6 +70,7 @@ ObjectModel::get_property(const Raul::URI& key) const
return (i != properties().end()) ? i->second : null_atom;
}
+
bool
ObjectModel::polyphonic() const
{
diff --git a/src/client/PortModel.cpp b/src/client/PortModel.cpp
index 50731ef0..be6d74a5 100644
--- a/src/client/PortModel.cpp
+++ b/src/client/PortModel.cpp
@@ -39,9 +39,9 @@ PortModel::supports(const Raul::URI& value_type) const
}
bool
-PortModel::port_property(const std::string& uri) const
+PortModel::port_property(const Raul::URI& uri) const
{
- return has_property(_uris.lv2_portProperty, Raul::URI(uri));
+ return has_property(_uris.lv2_portProperty, uri);
}
void
diff --git a/src/gui/App.cpp b/src/gui/App.cpp
index edd4ec06..35d31b3e 100644
--- a/src/gui/App.cpp
+++ b/src/gui/App.cpp
@@ -50,6 +50,8 @@
#include "WindowFactory.hpp"
#include "Port.hpp"
+#define LOG(s) s << "[GUI] "
+
using namespace std;
using namespace Raul;
using namespace Ingen::Client;
@@ -73,6 +75,7 @@ App::App(Ingen::Shared::World* world)
, _about_dialog(NULL)
, _window_factory(new WindowFactory())
, _world(world)
+ , _sample_rate(48000)
, _enable_signal(true)
{
Glib::set_application_name("Ingen");
@@ -146,7 +149,7 @@ App::run()
{
assert(_main);
_main->run();
- info << "[GUI] Exiting" << endl;
+ LOG(info) << "Exiting" << endl;
}
void
@@ -168,6 +171,8 @@ App::attach(SharedPtr<SigClientInterface> client)
sigc::mem_fun(this, &App::error_response));
_client->signal_error().connect(
sigc::mem_fun(this, &App::error_message));
+ _client->signal_property_change().connect(
+ sigc::mem_fun(this, &App::property_change));
}
void
@@ -211,6 +216,21 @@ App::error_message(const string& str)
}
void
+App::property_change(const Raul::URI& subject,
+ const Raul::URI& key,
+ const Raul::Atom& value)
+{
+ if (subject == uris().ingen_engine && key == uris().ingen_sampleRate) {
+ if (value.type() == Atom::INT) {
+ LOG(info) << "Sample rate: " << value << std::endl;
+ _sample_rate = value.get_int32();
+ } else {
+ error << "Engine sample rate property is not an integer" << std::endl;
+ }
+ }
+}
+
+void
App::port_activity(Port* port)
{
std::pair<ActivityPorts::iterator, bool> inserted = _activity_ports.insert(make_pair(port, false));
@@ -373,6 +393,12 @@ App::can_control(const Ingen::Port* port) const
|| port->supports(uris().atom_String)));
}
+uint32_t
+App::sample_rate() const
+{
+ return _sample_rate;
+}
+
} // namespace GUI
} // namespace Ingen
diff --git a/src/gui/App.hpp b/src/gui/App.hpp
index 96cd0152..bd753078 100644
--- a/src/gui/App.hpp
+++ b/src/gui/App.hpp
@@ -92,6 +92,8 @@ public:
bool disable_signals() { bool old = _enable_signal; _enable_signal = false; return old; }
void enable_signals(bool b) { _enable_signal = b; }
+ uint32_t sample_rate() const;
+
ConnectWindow* connect_window() const { return _connect_window; }
MessagesWindow* messages_dialog() const { return _messages_window; }
PatchTreeWindow* patch_tree() const { return _patch_tree_window; }
@@ -136,6 +138,10 @@ protected:
bool animate();
void error_response(int32_t id, const std::string& str);
+ void property_change(const Raul::URI& subject,
+ const Raul::URI& key,
+ const Raul::Atom& value);
+
static void* icon_destroyed(void* data);
static Gtk::Main* _main;
@@ -155,6 +161,8 @@ protected:
Ingen::Shared::World* _world;
+ uint32_t _sample_rate;
+
typedef std::map<Port*, bool> ActivityPorts;
ActivityPorts _activity_ports;
diff --git a/src/gui/Controls.cpp b/src/gui/Controls.cpp
index 98b1c726..e31c8d52 100644
--- a/src/gui/Controls.cpp
+++ b/src/gui/Controls.cpp
@@ -152,7 +152,7 @@ SliderControl::init(ControlPanel* panel, SharedPtr<const PortModel> pm)
boost::shared_ptr<NodeModel> parent = PtrCast<NodeModel>(_port_model->parent());
if (parent)
- parent->port_value_range(_port_model, min, max);
+ parent->port_value_range(_port_model, min, max, App::instance().sample_rate());
if (pm->is_integer() || pm->is_toggle()) {
_slider->set_increments(1, 10);
@@ -164,7 +164,8 @@ SliderControl::init(ControlPanel* panel, SharedPtr<const PortModel> pm)
pm->signal_property().connect(
sigc::mem_fun(this, &SliderControl::port_property_changed));
- _slider->set_range(std::min(min, pm->value().get_float()), std::max(max, pm->value().get_float()));
+ set_range(std::min(min, pm->value().get_float()),
+ std::max(max, pm->value().get_float()));
set_value(pm->value());
@@ -201,10 +202,8 @@ SliderControl::set_value(const Atom& atom)
if (val < lower || val > upper)
set_range(min(lower, val), max(lower, val));
_slider->set_value(val);
- }
-
- if (_value_spinner->get_value() != val)
_value_spinner->set_value(val);
+ }
_enable_signal = true;
}
@@ -231,6 +230,7 @@ SliderControl::set_range(float min, float max)
max = min + 1.0;
_slider->set_range(min, max);
+ _value_spinner->set_range(min, max);
}
void
diff --git a/src/gui/NodeMenu.cpp b/src/gui/NodeMenu.cpp
index 6cbba39d..0432d888 100644
--- a/src/gui/NodeMenu.cpp
+++ b/src/gui/NodeMenu.cpp
@@ -142,7 +142,7 @@ NodeMenu::on_menu_randomize()
for (NodeModel::Ports::const_iterator i = nm->ports().begin(); i != nm->ports().end(); ++i) {
if ((*i)->is_input() && App::instance().can_control(i->get())) {
float min = 0.0f, max = 1.0f;
- nm->port_value_range(*i, min, max);
+ nm->port_value_range(*i, min, max, App::instance().sample_rate());
const float val = ((rand() / (float)RAND_MAX) * (max - min) + min);
App::instance().engine()->set_property((*i)->path(),
App::instance().uris().ingen_value, val);
diff --git a/src/gui/Port.cpp b/src/gui/Port.cpp
index 25edf685..9b2a1c8f 100644
--- a/src/gui/Port.cpp
+++ b/src/gui/Port.cpp
@@ -111,7 +111,7 @@ Port::update_metadata()
if (parent) {
float min = 0.0f;
float max = 1.0f;
- parent->port_value_range(pm, min, max);
+ parent->port_value_range(pm, min, max, App::instance().sample_rate());
set_control_min(min);
set_control_max(max);
}
@@ -193,12 +193,20 @@ Port::property_changed(const URI& key, const Atom& value)
{
const LV2URIMap& uris = App::instance().uris();
if (value.type() == Atom::FLOAT) {
- if (key == uris.ingen_value && !_pressed)
- set_control(value.get_float(), false);
- else if (key == uris.lv2_minimum)
- set_control_min(value.get_float());
- else if (key == uris.lv2_maximum)
- set_control_max(value.get_float());
+ float val = value.get_float();
+ if (key == uris.ingen_value && !_pressed) {
+ set_control(val, false);
+ } else if (key == uris.lv2_minimum) {
+ if (model()->port_property(uris.lv2_sampleRate)) {
+ val *= App::instance().sample_rate();
+ }
+ set_control_min(val);
+ } else if (key == uris.lv2_maximum) {
+ if (model()->port_property(uris.lv2_sampleRate)) {
+ val *= App::instance().sample_rate();
+ }
+ set_control_max(val);
+ }
} else if (key == uris.lv2_portProperty) {
if (value == uris.lv2_toggled)
set_toggled(true);
diff --git a/src/gui/PortPropertiesWindow.cpp b/src/gui/PortPropertiesWindow.cpp
index a584939c..0b51074b 100644
--- a/src/gui/PortPropertiesWindow.cpp
+++ b/src/gui/PortPropertiesWindow.cpp
@@ -70,7 +70,8 @@ PortPropertiesWindow::present(SharedPtr<const PortModel> pm)
float min = 0.0f, max = 1.0f;
boost::shared_ptr<NodeModel> parent = PtrCast<NodeModel>(_port_model->parent());
if (parent)
- parent->port_value_range(_port_model, min, max);
+ parent->port_value_range(_port_model, min, max,
+ App::instance().sample_rate());
_initial_min = min;
_initial_max = max;
diff --git a/src/server/events/RegisterClient.cpp b/src/server/events/RegisterClient.cpp
index 71ec26bc..32c1a0c9 100644
--- a/src/server/events/RegisterClient.cpp
+++ b/src/server/events/RegisterClient.cpp
@@ -15,10 +15,12 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "ClientBroadcaster.hpp"
+#include "Driver.hpp"
+#include "Engine.hpp"
#include "Request.hpp"
#include "events/RegisterClient.hpp"
-#include "Engine.hpp"
-#include "ClientBroadcaster.hpp"
+#include "shared/LV2URIMap.hpp"
using namespace Raul;
@@ -49,6 +51,16 @@ void
RegisterClient::post_process()
{
_request->respond_ok();
+
+ /* Tell the client the engine's sample rate (which it needs to know to
+ interpret control bounds for lv2:sampleRate ports). This is a bit of a
+ kludge. TODO: keep a proper RDF model to describe the engine and send
+ that to clients.
+ */
+ const Ingen::Shared::LV2URIMap& uris = *_engine.world()->uris().get();
+ _client->set_property(uris.ingen_engine,
+ uris.ingen_sampleRate,
+ int32_t(_engine.driver()->sample_rate()));
}
} // namespace Server
diff --git a/src/shared/LV2URIMap.cpp b/src/shared/LV2URIMap.cpp
index d2c4f270..4ca5a033 100644
--- a/src/shared/LV2URIMap.cpp
+++ b/src/shared/LV2URIMap.cpp
@@ -81,10 +81,12 @@ LV2URIMap::LV2URIMap()
, ingen_controlBinding (NS_INGEN "controlBinding")
, ingen_document (NS_INGEN "document")
, ingen_enabled (NS_INGEN "enabled")
+ , ingen_engine (NS_INGEN "engine")
, ingen_nil (NS_INGEN "nil")
, ingen_node (NS_INGEN "node")
, ingen_polyphonic (NS_INGEN "polyphonic")
, ingen_polyphony (NS_INGEN "polyphony")
+ , ingen_sampleRate (NS_INGEN "sampleRate")
, ingen_selected (NS_INGEN "selected")
, ingen_value (NS_INGEN "value")
, ingenui_canvas_x (NS_INGENUI "canvas-x")
@@ -101,6 +103,7 @@ LV2URIMap::LV2URIMap()
, lv2_minimum (NS_LV2 "minimum")
, lv2_name (NS_LV2 "name")
, lv2_portProperty (NS_LV2 "portProperty")
+ , lv2_sampleRate (NS_LV2 "sampleRate")
, lv2_symbol (NS_LV2 "symbol")
, lv2_toggled (NS_LV2 "toggled")
, midi_Bender (NS_MIDI "Bender")
diff --git a/src/shared/LV2URIMap.hpp b/src/shared/LV2URIMap.hpp
index b7d0ff7b..75f6748e 100644
--- a/src/shared/LV2URIMap.hpp
+++ b/src/shared/LV2URIMap.hpp
@@ -113,10 +113,12 @@ public:
const Quark ingen_controlBinding;
const Quark ingen_document;
const Quark ingen_enabled;
+ const Quark ingen_engine;
const Quark ingen_nil;
const Quark ingen_node;
const Quark ingen_polyphonic;
const Quark ingen_polyphony;
+ const Quark ingen_sampleRate;
const Quark ingen_selected;
const Quark ingen_value;
const Quark ingenui_canvas_x;
@@ -133,6 +135,7 @@ public:
const Quark lv2_minimum;
const Quark lv2_name;
const Quark lv2_portProperty;
+ const Quark lv2_sampleRate;
const Quark lv2_symbol;
const Quark lv2_toggled;
const Quark midi_Bender;
diff --git a/src/shared/ResourceImpl.cpp b/src/shared/ResourceImpl.cpp
index 9f663be1..d315b8f0 100644
--- a/src/shared/ResourceImpl.cpp
+++ b/src/shared/ResourceImpl.cpp
@@ -152,11 +152,9 @@ ResourceImpl::type(
void
ResourceImpl::set_properties(const Properties& p)
{
- typedef Resource::Properties::const_iterator iterator;
- for (iterator i = p.begin(); i != p.end(); ++i)
- _properties.erase(i->first);
- for (iterator i = p.begin(); i != p.end(); ++i)
- add_property(i->first, i->second);
+ for (Resource::Properties::const_iterator i = p.begin(); i != p.end(); ++i) {
+ set_property(i->first, i->second);
+ }
}
void