X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fsurfaces%2Ffaderport8%2Ffaderport8.cc;h=2603a12e346b17310caa47d91bd98841b0016402;hb=057fd9259e35335d5e38e17d29f96dea27c17851;hp=be5f60a824f2c96786915f7d68319999137ef9c2;hpb=5dce10500cc09dfa703f5b6e90efd5ff9ba0936e;p=ardour.git diff --git a/libs/surfaces/faderport8/faderport8.cc b/libs/surfaces/faderport8/faderport8.cc index be5f60a824..2603a12e34 100644 --- a/libs/surfaces/faderport8/faderport8.cc +++ b/libs/surfaces/faderport8/faderport8.cc @@ -37,12 +37,14 @@ #include "ardour/debug.h" #include "ardour/midi_track.h" #include "ardour/midiport_manager.h" +#include "ardour/plugin.h" #include "ardour/plugin_insert.h" #include "ardour/processor.h" #include "ardour/rc_configuration.h" #include "ardour/route.h" #include "ardour/session.h" #include "ardour/session_configuration.h" +#include "ardour/tempo.h" #include "ardour/vca.h" #include "faderport8.h" @@ -89,13 +91,20 @@ FaderPort8::FaderPort8 (Session& s) , _connection_state (ConnectionState (0)) , _device_active (false) , _ctrls (*this) - , _channel_off (0) , _plugin_off (0) , _parameter_off (0) + , _show_presets (false) + , _showing_well_known (0) , _blink_onoff (false) , _shift_lock (false) , _shift_pressed (0) , gui (0) + , _link_enabled (false) + , _link_locked (false) + , _clock_mode (1) + , _scribble_mode (2) + , _two_line_text (false) + , _auto_pluginui (true) { boost::shared_ptr inp; boost::shared_ptr outp; @@ -128,37 +137,40 @@ FaderPort8::FaderPort8 (Session& s) ARDOUR::AudioEngine::instance()->Stopped.connect (port_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::engine_reset, this), this); ARDOUR::Port::PortDrop.connect (port_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::engine_reset, this), this); - StripableSelectionChanged.connect (selection_connection, MISSING_INVALIDATOR, boost::bind (&FaderPort8::gui_track_selection_changed, this), this); - + /* bind button events to call libardour actions */ setup_actions (); + _ctrls.FaderModeChanged.connect_same_thread (modechange_connections, boost::bind (&FaderPort8::notify_fader_mode_changed, this)); - _ctrls.MixModeChanged.connect_same_thread (modechange_connections, boost::bind (&FaderPort8::assign_strips, this, true)); + _ctrls.MixModeChanged.connect_same_thread (modechange_connections, boost::bind (&FaderPort8::assign_strips, this)); } FaderPort8::~FaderPort8 () { - cerr << "~FP8\n"; - disconnected (); - close (); + /* this will be called from the main UI thread. during Session::destroy(). + * There can be concurrent activity from BaseUI::main_thread -> AsyncMIDIPort + * -> MIDI::Parser::signal -> ... to any of the midi_connections + * + * stop event loop early and join thread */ + stop (); if (_input_port) { DEBUG_TRACE (DEBUG::FaderPort8, string_compose ("unregistering input port %1\n", boost::shared_ptr(_input_port)->name())); + Glib::Threads::Mutex::Lock em (AudioEngine::instance()->process_lock()); AudioEngine::instance()->unregister_port (_input_port); _input_port.reset (); } + disconnected (); // zero faders, turn lights off, clear strips + if (_output_port) { _output_port->drain (10000, 250000); /* check every 10 msecs, wait up to 1/4 second for the port to drain */ DEBUG_TRACE (DEBUG::FaderPort8, string_compose ("unregistering output port %1\n", boost::shared_ptr(_output_port)->name())); + Glib::Threads::Mutex::Lock em (AudioEngine::instance()->process_lock()); AudioEngine::instance()->unregister_port (_output_port); _output_port.reset (); } tear_down_gui (); - - /* stop event loop */ - DEBUG_TRACE (DEBUG::FaderPort8, "BaseUI::quit ()\n"); - BaseUI::quit (); } /* **************************************************************************** @@ -183,46 +195,50 @@ FaderPort8::do_request (FaderPort8Request* req) call_slot (MISSING_INVALIDATOR, req->the_slot); } else if (req->type == Quit) { stop (); + disconnected (); } } -int +void FaderPort8::stop () { + DEBUG_TRACE (DEBUG::FaderPort8, "BaseUI::quit ()\n"); BaseUI::quit (); - return 0; + close (); // drop references, disconnect from session signals } void FaderPort8::thread_init () { - struct sched_param rtparam; - pthread_set_name (event_loop_name().c_str()); PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048); ARDOUR::SessionEvent::create_per_thread_pool (event_loop_name(), 128); - memset (&rtparam, 0, sizeof (rtparam)); - rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */ - - if (pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam) != 0) { - // do we care? not particularly. - } + set_thread_priority (); } bool FaderPort8::periodic () { - /* prepare TC display -- handled by stripable Periodic () */ - if (_ctrls.display_timecode ()) { - // TODO allow BBT, HHMMSS - // used in FP8Strip::periodic_update_timecode + /* prepare TC display -- handled by stripable Periodic () + * in FP8Strip::periodic_update_timecode + */ + if (_ctrls.display_timecode () && clock_mode ()) { Timecode::Time TC; session->timecode_time (TC); _timecode = Timecode::timecode_format_time(TC); + + char buf[16]; + Timecode::BBT_Time BBT = session->tempo_map ().bbt_at_frame (session->transport_frame ()); + snprintf (buf, sizeof (buf), + " %02" PRIu32 "|%02" PRIu32 "|%02" PRIu32 "|%02" PRIu32, + BBT.bars % 100, BBT.beats %100, + (BBT.ticks/ 100) %100, BBT.ticks %100); + _musical_time = std::string (buf); } else { _timecode.clear (); + _musical_time.clear (); } /* update stripables */ @@ -255,8 +271,7 @@ FaderPort8::set_active (bool yn) BaseUI::run (); connect_session_signals (); } else { - BaseUI::quit (); - close (); + stop (); } ControlProtocol::set_active (yn); @@ -302,7 +317,8 @@ FaderPort8::connected () // ideally check firmware version >= 1.01 (USB bcdDevice 0x0101) (vendor 0x194f prod 0x0202) // but we don't have a handle to the underlying USB device here. - _channel_off = _plugin_off = _parameter_off = 0; + memset (_channel_off, 0, sizeof (_channel_off)); + _plugin_off = _parameter_off = 0; _blink_onoff = false; _shift_lock = false; _shift_pressed = 0; @@ -320,7 +336,7 @@ FaderPort8::connected () tx_midi3 (0x90, 0x46, 0x00); send_session_state (); - assign_strips (true); + assign_strips (); Glib::RefPtr blink_timer = Glib::TimeoutSource::create (200); @@ -445,7 +461,7 @@ FaderPort8::midi_input_handler (Glib::IOCondition ioc, boost::weak_ptr port (wport.lock()); - if (!port) { + if (!port || !_input_port) { return false; } @@ -685,6 +701,10 @@ FaderPort8::get_state () child->add_child_nocopy (boost::shared_ptr(_output_port)->get_state()); node.add_child_nocopy (*child); + node.set_property (X_("clock-mode"), _clock_mode); + node.set_property (X_("scribble-mode"), _scribble_mode); + node.set_property (X_("two-line-text"), _two_line_text); + for (UserActionMap::const_iterator i = _user_action_map.begin (); i != _user_action_map.end (); ++i) { if (i->second.empty()) { continue; @@ -694,12 +714,12 @@ FaderPort8::get_state () continue; } XMLNode* btn = new XMLNode (X_("Button")); - btn->add_property (X_("id"), name); + btn->set_property (X_("id"), name); if (!i->second.action(true).empty ()) { - btn->add_property ("press", i->second.action(true)._action_name); + btn->set_property ("press", i->second.action(true)._action_name); } if (!i->second.action(false).empty ()) { - btn->add_property ("release", i->second.action(false)._action_name); + btn->set_property ("release", i->second.action(false)._action_name); } node.add_child_nocopy (*btn); } @@ -735,6 +755,10 @@ FaderPort8::set_state (const XMLNode& node, int version) } } + node.get_property (X_("clock-mode"), _clock_mode); + node.get_property (X_("scribble-mode"), _scribble_mode); + node.get_property (X_("two-line-text"), _two_line_text); + _user_action_map.clear (); // TODO: When re-loading state w/o surface re-init becomes possible, // unset lights and reset colors of user buttons. @@ -743,23 +767,23 @@ FaderPort8::set_state (const XMLNode& node, int version) if ((*n)->name() != X_("Button")) { continue; } - XMLProperty const* prop = (*n)->property (X_("id")); - if (!prop) { + + std::string id_str; + if (!(*n)->get_property (X_("id"), id_str)) { continue; } FP8Controls::ButtonId id; - if (!_ctrls.button_name_to_enum (prop->value(), id)) { + if (!_ctrls.button_name_to_enum (id_str, id)) { continue; } - prop = (*n)->property (X_("press")); - if (prop) { - set_button_action (id, true, prop->value()); + std::string action_str; + if ((*n)->get_property (X_("press"), action_str)) { + set_button_action (id, true, action_str); } - prop = (*n)->property (X_("release")); - if (prop) { - set_button_action (id, false, prop->value()); + if ((*n)->get_property (X_("release"), action_str)) { + set_button_action (id, false, action_str); } } @@ -834,52 +858,6 @@ static bool flt_instrument (boost::shared_ptr s) { return 0 != r->the_instrument (); } -struct FP8SortByNewDisplayOrder -{ - // return (a < b) - bool operator () (const boost::shared_ptr & a, const boost::shared_ptr & b) const - { - if (a->presentation_info().flags () == b->presentation_info().flags ()) { - return a->presentation_info().order() < b->presentation_info().order(); - } - - int cmp_a = 0; - int cmp_b = 0; - - if (a->presentation_info().flags () & ARDOUR::PresentationInfo::VCA) { - cmp_a = 1; - } -#ifdef MIXBUS - else if (a->presentation_info().flags () & ARDOUR::PresentationInfo::MasterOut) { - cmp_a = 3; - } - else if (a->presentation_info().flags () & ARDOUR::PresentationInfo::Mixbus || a->mixbus()) { - cmp_a = 2; - } -#endif - - if (b->presentation_info().flags () & ARDOUR::PresentationInfo::VCA) { - cmp_b = 1; - } -#ifdef MIXBUS - else if (b->presentation_info().flags () & ARDOUR::PresentationInfo::MasterOut) { - cmp_b = 3; - } - else if (b->presentation_info().flags () & ARDOUR::PresentationInfo::Mixbus || b->mixbus()) { - cmp_b = 2; - } -#endif - -#ifdef MIXBUS - // this can happen with older MB sessions (no PresentationInfo::Mixbus flag) - if (cmp_a == cmp_b) { - return a->presentation_info().order() < b->presentation_info().order(); - } -#endif - return cmp_a < cmp_b; - } -}; - void FaderPort8::filter_stripables (StripableList& strips) const { @@ -920,6 +898,9 @@ FaderPort8::filter_stripables (StripableList& strips) const case MixFX: flt = &flt_auxbus; break; + default: + assert (0); + // fall through case MixAll: allow_master = true; flt = &flt_all; @@ -940,10 +921,10 @@ FaderPort8::filter_stripables (StripableList& strips) const strips.push_back (*s); } } - strips.sort (FP8SortByNewDisplayOrder()); + strips.sort (Stripable::Sorter(true)); } -/* Track/Pan mode: assign stripable to strips */ +/* Track/Pan mode: assign stripable to strips, Send-mode: selection */ void FaderPort8::assign_stripables (bool select_only) { @@ -955,11 +936,13 @@ FaderPort8::assign_stripables (bool select_only) } int n_strips = strips.size(); - _channel_off = std::min (_channel_off, n_strips - 8); - _channel_off = std::max (0, _channel_off); + int channel_off = get_channel_off (_ctrls.mix_mode ()); + channel_off = std::min (channel_off, n_strips - 8); + channel_off = std::max (0, channel_off); + set_channel_off (_ctrls.mix_mode (), channel_off); uint8_t id = 0; - int skip = _channel_off; + int skip = channel_off; for (StripableList::const_iterator s = strips.begin(); s != strips.end(); ++s) { if (skip > 0) { --skip; @@ -976,6 +959,7 @@ FaderPort8::assign_stripables (bool select_only) boost::bind (&FaderPort8::notify_stripable_property_changed, this, boost::weak_ptr (*s), _1), this); if (select_only) { + /* used in send mode */ _ctrls.strip(id).set_text_line (3, (*s)->name (), true); _ctrls.strip(id).select_button ().set_color ((*s)->presentation_info ().color()); /* update selection lights */ @@ -994,6 +978,102 @@ FaderPort8::assign_stripables (bool select_only) } for (; id < 8; ++id) { _ctrls.strip(id).unset_controllables (select_only ? (FP8Strip::CTRL_SELECT | FP8Strip::CTRL_TEXT3) : FP8Strip::CTRL_ALL); + _ctrls.strip(id).set_periodic_display_mode (FP8Strip::Stripables); + } +} + +/* **************************************************************************** + * Control Link/Lock + */ + +void +FaderPort8::unlock_link (bool drop) +{ + link_locked_connection.disconnect (); + + if (drop) { + stop_link (); // calls back here with drop = false + return; + } + + _link_locked = false; + + if (_link_enabled) { + assert (_ctrls.button (FP8Controls::BtnLink).is_active ()); + _link_control.reset (); + start_link (); // re-connect & update LED colors + } else { + _ctrls.button (FP8Controls::BtnLink).set_active (false); + _ctrls.button (FP8Controls::BtnLink).set_color (0x888888ff); + _ctrls.button (FP8Controls::BtnLock).set_active (false); + _ctrls.button (FP8Controls::BtnLock).set_color (0x888888ff); + } +} + +void +FaderPort8::lock_link () +{ + boost::shared_ptr ac = boost::dynamic_pointer_cast (_link_control.lock ()); + if (!ac) { + return; + } + ac->DropReferences.connect (link_locked_connection, MISSING_INVALIDATOR, boost::bind (&FaderPort8::unlock_link, this, true), this); + + // stop watching for focus events + link_connection.disconnect (); + + _link_locked = true; + + _ctrls.button (FP8Controls::BtnLock).set_color (0x00ff00ff); + _ctrls.button (FP8Controls::BtnLink).set_color (0x00ff00ff); +} + +void +FaderPort8::stop_link () +{ + if (!_link_enabled) { + return; + } + link_connection.disconnect (); + _link_control.reset (); + _link_enabled = false; + unlock_link (); // also updates button colors +} + +void +FaderPort8::start_link () +{ + assert (!_link_locked); + + _link_enabled = true; + _ctrls.button (FP8Controls::BtnLink).set_active (true); + _ctrls.button (FP8Controls::BtnLock).set_active (true); + nofity_focus_control (_link_control); // update BtnLink, BtnLock colors + + PBD::Controllable::GUIFocusChanged.connect (link_connection, MISSING_INVALIDATOR, boost::bind (&FaderPort8::nofity_focus_control, this, _1), this); +} + + +/* **************************************************************************** + * Plugin selection and parameters + */ + +void +FaderPort8::toggle_preset_param_mode () +{ + FaderMode fadermode = _ctrls.fader_mode (); + if (fadermode != ModePlugins || _proc_params.size() == 0) { + return; + } + _show_presets = ! _show_presets; + assign_processor_ctrls (); +} + +void +FaderPort8::preset_changed () +{ + if (_show_presets) { + assign_processor_ctrls (); } } @@ -1006,6 +1086,13 @@ FaderPort8::assign_processor_ctrls () } set_periodic_display_mode (FP8Strip::PluginParam); + if (_show_presets) { + if (assign_plugin_presets (_plugin_insert.lock ())) { + return; + } + _show_presets = false; + } + std::vector toggle_params; std::vector slider_params; @@ -1025,25 +1112,27 @@ FaderPort8::assign_processor_ctrls () uint8_t id = 0; for (size_t i = _parameter_off; i < (size_t)n_parameters; ++i) { if (i >= toggle_params.size ()) { - _ctrls.strip(id).unset_controllables (FP8Strip::CTRL_ALL & ~FP8Strip::CTRL_FADER & ~FP8Strip::CTRL_TEXT0 & ~FP8Strip::CTRL_TEXT1); + _ctrls.strip(id).unset_controllables (FP8Strip::CTRL_ALL & ~FP8Strip::CTRL_FADER & ~FP8Strip::CTRL_TEXT01 & ~FP8Strip::CTRL_TEXT2); } else if (i >= slider_params.size ()) { _ctrls.strip(id).unset_controllables (FP8Strip::CTRL_ALL & ~FP8Strip::CTRL_SELECT & ~FP8Strip::CTRL_TEXT3); } else { - _ctrls.strip(id).unset_controllables (FP8Strip::CTRL_ALL & ~FP8Strip::CTRL_FADER & ~FP8Strip::CTRL_TEXT0 & ~FP8Strip::CTRL_TEXT1 & ~FP8Strip::CTRL_SELECT & ~FP8Strip::CTRL_TEXT3); + _ctrls.strip(id).unset_controllables (FP8Strip::CTRL_ALL & ~FP8Strip::CTRL_FADER & ~FP8Strip::CTRL_TEXT & ~FP8Strip::CTRL_SELECT); } if (i < slider_params.size ()) { _ctrls.strip(id).set_fader_controllable (slider_params[i]->ac); - _ctrls.strip(id).set_text_line (0, slider_params[i]->name); + std::string param_name = slider_params[i]->name; + _ctrls.strip(id).set_text_line (0, param_name.substr (0, 9)); + _ctrls.strip(id).set_text_line (1, param_name.length () > 9 ? param_name.substr (9) : ""); } if (i < toggle_params.size ()) { _ctrls.strip(id).set_select_controllable (toggle_params[i]->ac); _ctrls.strip(id).set_text_line (3, toggle_params[i]->name, true); } - if (++id == 8) { - break; - } + if (++id == 8) { + break; + } } // clear remaining @@ -1052,6 +1141,65 @@ FaderPort8::assign_processor_ctrls () } } +bool +FaderPort8::assign_plugin_presets (boost::shared_ptr pi) +{ + if (!pi) { + return false; + } + boost::shared_ptr plugin = pi->plugin (); + + std::vector presets = plugin->get_presets (); + if (presets.size () == 0) { + return false; + } + + int n_parameters = presets.size (); + + _parameter_off = std::min (_parameter_off, n_parameters - 7); + _parameter_off = std::max (0, _parameter_off); + Plugin::PresetRecord active = plugin->last_preset (); + + uint8_t id = 0; + for (size_t i = _parameter_off; i < (size_t)n_parameters; ++i) { + _ctrls.strip(id).unset_controllables (FP8Strip::CTRL_ALL & ~FP8Strip::CTRL_TEXT01 & ~FP8Strip::CTRL_TEXT3 & ~FP8Strip::CTRL_SELECT); + boost::function cb (boost::bind (&FaderPort8::select_plugin_preset, this, i)); + _ctrls.strip(id).set_select_cb (cb); + _ctrls.strip(id).select_button ().set_active (true); + if (active != presets.at(i)) { + _ctrls.strip(id).select_button ().set_color (0x0000ffff); + _ctrls.strip(id).select_button ().set_blinking (false); + } else { + _ctrls.strip(id).select_button ().set_color (0x00ffffff); + _ctrls.strip(id).select_button ().set_blinking (plugin->parameter_changed_since_last_preset ()); + } + std::string label = presets.at(i).label; + _ctrls.strip(id).set_text_line (0, label.substr (0, 9)); + _ctrls.strip(id).set_text_line (1, label.length () > 9 ? label.substr (9) : ""); + _ctrls.strip(id).set_text_line (3, "PRESET", true); + if (++id == 7) { + break; + } + } + + // clear remaining + for (; id < 7; ++id) { + _ctrls.strip(id).unset_controllables (); + } + + // pin clear-preset to the last slot + assert (id == 7); + _ctrls.strip(id).unset_controllables (FP8Strip::CTRL_ALL & ~FP8Strip::CTRL_TEXT0 & ~FP8Strip::CTRL_TEXT3 & ~FP8Strip::CTRL_SELECT); + boost::function cb (boost::bind (&FaderPort8::select_plugin_preset, this, SIZE_MAX)); + _ctrls.strip(id).set_select_cb (cb); + _ctrls.strip(id).select_button ().set_blinking (false); + _ctrls.strip(id).select_button ().set_color (active.uri.empty() ? 0x00ffffff : 0x0000ffff); + _ctrls.strip(id).select_button ().set_active (true); + _ctrls.strip(id).set_text_line (0, _("(none)")); + _ctrls.strip(id).set_text_line (3, "PRESET", true); + return true; +} + void FaderPort8::build_well_known_processor_ctrls (boost::shared_ptr s, bool eq) { @@ -1060,8 +1208,17 @@ FaderPort8::build_well_known_processor_ctrls (boost::shared_ptr s, bo _proc_params.clear (); if (eq) { int cnt = s->eq_band_cnt(); - PUSH_BACK_NON_NULL ("Enable", s->eq_enable_controllable ()); - PUSH_BACK_NON_NULL ("HPF", s->eq_hpf_controllable ()); + +#ifdef MIXBUS32C + PUSH_BACK_NON_NULL ("Flt In", s->filter_enable_controllable (true)); // both HP/LP + PUSH_BACK_NON_NULL ("HP Freq", s->filter_freq_controllable (true)); + PUSH_BACK_NON_NULL ("LP Freq", s->filter_freq_controllable (false)); + PUSH_BACK_NON_NULL ("EQ In", s->eq_enable_controllable ()); +#elif defined (MIXBUS) + PUSH_BACK_NON_NULL ("EQ In", s->eq_enable_controllable ()); + PUSH_BACK_NON_NULL ("HP Freq", s->filter_freq_controllable (true)); +#endif + for (int band = 0; band < cnt; ++band) { std::string bn = s->eq_band_name (band); PUSH_BACK_NON_NULL (string_compose ("Gain %1", bn), s->eq_gain_controllable (band)); @@ -1070,7 +1227,7 @@ FaderPort8::build_well_known_processor_ctrls (boost::shared_ptr s, bo PUSH_BACK_NON_NULL (string_compose ("Shape %1", bn), s->eq_shape_controllable (band)); } } else { - PUSH_BACK_NON_NULL ("Enable", s->comp_enable_controllable ()); + PUSH_BACK_NON_NULL ("Comp In", s->comp_enable_controllable ()); PUSH_BACK_NON_NULL ("Threshold", s->comp_threshold_controllable ()); PUSH_BACK_NON_NULL ("Speed", s->comp_speed_controllable ()); PUSH_BACK_NON_NULL ("Mode", s->comp_mode_controllable ()); @@ -1081,13 +1238,30 @@ void FaderPort8::select_plugin (int num) { // make sure drop_ctrl_connections() was called - assert (_proc_params.size() == 0 && _showing_well_known == 0); + assert (_proc_params.size() == 0 && _showing_well_known == 0 && _plugin_insert.expired()); boost::shared_ptr r = boost::dynamic_pointer_cast (first_selected_stripable()); if (!r) { _ctrls.set_fader_mode (ModeTrack); return; } + + // Toggle Bypass + if (shift_mod ()) { + if (num >= 0) { + boost::shared_ptr pi = boost::dynamic_pointer_cast (r->nth_plugin (num)); +#ifdef MIXBUS + if (pi && !pi->is_channelstrip () && pi->display_to_user ()) +#else + if (pi && pi->display_to_user ()) +#endif + { + pi->enable (! pi->enabled ()); + } + } + return; + } + if (num < 0) { build_well_known_processor_ctrls (r, num == -1); assign_processor_ctrls (); @@ -1102,6 +1276,33 @@ FaderPort8::select_plugin (int num) return; } + // disconnect signals from spill_plugins: processors_changed and ActiveChanged + processor_connections.drop_connections (); + r->DropReferences.connect (processor_connections, MISSING_INVALIDATOR, boost::bind (&FP8Controls::set_fader_mode, &_ctrls, ModeTrack), this); + + boost::shared_ptr pi = boost::dynamic_pointer_cast (proc); + assert (pi); // nth_plugin() always returns a PI. + /* _plugin_insert is used for Bypass/Enable & presets */ +#ifdef MIXBUS + if (!pi->is_channelstrip () && pi->display_to_user ()) +#else + if (pi->display_to_user ()) +#endif + { + _plugin_insert = boost::weak_ptr (pi); + pi->ActiveChanged.connect (processor_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::notify_plugin_active_changed, this), this); + boost::shared_ptr plugin = pi->plugin (); + + plugin->PresetAdded.connect (processor_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::preset_changed, this), this); + plugin->PresetRemoved.connect (processor_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::preset_changed, this), this); + plugin->PresetLoaded.connect (processor_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::preset_changed, this), this); + plugin->PresetDirty.connect (processor_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::preset_changed, this), this); + + if (_auto_pluginui) { + pi->ShowUI (); /* EMIT SIGNAL */ + } + } + // switching to "Mode Track" -> calls FaderPort8::notify_fader_mode_changed() // which drops the references, disconnects the signal and re-spills tracks proc->DropReferences.connect (processor_connections, MISSING_INVALIDATOR, boost::bind (&FP8Controls::set_fader_mode, &_ctrls, ModeTrack), this); @@ -1121,6 +1322,28 @@ FaderPort8::select_plugin (int num) // display assign_processor_ctrls (); + notify_plugin_active_changed (); +} + +void +FaderPort8::select_plugin_preset (size_t num) +{ + assert (_proc_params.size() > 0); + boost::shared_ptr pi = _plugin_insert.lock(); + if (!pi) { + _ctrls.set_fader_mode (ModeTrack); + return; + } + if (num == SIZE_MAX) { + pi->plugin ()->clear_preset (); + } else { + std::vector presets = pi->plugin ()->get_presets (); + if (num < presets.size ()) { + pi->load_preset (presets.at (num)); + } + } + _show_presets = false; + assign_processor_ctrls (); } /* short 4 chars at most */ @@ -1177,8 +1400,8 @@ FaderPort8::spill_plugins () } int n_controls = 0; set p = proc->what_can_be_automated (); - for (set::iterator i = p.begin(); i != p.end(); ++i) { - std::string n = proc->describe_parameter (*i); + for (set::iterator j = p.begin(); j != p.end(); ++j) { + std::string n = proc->describe_parameter (*j); if (n == "hidden") { continue; } @@ -1228,14 +1451,16 @@ FaderPort8::spill_plugins () _ctrls.strip(id).unset_controllables (FP8Strip::CTRL_ALL & ~FP8Strip::CTRL_TEXT & ~FP8Strip::CTRL_SELECT); _ctrls.strip(id).set_select_cb (cb); - _ctrls.strip(id).select_button ().set_color (0x00ff00ff); - _ctrls.strip(id).select_button ().set_active (true /*proc->enabled()*/); + _ctrls.strip(id).select_button ().set_color (proc->enabled () ? 0x00ff00ff : 0xff0000ff); + _ctrls.strip(id).select_button ().set_active (true); _ctrls.strip(id).select_button ().set_blinking (false); _ctrls.strip(id).set_text_line (0, proc->name()); _ctrls.strip(id).set_text_line (1, pi->plugin()->maker()); _ctrls.strip(id).set_text_line (2, plugintype (pi->type())); _ctrls.strip(id).set_text_line (3, ""); + pi->ActiveChanged.connect (processor_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::spill_plugins, this), this); + if (++id == spillwidth) { break; } @@ -1276,6 +1501,10 @@ FaderPort8::spill_plugins () assert (id == 8); } +/* **************************************************************************** + * Aux Sends and Mixbus assigns + */ + void FaderPort8::assign_sends () { @@ -1314,7 +1543,7 @@ FaderPort8::assign_sends () break; } - _ctrls.strip(id).unset_controllables (FP8Strip::CTRL_ALL & ~FP8Strip::CTRL_FADER & ~FP8Strip::CTRL_TEXT0 & ~FP8Strip::CTRL_TEXT1 & ~FP8Strip::CTRL_TEXT3 & ~FP8Strip::CTRL_SELECT); + _ctrls.strip(id).unset_controllables (FP8Strip::CTRL_ALL & ~FP8Strip::CTRL_FADER & ~FP8Strip::CTRL_TEXT01 & ~FP8Strip::CTRL_TEXT3 & ~FP8Strip::CTRL_SELECT); _ctrls.strip(id).set_fader_controllable (send); _ctrls.strip(id).set_text_line (0, s->send_name (i)); _ctrls.strip(id).set_mute_controllable (s->send_enable_controllable (i)); @@ -1336,21 +1565,13 @@ FaderPort8::assign_sends () assign_stripables (true); } -void -FaderPort8::set_periodic_display_mode (FP8Strip::DisplayMode m) -{ - for (uint8_t id = 0; id < 8; ++id) { - _ctrls.strip(id).set_periodic_display_mode (m); - } -} +/* **************************************************************************** + * Main stripable assignment (dispatch depending on mode) + */ void -FaderPort8::assign_strips (bool reset_bank) +FaderPort8::assign_strips () { - if (reset_bank) { - _channel_off = 0; - } - assigned_stripable_connections.drop_connections (); _assigned_strips.clear (); @@ -1359,7 +1580,7 @@ FaderPort8::assign_strips (bool reset_bank) case ModeTrack: case ModePan: assign_stripables (); - gui_track_selection_changed (); // update selection, automation-state + stripable_selection_changed (); // update selection, automation-state break; case ModePlugins: if (_proc_params.size() > 0) { @@ -1374,15 +1595,87 @@ FaderPort8::assign_strips (bool reset_bank) } } +/* **************************************************************************** + * some helper functions + */ + +void +FaderPort8::set_periodic_display_mode (FP8Strip::DisplayMode m) +{ + for (uint8_t id = 0; id < 8; ++id) { + _ctrls.strip(id).set_periodic_display_mode (m); + } +} void FaderPort8::drop_ctrl_connections () { _proc_params.clear(); + if (_auto_pluginui) { + boost::shared_ptr pi = _plugin_insert.lock (); + if (pi) { + pi->HideUI (); /* EMIT SIGNAL */ + } + } + _plugin_insert.reset (); + _show_presets = false; processor_connections.drop_connections (); _showing_well_known = 0; + notify_plugin_active_changed (); +} + +/* functor for FP8Strip's select button */ +void +FaderPort8::select_strip (boost::weak_ptr ws) +{ + boost::shared_ptr s = ws.lock(); + if (!s) { + return; + } +#if 1 /* single exclusive selection by default, toggle via shift */ + +# if 1 /* selecting a selected strip -> move fader to unity */ + if (s == first_selected_stripable () && !shift_mod ()) { + if (_ctrls.fader_mode () == ModeTrack) { + boost::shared_ptr ac = s->gain_control (); + ac->start_touch (ac->session().transport_frame()); + ac->set_value (ac->normal (), PBD::Controllable::UseGroup); + } + return; + } +# endif + + if (shift_mod ()) { + ToggleStripableSelection (s); + } else { + SetStripableSelection (s); + } +#else + /* tri-state selection: This allows to set the "first selected" + * with a single click without clearing the selection. + * Single de/select via shift. + */ + if (shift_mod ()) { + if (s->is_selected ()) { + RemoveStripableFromSelection (s); + } else { + SetStripableSelection (s); + } + return; + } + if (s->is_selected () && s != first_selected_stripable ()) { + set_first_selected_stripable (s); + stripable_selection_changed (); + } else { + ToggleStripableSelection (s); + } +#endif } +/* **************************************************************************** + * Assigned Stripable Callbacks + */ + void FaderPort8::notify_fader_mode_changed () { @@ -1404,19 +1697,16 @@ FaderPort8::notify_fader_mode_changed () case ModeSend: _plugin_off = 0; _parameter_off = 0; + stop_link (); // force unset rec-arm button, see also FaderPort8::button_arm _ctrls.button (FP8Controls::BtnArm).set_active (false); ARMButtonChange (false); break; } - assign_strips (false); + assign_strips (); notify_automation_mode_changed (); } -/* **************************************************************************** - * Assigned Stripable Callbacks - */ - void FaderPort8::notify_stripable_added_or_removed () { @@ -1427,43 +1717,7 @@ FaderPort8::notify_stripable_added_or_removed () * - Properties::hidden * - Properties::order */ - assign_strips (false); -} - -/* functor for FP8Strip's select button */ -void -FaderPort8::select_strip (boost::weak_ptr ws) -{ - boost::shared_ptr s = ws.lock(); - if (!s) { - return; - } -#if 1 /* single exclusive selection by default, toggle via shift */ - if (shift_mod ()) { - ToggleStripableSelection (s); - } else { - SetStripableSelection (s); - } -#else - /* tri-state selection: This allows to set the "first selected" - * with a single click without clearing the selection. - * Single de/select via shift. - */ - if (shift_mod ()) { - if (s->is_selected ()) { - RemoveStripableFromSelection (s); - } else { - SetStripableSelection (s); - } - return; - } - if (s->is_selected () && s != first_selected_stripable ()) { - set_first_selected_stripable (s); - gui_track_selection_changed (); - } else { - ToggleStripableSelection (s); - } -#endif + assign_strips (); } /* called from static PresentationInfo::Change */ @@ -1523,8 +1777,14 @@ FaderPort8::notify_stripable_property_changed (boost::weak_ptr ws, co } void -FaderPort8::gui_track_selection_changed (/*ARDOUR::StripableNotificationListPtr*/) +FaderPort8::stripable_selection_changed () { + if (!_device_active) { + /* this can be called anytime from the static + * ControlProtocol::StripableSelectionChanged + */ + return; + } automation_state_connections.drop_connections(); switch (_ctrls.fader_mode ()) { @@ -1593,16 +1853,18 @@ FaderPort8::move_selected_into_view () } int off = std::distance (strips.begin(), it); - if (_channel_off <= off && off < _channel_off + 8) { + int channel_off = get_channel_off (_ctrls.mix_mode ()); + if (channel_off <= off && off < channel_off + 8) { return; } - if (_channel_off > off) { - _channel_off = off; + if (channel_off > off) { + channel_off = off; } else { - _channel_off = off - 7; + channel_off = off - 7; } - assign_strips (false); + set_channel_off (_ctrls.mix_mode (), channel_off); + assign_strips (); } void @@ -1655,8 +1917,8 @@ FaderPort8::bank (bool down, bool page) if (down) { dt *= -1; } - _channel_off += dt; - assign_strips (false); + set_channel_off (_ctrls.mix_mode (), get_channel_off (_ctrls.mix_mode ()) + dt); + assign_strips (); } void