X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fsurfaces%2Ffaderport8%2Ffaderport8.cc;h=bbb85faac505cf1f3da08d5460bfef51310b13f4;hb=c0d333ba9cdf7ec4039ad34eb765e6a077430eb7;hp=d01c48f57fc64eb6910b8b604a9def9607822c97;hpb=10db824461e3bd8eb0661ddfb35da283192e8c29;p=ardour.git diff --git a/libs/surfaces/faderport8/faderport8.cc b/libs/surfaces/faderport8/faderport8.cc index d01c48f57f..bbb85faac5 100644 --- a/libs/surfaces/faderport8/faderport8.cc +++ b/libs/surfaces/faderport8/faderport8.cc @@ -37,22 +37,25 @@ #include "ardour/debug.h" #include "ardour/midi_track.h" #include "ardour/midiport_manager.h" +#include "ardour/panner_shell.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" using namespace ARDOUR; -using namespace ArdourSurface; using namespace PBD; using namespace Glib; using namespace std; -using namespace ArdourSurface::FP8Types; +using namespace ArdourSurface::FP_NAMESPACE; +using namespace ArdourSurface::FP_NAMESPACE::FP8Types; #include "pbd/i18n.h" @@ -84,24 +87,41 @@ debug_2byte_msg (std::string const& msg, int b0, int b1) } FaderPort8::FaderPort8 (Session& s) +#ifdef FADERPORT16 + : ControlProtocol (s, _("PreSonus FaderPort16")) +#else : ControlProtocol (s, _("PreSonus FaderPort8")) +#endif , AbstractUI (name()) , _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) + , _timer_divider (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; +#ifdef FADERPORT16 + inp = AudioEngine::instance()->register_input_port (DataType::MIDI, "FaderPort16 Recv", true); + outp = AudioEngine::instance()->register_output_port (DataType::MIDI, "FaderPort16 Send", true); +#else inp = AudioEngine::instance()->register_input_port (DataType::MIDI, "FaderPort8 Recv", true); outp = AudioEngine::instance()->register_output_port (DataType::MIDI, "FaderPort8 Send", true); +#endif _input_port = boost::dynamic_pointer_cast(inp); _output_port = boost::dynamic_pointer_cast(outp); @@ -109,8 +129,13 @@ FaderPort8::FaderPort8 (Session& s) throw failed_constructor(); } +#ifdef FADERPORT16 + _input_bundle.reset (new ARDOUR::Bundle (_("FaderPort16 (Receive)"), true)); + _output_bundle.reset (new ARDOUR::Bundle (_("FaderPort16 (Send) "), false)); +#else _input_bundle.reset (new ARDOUR::Bundle (_("FaderPort8 (Receive)"), true)); _output_bundle.reset (new ARDOUR::Bundle (_("FaderPort8 (Send) "), false)); +#endif _input_bundle->add_channel ( inp->name(), @@ -132,33 +157,36 @@ FaderPort8::FaderPort8 (Session& s) 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,48 +211,60 @@ 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_sample (session->transport_sample ()); + 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 (); } +#ifdef FADERPORT16 + /* every second, send "running" */ + if (++_timer_divider == 10) { + _timer_divider = 0; + tx_midi3 (0xa0, 0x00, 0x00); + } +#endif + /* update stripables */ Periodic (); return true; @@ -255,8 +295,7 @@ FaderPort8::set_active (bool yn) BaseUI::run (); connect_session_signals (); } else { - BaseUI::quit (); - close (); + stop (); } ControlProtocol::set_active (yn); @@ -302,10 +341,12 @@ 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; + _timer_divider = 0; start_midi_handling (); _ctrls.initialize (); @@ -320,7 +361,7 @@ FaderPort8::connected () tx_midi3 (0x90, 0x46, 0x00); send_session_state (); - assign_strips (true); + assign_strips (); Glib::RefPtr blink_timer = Glib::TimeoutSource::create (200); @@ -338,7 +379,7 @@ FaderPort8::disconnected () { stop_midi_handling (); if (_device_active) { - for (uint8_t id = 0; id < 8; ++id) { + for (uint8_t id = 0; id < N_STRIPS; ++id) { _ctrls.strip(id).unset_controllables (); } _ctrls.all_lights_off (); @@ -445,7 +486,7 @@ FaderPort8::midi_input_handler (Glib::IOCondition ioc, boost::weak_ptr port (wport.lock()); - if (!port) { + if (!port || !_input_port) { return false; } @@ -463,7 +504,7 @@ FaderPort8::midi_input_handler (Glib::IOCondition ioc, boost::weak_ptr(port)->name())); #endif - framepos_t now = session->engine().sample_time(); + samplepos_t now = session->engine().sample_time(); port->parse (now); } @@ -537,13 +578,17 @@ void FaderPort8::controller_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb) { debug_2byte_msg ("CC", tb->controller_number, tb->value); - // encoder - // val Bit 7 = direction, Bits 0-6 = number of steps + /* encoder + * val Bit 6 = direction, Bits 0-5 = number of steps + */ + static const uint8_t dir_mask = 0x40; + static const uint8_t step_mask = 0x3f; + if (tb->controller_number == 0x3c) { - encoder_navigate (tb->value & 0x40 ? true : false, tb->value & 0x3f); + encoder_navigate (tb->value & dir_mask ? true : false, tb->value & step_mask); } if (tb->controller_number == 0x10) { - encoder_parameter (tb->value & 0x40 ? true : false, tb->value & 0x3f); + encoder_parameter (tb->value & dir_mask ? true : false, tb->value & step_mask); } } @@ -553,7 +598,12 @@ FaderPort8::note_on_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb) debug_2byte_msg ("ON", tb->note_number, tb->velocity); /* fader touch */ - if (tb->note_number >= 0x68 && tb->note_number <= 0x6f) { +#ifdef FADERPORT16 + static const uint8_t touch_id_uppper = 0x77; +#else + static const uint8_t touch_id_uppper = 0x6f; +#endif + if (tb->note_number >= 0x68 && tb->note_number <= touch_id_uppper) { _ctrls.midi_touch (tb->note_number - 0x68, tb->velocity); return; } @@ -592,7 +642,12 @@ FaderPort8::note_off_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb) { debug_2byte_msg ("OF", tb->note_number, tb->velocity); - if (tb->note_number >= 0x68 && tb->note_number <= 0x6f) { +#ifdef FADERPORT16 + static const uint8_t touch_id_uppper = 0x77; +#else + static const uint8_t touch_id_uppper = 0x6f; +#endif + if (tb->note_number >= 0x68 && tb->note_number <= touch_id_uppper) { // fader touch _ctrls.midi_touch (tb->note_number - 0x68, tb->velocity); return; @@ -685,6 +740,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; @@ -735,6 +794,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. @@ -897,10 +960,10 @@ FaderPort8::filter_stripables (StripableList& strips) const strips.push_back (*s); } } - strips.sort (Stripable::Sorter()); + 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) { @@ -912,11 +975,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 - N_STRIPS); + 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; @@ -932,7 +997,15 @@ FaderPort8::assign_stripables (bool select_only) (*s)->presentation_info ().PropertyChanged.connect (assigned_stripable_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::notify_stripable_property_changed, this, boost::weak_ptr (*s), _1), this); + if (boost::shared_ptr r = boost::dynamic_pointer_cast(*s)) { + if (r->panner_shell()) { + r->panner_shell()->Changed.connect (assigned_stripable_connections, MISSING_INVALIDATOR, + boost::bind (&FaderPort8::notify_stripable_property_changed, this, boost::weak_ptr (*s), PropertyChange()), 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 */ @@ -945,19 +1018,111 @@ FaderPort8::assign_stripables (bool select_only) boost::function cb (boost::bind (&FaderPort8::select_strip, this, boost::weak_ptr (*s))); _ctrls.strip(id).set_select_cb (cb); - if (++id == 8) { + if (++id == N_STRIPS) { break; } } - for (; id < 8; ++id) { + for (; id < N_STRIPS; ++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 (); + } +} + void FaderPort8::assign_processor_ctrls () { @@ -967,6 +1132,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; @@ -980,37 +1152,98 @@ FaderPort8::assign_processor_ctrls () int n_parameters = std::max (toggle_params.size(), slider_params.size()); - _parameter_off = std::min (_parameter_off, n_parameters - 8); + _parameter_off = std::min (_parameter_off, n_parameters - N_STRIPS); _parameter_off = std::max (0, _parameter_off); 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 == N_STRIPS) { + break; + } + } + + // clear remaining + for (; id < N_STRIPS; ++id) { + _ctrls.strip(id).unset_controllables (); + } +} + +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 - (N_STRIPS - 1)); + _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 == (N_STRIPS - 1)) { + break; + } } // clear remaining - for (; id < 8; ++id) { + for (; id < (N_STRIPS - 1); ++id) { _ctrls.strip(id).unset_controllables (); } + + // pin clear-preset to the last slot + assert (id == (N_STRIPS - 1)); + _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 @@ -1051,13 +1284,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 (); @@ -1072,6 +1322,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); @@ -1091,6 +1368,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 */ @@ -1160,7 +1459,7 @@ FaderPort8::spill_plugins () } int n_plugins = procs.size(); - int spillwidth = 8; + int spillwidth = N_STRIPS; bool have_well_known_eq = false; bool have_well_known_comp = false; @@ -1198,14 +1497,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; } @@ -1216,7 +1517,7 @@ FaderPort8::spill_plugins () } if (have_well_known_comp) { - assert (id < 8); + assert (id < N_STRIPS); boost::function cb (boost::bind (&FaderPort8::select_plugin, this, -2)); _ctrls.strip(id).unset_controllables (FP8Strip::CTRL_ALL & ~FP8Strip::CTRL_TEXT & ~FP8Strip::CTRL_SELECT); _ctrls.strip(id).set_select_cb (cb); @@ -1230,7 +1531,7 @@ FaderPort8::spill_plugins () ++id; } if (have_well_known_eq) { - assert (id < 8); + assert (id < N_STRIPS); boost::function cb (boost::bind (&FaderPort8::select_plugin, this, -1)); _ctrls.strip(id).unset_controllables (FP8Strip::CTRL_ALL & ~FP8Strip::CTRL_TEXT & ~FP8Strip::CTRL_SELECT); _ctrls.strip(id).set_select_cb (cb); @@ -1243,7 +1544,7 @@ FaderPort8::spill_plugins () _ctrls.strip(id).set_text_line (3, ""); ++id; } - assert (id == 8); + assert (id == N_STRIPS); } /* **************************************************************************** @@ -1273,7 +1574,7 @@ FaderPort8::assign_sends () set_periodic_display_mode (FP8Strip::SendDisplay); - _plugin_off = std::min (_plugin_off, n_sends - 8); + _plugin_off = std::min (_plugin_off, n_sends - N_STRIPS); _plugin_off = std::max (0, _plugin_off); uint8_t id = 0; @@ -1288,21 +1589,21 @@ 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)); - if (++id == 8) { + if (++id == N_STRIPS) { break; } } // clear remaining - for (; id < 8; ++id) { + for (; id < N_STRIPS; ++id) { _ctrls.strip(id).unset_controllables (FP8Strip::CTRL_ALL & ~FP8Strip::CTRL_TEXT3 & ~FP8Strip::CTRL_SELECT); } #ifdef MIXBUS // master-assign on last solo - _ctrls.strip(7).set_solo_controllable (s->master_send_enable_controllable ()); + _ctrls.strip(N_STRIPS - 1).set_solo_controllable (s->master_send_enable_controllable ()); #endif /* set select buttons */ assigned_stripable_connections.drop_connections (); @@ -1315,12 +1616,8 @@ FaderPort8::assign_sends () */ void -FaderPort8::assign_strips (bool reset_bank) +FaderPort8::assign_strips () { - if (reset_bank) { - _channel_off = 0; - } - assigned_stripable_connections.drop_connections (); _assigned_strips.clear (); @@ -1351,7 +1648,7 @@ FaderPort8::assign_strips (bool reset_bank) void FaderPort8::set_periodic_display_mode (FP8Strip::DisplayMode m) { - for (uint8_t id = 0; id < 8; ++id) { + for (uint8_t id = 0; id < N_STRIPS; ++id) { _ctrls.strip(id).set_periodic_display_mode (m); } } @@ -1360,8 +1657,17 @@ 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 */ @@ -1373,6 +1679,18 @@ FaderPort8::select_strip (boost::weak_ptr ws) 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_sample()); + ac->set_value (ac->normal (), PBD::Controllable::UseGroup); + } + return; + } +# endif + if (shift_mod ()) { ToggleStripableSelection (s); } else { @@ -1425,12 +1743,13 @@ 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 (); } @@ -1444,7 +1763,7 @@ FaderPort8::notify_stripable_added_or_removed () * - Properties::hidden * - Properties::order */ - assign_strips (false); + assign_strips (); } /* called from static PresentationInfo::Change */ @@ -1487,6 +1806,10 @@ FaderPort8::notify_stripable_property_changed (boost::weak_ptr ws, co _ctrls.strip(id).select_button ().set_color (s->presentation_info ().color()); } + if (what_changed.empty ()) { + _ctrls.strip(id).set_stripable (s, _ctrls.fader_mode() == ModePan); + } + if (what_changed.contains (Properties::name)) { switch (_ctrls.fader_mode ()) { case ModeSend: @@ -1580,16 +1903,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 + N_STRIPS) { return; } - if (_channel_off > off) { - _channel_off = off; + if (channel_off > off) { + channel_off = off; } else { - _channel_off = off - 7; + channel_off = off - (N_STRIPS - 1); } - assign_strips (false); + set_channel_off (_ctrls.mix_mode (), channel_off); + assign_strips (); } void @@ -1638,18 +1963,18 @@ FaderPort8::select_prev_next (bool next) void FaderPort8::bank (bool down, bool page) { - int dt = page ? 8 : 1; + int dt = page ? N_STRIPS : 1; 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 FaderPort8::bank_param (bool down, bool page) { - int dt = page ? 8 : 1; + int dt = page ? N_STRIPS : 1; if (down) { dt *= -1; }