diff options
author | David Robillard <d@drobilla.net> | 2007-07-03 02:37:24 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2007-07-03 02:37:24 +0000 |
commit | 0da29770276604a7f0a367cd8eb5ff2fff7a2233 (patch) | |
tree | 87f37c252457eab66c0806e097a2d147d8d66916 | |
parent | ef0b9a740996c432a6a96180814d4f8d0ee16842 (diff) |
Pan automation/serialization fixes.
"Live" Midi CC sending from Midi CC automation track controllers.
git-svn-id: svn://localhost/ardour2/trunk@2097 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r-- | gtk2_ardour/audio_time_axis.cc | 13 | ||||
-rw-r--r-- | gtk2_ardour/automation_controller.cc | 6 | ||||
-rw-r--r-- | gtk2_ardour/midi_time_axis.cc | 24 | ||||
-rw-r--r-- | gtk2_ardour/route_time_axis.cc | 23 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_ring_buffer.h | 6 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_track.h | 16 | ||||
-rw-r--r-- | libs/ardour/ardour/panner.h | 7 | ||||
-rw-r--r-- | libs/ardour/ardour/param_id.h | 10 | ||||
-rw-r--r-- | libs/ardour/automatable.cc | 2 | ||||
-rw-r--r-- | libs/ardour/automation_event.cc | 7 | ||||
-rw-r--r-- | libs/ardour/midi_track.cc | 30 | ||||
-rw-r--r-- | libs/ardour/panner.cc | 16 |
12 files changed, 118 insertions, 42 deletions
diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc index d032aaca9f..6e80c0b636 100644 --- a/gtk2_ardour/audio_time_axis.cc +++ b/gtk2_ardour/audio_time_axis.cc @@ -336,13 +336,20 @@ AudioTimeAxisView::update_pans () /* Man I hate that damn stereo->stereo panner */ uint32_t i = 0; for (p = _route->panner().begin(); p != _route->panner().end(); ++p) { + boost::shared_ptr<AutomationControl> pan_control = (*p)->pan_control(); + + if (pan_control->list()->param_id().type() == NullAutomation) { + error << "Pan control has NULL automation type!" << endmsg; + continue; + } + boost::shared_ptr<AutomationTimeAxisView> pan_track(new AutomationTimeAxisView (_session, - _route, _route/*FIXME*/, (*p)->pan_control(), + _route, _route/*FIXME*/, pan_control, editor, *this, parent_canvas, - _route->describe_parameter((*p)->pan_control()->list()->param_id()), - ParamID(PanAutomation, i).to_string()/* FIXME: correct state name? */)); + _route->describe_parameter(pan_control->list()->param_id()), + pan_control->list()->param_id().to_string()/* FIXME: correct state name? */)); add_automation_child(ParamID(PanAutomation, i), pan_track); ++i; } diff --git a/gtk2_ardour/automation_controller.cc b/gtk2_ardour/automation_controller.cc index a95d469d7f..3cb4cc5a1e 100644 --- a/gtk2_ardour/automation_controller.cc +++ b/gtk2_ardour/automation_controller.cc @@ -75,7 +75,11 @@ void AutomationController::update_label(char* label, int label_len) { if (label && label_len) - snprintf(label, label_len, "%.3f", _controllable->get_value()); + // Hack to display CC rounded to int + if (_controllable->list()->param_id().type() == MidiCCAutomation) + snprintf(label, label_len, "%d", (int)_controllable->get_value()); + else + snprintf(label, label_len, "%.3f", _controllable->get_value()); } void diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc index 541a49d350..09bda6a2d7 100644 --- a/gtk2_ardour/midi_time_axis.cc +++ b/gtk2_ardour/midi_time_axis.cc @@ -166,13 +166,20 @@ MidiTimeAxisView::build_automation_action_menu () void MidiTimeAxisView::add_controller_track() { - AddMidiCCTrackDialog dialog; - dialog.set_transient_for(editor); - int response = dialog.run(); - if (response == Gtk::RESPONSE_ACCEPT) { - ParamID param = dialog.parameter(); - create_automation_child(param); + int response; + ParamID param; + + { + AddMidiCCTrackDialog dialog; + dialog.set_transient_for(editor); + response = dialog.run(); + + if (response == Gtk::RESPONSE_ACCEPT) + param = dialog.parameter(); } + + if (response == Gtk::RESPONSE_ACCEPT) + create_automation_child(param); } void @@ -182,11 +189,11 @@ MidiTimeAxisView::create_automation_child (ParamID param) /* FIXME: this all probably leaks */ - boost::shared_ptr<AutomationControl> c =_route->control(param); + boost::shared_ptr<AutomationControl> c = _route->control(param); if (!c) { boost::shared_ptr<AutomationList> al(new ARDOUR::AutomationList(param, 0, 127, 64)); - c = boost::shared_ptr<AutomationControl>(new AutomationControl(_session, al)); + c = boost::shared_ptr<AutomationControl>(new MidiTrack::MidiControl(midi_track(), al)); _route->add_control(c); } @@ -197,6 +204,7 @@ MidiTimeAxisView::create_automation_child (ParamID param) parent_canvas, _route->describe_parameter(param), c->list()->param_id().to_string() /* FIXME: correct state name? */)); + add_automation_child(param, track); } else { diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc index 3f37b73f12..e4c285f7ac 100644 --- a/gtk2_ardour/route_time_axis.cc +++ b/gtk2_ardour/route_time_axis.cc @@ -434,6 +434,9 @@ RouteTimeAxisView::build_automation_action_menu () automation_items.push_back (MenuElem (_("Hide all automation"), mem_fun(*this, &RouteTimeAxisView::hide_all_automation))); + if (subplugin_menu.get_parent()) + subplugin_menu.detach(); + automation_items.push_back (MenuElem (_("Plugins"), subplugin_menu)); map<ARDOUR::ParamID, RouteAutomationNode*>::iterator i; @@ -441,18 +444,16 @@ RouteTimeAxisView::build_automation_action_menu () automation_items.push_back (SeparatorElem()); - if ( ! i->second->menu_item) { - automation_items.push_back(CheckMenuElem (_route->describe_parameter(i->second->param), - bind (mem_fun(*this, &RouteTimeAxisView::toggle_automation_track), i->second->param))); + if (i->second->menu_item) + delete i->second->menu_item; - i->second->menu_item = static_cast<Gtk::CheckMenuItem*>(&automation_items.back()); + automation_items.push_back(CheckMenuElem (_route->describe_parameter(i->second->param), + bind (mem_fun(*this, &RouteTimeAxisView::toggle_automation_track), i->second->param))); - } else { - automation_items.push_back (*i->second->menu_item); - } - - //i->second->menu_item->set_active(show_automation(i->second->param)); - i->second->menu_item->set_active(false); + i->second->menu_item = static_cast<Gtk::CheckMenuItem*>(&automation_items.back()); + + i->second->menu_item->set_active(show_automation(i->second->param)); + //i->second->menu_item->set_active(false); } } @@ -1796,6 +1797,8 @@ RouteTimeAxisView::add_automation_child(ParamID param, boost::shared_ptr<Automat _show_automation.insert(param); _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ } + + build_display_menu(); } diff --git a/libs/ardour/ardour/midi_ring_buffer.h b/libs/ardour/ardour/midi_ring_buffer.h index 0ceedd7d74..3effb96664 100644 --- a/libs/ardour/ardour/midi_ring_buffer.h +++ b/libs/ardour/ardour/midi_ring_buffer.h @@ -232,7 +232,7 @@ public: size_t write(double time, size_t size, const Byte* buf); bool read(double* time, size_t* size, Byte* buf); - size_t read(MidiBuffer& dst, nframes_t start, nframes_t end); + size_t read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t offset=0); }; @@ -268,10 +268,10 @@ MidiRingBuffer::write(double time, size_t size, const Byte* buf) /** Read a block of MIDI events from buffer. * * Timestamps of events returned are relative to start (ie event with stamp 0 - * occurred at start). + * occurred at start), with offset added. */ inline size_t -MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end) +MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t offset) { if (read_space() == 0) return 0; diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h index fb350b8838..c437ca73de 100644 --- a/libs/ardour/ardour/midi_track.h +++ b/libs/ardour/ardour/midi_track.h @@ -21,6 +21,7 @@ #define __ardour_midi_track_h__ #include <ardour/track.h> +#include <ardour/midi_ring_buffer.h> namespace ARDOUR { @@ -71,6 +72,19 @@ public: int set_state(const XMLNode& node); + bool write_immediate_event(size_t size, const Byte* buf); + + struct MidiControl : public AutomationControl { + MidiControl(boost::shared_ptr<MidiTrack> route, boost::shared_ptr<AutomationList> al) + : AutomationControl (route->session(), al, al->param_id().to_string()) + , _route (route) + {} + + void set_value (float val); + + boost::weak_ptr<MidiTrack> _route; + }; + protected: XMLNode& state (bool full); @@ -80,6 +94,8 @@ private: int set_diskstream (boost::shared_ptr<MidiDiskstream> ds); void set_state_part_two (); void set_state_part_three (); + + MidiRingBuffer _immediate_events; }; } /* namespace ARDOUR*/ diff --git a/libs/ardour/ardour/panner.h b/libs/ardour/ardour/panner.h index a6cfc9a6c1..1852bdd189 100644 --- a/libs/ardour/ardour/panner.h +++ b/libs/ardour/ardour/panner.h @@ -21,6 +21,7 @@ #define __ardour_panner_h__ #include <cmath> +#include <cassert> #include <vector> #include <string> #include <iostream> @@ -106,7 +107,7 @@ class StreamPanner : public sigc::trackable, public PBD::Stateful PanControllable (Session& s, std::string name, StreamPanner& p, ParamID param) : AutomationControl (s, boost::shared_ptr<AutomationList>(new AutomationList( param, 0.0, 1.0, 0.5)), name) - , panner (p) {} + , panner (p) { assert(param.type() != NullAutomation); } StreamPanner& panner; @@ -124,7 +125,7 @@ class StreamPanner : public sigc::trackable, public PBD::Stateful class BaseStereoPanner : public StreamPanner { public: - BaseStereoPanner (Panner&); + BaseStereoPanner (Panner&, ParamID param); ~BaseStereoPanner (); /* this class just leaves the pan law itself to be defined @@ -151,7 +152,7 @@ class BaseStereoPanner : public StreamPanner class EqualPowerStereoPanner : public BaseStereoPanner { public: - EqualPowerStereoPanner (Panner&); + EqualPowerStereoPanner (Panner&, ParamID param); ~EqualPowerStereoPanner (); void distribute_automated (AudioBuffer& src, BufferSet& obufs, diff --git a/libs/ardour/ardour/param_id.h b/libs/ardour/ardour/param_id.h index d9763d5594..954b62894c 100644 --- a/libs/ardour/ardour/param_id.h +++ b/libs/ardour/ardour/param_id.h @@ -55,8 +55,6 @@ public: ParamID(const std::string& str) : _type(NullAutomation), _id(0) { if (str == "gain") { _type = GainAutomation; - } else if (str == "pan") { - _type = PanAutomation; } else if (str == "solo") { _type = SoloAutomation; } else if (str == "mute") { @@ -67,14 +65,17 @@ public: _type = FadeOutAutomation; } else if (str == "envelope") { _type = EnvelopeAutomation; + } else if (str == "pan") { + _type = PanAutomation; + } else if (str.length() > 4 && str.substr(0, 4) == "pan-") { + _type = PanAutomation; + _id = atoi(str.c_str()+4); } else if (str.length() > 10 && str.substr(0, 10) == "parameter-") { _type = PluginAutomation; _id = atoi(str.c_str()+10); - //PBD::info << "Parameter: " << str << " -> " << _id << endl; } else if (str.length() > 7 && str.substr(0, 7) == "midicc-") { _type = MidiCCAutomation; _id = atoi(str.c_str()+7); - //PBD::info << "MIDI CC: " << str << " -> " << _id << endl; } else { PBD::warning << "Unknown ParamID '" << str << "'" << endmsg; } @@ -119,6 +120,7 @@ public: } else if (_type == MidiCCAutomation) { return string_compose("midicc-%1", _id); } else { + assert(false); PBD::warning << "Uninitialized ParamID to_string() called." << endmsg; return ""; } diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc index 5b31904615..ab45edee03 100644 --- a/libs/ardour/automatable.cc +++ b/libs/ardour/automatable.cc @@ -167,11 +167,11 @@ Automatable::control (ParamID parameter, bool create_if_missing) return i->second; } else if (create_if_missing) { - assert(parameter.type() != GainAutomation); boost::shared_ptr<AutomationList> al (new AutomationList ( parameter, FLT_MIN, FLT_MAX, default_parameter_value (parameter))); boost::shared_ptr<AutomationControl> ac (new AutomationControl(_session, al)); add_control(ac); + cerr << "WARNING: Default AutomationControl created for " << parameter.to_string() << endl; return ac; } else { diff --git a/libs/ardour/automation_event.cc b/libs/ardour/automation_event.cc index 9c1a6126f6..8545f47e42 100644 --- a/libs/ardour/automation_event.cc +++ b/libs/ardour/automation_event.cc @@ -57,7 +57,7 @@ static void dumpit (const AutomationList& al, string prefix = "") AutomationList::AutomationList (ParamID id, double min_val, double max_val, double default_val) : _param_id(id) , _curve(new Curve(*this)) -{ +{ _param_id = id; _frozen = 0; _changed_when_thawed = false; @@ -73,7 +73,7 @@ AutomationList::AutomationList (ParamID id, double min_val, double max_val, doub _lookup_cache.range.first = _events.end(); _sort_pending = false; - + assert(_param_id.type() != NullAutomation); AutomationListCreated(this); } @@ -100,6 +100,7 @@ AutomationList::AutomationList (const AutomationList& other) } mark_dirty (); + assert(_param_id.type() != NullAutomation); AutomationListCreated(this); } @@ -135,6 +136,7 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl mark_dirty (); + assert(_param_id.type() != NullAutomation); AutomationListCreated(this); } @@ -162,6 +164,7 @@ AutomationList::AutomationList (const XMLNode& node, ParamID id) if (id) _param_id = id; + assert(_param_id.type() != NullAutomation); AutomationListCreated(this); } diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index a10161bc72..075497c195 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -36,6 +36,7 @@ #include <ardour/utils.h> #include <ardour/buffer_set.h> #include <ardour/meter.h> +#include <ardour/midi_events.h> #include "i18n.h" @@ -45,6 +46,7 @@ using namespace PBD; MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mode) : Track (sess, name, flag, mode, DataType::MIDI) + , _immediate_events(1024) // FIXME: size? { MidiDiskstream::Flag dflags = MidiDiskstream::Flag (0); @@ -74,6 +76,7 @@ MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mo MidiTrack::MidiTrack (Session& sess, const XMLNode& node) : Track (sess, node) + , _immediate_events(1024) // FIXME: size? { _set_state(node, false); @@ -556,6 +559,8 @@ MidiTrack::process_output_buffers (BufferSet& bufs, if (muted()) { IO::silence(nframes, offset); } else { + MidiBuffer& out_buf = bufs.get_midi(0); + _immediate_events.read(out_buf, 0, 0, offset + nframes-1); // all stamps = 0 deliver_output(bufs, start_frame, end_frame, nframes, offset); } } @@ -620,3 +625,28 @@ MidiTrack::set_mode (TrackMode m) return 0; } + +/** \return true on success, false on failure (no buffer space left) + */ +bool +MidiTrack::write_immediate_event(size_t size, const Byte* buf) +{ + return (_immediate_events.write(0, size, buf) == size); +} + +void +MidiTrack::MidiControl::set_value(float val) +{ + assert(val >= 0); + assert(val <= 127.0); + + boost::shared_ptr<MidiTrack> midi_track = _route.lock(); + + if (midi_track && !_list->automation_playback()) { + Byte ev[3] = { MIDI_CMD_CONTROL, _list->param_id().id(), (int)val }; + midi_track->write_immediate_event(3, ev); + } + + AutomationControl::set_value(val); +} + diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc index a20342330f..3912faf9e7 100644 --- a/libs/ardour/panner.cc +++ b/libs/ardour/panner.cc @@ -73,6 +73,8 @@ StreamPanner::StreamPanner (Panner& p, ParamID param) : parent (p) , _control (new PanControllable(p.session(), X_("panner"), *this, param)) { + assert(param.type() != NullAutomation); + _muted = false; parent.session().add_controllable (_control); @@ -189,8 +191,8 @@ StreamPanner::add_state (XMLNode& node) /*---------------------------------------------------------------------- */ -BaseStereoPanner::BaseStereoPanner (Panner& p) - : StreamPanner (p, ParamID(PanAutomation, 0)) +BaseStereoPanner::BaseStereoPanner (Panner& p, ParamID param) + : StreamPanner (p, param) { } @@ -346,8 +348,8 @@ BaseStereoPanner::distribute (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain /*---------------------------------------------------------------------- */ -EqualPowerStereoPanner::EqualPowerStereoPanner (Panner& p) - : BaseStereoPanner (p) +EqualPowerStereoPanner::EqualPowerStereoPanner (Panner& p, ParamID param) + : BaseStereoPanner (p, param) { update (); @@ -461,9 +463,9 @@ EqualPowerStereoPanner::distribute_automated (AudioBuffer& srcbuf, BufferSet& ob } StreamPanner* -EqualPowerStereoPanner::factory (Panner& parent, ParamID who_cares) +EqualPowerStereoPanner::factory (Panner& parent, ParamID param) { - return new EqualPowerStereoPanner (parent); + return new EqualPowerStereoPanner (parent, param); } XMLNode& @@ -798,7 +800,7 @@ Panner::reset (uint32_t nouts, uint32_t npans) outputs.push_back (Output (1.0, 0)); for (n = 0; n < npans; ++n) { - push_back (new EqualPowerStereoPanner (*this)); + push_back (new EqualPowerStereoPanner (*this, ParamID(PanAutomation, n))); } break; |