From ffdf5ada616d285fafb58f45c2e3d37b212a328a Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 5 Oct 2006 01:49:32 +0000 Subject: [PATCH] Generic MIDI control now saves+restores its state; PBD::ID now requires a buffer size for its print() method git-svn-id: svn://localhost/ardour2/trunk@949 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/editor.cc | 2 +- gtk2_ardour/main.cc | 8 +--- libs/ardour/ardour/control_protocol_manager.h | 5 ++ libs/ardour/ardour/io.h | 2 +- libs/ardour/ardour/panner.h | 2 +- libs/ardour/ardour/plugin.h | 7 ++- libs/ardour/ardour/route.h | 2 +- libs/ardour/ardour/session.h | 17 ++++--- libs/ardour/audio_diskstream.cc | 2 +- libs/ardour/audio_track.cc | 10 +++- libs/ardour/audioregion.cc | 2 +- libs/ardour/control_protocol_manager.cc | 48 ++++++++++++++++++- libs/ardour/crossfade.cc | 4 +- libs/ardour/io.cc | 11 ++++- libs/ardour/location.cc | 2 +- libs/ardour/panner.cc | 10 +++- libs/ardour/playlist.cc | 2 +- libs/ardour/plugin.cc | 10 ++-- libs/ardour/redirect.cc | 2 +- libs/ardour/region.cc | 2 +- libs/ardour/route.cc | 20 +++++--- libs/ardour/session_state.cc | 38 +++++++++++++-- libs/ardour/source.cc | 2 +- libs/ardour/track.cc | 2 +- libs/pbd/controllable.cc | 24 ++++++++-- libs/pbd/id.cc | 9 ++-- libs/pbd/pbd/controllable.h | 14 +++--- libs/pbd/pbd/id.h | 2 +- .../generic_midi_control_protocol.cc | 20 +++++--- .../surfaces/generic_midi/midicontrollable.cc | 2 + .../tranzport/tranzport_control_protocol.cc | 3 +- 31 files changed, 209 insertions(+), 77 deletions(-) diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 9ab8efb742..f1fe88cd7a 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -2162,7 +2162,7 @@ Editor::get_state () XMLNode* node = new XMLNode ("Editor"); char buf[32]; - _id.print (buf); + _id.print (buf, sizeof (buf)); node->add_property ("id", buf); if (is_realized()) { diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc index ce7a129d08..049ef29ead 100644 --- a/gtk2_ardour/main.cc +++ b/gtk2_ardour/main.cc @@ -383,13 +383,7 @@ int main (int argc, char *argv[]) cout << _("Ardour/GTK ") << VERSIONSTRING << _("\n (built using ") - << gtk_ardour_major_version << '.' - << gtk_ardour_minor_version << '.' - << gtk_ardour_micro_version - << _(" with libardour ") - << libardour_major_version << '.' - << libardour_minor_version << '.' - << libardour_micro_version + << ARDOUR::get_ardour_revision () #ifdef __GNUC__ << _(" and GCC version ") << __VERSION__ #endif diff --git a/libs/ardour/ardour/control_protocol_manager.h b/libs/ardour/ardour/control_protocol_manager.h index 8eda7a4555..99de5479fb 100644 --- a/libs/ardour/ardour/control_protocol_manager.h +++ b/libs/ardour/ardour/control_protocol_manager.h @@ -24,6 +24,9 @@ struct ControlProtocolInfo { bool requested; bool mandatory; XMLNode* state; + + ControlProtocolInfo() : descriptor (0), protocol (0), state (0) {} + ~ControlProtocolInfo() { if (state) { delete state; } } }; class ControlProtocolManager : public sigc::trackable, public Stateful @@ -46,6 +49,8 @@ struct ControlProtocolInfo { static const std::string state_node_name; + void set_protocol_states (const XMLNode&); + int set_state (const XMLNode&); XMLNode& get_state (void); diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index 163ae462f3..c32ef31de8 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -295,7 +295,7 @@ public: gain_t initial, gain_t target, bool invert_polarity); struct GainControllable : public PBD::Controllable { - GainControllable (IO& i) : io (i) {} + GainControllable (std::string name, IO& i) : Controllable (name), io (i) {} void set_value (float val); float get_value (void) const; diff --git a/libs/ardour/ardour/panner.h b/libs/ardour/ardour/panner.h index 3091527e59..0cb0c3dfaa 100644 --- a/libs/ardour/ardour/panner.h +++ b/libs/ardour/ardour/panner.h @@ -114,7 +114,7 @@ class StreamPanner : public sigc::trackable, public Stateful bool _muted; struct PanControllable : public PBD::Controllable { - PanControllable (StreamPanner& p) : panner (p) {} + PanControllable (std::string name, StreamPanner& p) : Controllable (name), panner (p) {} StreamPanner& panner; diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h index dcc657018a..bc71da84ae 100644 --- a/libs/ardour/ardour/plugin.h +++ b/libs/ardour/ardour/plugin.h @@ -98,9 +98,8 @@ class Plugin : public PBD::StatefulDestructible, public sigc::trackable float step; float smallstep; float largestep; - - bool min_unbound; - bool max_unbound; + bool min_unbound; + bool max_unbound; }; virtual uint32_t unique_id() const = 0; @@ -162,7 +161,7 @@ class Plugin : public PBD::StatefulDestructible, public sigc::trackable void setup_controls (); struct PortControllable : public PBD::Controllable { - PortControllable (Plugin&, uint32_t abs_port_id, + PortControllable (std::string name, Plugin&, uint32_t abs_port_id, float lower, float upper, bool toggled, bool logarithmic); void set_value (float); diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 8ebc598e95..b3ac609880 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -222,7 +222,7 @@ class Route : public IO SoloControl }; - ToggleControllable (Route&, ToggleType); + ToggleControllable (std::string name, Route&, ToggleType); void set_value (float); float get_value (void) const; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 79fd442995..ca7c38b281 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -93,7 +93,7 @@ class AudioRegion; class Region; class Playlist; class VSTPlugin; -class ControlProtocolManager; +class ControlProtocolInfo; struct AudioExportSpecification; struct RouteGroup; @@ -415,7 +415,7 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible XMLNode& get_state(); int set_state(const XMLNode& node); // not idempotent XMLNode& get_template(); - + void add_instant_xml (XMLNode&, const std::string& dir); enum StateOfTheState { @@ -904,6 +904,9 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible PBD::Controllable* controllable_by_id (const PBD::ID&); + void add_controllable (PBD::Controllable*); + void remove_controllable (PBD::Controllable*); + protected: friend class AudioEngine; void set_block_size (nframes_t nframes); @@ -1667,19 +1670,19 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible LayerModel layer_model; CrossfadeModel xfade_model; - typedef std::list Controllables; + typedef std::set Controllables; Glib::Mutex controllables_lock; Controllables controllables; - void add_controllable (PBD::Controllable*); - void remove_controllable (PBD::Controllable*); - - void reset_native_file_format(); bool first_file_data_format_reset; bool first_file_header_format_reset; void config_changed (const char*); + + void add_control_protocol (const ControlProtocolInfo* const, XMLNode*); + XMLNode& get_control_protocol_state (); + }; } // namespace ARDOUR diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index efe4e89cd1..1374589608 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -1759,7 +1759,7 @@ AudioDiskstream::get_state () node->add_property ("speed", buf); node->add_property("name", _name); - id().print (buf); + id().print (buf, sizeof (buf)); node->add_property("id", buf); if (!capturing_sources.empty() && _session.get_record_enabled()) { diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 2860470abd..171f2d7c6b 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -246,6 +246,10 @@ AudioTrack::set_state (const XMLNode& node) sscanf (prop->value().c_str(), "%d", &x); set_remote_control_id (x); } + + } else if (child->name() == X_("recenable")) { + _rec_enable_control.set_state (*child); + _session.add_controllable (&_rec_enable_control); } } @@ -273,7 +277,7 @@ AudioTrack::state(bool full_state) for (vector::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) { inode = new XMLNode (X_("insert")); - (*i)->id.print (buf); + (*i)->id.print (buf, sizeof (buf)); inode->add_property (X_("id"), buf); inode->add_child_copy ((*i)->state); @@ -317,9 +321,11 @@ AudioTrack::state(bool full_state) diskstream. */ - _diskstream->id().print (buf); + _diskstream->id().print (buf, sizeof (buf)); root.add_property ("diskstream-id", buf); + root.add_child_nocopy (_rec_enable_control.get_state()); + return root; } diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index ee3840063d..855ff074ca 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -688,7 +688,7 @@ AudioRegion::state (bool full) for (uint32_t n=0; n < sources.size(); ++n) { snprintf (buf2, sizeof(buf2), "source-%d", n); - sources[n]->id().print (buf); + sources[n]->id().print (buf, sizeof (buf)); node.add_property (buf2, buf); } diff --git a/libs/ardour/control_protocol_manager.cc b/libs/ardour/control_protocol_manager.cc index 5c02936ba0..7170b45656 100644 --- a/libs/ardour/control_protocol_manager.cc +++ b/libs/ardour/control_protocol_manager.cc @@ -50,7 +50,7 @@ ControlProtocolManager::set_session (Session& s) instantiate (**i); (*i)->requested = false; - if ((*i)->state) { + if ((*i)->protocol && (*i)->state) { (*i)->protocol->set_state (*(*i)->state); } } @@ -93,6 +93,10 @@ ControlProtocolManager::instantiate (ControlProtocolInfo& cpi) Glib::Mutex::Lock lm (protocols_lock); control_protocols.push_back (cpi.protocol); + if (cpi.state) { + cpi.protocol->set_state (*cpi.state); + } + return cpi.protocol; } @@ -154,7 +158,7 @@ ControlProtocolManager::discover_control_protocols (string path) vector *found; PathScanner scanner; - cerr << "looking for control protocols in " << path << endl; + info << string_compose (_("looking for control protocols in %1"), path) << endmsg; found = scanner (path, protocol_filter, 0, false, true); @@ -261,11 +265,20 @@ ControlProtocolManager::set_state (const XMLNode& node) for (citer = clist.begin(); citer != clist.end(); ++citer) { if ((*citer)->name() == X_("Protocol")) { + prop = (*citer)->property (X_("active")); + if (prop && prop->value() == X_("yes")) { if ((prop = (*citer)->property (X_("name"))) != 0) { ControlProtocolInfo* cpi = cpi_by_name (prop->value()); if (cpi) { + + if (!(*citer)->children().empty()) { + cpi->state = (*citer)->children().front (); + } else { + cpi->state = 0; + } + if (_session) { instantiate (*cpi); } else { @@ -294,3 +307,34 @@ ControlProtocolManager::get_state (void) return *root; } + +void +ControlProtocolManager::set_protocol_states (const XMLNode& node) +{ + XMLNodeList nlist; + XMLNodeConstIterator niter; + XMLProperty* prop; + + nlist = node.children(); + + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { + + XMLNode* child = (*niter); + + if ((prop = child->property ("name")) == 0) { + error << _("control protocol XML node has no name property. Ignored.") << endmsg; + continue; + } + + ControlProtocolInfo* cpi = cpi_by_name (prop->value()); + + if (!cpi) { + warning << string_compose (_("control protocol \"%1\" is not known. Ignored"), prop->value()) << endmsg; + continue; + } + + /* copy the node so that ownership is clear */ + + cpi->state = new XMLNode (*child); + } +} diff --git a/libs/ardour/crossfade.cc b/libs/ardour/crossfade.cc index acf254e73a..32a9e2b533 100644 --- a/libs/ardour/crossfade.cc +++ b/libs/ardour/crossfade.cc @@ -679,9 +679,9 @@ Crossfade::get_state () char buf[64]; LocaleGuard lg (X_("POSIX")); - _out->id().print (buf); + _out->id().print (buf, sizeof (buf)); node->add_property ("out", buf); - _in->id().print (buf); + _in->id().print (buf, sizeof (buf)); node->add_property ("in", buf); node->add_property ("active", (_active ? "yes" : "no")); node->add_property ("follow-overlap", (_follow_overlap ? "yes" : "no")); diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index f38f938675..34070f3dff 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -107,7 +107,7 @@ IO::IO (Session& s, string name, : _session (s), _name (name), _default_type(default_type), - _gain_control (*this), + _gain_control (X_("gaincontrol"), *this), _gain_automation_curve (0.0, 2.0, 1.0), _input_minimum (input_min), _input_maximum (input_max), @@ -1431,7 +1431,7 @@ IO::state (bool full_state) Glib::Mutex::Lock lm (io_lock); node->add_property("name", _name); - id().print (buf); + id().print (buf, sizeof (buf)); node->add_property("id", buf); str = ""; @@ -1513,6 +1513,7 @@ IO::state (bool full_state) } node->add_child_nocopy (_panner->state (full_state)); + node->add_child_nocopy (_gain_control.get_state ()); snprintf (buf, sizeof(buf), "%2.12f", gain()); node->add_property ("gain", buf); @@ -1627,9 +1628,15 @@ IO::set_state (const XMLNode& node) } for (iter = node.children().begin(); iter != node.children().end(); ++iter) { + if ((*iter)->name() == "Panner") { _panner->set_state (**iter); } + + if ((*iter)->name() == X_("gaincontrol")) { + _gain_control.set_state (**iter); + _session.add_controllable (&_gain_control); + } } if ((prop = node.property ("automation-state")) != 0) { diff --git a/libs/ardour/location.cc b/libs/ardour/location.cc index 5716d9fad5..39331cfda6 100644 --- a/libs/ardour/location.cc +++ b/libs/ardour/location.cc @@ -266,7 +266,7 @@ Location::get_state (void) node->add_child_nocopy(cd_info_node(m->first, m->second)); } - id().print (buf); + id().print (buf, sizeof (buf)); node->add_property("id", buf); node->add_property ("name", name()); snprintf (buf, sizeof (buf), "%u", start()); diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc index 257a21fe58..22053ce56b 100644 --- a/libs/ardour/panner.cc +++ b/libs/ardour/panner.cc @@ -67,7 +67,7 @@ static double direct_pan_to_control (pan_t val) { StreamPanner::StreamPanner (Panner& p) : parent (p), - _control (*this) + _control (X_("panner"), *this) { _muted = false; @@ -543,6 +543,7 @@ EqualPowerStereoPanner::state (bool full_state) root->add_property (X_("automation-style"), buf); StreamPanner::add_state (*root); + root->add_child_nocopy (_control.get_state ()); return *root; } @@ -575,6 +576,13 @@ EqualPowerStereoPanner::set_state (const XMLNode& node) } StreamPanner::set_state (node); + + for (XMLNodeConstIterator iter = node.children().begin(); iter != node.children().end(); ++iter) { + if ((*iter)->name() == X_("panner")) { + _control.set_state (**iter); + parent.session().add_controllable (&_control); + } + } return 0; } diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index 7a87033a56..6d6a07da95 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -1420,7 +1420,7 @@ Playlist::state (bool full_state) node->add_property (X_("name"), _name); - _orig_diskstream_id.print (buf); + _orig_diskstream_id.print (buf, sizeof (buf)); node->add_property (X_("orig_diskstream_id"), buf); node->add_property (X_("frozen"), _frozen ? "yes" : "no"); diff --git a/libs/ardour/plugin.cc b/libs/ardour/plugin.cc index 9a82c3bbab..3b471014eb 100644 --- a/libs/ardour/plugin.cc +++ b/libs/ardour/plugin.cc @@ -95,15 +95,17 @@ Plugin::get_nth_control (uint32_t n) Plugin::ParameterDescriptor desc; get_parameter_descriptor (n, desc); - - controls[n] = new PortControllable (*this, n, desc.lower, desc.upper, desc.toggled, desc.logarithmic); + + controls[n] = new PortControllable (describe_parameter (n), *this, n, + desc.lower, desc.upper, desc.toggled, desc.logarithmic); } return controls[n]; } -Plugin::PortControllable::PortControllable (Plugin& p, uint32_t port_id, float low, float up, bool t, bool loga) - : plugin (p), absolute_port (port_id) +Plugin::PortControllable::PortControllable (string name, Plugin& p, uint32_t port_id, + float low, float up, bool t, bool loga) + : Controllable (name), plugin (p), absolute_port (port_id) { toggled = t; logarithmic = loga; diff --git a/libs/ardour/redirect.cc b/libs/ardour/redirect.cc index 41d6e59246..9323966f96 100644 --- a/libs/ardour/redirect.cc +++ b/libs/ardour/redirect.cc @@ -233,7 +233,7 @@ Redirect::state (bool full_state) path = _session.snap_name(); path += "-redirect-"; - id().print (buf); + id().print (buf, sizeof (buf)); path += buf; path += ".automation"; diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index 6c7e72be46..a13ddd77cd 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -860,7 +860,7 @@ Region::state (bool full_state) XMLNode *node = new XMLNode ("Region"); char buf[64]; - _id.print (buf); + _id.print (buf, sizeof (buf)); node->add_property ("id", buf); node->add_property ("name", _name); snprintf (buf, sizeof (buf), "%u", _start); diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 9c752eefeb..70a5d586a0 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -55,16 +55,16 @@ uint32_t Route::order_key_cnt = 0; Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg, DataType default_type) : IO (sess, name, input_min, input_max, output_min, output_max, default_type), _flags (flg), - _solo_control (*this, ToggleControllable::SoloControl), - _mute_control (*this, ToggleControllable::MuteControl) + _solo_control (X_("solo"), *this, ToggleControllable::SoloControl), + _mute_control (X_("mute"), *this, ToggleControllable::MuteControl) { init (); } Route::Route (Session& sess, const XMLNode& node) : IO (sess, "route"), - _solo_control (*this, ToggleControllable::SoloControl), - _mute_control (*this, ToggleControllable::MuteControl) + _solo_control (X_("solo"), *this, ToggleControllable::SoloControl), + _mute_control (X_("mute"), *this, ToggleControllable::MuteControl) { init (); set_state (node); @@ -1379,6 +1379,8 @@ Route::state(bool full_state) node->add_property ("order-keys", order_string); node->add_child_nocopy (IO::state (full_state)); + node->add_child_nocopy (_solo_control.get_state ()); + node->add_child_nocopy (_mute_control.get_state ()); if (_control_outs) { XMLNode* cnode = new XMLNode (X_("ControlOuts")); @@ -1684,6 +1686,12 @@ Route::set_state (const XMLNode& node) } else if (child->name() == "extra") { _extra_xml = new XMLNode (*child); + } else if (child->name() == "solo") { + _solo_control.set_state (*child); + _session.add_controllable (&_solo_control); + } else if (child->name() == "mute") { + _mute_control.set_state (*child); + _session.add_controllable (&_mute_control); } } @@ -2220,8 +2228,8 @@ Route::automation_snapshot (nframes_t now) } } -Route::ToggleControllable::ToggleControllable (Route& s, ToggleType tp) - : route (s), type(tp) +Route::ToggleControllable::ToggleControllable (std::string name, Route& s, ToggleType tp) + : Controllable (name), route (s), type(tp) { } diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index cb52b9c4e4..159f8a8473 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -84,6 +84,8 @@ #include #include +#include + #include "i18n.h" #include @@ -242,7 +244,6 @@ Session::first_stage_init (string fullpath, string snapshot_name) Curve::CurveCreated.connect (mem_fun (*this, &Session::add_curve)); AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list)); - Controllable::Created.connect (mem_fun (*this, &Session::add_controllable)); Controllable::GoingAway.connect (mem_fun (*this, &Session::remove_controllable)); IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers)); @@ -967,6 +968,8 @@ Session::state(bool full_state) node->add_child_nocopy (_tempo_map->get_state()); + node->add_child_nocopy (get_control_protocol_state()); + if (_extra_xml) { node->add_child_copy (*_extra_xml); } @@ -974,6 +977,25 @@ Session::state(bool full_state) return *node; } +XMLNode& +Session::get_control_protocol_state () +{ + ControlProtocolManager& cpm (ControlProtocolManager::instance()); + XMLNode* node = new XMLNode (X_("ControlProtocols")); + + cpm.foreach_known_protocol (bind (mem_fun (*this, &Session::add_control_protocol), node)); + + return *node; +} + +void +Session::add_control_protocol (const ControlProtocolInfo* const cpi, XMLNode* node) +{ + if (cpi->protocol) { + node->add_child_nocopy (cpi->protocol->get_state()); + } +} + int Session::set_state (const XMLNode& node) { @@ -1030,6 +1052,7 @@ Session::set_state (const XMLNode& node) EditGroups MixGroups Click + ControlProtocols */ if (use_config_midi_ports ()) { @@ -1161,6 +1184,10 @@ Session::set_state (const XMLNode& node) _click_io->set_state (*child); } + if ((child = find_named_node (node, "ControlProtocols")) != 0) { + ControlProtocolManager::instance().set_protocol_states (*child); + } + /* here beginneth the second phase ... */ StateReady (); /* EMIT SIGNAL */ @@ -2719,7 +2746,7 @@ void Session::add_controllable (Controllable* c) { Glib::Mutex::Lock lm (controllables_lock); - controllables.push_back (c); + controllables.insert (c); } void @@ -2730,7 +2757,12 @@ Session::remove_controllable (Controllable* c) } Glib::Mutex::Lock lm (controllables_lock); - controllables.remove (c); + + Controllables::iterator x = controllables.find (c); + + if (x != controllables.end()) { + controllables.erase (x); + } } Controllable* diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc index e4e036584c..7ade8a8573 100644 --- a/libs/ardour/source.cc +++ b/libs/ardour/source.cc @@ -71,7 +71,7 @@ Source::get_state () char buf[64]; node->add_property ("name", _name); - _id.print (buf); + _id.print (buf, sizeof (buf)); node->add_property ("id", buf); if (_timestamp != 0) { diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index cfa7d71a23..6d959ed88d 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -119,7 +119,7 @@ Track::freeze_state() const } Track::RecEnableControllable::RecEnableControllable (Track& s) - : track (s) + : Controllable (X_("recenable")), track (s) { } diff --git a/libs/pbd/controllable.cc b/libs/pbd/controllable.cc index b1176c64a5..80c6811e6a 100644 --- a/libs/pbd/controllable.cc +++ b/libs/pbd/controllable.cc @@ -1,26 +1,40 @@ #include #include +#include #include "i18n.h" using namespace PBD; -sigc::signal Controllable::Created; sigc::signal Controllable::GoingAway; sigc::signal Controllable::StartLearning; sigc::signal Controllable::StopLearning; -Controllable::Controllable () +Controllable::Controllable (std::string name) + : _name (name) { - Created (this); } XMLNode& Controllable::get_state () { - XMLNode* node = new XMLNode (X_("Controllable")); + XMLNode* node = new XMLNode (_name); char buf[64]; - _id.print (buf); + _id.print (buf, sizeof (buf)); node->add_property (X_("id"), buf); return *node; } + +int +Controllable::set_state (const XMLNode& node) +{ + const XMLProperty* prop = node.property (X_("id")); + + if (prop) { + _id = prop->value(); + return 0; + } else { + error << _("Controllable state node has no ID property") << endmsg; + return -1; + } +} diff --git a/libs/pbd/id.cc b/libs/pbd/id.cc index c99e242bee..353776de9f 100644 --- a/libs/pbd/id.cc +++ b/libs/pbd/id.cc @@ -40,16 +40,15 @@ ID::string_assign (string str) } void -ID::print (char* buf) const +ID::print (char* buf, uint32_t bufsize) const { - /* XXX sizeof buf is unknown. bad API design */ - snprintf (buf, 32, "%" PRIu64, _id); + snprintf (buf, bufsize, "%" PRIu64, _id); } string ID::to_s() const { char buf[32]; // see print() - print(buf); + print(buf, sizeof (buf)); return string(buf); } @@ -64,7 +63,7 @@ ostream& operator<< (ostream& ostr, const ID& _id) { char buf[32]; - _id.print (buf); + _id.print (buf, sizeof (buf)); ostr << buf; return ostr; } diff --git a/libs/pbd/pbd/controllable.h b/libs/pbd/pbd/controllable.h index c46e477b6e..ff8f8a9b52 100644 --- a/libs/pbd/pbd/controllable.h +++ b/libs/pbd/pbd/controllable.h @@ -1,6 +1,8 @@ #ifndef __pbd_controllable_h__ #define __pbd_controllable_h__ +#include + #include #include @@ -13,7 +15,7 @@ namespace PBD { class Controllable : public virtual sigc::trackable, public Stateful { public: - Controllable (); + Controllable (std::string name); virtual ~Controllable() { GoingAway (this); } virtual void set_value (float) = 0; @@ -23,22 +25,20 @@ class Controllable : public virtual sigc::trackable, public Stateful { sigc::signal LearningFinished; - static sigc::signal Created; static sigc::signal GoingAway; - static sigc::signal StartLearning; static sigc::signal StopLearning; sigc::signal Changed; - const PBD::ID& id() const { return _id; } - - int set_state (const XMLNode&) { return 0; } + int set_state (const XMLNode&); XMLNode& get_state (); + std::string name() const { return _name; } + private: - PBD::ID _id; + std::string _name; }; } diff --git a/libs/pbd/pbd/id.h b/libs/pbd/pbd/id.h index c110362734..eb3691d99e 100644 --- a/libs/pbd/pbd/id.h +++ b/libs/pbd/pbd/id.h @@ -27,7 +27,7 @@ class ID { return _id < other._id; } - void print (char* buf) const; + void print (char* buf, uint32_t bufsize) const; std::string to_s() const; static uint64_t counter() { return _counter; } diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc index d905c0bc41..a8a5b6eace 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc @@ -39,7 +39,7 @@ using namespace PBD; #include "i18n.h" GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s) - : ControlProtocol (s, _("GenericMIDI")) + : ControlProtocol (s, _("Generic MIDI")) { MIDI::Manager* mm = MIDI::Manager::instance(); @@ -173,7 +173,10 @@ GenericMidiControlProtocol::stop_learning (Controllable* c) XMLNode& GenericMidiControlProtocol::get_state () { - XMLNode* node = new XMLNode (_name); /* node name must match protocol name */ + XMLNode* node = new XMLNode ("Protocol"); + + node->add_property (X_("name"), _name); + XMLNode* children = new XMLNode (X_("controls")); node->add_child_nocopy (*children); @@ -215,19 +218,24 @@ GenericMidiControlProtocol::set_state (const XMLNode& node) XMLProperty* prop; if ((prop = (*niter)->property ("id")) != 0) { - + ID id = prop->value (); - + c = session->controllable_by_id (id); - + if (c) { MIDIControllable* mc = new MIDIControllable (*_port, *c); if (mc->set_state (**niter) == 0) { controllables.insert (mc); } + + } else { + warning << string_compose (_("Generic MIDI control: controllable %1 not found in session (ignored)"), + id) + << endmsg; } } } - + return 0; } diff --git a/libs/surfaces/generic_midi/midicontrollable.cc b/libs/surfaces/generic_midi/midicontrollable.cc index d6135fd2a8..1cf32f11f6 100644 --- a/libs/surfaces/generic_midi/midicontrollable.cc +++ b/libs/surfaces/generic_midi/midicontrollable.cc @@ -345,6 +345,8 @@ MIDIControllable::set_state (const XMLNode& node) return -1; } + bind_midi (control_channel, control_type, control_additional); + return 0; } diff --git a/libs/surfaces/tranzport/tranzport_control_protocol.cc b/libs/surfaces/tranzport/tranzport_control_protocol.cc index 04d56c575c..2e2d943244 100644 --- a/libs/surfaces/tranzport/tranzport_control_protocol.cc +++ b/libs/surfaces/tranzport/tranzport_control_protocol.cc @@ -1577,7 +1577,8 @@ TranzportControlProtocol::print (int row, int col, const char *text) XMLNode& TranzportControlProtocol::get_state () { - XMLNode* node = new XMLNode (_name); /* node name must match protocol name */ + XMLNode* node = new XMLNode (X_("Protocol")); + node->add_property (X_("name"), _name); return *node; } -- 2.30.2