X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Frc_option_editor.cc;h=3569d939cc72580f83ca4b4498e2f8ae18423699;hb=a2c0b10d8a6cf4ab5a0fdcdfe157c35c0ed9a709;hp=8e562f4279805bfd06ba6f31bd4b96b718951f6d;hpb=094d08dc2b15e3565e62258e76097e9d1356bec6;p=ardour.git diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc index 8e562f4279..3569d939cc 100644 --- a/gtk2_ardour/rc_option_editor.cc +++ b/gtk2_ardour/rc_option_editor.cc @@ -41,32 +41,34 @@ #include "pbd/fpu.h" #include "pbd/cpus.h" +#include "pbd/i18n.h" +#include "ardour/audio_backend.h" #include "ardour/audioengine.h" #include "ardour/profile.h" #include "ardour/dB.h" #include "ardour/rc_configuration.h" #include "ardour/control_protocol_manager.h" +#include "ardour/port_manager.h" #include "ardour/plugin_manager.h" #include "control_protocol/control_protocol.h" #include "canvas/wave_view.h" -#include "ardour_window.h" #include "ardour_dialog.h" #include "ardour_ui.h" +#include "ardour_window.h" #include "color_theme_manager.h" #include "gui_thread.h" +#include "keyboard.h" #include "meter_patterns.h" #include "midi_tracer.h" #include "rc_option_editor.h" -#include "utils.h" -#include "midi_port_dialog.h" #include "sfdb_ui.h" -#include "keyboard.h" #include "theme_manager.h" +#include "tooltips.h" #include "ui_config.h" -#include "pbd/i18n.h" +#include "utils.h" using namespace std; using namespace Gtk; @@ -1853,6 +1855,292 @@ private: }; +class MidiPortOptions : public OptionEditorBox, public sigc::trackable +{ + public: + MidiPortOptions() { + + setup_midi_port_view (midi_output_view, false); + setup_midi_port_view (midi_input_view, true); + + + input_label.set_markup (string_compose ("%1", _("MIDI Inputs"))); + _box->pack_start (input_label, false, false); + _box->pack_start (midi_input_view); + + output_label.set_markup (string_compose ("%1", _("MIDI Outputs"))); + _box->pack_start (output_label, false, false); + _box->pack_start (midi_output_view); + + midi_output_view.show (); + midi_input_view.show (); + + _box->signal_show().connect (sigc::mem_fun (*this, &MidiPortOptions::on_show)); + } + + void parameter_changed (string const&) {} + void set_state_from_config() {} + + void on_show () { + refill (); + + AudioEngine::instance()->PortRegisteredOrUnregistered.connect (connections, + invalidator (*this), + boost::bind (&MidiPortOptions::refill, this), + gui_context()); + AudioEngine::instance()->MidiPortInfoChanged.connect (connections, + invalidator (*this), + boost::bind (&MidiPortOptions::refill, this), + gui_context()); + AudioEngine::instance()->MidiSelectionPortsChanged.connect (connections, + invalidator (*this), + boost::bind (&MidiPortOptions::refill, this), + gui_context()); + } + + void refill () { + + if (refill_midi_ports (true, midi_input_view)) { + input_label.show (); + } else { + input_label.hide (); + } + if (refill_midi_ports (false, midi_output_view)) { + output_label.show (); + } else { + output_label.hide (); + } + } + + private: + PBD::ScopedConnectionList connections; + + /* MIDI port management */ + struct MidiPortColumns : public Gtk::TreeModel::ColumnRecord { + + MidiPortColumns () { + add (pretty_name); + add (music_data); + add (control_data); + add (selection); + add (name); + add (filler); + } + + Gtk::TreeModelColumn pretty_name; + Gtk::TreeModelColumn music_data; + Gtk::TreeModelColumn control_data; + Gtk::TreeModelColumn selection; + Gtk::TreeModelColumn name; + Gtk::TreeModelColumn filler; + }; + + MidiPortColumns midi_port_columns; + Gtk::TreeView midi_input_view; + Gtk::TreeView midi_output_view; + Gtk::Label input_label; + Gtk::Label output_label; + + void setup_midi_port_view (Gtk::TreeView&, bool with_selection); + bool refill_midi_ports (bool for_input, Gtk::TreeView&); + void pretty_name_edit (std::string const & path, std::string const & new_text, Gtk::TreeView*); + void midi_music_column_toggled (std::string const & path, Gtk::TreeView*); + void midi_control_column_toggled (std::string const & path, Gtk::TreeView*); + void midi_selection_column_toggled (std::string const & path, Gtk::TreeView*); +}; + +void +MidiPortOptions::setup_midi_port_view (Gtk::TreeView& view, bool with_selection) +{ + int pretty_name_column; + int music_column; + int control_column; + int selection_column; + TreeViewColumn* col; + Gtk::Label* l; + + pretty_name_column = view.append_column_editable (_("Name (click to edit)"), midi_port_columns.pretty_name) - 1; + + col = manage (new TreeViewColumn ("", midi_port_columns.music_data)); + col->set_alignment (ALIGN_CENTER); + l = manage (new Label (_("Music Data"))); + set_tooltip (*l, string_compose (_("If ticked, %1 will consider this port to be a source of music performance data."), PROGRAM_NAME)); + col->set_widget (*l); + l->show (); + music_column = view.append_column (*col) - 1; + + col = manage (new TreeViewColumn ("", midi_port_columns.control_data)); + col->set_alignment (ALIGN_CENTER); + l = manage (new Label (_("Control Data"))); + set_tooltip (*l, string_compose (_("If ticked, %1 will consider this port to be a source of control data."), PROGRAM_NAME)); + col->set_widget (*l); + l->show (); + control_column = view.append_column (*col) - 1; + + if (with_selection) { + col = manage (new TreeViewColumn (_("Follow Selection"), midi_port_columns.selection)); + selection_column = view.append_column (*col) - 1; + l = manage (new Label (_("Follow Selection"))); + set_tooltip (*l, string_compose (_("If ticked, and \"MIDI input follows selection\" is enabled,\n%1 will automatically connect the first selected MIDI track to this port.\n"), PROGRAM_NAME)); + col->set_widget (*l); + l->show (); + } + + /* filler column so that the last real column doesn't expand */ + view.append_column ("", midi_port_columns.filler); + + CellRendererText* pretty_name_cell = dynamic_cast (view.get_column_cell_renderer (pretty_name_column)); + pretty_name_cell->property_editable() = true; + pretty_name_cell->signal_edited().connect (sigc::bind (sigc::mem_fun (*this, &MidiPortOptions::pretty_name_edit), &view)); + + CellRendererToggle* toggle_cell; + + toggle_cell = dynamic_cast (view.get_column_cell_renderer (music_column)); + toggle_cell->property_activatable() = true; + toggle_cell->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiPortOptions::midi_music_column_toggled), &view)); + + toggle_cell = dynamic_cast (view.get_column_cell_renderer (control_column)); + toggle_cell->property_activatable() = true; + toggle_cell->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiPortOptions::midi_control_column_toggled), &view)); + + if (with_selection) { + toggle_cell = dynamic_cast (view.get_column_cell_renderer (selection_column)); + toggle_cell->property_activatable() = true; + toggle_cell->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiPortOptions::midi_selection_column_toggled), &view)); + } + + view.get_selection()->set_mode (SELECTION_NONE); + view.set_tooltip_column (4); /* port "real" name */ +} + +bool +MidiPortOptions::refill_midi_ports (bool for_input, Gtk::TreeView& view) +{ + using namespace ARDOUR; + + std::vector ports; + + AudioEngine::instance()->get_known_midi_ports (ports); + + if (ports.empty()) { + view.hide (); + return false; + } + + Glib::RefPtr model = Gtk::ListStore::create (midi_port_columns); + + for (vector::const_iterator s = ports.begin(); s != ports.end(); ++s) { + + if (AudioEngine::instance()->port_is_mine (*s)) { + continue; + } + + PortManager::MidiPortInformation mpi (AudioEngine::instance()->midi_port_information (*s)); + + if (mpi.pretty_name.empty()) { + /* vanished since get_known_midi_ports() */ + continue; + } + + if (for_input != mpi.input) { + continue; + } + + TreeModel::Row row = *(model->append()); + + row[midi_port_columns.pretty_name] = mpi.pretty_name; + row[midi_port_columns.music_data] = mpi.properties & MidiPortMusic; + row[midi_port_columns.control_data] = mpi.properties & MidiPortControl; + row[midi_port_columns.selection] = mpi.properties & MidiPortSelection; + row[midi_port_columns.name] = *s; + } + + view.set_model (model); + + return true; +} + +void +MidiPortOptions::midi_music_column_toggled (string const & path, TreeView* view) +{ + TreeIter iter = view->get_model()->get_iter (path); + + if (!iter) { + return; + } + + bool new_value = ! bool ((*iter)[midi_port_columns.music_data]); + + /* don't reset model - wait for MidiPortInfoChanged signal */ + + if (new_value) { + ARDOUR::AudioEngine::instance()->add_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortMusic); + } else { + ARDOUR::AudioEngine::instance()->remove_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortMusic); + } +} + +void +MidiPortOptions::midi_control_column_toggled (string const & path, TreeView* view) +{ + TreeIter iter = view->get_model()->get_iter (path); + + if (!iter) { + return; + } + + bool new_value = ! bool ((*iter)[midi_port_columns.control_data]); + + /* don't reset model - wait for MidiPortInfoChanged signal */ + + if (new_value) { + ARDOUR::AudioEngine::instance()->add_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortControl); + } else { + ARDOUR::AudioEngine::instance()->remove_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortControl); + } +} + +void +MidiPortOptions::midi_selection_column_toggled (string const & path, TreeView* view) +{ + TreeIter iter = view->get_model()->get_iter (path); + + if (!iter) { + return; + } + + bool new_value = ! bool ((*iter)[midi_port_columns.selection]); + + /* don't reset model - wait for MidiSelectionPortsChanged signal */ + + if (new_value) { + ARDOUR::AudioEngine::instance()->add_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortSelection); + } else { + ARDOUR::AudioEngine::instance()->remove_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortSelection); + } +} + +void +MidiPortOptions::pretty_name_edit (std::string const & path, string const & new_text, Gtk::TreeView* view) +{ + TreeIter iter = view->get_model()->get_iter (path); + + if (!iter) { + return; + } + + boost::shared_ptr backend = ARDOUR::AudioEngine::instance()->current_backend(); + if (backend) { + ARDOUR::PortEngine::PortHandle ph = backend->get_port_by_name ((*iter)[midi_port_columns.name]); + if (ph) { + backend->set_port_property (ph, "http://jackaudio.org/metadata/pretty-name", new_text, ""); + (*iter)[midi_port_columns.pretty_name] = new_text; + } + } +} + +/*============*/ + RCOptionEditor::RCOptionEditor () : OptionEditorContainer (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME)) @@ -2248,6 +2536,14 @@ if (!Profile->get_mixbus()) { )); } // !mixbus + add_option (_("Editor"), + new BoolOption ( + "use-time-rulers-to-zoom-with-vertical-drag", + _("Use time rulers area to zoom when clicking and dragging vertically"), + sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_time_rulers_to_zoom_with_vertical_drag), + sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_time_rulers_to_zoom_with_vertical_drag) + )); + add_option (_("Editor"), new BoolOption ( "update-editor-during-summary-drag", @@ -2720,6 +3016,16 @@ if (!ARDOUR::Profile->get_mixbus()) { sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback) )); + add_option (_("MIDI/Ports"), + new BoolOption ( + "get-midi-input-follows-selection", + _("MIDI input follows MIDI track selection"), + sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_input_follows_selection), + sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_input_follows_selection) + )); + + add_option (_("MIDI/Ports"), new MidiPortOptions ()); + add_option (_("MIDI/Sync"), new OptionEditorHeading (_("MIDI Clock"))); add_option (_("MIDI/Sync"), @@ -2841,7 +3147,7 @@ if (!ARDOUR::Profile->get_mixbus()) { /* VIDEO Timeline */ add_option (_("Video"), new VideoTimelineOptions (_rc_config)); -#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT) +#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT) add_option (_("Plugins"), new RcActionButton (_("Scan for Plugins"), sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh))); @@ -2850,7 +3156,7 @@ if (!ARDOUR::Profile->get_mixbus()) { add_option (_("Plugins"), new OptionEditorHeading (_("General"))); -#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT) +#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT) bo = new BoolOption ( "show-plugin-scan-window", _("Always Display Plugin Scan Progress"), @@ -2882,12 +3188,22 @@ if (!ARDOUR::Profile->get_mixbus()) { Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(), _("When enabled plugins will be activated when they are added to tracks/busses. When disabled plugins will be left inactive when they are added to tracks/busses")); -#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT) +#if (defined WINDOWS_VST_SUPPORT || defined MACVST_SUPPORT || defined LXVST_SUPPORT) add_option (_("Plugins/VST"), new OptionEditorHeading (_("VST"))); add_option (_("Plugins/VST"), new RcActionButton (_("Scan for Plugins"), sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh))); +#if (defined AUDIOUNIT_SUPPORT && defined MACVST_SUPPORT) + bo = new BoolOption ( + "", + _("Enable Mac VST support (requires restart or re-scan)"), + sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_macvst), + sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_macvst) + ); + add_option (_("Plugins/VST"), bo); +#endif + bo = new BoolOption ( "discover-vst-on-start", _("Scan for [new] VST Plugins on Application Start"), @@ -2960,11 +3276,11 @@ if (!ARDOUR::Profile->get_mixbus()) { bo = new BoolOption ( "discover-audio-units", - _("Scan for AudioUnit Plugins on Application Start"), + _("Scan for [new] AudioUnit Plugins on Application Start"), sigc::mem_fun (*_rc_config, &RCConfiguration::get_discover_audio_units), sigc::mem_fun (*_rc_config, &RCConfiguration::set_discover_audio_units) ); - add_option (_("Plugins"), bo); + add_option (_("Plugins/Audio Unit"), bo); Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(), _("When enabled Audio Unit Plugins are discovered on application start. When disabled AU plugins will only be available after triggering a 'Scan' manually. The first successful scan will enable AU auto-scan, Any crash during plugin discovery will disable it.")); @@ -2979,7 +3295,7 @@ if (!ARDOUR::Profile->get_mixbus()) { _("AU Blacklist:"))); #endif -#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT || defined HAVE_LV2) +#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT || defined HAVE_LV2) add_option (_("Plugins"), new OptionEditorHeading (_("Plugin GUI"))); add_option (_("Plugins"), new BoolOption ( @@ -3355,6 +3671,8 @@ if (!ARDOUR::Profile->get_mixbus()) { add_option (_("Theme/Colors"), new ColorThemeManager); + Widget::show_all (); + //trigger some parameter-changed messages which affect widget-visibility or -sensitivity parameter_changed ("send-ltc"); parameter_changed ("sync-source");