From ea23298f10e9587eba483cb54a6f7d75ca68126a Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 7 Jul 2010 00:40:58 +0000 Subject: [PATCH] Setup fixed ports for MIDI control data; hence remove configuration of those ports. Move MIDI tracer to the Windows menu. Trim some unused code from the midi++ Manager. git-svn-id: svn://localhost/ardour2/branches/3.0@7384 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/ardev_common.sh.in | 2 - gtk2_ardour/ardour.menus.in | 1 + gtk2_ardour/ardour_ui.cc | 3 - gtk2_ardour/ardour_ui.h | 4 + gtk2_ardour/ardour_ui2.cc | 4 + gtk2_ardour/ardour_ui_dialogs.cc | 17 + gtk2_ardour/ardour_ui_ed.cc | 2 + gtk2_ardour/midi_tracer.cc | 69 +++- gtk2_ardour/midi_tracer.h | 12 +- gtk2_ardour/rc_option_editor.cc | 257 --------------- gtk2_ardour/rc_option_editor.h | 2 +- libs/ardour/ardour/ardour.h | 7 - libs/ardour/ardour/rc_configuration.h | 2 - libs/ardour/ardour/rc_configuration_vars.h | 4 - libs/ardour/ardour/session.h | 29 +- libs/ardour/globals.cc | 88 ----- libs/ardour/rc_configuration.cc | 21 +- libs/ardour/session.cc | 14 +- libs/ardour/session_midi.cc | 300 +----------------- libs/ardour/session_state.cc | 53 ++-- libs/ardour/session_transport.cc | 8 +- libs/ardour/ticker.cc | 2 +- libs/midi++2/manager.cc | 159 ++-------- libs/midi++2/midi++/manager.h | 30 +- libs/midi++2/midi++/mmc.h | 9 +- libs/midi++2/midi++/port.h | 4 +- libs/midi++2/mmc.cc | 30 +- libs/midi++2/port.cc | 55 ++-- .../generic_midi_control_protocol.cc | 31 +- .../generic_midi_control_protocol.h | 6 +- libs/surfaces/mackie/interface.cc | 39 +-- 31 files changed, 249 insertions(+), 1015 deletions(-) diff --git a/gtk2_ardour/ardev_common.sh.in b/gtk2_ardour/ardev_common.sh.in index 10a37a6ae8..1aef253d09 100644 --- a/gtk2_ardour/ardev_common.sh.in +++ b/gtk2_ardour/ardev_common.sh.in @@ -9,10 +9,8 @@ export ARDOUR_SURFACES_PATH=$libs/surfaces/osc:$libs/surfaces/generic_midi:$libs export ARDOUR_DATA_PATH=$TOP/gtk2_ardour:build/default/gtk2_ardour:. if test -d $HOME/gtk/inst ; then - echo USING NEW CLEARLOOKS export GTK_PATH=~/.ardour3:$libs/clearlooks-newer else - echo USING OLD CLEARLOOKS export GTK_PATH=~/.ardour3:$libs/clearlooks-older fi diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in index 85df23ab14..e2edc18f0a 100644 --- a/gtk2_ardour/ardour.menus.in +++ b/gtk2_ardour/ardour.menus.in @@ -437,6 +437,7 @@ + diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 10fdeb991e..11cea54c02 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -365,9 +365,6 @@ ARDOUR_UI::post_engine () /* Things to be done once we create the AudioEngine */ - MIDI::Manager::instance()->set_api_data (engine->jack()); - setup_midi (); - ARDOUR::init_post_engine (); ActionManager::init (); diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index 643202a32b..c0cc88f24e 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -84,6 +84,7 @@ class RouteParams_UI; class SessionOptionEditor; class Splash; class ThemeManager; +class MidiTracer; namespace Gtkmm2ext { class TearOff; @@ -164,6 +165,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr void toggle_theme_manager (); void toggle_bundle_manager (); void toggle_big_clock_window (); + void toggle_midi_tracer_window (); void toggle_route_params_window (); void toggle_editing_space(); @@ -325,6 +327,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr void update_transport_clocks (nframes_t pos); void record_state_changed (); + MidiTracer* _midi_tracer_window; + /* Transport Control */ void detach_tearoff (Gtk::Box* parent, Gtk::Widget* contents); diff --git a/gtk2_ardour/ardour_ui2.cc b/gtk2_ardour/ardour_ui2.cc index 9991a1dc14..3a321cc5e3 100644 --- a/gtk2_ardour/ardour_ui2.cc +++ b/gtk2_ardour/ardour_ui2.cc @@ -45,6 +45,7 @@ #include "actions.h" #include "utils.h" #include "theme_manager.h" +#include "midi_tracer.h" #include "i18n.h" @@ -106,6 +107,9 @@ ARDOUR_UI::setup_windows () setup_transport(); build_menu_bar (); + _midi_tracer_window = new MidiTracer (); + manage_window (*_midi_tracer_window); + setup_tooltips (); return 0; diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc index 0c1240e435..6ae05ef0ee 100644 --- a/gtk2_ardour/ardour_ui_dialogs.cc +++ b/gtk2_ardour/ardour_ui_dialogs.cc @@ -39,6 +39,7 @@ #include "bundle_manager.h" #include "keyeditor.h" #include "gui_thread.h" +#include "midi_tracer.h" #include "i18n.h" @@ -214,6 +215,22 @@ ARDOUR_UI::toggle_big_clock_window () } } +void +ARDOUR_UI::toggle_midi_tracer_window () +{ + RefPtr act = ActionManager::get_action (X_("Common"), X_("ToggleMIDITracer")); + if (!act) { + return; + } + + RefPtr tact = RefPtr::cast_dynamic (act); + if (tact->get_active ()) { + _midi_tracer_window->show_all (); + } else { + _midi_tracer_window->hide (); + } +} + void ARDOUR_UI::toggle_rc_options_window () { diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index b29da7ba70..80950e2d32 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -225,6 +225,8 @@ ARDOUR_UI::install_actions () ActionManager::session_sensitive_actions.push_back (act); act = ActionManager::register_toggle_action (common_actions, X_("ToggleBigClock"), _("Big Clock"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_big_clock_window)); ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_toggle_action (common_actions, X_("ToggleMIDITracer"), _("MIDI Tracer"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_midi_tracer_window)); + ActionManager::session_sensitive_actions.push_back (act); ActionManager::register_action (common_actions, X_("About"), _("About"), sigc::mem_fun(*this, &ARDOUR_UI::show_about)); ActionManager::register_action (common_actions, X_("Chat"), _("Chat"), sigc::mem_fun(*this, &ARDOUR_UI::launch_chat)); ActionManager::register_toggle_action (common_actions, X_("ToggleThemeManager"), _("Theme Manager"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_theme_manager)); diff --git a/gtk2_ardour/midi_tracer.cc b/gtk2_ardour/midi_tracer.cc index a12f756a0f..a1ac7e14f9 100644 --- a/gtk2_ardour/midi_tracer.cc +++ b/gtk2_ardour/midi_tracer.cc @@ -1,3 +1,22 @@ +/* + Copyright (C) 2010 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + #define __STDC_FORMAT_MACROS 1 #include @@ -6,6 +25,7 @@ #include #include "midi++/parser.h" +#include "midi++/manager.h" #include "midi_tracer.h" #include "gui_thread.h" @@ -16,9 +36,9 @@ using namespace std; using namespace MIDI; using namespace Glib; -MidiTracer::MidiTracer (const std::string& name, Parser& p) - : ArdourDialog (string_compose (_("MIDI Trace %1"), name)) - , parser (p) +MidiTracer::MidiTracer () + : ArdourDialog (_("MIDI Tracer")) + , parser (0) , line_count_adjustment (200, 1, 2000, 1, 10) , line_count_spinner (line_count_adjustment) , line_count_label (_("Store this many lines: ")) @@ -32,6 +52,18 @@ MidiTracer::MidiTracer (const std::string& name, Parser& p) , base_button (_("Decimal")) , collect_button (_("Enabled")) { + get_vbox()->set_spacing (4); + + Manager::instance()->PortsChanged.connect (_manager_connection, invalidator (*this), boost::bind (&MidiTracer::ports_changed, this), gui_context()); + + HBox* pbox = manage (new HBox); + pbox->pack_start (*manage (new Label (_("Port:"))), false, false); + + _port_combo.signal_changed().connect (sigc::mem_fun (*this, &MidiTracer::port_changed)); + pbox->pack_start (_port_combo); + pbox->show_all (); + get_vbox()->pack_start (*pbox, false, false); + scroller.add (text); get_vbox()->set_border_width (12); get_vbox()->pack_start (scroller, true, true); @@ -71,7 +103,8 @@ MidiTracer::MidiTracer (const std::string& name, Parser& p) collect_button.show (); autoscroll_button.show (); - connect (); + ports_changed (); + port_changed (); } @@ -80,16 +113,36 @@ MidiTracer::~MidiTracer() } void -MidiTracer::connect () +MidiTracer::ports_changed () +{ + string const c = _port_combo.get_active_text (); + _port_combo.clear (); + + Manager::PortList const & p = Manager::instance()->get_midi_ports (); + for (Manager::PortList::const_iterator i = p.begin(); i != p.end(); ++i) { + _port_combo.append_text ((*i)->name()); + } + + _port_combo.set_active_text (c); +} + +void +MidiTracer::port_changed () { disconnect (); - parser.any.connect_same_thread (connection, boost::bind (&MidiTracer::tracer, this, _1, _2, _3)); + + Port* p = Manager::instance()->port (_port_combo.get_active_text()); + + if (p) { + Parser* parser = p->input() ? p->input() : p->output(); + parser->any.connect_same_thread (_parser_connection, boost::bind (&MidiTracer::tracer, this, _1, _2, _3)); + } } void MidiTracer::disconnect () { - connection.disconnect (); + _parser_connection.disconnect (); } void @@ -330,7 +383,7 @@ void MidiTracer::collect_toggle () { if (collect_button.get_active ()) { - connect (); + port_changed (); } else { disconnect (); } diff --git a/gtk2_ardour/midi_tracer.h b/gtk2_ardour/midi_tracer.h index fb5943370d..b37c4a2351 100644 --- a/gtk2_ardour/midi_tracer.h +++ b/gtk2_ardour/midi_tracer.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "pbd/signals.h" #include "pbd/ringbuffer.h" @@ -21,11 +22,11 @@ namespace MIDI { class MidiTracer : public ArdourDialog { public: - MidiTracer (const std::string&, MIDI::Parser&); + MidiTracer (); ~MidiTracer(); private: - MIDI::Parser& parser; + MIDI::Parser* parser; Gtk::TextView text; Gtk::ScrolledWindow scroller; Gtk::Adjustment line_count_adjustment; @@ -53,14 +54,17 @@ class MidiTracer : public ArdourDialog Gtk::CheckButton autoscroll_button; Gtk::CheckButton base_button; Gtk::CheckButton collect_button; + Gtk::ComboBoxText _port_combo; void base_toggle (); void autoscroll_toggle (); void collect_toggle (); - void connect (); + void port_changed (); + void ports_changed (); void disconnect (); - PBD::ScopedConnection connection; + PBD::ScopedConnection _parser_connection; + PBD::ScopedConnection _manager_connection; }; #endif /* __ardour_gtk_midi_tracer_h__ */ diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc index ec3af3e745..bec67099ea 100644 --- a/gtk2_ardour/rc_option_editor.cc +++ b/gtk2_ardour/rc_option_editor.cc @@ -30,225 +30,6 @@ using namespace Gtkmm2ext; using namespace PBD; using namespace ARDOUR; -class MIDIPorts : public OptionEditorBox -{ -public: - MIDIPorts (RCConfiguration* c, list* > const & o) - : _rc_config (c), - _add_port_button (Stock::ADD), - _port_combos (o) - { - _store = ListStore::create (_model); - _view.set_model (_store); - _view.append_column (_("Name"), _model.name); - _view.get_column(0)->set_resizable (true); - _view.get_column(0)->set_expand (true); - _view.append_column_editable (_("Online"), _model.online); - _view.append_column_editable (_("Trace input"), _model.trace_input); - _view.append_column_editable (_("Trace output"), _model.trace_output); - - HBox* h = manage (new HBox); - h->set_spacing (4); - h->pack_start (_view, true, true); - - VBox* v = manage (new VBox); - v->set_spacing (4); - v->pack_start (_add_port_button, false, false); - h->pack_start (*v, false, false); - - _box->pack_start (*h); - - ports_changed (); - - _store->signal_row_changed().connect (sigc::mem_fun (*this, &MIDIPorts::model_changed)); - - _add_port_button.signal_clicked().connect (sigc::mem_fun (*this, &MIDIPorts::add_port_clicked)); - } - - void parameter_changed (string const &) {} - void set_state_from_config () {} - -private: - - typedef std::map PortTraceMap; - PortTraceMap port_input_trace_map; - PortTraceMap port_output_trace_map; - - void model_changed (TreeModel::Path const &, TreeModel::iterator const & i) - { - TreeModel::Row r = *i; - - MIDI::Port* port = r[_model.port]; - if (!port) { - return; - } - - if (port->input()) { - - if (r[_model.online] == port->input()->offline()) { - port->input()->set_offline (!r[_model.online]); - } - - if (r[_model.trace_input] != port->input()->tracing()) { - PortTraceMap::iterator x = port_input_trace_map.find (port); - MidiTracer* mt; - - if (x == port_input_trace_map.end()) { - mt = new MidiTracer (port->name() + string (" [input]"), *port->input()); - port_input_trace_map.insert (pair (port, mt)); - } else { - mt = x->second; - } - mt->present (); - } - } - - if (port->output()) { - - if (r[_model.trace_output] != port->output()->tracing()) { - PortTraceMap::iterator x = port_output_trace_map.find (port); - MidiTracer* mt; - - if (x == port_output_trace_map.end()) { - mt = new MidiTracer (port->name() + string (" [output]"), *port->output()); - port_output_trace_map.insert (pair (port, mt)); - } else { - mt = x->second; - } - mt->present (); - } - - } - } - - void setup_ports_combo (ComboOption* c) - { - c->clear (); - MIDI::Manager::PortList const & ports = MIDI::Manager::instance()->get_midi_ports (); - for (MIDI::Manager::PortList::const_iterator i = ports.begin(); i != ports.end(); ++i) { - c->add ((*i)->name(), (*i)->name()); - } - } - - void ports_changed () - { - /* XXX: why is this coming from here? */ - MIDI::Manager::PortList const & ports = MIDI::Manager::instance()->get_midi_ports (); - - _store->clear (); - port_connections.drop_connections (); - - for (MIDI::Manager::PortList::const_iterator i = ports.begin(); i != ports.end(); ++i) { - - TreeModel::Row r = *_store->append (); - - r[_model.name] = (*i)->name(); - - if ((*i)->input()) { - r[_model.online] = !(*i)->input()->offline(); - (*i)->input()->OfflineStatusChanged.connect (port_connections, MISSING_INVALIDATOR, boost::bind (&MIDIPorts::port_offline_changed, this, (*i)), gui_context()); - r[_model.trace_input] = (*i)->input()->tracing(); - } - - if ((*i)->output()) { - r[_model.trace_output] = (*i)->output()->tracing(); - } - - r[_model.port] = (*i); - } - - for (list* >::iterator i = _port_combos.begin(); i != _port_combos.end(); ++i) { - setup_ports_combo (*i); - } - } - - void port_offline_changed (MIDI::Port* p) - { - if (!p->input()) { - return; - } - - for (TreeModel::Children::iterator i = _store->children().begin(); i != _store->children().end(); ++i) { - if ((*i)[_model.port] == p) { - (*i)[_model.online] = !p->input()->offline(); - } - } - } - - void add_port_clicked () - { - MidiPortDialog dialog; - - dialog.set_position (WIN_POS_MOUSE); - - dialog.show (); - - int const r = dialog.run (); - - switch (r) { - case RESPONSE_ACCEPT: - break; - default: - return; - break; - } - - Glib::ustring const mode = dialog.port_mode_combo.get_active_text (); - string smod; - - if (mode == _("input")) { - smod = X_("input"); - } else if (mode == (_("output"))) { - smod = X_("output"); - } else { - smod = "duplex"; - } - - XMLNode node (X_("MIDI-port")); - - node.add_property ("tag", dialog.port_name.get_text()); - node.add_property ("device", X_("ardour")); // XXX this can't be right for all types - node.add_property ("mode", smod); - - if (MIDI::Manager::instance()->add_port (node) != 0) { - cerr << " there are now " << MIDI::Manager::instance()->nports() << endl; - ports_changed (); - } - } - - class MIDIModelColumns : public TreeModelColumnRecord - { - public: - MIDIModelColumns () - { - add (name); - add (online); - add (trace_input); - add (trace_output); - add (port); - } - - TreeModelColumn name; - TreeModelColumn online; - TreeModelColumn trace_input; - TreeModelColumn trace_output; - TreeModelColumn port; - }; - - RCConfiguration* _rc_config; - Glib::RefPtr _store; - MIDIModelColumns _model; - TreeView _view; - Button _add_port_button; - ComboBoxText _mtc_combo; - ComboBoxText _midi_clock_combo; - ComboBoxText _mmc_combo; - ComboBoxText _mpc_combo; - list* > _port_combos; - PBD::ScopedConnectionList port_connections; -}; - - class ClickOptions : public OptionEditorBox { public: @@ -1429,44 +1210,6 @@ RCOptionEditor::RCOptionEditor () sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs) )); - /* MIDI CONTROL */ - - list* > midi_combos; - - midi_combos.push_back (new ComboOption ( - "mtc-port-name", - _("Send/Receive MTC via"), - sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_port_name), - sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_port_name) - )); - - midi_combos.push_back (new ComboOption ( - "midi-clock-port-name", - _("Send/Receive MIDI clock via"), - sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_clock_port_name), - sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_clock_port_name) - )); - - midi_combos.push_back (new ComboOption ( - "mmc-port-name", - _("Send/Receive MMC via"), - sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_port_name), - sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_port_name) - )); - - midi_combos.push_back (new ComboOption ( - "midi-port-name", - _("Send/Receive MIDI parameter control via"), - sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_port_name), - sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_port_name) - )); - - add_option (_("MIDI control"), new MIDIPorts (_rc_config, midi_combos)); - - for (list* >::iterator i = midi_combos.begin(); i != midi_combos.end(); ++i) { - add_option (_("MIDI control"), *i); - } - add_option (_("MIDI control"), new BoolOption ( "send-mtc", diff --git a/gtk2_ardour/rc_option_editor.h b/gtk2_ardour/rc_option_editor.h index c0b558fac1..367c85402b 100644 --- a/gtk2_ardour/rc_option_editor.h +++ b/gtk2_ardour/rc_option_editor.h @@ -5,7 +5,7 @@ * * This is subclassed from OptionEditor. Simple options (e.g. boolean and simple choices) * are expressed using subclasses of Option. More complex UI elements are represented - * using individual classes subclassed rom OptionEditorBox. + * using individual classes subclassed from OptionEditorBox. */ /** Editor for options which are obtained from and written back to one of the .rc files. */ diff --git a/libs/ardour/ardour/ardour.h b/libs/ardour/ardour/ardour.h index 2b1f7bbb04..11a5940c7c 100644 --- a/libs/ardour/ardour/ardour.h +++ b/libs/ardour/ardour/ardour.h @@ -71,13 +71,6 @@ namespace ARDOUR { static const double SHUTTLE_FRACT_SPEED1=0.48412291827; /* derived from A1,A2 */ void setup_fpu (); - - extern MIDI::Port* default_mmc_port; - extern MIDI::Port* default_mtc_port; - extern MIDI::Port* default_midi_port; - extern MIDI::Port *default_midi_clock_port; - - int setup_midi (); } #endif /* __ardour_ardour_h__ */ diff --git a/libs/ardour/ardour/rc_configuration.h b/libs/ardour/ardour/rc_configuration.h index 35b22106dd..de697a0b88 100644 --- a/libs/ardour/ardour/rc_configuration.h +++ b/libs/ardour/ardour/rc_configuration.h @@ -43,8 +43,6 @@ class RCConfiguration : public Configuration XMLNode& get_variables (); void set_variables (XMLNode const &); - std::map midi_ports; - int load_state (); int save_state (); diff --git a/libs/ardour/ardour/rc_configuration_vars.h b/libs/ardour/ardour/rc_configuration_vars.h index e98f396b95..be07069f7f 100644 --- a/libs/ardour/ardour/rc_configuration_vars.h +++ b/libs/ardour/ardour/rc_configuration_vars.h @@ -25,10 +25,6 @@ CONFIG_VARIABLE (AutoConnectOption, input_auto_connect, "input-auto-connect", Au /* MIDI and MIDI related */ -CONFIG_VARIABLE (std::string, mtc_port_name, "mtc-port-name", "control") -CONFIG_VARIABLE (std::string, mmc_port_name, "mmc-port-name", "control") -CONFIG_VARIABLE (std::string, midi_port_name, "midi-port-name", "control") -CONFIG_VARIABLE (std::string, midi_clock_port_name, "midi-clock-port-name", "control") CONFIG_VARIABLE (bool, trace_midi_input, "trace-midi-input", false) CONFIG_VARIABLE (bool, trace_midi_output, "trace-midi-output", false) CONFIG_VARIABLE (bool, send_mtc, "send-mtc", false) diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 77b75a819a..a7c3aae7a7 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -641,23 +641,17 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi /* MIDI control */ void midi_panic(void); - int set_mtc_port (std::string port_tag); - int set_midi_port (std::string port_tag); - int set_midi_clock_port (std::string port_tag); - MIDI::Port *mtc_port() const { return _mtc_port; } - MIDI::Port *midi_port() const { return _midi_port; } - MIDI::Port *midi_clock_port() const { return _midi_clock_port; } + MIDI::Port *mtc_input_port() const { return _mtc_input_port; } + MIDI::Port *mtc_output_port() const { return _mtc_output_port; } + MIDI::Port *midi_input_port() const { return _midi_input_port; } + MIDI::Port *midi_output_port() const { return _midi_output_port; } + MIDI::Port *midi_clock_input_port() const { return _midi_clock_input_port; } + MIDI::Port *midi_clock_output_port() const { return _midi_clock_output_port; } PBD::Signal0 MTC_PortChanged; PBD::Signal0 MIDI_PortChanged; PBD::Signal0 MIDIClock_PortChanged; - void set_trace_midi_input (bool, MIDI::Port* port = 0); - void set_trace_midi_output (bool, MIDI::Port* port = 0); - - bool get_trace_midi_input(MIDI::Port *port = 0); - bool get_trace_midi_output(MIDI::Port *port = 0); - /* Scrubbing */ void start_scrub (nframes_t where); @@ -950,9 +944,12 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi void check_declick_out (); MIDI::MachineControl* _mmc; - MIDI::Port* _mtc_port; - MIDI::Port* _midi_port; - MIDI::Port* _midi_clock_port; + MIDI::Port* _mtc_input_port; + MIDI::Port* _mtc_output_port; + MIDI::Port* _midi_input_port; + MIDI::Port* _midi_output_port; + MIDI::Port* _midi_clock_input_port; + MIDI::Port* _midi_clock_output_port; std::string _path; std::string _name; bool _is_new; @@ -1154,8 +1151,6 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi int start_midi_thread (); void terminate_midi_thread (); - int use_config_midi_ports (); - void set_play_loop (bool yn); void unset_play_loop (); void overwrite_some_buffers (Track *); diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc index e4addcd88a..111b824c28 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -98,11 +98,6 @@ using namespace ARDOUR; using namespace std; using namespace PBD; -MIDI::Port *ARDOUR::default_mmc_port = 0; -MIDI::Port *ARDOUR::default_mtc_port = 0; -MIDI::Port *ARDOUR::default_midi_port = 0; -MIDI::Port *ARDOUR::default_midi_clock_port = 0; - compute_peak_t ARDOUR::compute_peak = 0; find_peaks_t ARDOUR::find_peaks = 0; apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0; @@ -146,87 +141,6 @@ ARDOUR::make_property_quarks () DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for envelope_FAKE = %1\n", Properties::envelope.property_id)); } -int -ARDOUR::setup_midi () -{ - if (Config->midi_ports.size() == 0) { - return 0; - } - - BootMessage (_("Configuring MIDI ports")); - - for (std::map::iterator i = Config->midi_ports.begin(); i != Config->midi_ports.end(); ++i) { - MIDI::Manager::instance()->add_port (i->second); - } - - MIDI::Port* first; - const MIDI::Manager::PortList& ports = MIDI::Manager::instance()->get_midi_ports(); - - if (ports.size() > 1) { - - first = ports.front(); - - /* More than one port, so try using specific names for each port */ - - default_mmc_port = MIDI::Manager::instance()->port (Config->get_mmc_port_name()); - default_mtc_port = MIDI::Manager::instance()->port (Config->get_mtc_port_name()); - default_midi_port = MIDI::Manager::instance()->port (Config->get_midi_port_name()); - default_midi_clock_port = MIDI::Manager::instance()->port (Config->get_midi_clock_port_name()); - - /* If that didn't work, just use the first listed port */ - - if (default_mmc_port == 0) { - default_mmc_port = first; - } - - if (default_mtc_port == 0) { - default_mtc_port = first; - } - - if (default_midi_port == 0) { - default_midi_port = first; - } - - if (default_midi_clock_port == 0) { - default_midi_clock_port = first; - } - - } else if (ports.size() == 1) { - - first = ports.front(); - - /* Only one port described, so use it for both MTC and MMC */ - - default_mmc_port = first; - default_mtc_port = default_mmc_port; - default_midi_port = default_mmc_port; - default_midi_clock_port = default_mmc_port; - } - - if (default_mmc_port == 0) { - warning << string_compose (_("No MMC control (MIDI port \"%1\" not available)"), Config->get_mmc_port_name()) - << endmsg; - } - - - if (default_mtc_port == 0) { - warning << string_compose (_("No MTC support (MIDI port \"%1\" not available)"), Config->get_mtc_port_name()) - << endmsg; - } - - if (default_midi_port == 0) { - warning << string_compose (_("No MIDI parameter support (MIDI port \"%1\" not available)"), Config->get_midi_port_name()) - << endmsg; - } - - if (default_midi_clock_port == 0) { - warning << string_compose (_("No MIDI Clock support (MIDI port \"%1\" not available)"), Config->get_midi_clock_port_name()) - << endmsg; - } - - return 0; -} - void setup_hardware_optimization (bool try_optimization) { @@ -373,8 +287,6 @@ ARDOUR::init (bool use_vst, bool try_optimization) Config->set_use_vst (use_vst); - cerr << "After config loaded, MTC port name = " << Config->get_mtc_port_name() << endl; - Profile = new RuntimeProfile; diff --git a/libs/ardour/rc_configuration.cc b/libs/ardour/rc_configuration.cc index d503fb3503..a50a994f87 100644 --- a/libs/ardour/rc_configuration.cc +++ b/libs/ardour/rc_configuration.cc @@ -258,26 +258,7 @@ RCConfiguration::set_state (const XMLNode& root, int /*version*/) node = *niter; - if (node->name() == "MIDI-port") { - - try { - - MIDI::Port::Descriptor desc (*node); - map::iterator x; - - if ((x = midi_ports.find (desc.tag)) != midi_ports.end()) { - warning << string_compose (_("Duplicate MIDI port definition found (tag=\"%1\") - ignored"), - desc.tag) << endmsg; - continue; - } - midi_ports.insert (pair(desc.tag,*node)); - } - - catch (failed_constructor& err) { - warning << _("ill-formed MIDI port specification in ardour rcfile (ignored)") << endmsg; - } - - } else if (node->name() == "Config") { + if (node->name() == "Config") { set_variables (*node); diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 5e56b82e68..a098bc3948 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -137,9 +137,6 @@ Session::Session (AudioEngine &eng, _target_transport_speed (0.0), _requested_return_frame (-1), _mmc (0), - _mtc_port (default_mtc_port), - _midi_port (default_midi_port), - _midi_clock_port (default_midi_clock_port), _session_dir (new SessionDirectory(fullpath)), state_tree (0), _butler (new Butler (*this)), @@ -307,6 +304,13 @@ Session::destroy () delete _mmc; + delete _mtc_input_port; + delete _mtc_output_port; + delete _midi_input_port; + delete _midi_output_port; + delete _midi_clock_input_port; + delete _midi_clock_output_port; + /* not strictly necessary, but doing it here allows the shared_ptr debugging to work */ playlists.reset (); @@ -3855,11 +3859,11 @@ Session::get_available_sync_options () const ret.push_back (JACK); - if (mtc_port()) { + if (mtc_input_port()) { ret.push_back (MTC); } - if (midi_clock_port()) { + if (midi_clock_input_port()) { ret.push_back (MIDIClock); } diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc index 1f8f28cfc1..109a2bb5bc 100644 --- a/libs/ardour/session_midi.cc +++ b/libs/ardour/session_midi.cc @@ -71,298 +71,6 @@ Session::midi_panic() } } -int -Session::use_config_midi_ports () -{ - string port_name; - - if (default_mmc_port) { - _mmc->set_port (default_mmc_port); - } - - if (default_mtc_port) { - set_mtc_port (default_mtc_port->name()); - } else { - set_mtc_port (""); - } - - if (default_midi_port) { - set_midi_port (default_midi_port->name()); - } else { - set_midi_port (""); - } - - if (default_midi_clock_port) { - set_midi_clock_port (default_midi_clock_port->name()); - } else { - set_midi_clock_port (""); - } - - return 0; -} - - -/*********************************************************************** - MTC, MMC, etc. -**********************************************************************/ - -int -Session::set_mtc_port (string port_tag) -{ - MTC_Slave *ms; - - if (port_tag.length() == 0) { - - if (_slave && ((ms = dynamic_cast (_slave)) != 0)) { - error << string_compose (_("%1 is slaved to MTC - port cannot be reset"), PROGRAM_NAME) << endmsg; - return -1; - } - - if (_mtc_port == 0) { - return 0; - } - - _mtc_port = 0; - goto out; - } - - MIDI::Port* port; - - if ((port = MIDI::Manager::instance()->port (port_tag)) == 0) { - error << string_compose (_("unknown port %1 requested for MTC"), port_tag) << endl; - return -1; - } - - _mtc_port = port; - - if (_slave && ((ms = dynamic_cast (_slave)) != 0)) { - ms->rebind (*port); - } - - Config->set_mtc_port_name (port_tag); - - out: - MTC_PortChanged(); /* EMIT SIGNAL */ - set_dirty(); - return 0; -} - -int -Session::set_midi_port (string /*port_tag*/) -{ -#if 0 - if (port_tag.length() == 0) { - if (_midi_port == 0) { - return 0; - } - _midi_port = 0; - goto out; - } - - MIDI::Port* port; - - if ((port = MIDI::Manager::instance()->port (port_tag)) == 0) { - return -1; - } - - _midi_port = port; - - /* XXX need something to forward this to control protocols ? or just - use the signal below - */ - - Config->set_midi_port_name (port_tag); - - out: -#endif - MIDI_PortChanged(); /* EMIT SIGNAL */ - set_dirty(); - return 0; -} - -int -Session::set_midi_clock_port (string port_tag) -{ - MIDIClock_Slave *ms; - - if (port_tag.length() == 0) { - - if (_slave && ((ms = dynamic_cast (_slave)) != 0)) { - error << string_compose (_("%1 is slaved to MIDI Clock - port cannot be reset"), PROGRAM_NAME) << endmsg; - return -1; - } - - if (_midi_clock_port == 0) { - return 0; - } - - _midi_clock_port = 0; - goto out; - } - - MIDI::Port* port; - - if ((port = MIDI::Manager::instance()->port (port_tag)) == 0) { - error << string_compose (_("unknown port %1 requested for MIDI Clock"), port_tag) << endl; - return -1; - } - - _midi_clock_port = port; - - if (_slave && ((ms = dynamic_cast (_slave)) != 0)) { - ms->rebind (*port); - } - - Config->set_midi_clock_port_name (port_tag); - - out: - MIDIClock_PortChanged(); /* EMIT SIGNAL */ - set_dirty(); - return 0; -} - -void -Session::set_trace_midi_input (bool yn, MIDI::Port* port) -{ - MIDI::Parser* input_parser; - - cerr << "enabling tracing: " << yn << " for input port " << port->name() << endl; - - if (port) { - if ((input_parser = port->input()) != 0) { - input_parser->trace (yn, &cout, "input: "); - } - } else { - - if (_mmc->port()) { - if ((input_parser = _mmc->port()->input()) != 0) { - input_parser->trace (yn, &cout, "input: "); - } - } - - if (_mtc_port && _mtc_port != _mmc->port()) { - if ((input_parser = _mtc_port->input()) != 0) { - input_parser->trace (yn, &cout, "input: "); - } - } - - if (_midi_port && _midi_port != _mmc->port() && _midi_port != _mtc_port) { - if ((input_parser = _midi_port->input()) != 0) { - input_parser->trace (yn, &cout, "input: "); - } - } - - if (_midi_clock_port - && _midi_clock_port != _mmc->port() - && _midi_clock_port != _mtc_port - && _midi_clock_port != _midi_port) { - if ((input_parser = _midi_clock_port->input()) != 0) { - input_parser->trace (yn, &cout, "input: "); - } - } - } - - Config->set_trace_midi_input (yn); -} - -void -Session::set_trace_midi_output (bool yn, MIDI::Port* port) -{ - MIDI::Parser* output_parser; - - if (port) { - if ((output_parser = port->output()) != 0) { - output_parser->trace (yn, &cout, "output: "); - } - } else { - if (_mmc->port()) { - if ((output_parser = _mmc->port()->output()) != 0) { - output_parser->trace (yn, &cout, "output: "); - } - } - - if (_mtc_port && _mtc_port != _mmc->port()) { - if ((output_parser = _mtc_port->output()) != 0) { - output_parser->trace (yn, &cout, "output: "); - } - } - - if (_midi_port && _midi_port != _mmc->port() && _midi_port != _mtc_port) { - if ((output_parser = _midi_port->output()) != 0) { - output_parser->trace (yn, &cout, "output: "); - } - } - - } - - Config->set_trace_midi_output (yn); -} - -bool -Session::get_trace_midi_input(MIDI::Port *port) -{ - MIDI::Parser* input_parser; - if (port) { - if ((input_parser = port->input()) != 0) { - return input_parser->tracing(); - } - } - else { - if (_mmc->port()) { - if ((input_parser = _mmc->port()->input()) != 0) { - return input_parser->tracing(); - } - } - - if (_mtc_port) { - if ((input_parser = _mtc_port->input()) != 0) { - return input_parser->tracing(); - } - } - - if (_midi_port) { - if ((input_parser = _midi_port->input()) != 0) { - return input_parser->tracing(); - } - } - } - - return false; -} - -bool -Session::get_trace_midi_output(MIDI::Port *port) -{ - MIDI::Parser* output_parser; - if (port) { - if ((output_parser = port->output()) != 0) { - return output_parser->tracing(); - } - } - else { - if (_mmc->port()) { - if ((output_parser = _mmc->port()->output()) != 0) { - return output_parser->tracing(); - } - } - - if (_mtc_port) { - if ((output_parser = _mtc_port->output()) != 0) { - return output_parser->tracing(); - } - } - - if (_midi_port) { - if ((output_parser = _midi_port->output()) != 0) { - return output_parser->tracing(); - } - } - } - - return false; - -} - void Session::setup_midi_control () { @@ -649,7 +357,7 @@ Session::send_full_time_code(nframes_t /*nframes*/) _send_timecode_update = false; - if (_mtc_port == 0 || !session_send_mtc || _slave) { + if (_mtc_output_port == 0 || !session_send_mtc || _slave) { return 0; } @@ -684,7 +392,7 @@ Session::send_full_time_code(nframes_t /*nframes*/) msg[8] = timecode.frames; // Send message at offset 0, sent time is for the start of this cycle - if (_mtc_port->midimsg (msg, sizeof (msg), 0)) { + if (_mtc_output_port->midimsg (msg, sizeof (msg), 0)) { error << _("Session: could not send full MIDI time code") << endmsg; return -1; } @@ -702,7 +410,7 @@ Session::send_full_time_code(nframes_t /*nframes*/) int Session::send_midi_time_code_for_cycle(nframes_t nframes) { - if (_mtc_port == 0 || _slave || !session_send_mtc || transmitting_timecode_time.negative || (next_quarter_frame_to_send < 0)) { + if (_mtc_output_port == 0 || _slave || !session_send_mtc || transmitting_timecode_time.negative || (next_quarter_frame_to_send < 0)) { // cerr << "(MTC) Not sending MTC\n"; return 0; } @@ -763,7 +471,7 @@ Session::send_midi_time_code_for_cycle(nframes_t nframes) nframes_t out_stamp = msg_time - _transport_frame; assert(out_stamp < nframes); - if (_mtc_port->midimsg (mtc_msg, 2, out_stamp)) { + if (_mtc_output_port->midimsg (mtc_msg, 2, out_stamp)) { error << string_compose(_("Session: cannot send quarter-frame MTC message (%1)"), strerror (errno)) << endmsg; return -1; diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 6800aced51..76570cb64a 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -55,6 +55,7 @@ #include "midi++/mmc.h" #include "midi++/port.h" +#include "midi++/manager.h" #include "pbd/boost_debug.h" #include "pbd/controllable_descriptor.h" @@ -276,6 +277,17 @@ Session::first_stage_init (string fullpath, string snapshot_name) Delivery::disable_panners (); IO::disable_connecting (); + + /* Create MIDI control ports */ + + MIDI::Manager* m = MIDI::Manager::instance (); + + _mtc_input_port = m->add_port (new MIDI::Port ("MTC", O_RDONLY, _engine.jack())); + _mtc_output_port = m->add_port (new MIDI::Port ("MTC", O_WRONLY, _engine.jack())); + _midi_input_port = m->add_port (new MIDI::Port ("MIDI control", O_RDONLY, _engine.jack())); + _midi_output_port = m->add_port (new MIDI::Port ("MIDI control", O_WRONLY, _engine.jack())); + _midi_clock_input_port = m->add_port (new MIDI::Port ("MIDI clock", O_RDONLY, _engine.jack())); + _midi_clock_output_port = m->add_port (new MIDI::Port ("MIDI clock", O_WRONLY, _engine.jack())); } int @@ -1243,8 +1255,6 @@ Session::set_state (const XMLNode& node, int version) error << _("Session: XML state has no options section") << endmsg; } - use_config_midi_ports (); - if (version >= 3000) { if ((child = find_named_node (node, "Metadata")) == 0) { warning << _("Session: XML state has no metadata section") << endmsg; @@ -3247,18 +3257,10 @@ Session::config_changed (std::string p, bool ours) } else if (p == "send-mtc") { - /* only set the internal flag if we have - a port. - */ - - if (_mtc_port != 0) { - session_send_mtc = Config->get_send_mtc(); - if (session_send_mtc) { - /* mark us ready to send */ - next_quarter_frame_to_send = 0; - } - } else { - session_send_mtc = false; + session_send_mtc = Config->get_send_mtc(); + if (session_send_mtc) { + /* mark us ready to send */ + next_quarter_frame_to_send = 0; } } else if (p == "send-mmc") { @@ -3267,13 +3269,7 @@ Session::config_changed (std::string p, bool ours) } else if (p == "midi-feedback") { - /* only set the internal flag if we have - a port. - */ - - if (_mtc_port != 0) { - session_midi_feedback = Config->get_midi_feedback(); - } + session_midi_feedback = Config->get_midi_feedback(); } else if (p == "jack-time-master") { @@ -3311,22 +3307,13 @@ Session::config_changed (std::string p, bool ours) sync_order_keys ("session"); } else if (p == "initial-program-change") { - if (_mmc->port() && Config->get_initial_program_change() >= 0) { + if (_mmc->output_port() && Config->get_initial_program_change() >= 0) { MIDI::byte buf[2]; buf[0] = MIDI::program; // channel zero by default buf[1] = (Config->get_initial_program_change() & 0x7f); - _mmc->port()->midimsg (buf, sizeof (buf), 0); - } - } else if (p == "initial-program-change") { - - if (_mmc->port() && Config->get_initial_program_change() >= 0) { - MIDI::byte* buf = new MIDI::byte[2]; - - buf[0] = MIDI::program; // channel zero by default - buf[1] = (Config->get_initial_program_change() & 0x7f); - // deliver_midi (_mmc_port, buf, 2); + _mmc->output_port()->midimsg (buf, sizeof (buf), 0); } } else if (p == "solo-mute-override") { // catch_up_on_solo_mute_override (); @@ -3379,7 +3366,7 @@ Session::load_diskstreams_2X (XMLNode const & node, int) void Session::setup_midi_machine_control () { - _mmc = new MIDI::MachineControl; + _mmc = new MIDI::MachineControl (_engine.jack()); _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1)); _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1)); diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index cc90dc3c7d..1123a6038b 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -1246,9 +1246,9 @@ Session::switch_to_sync_source (SyncSource src) return; } - if (_mtc_port) { + if (_mtc_input_port) { try { - new_slave = new MTC_Slave (*this, *_mtc_port); + new_slave = new MTC_Slave (*this, *_mtc_input_port); } catch (failed_constructor& err) { @@ -1266,9 +1266,9 @@ Session::switch_to_sync_source (SyncSource src) return; } - if (_midi_clock_port) { + if (_midi_clock_input_port) { try { - new_slave = new MIDIClock_Slave (*this, *_midi_clock_port, 24); + new_slave = new MIDIClock_Slave (*this, *_midi_clock_input_port, 24); } catch (failed_constructor& err) { diff --git a/libs/ardour/ticker.cc b/libs/ardour/ticker.cc index 4327e25c72..f1792e3ffd 100644 --- a/libs/ardour/ticker.cc +++ b/libs/ardour/ticker.cc @@ -62,7 +62,7 @@ MidiClockTicker::session_going_away () void MidiClockTicker::update_midi_clock_port() { - _midi_port = _session->midi_clock_port(); + _midi_port = _session->midi_clock_output_port(); } void MidiClockTicker::transport_state_changed() diff --git a/libs/midi++2/manager.cc b/libs/midi++2/manager.cc index 5c464fa060..c8094d4d4f 100644 --- a/libs/midi++2/manager.cc +++ b/libs/midi++2/manager.cc @@ -32,17 +32,10 @@ using namespace std; using namespace MIDI; using namespace PBD; -/* XXX check for strdup leaks */ - Manager *Manager::theManager = 0; Manager::Manager () { - inputPort = 0; - outputPort = 0; - inputChannelNumber = 0; - outputChannelNumber = 0; - api_data = 0; } Manager::~Manager () @@ -57,144 +50,13 @@ Manager::~Manager () } Port * -Manager::add_port (const XMLNode& node) +Manager::add_port (Port* p) { - Port::Descriptor desc (node); - Port *port; - PortList::iterator p; - - for (p = _ports.begin(); p != _ports.end(); ++p) { - - if (desc.tag == (*p)->name()) { - break; - } - - } - - if (p != _ports.end()) { - return 0; - } - - port = new Port (node, (jack_client_t *) api_data); - - if (port == 0) { - return 0; - } - - if (!port->ok()) { - delete port; - return 0; - } - - _ports.push_back (port); - - /* first port added becomes the default input - port. - */ - - if (inputPort == 0) { - inputPort = port; - } - - if (outputPort == 0) { - outputPort = port; - } + _ports.push_back (p); PortsChanged (); /* EMIT SIGNAL */ - return port; -} - -int -Manager::remove_port (Port* port) -{ - if (inputPort == port) { - inputPort = 0; - } - - if (outputPort == port) { - outputPort = 0; - } - - _ports.remove (port); - delete port; - - PortsChanged (); /* EMIT SIGNAL */ - - return 0; -} - -int -Manager::set_input_port (string tag) -{ - for (PortList::iterator p = _ports.begin(); p != _ports.end(); ++p) { - if ((*p)->name() == tag) { - inputPort = (*p); - return 0; - } - } - - return -1; -} - -int -Manager::set_output_port (string tag) -{ - PortList::iterator p; - - for (p = _ports.begin(); p != _ports.end(); ++p) { - if ((*p)->name() == tag) { - inputPort = (*p); - break; - } - } - - if (p == _ports.end()) { - return -1; - } - - // XXX send a signal to say we're about to change output ports - - if (outputPort) { - for (channel_t chan = 0; chan < 16; chan++) { - outputPort->channel (chan)->all_notes_off (0); - } - } - - outputPort = (*p); - - // XXX send a signal to say we've changed output ports - - return 0; -} - -Port * -Manager::port (string name) -{ - for (PortList::iterator p = _ports.begin(); p != _ports.end(); ++p) { - if (name == (*p)->name()) { - return (*p); - } - } - - return 0; -} - -int -Manager::foreach_port (int (*func)(const Port &, size_t, void *), - void *arg) -{ - int n = 0; - - for (PortList::const_iterator p = _ports.begin(); p != _ports.end(); ++p, ++n) { - int retval; - - if ((retval = func (**p, n, arg)) != 0) { - return retval; - } - } - - return 0; + return p; } void @@ -230,3 +92,18 @@ Manager::reconnect () (*p)->reconnect (); } } + +Port* +Manager::port (string const & n) +{ + PortList::const_iterator p = _ports.begin(); + while (p != _ports.end() && (*p)->name() != n) { + ++p; + } + + if (p == _ports.end()) { + return 0; + } + + return *p; +} diff --git a/libs/midi++2/midi++/manager.h b/libs/midi++2/midi++/manager.h index 563062aaea..2193c1eb23 100644 --- a/libs/midi++2/midi++/manager.h +++ b/libs/midi++2/midi++/manager.h @@ -21,7 +21,6 @@ #define __midi_manager_h__ #include -#include #include @@ -34,8 +33,6 @@ class Manager { public: ~Manager (); - void set_api_data(void* data) { api_data = data; } - /** Signal the start of an audio cycle. * This MUST be called before any reading/writing for this cycle. * Realtime safe. @@ -49,26 +46,9 @@ class Manager { */ void cycle_end(); - Port *add_port (const XMLNode& node); - int remove_port (Port*); + Port* add_port (Port *); - Port *port (std::string name); - - size_t nports () const { return _ports.size(); } - - /* defaults for clients who are not picky */ - - Port *inputPort; - Port *outputPort; - channel_t inputChannelNumber; - channel_t outputChannelNumber; - - int set_input_port (std::string); - int set_output_port (std::string); - int set_input_channel (channel_t); - int set_output_channel (channel_t); - - int foreach_port (int (*func)(const Port &, size_t n, void *), void *arg); + Port* port (std::string const &); typedef std::list PortList; @@ -90,13 +70,9 @@ class Manager { /* This is a SINGLETON pattern */ Manager (); - static Manager *theManager; + std::list _ports; - - void* api_data; - - void close_ports (); }; } // namespace MIDI diff --git a/libs/midi++2/midi++/mmc.h b/libs/midi++2/midi++/mmc.h index ec48527789..ec3eb8bbb1 100644 --- a/libs/midi++2/midi++/mmc.h +++ b/libs/midi++2/midi++/mmc.h @@ -20,6 +20,7 @@ #ifndef __midipp_mmc_h_h__ #define __midipp_mmc_h_h__ +#include #include "control_protocol/timecode.h" #include "pbd/signals.h" #include "pbd/ringbuffer.h" @@ -87,10 +88,9 @@ class MachineControl cmdResume = 0x7F }; - MachineControl (); - void set_port (Port* p); + MachineControl (jack_client_t *); - Port* port() { return _port; } + Port* output_port() { return _output_port; } void set_receive_device_id (byte id); void set_send_device_id (byte id); @@ -255,7 +255,8 @@ class MachineControl private: byte _receive_device_id; byte _send_device_id; - Port* _port; + Port* _input_port; + Port* _output_port; bool _enable_send; ///< true if MMC sending is enabled void process_mmc_message (Parser &p, byte *, size_t len); diff --git a/libs/midi++2/midi++/port.h b/libs/midi++2/midi++/port.h index 8c875a6615..ca977fad2f 100644 --- a/libs/midi++2/midi++/port.h +++ b/libs/midi++2/midi++/port.h @@ -42,6 +42,7 @@ class PortRequest; class Port { public: + Port (std::string const &, int, jack_client_t *); Port (const XMLNode&, jack_client_t *); ~Port (); @@ -135,7 +136,7 @@ private: static size_t nports; - int create_ports(const XMLNode&); + void create_port_names (); int create_ports (); jack_client_t* _jack_client; @@ -156,6 +157,7 @@ private: void flush (void* jack_port_buffer); void jack_halted (); void make_connections(); + void init (std::string const &, int); static pthread_t _process_thread; diff --git a/libs/midi++2/mmc.cc b/libs/midi++2/mmc.cc index 597904d293..406fd0ef19 100644 --- a/libs/midi++2/mmc.cc +++ b/libs/midi++2/mmc.cc @@ -18,6 +18,7 @@ $Id$ */ +#include #include #include "control_protocol/timecode.h" @@ -25,6 +26,7 @@ #include "midi++/mmc.h" #include "midi++/port.h" #include "midi++/parser.h" +#include "midi++/manager.h" using namespace std; using namespace MIDI; @@ -193,30 +195,20 @@ static void build_mmc_cmd_map () } -MachineControl::MachineControl () - : _port (0) +MachineControl::MachineControl (jack_client_t* jack) { build_mmc_cmd_map (); _receive_device_id = 0; _send_device_id = 0x7f; -} -void -MachineControl::set_port (Port* p) -{ - _port = p; + _input_port = Manager::instance()->add_port (new Port ("MMC", O_RDONLY, jack)); + _output_port = Manager::instance()->add_port (new Port ("MMC", O_WRONLY, jack)); - port_connections.drop_connections (); - - if (_port->input()) { - _port->input()->mmc.connect_same_thread (port_connections, boost::bind (&MachineControl::process_mmc_message, this, _1, _2, _3)); - _port->input()->start.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_start, this, _1, _2)); - _port->input()->contineu.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_continue, this, _1, _2)); - _port->input()->stop.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_stop, this, _1, _2)); - } else { - warning << "MMC connected to a non-input port: useless!" << endmsg; - } + _input_port->input()->mmc.connect_same_thread (port_connections, boost::bind (&MachineControl::process_mmc_message, this, _1, _2, _3)); + _input_port->input()->start.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_start, this, _1, _2)); + _input_port->input()->contineu.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_continue, this, _1, _2)); + _input_port->input()->stop.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_stop, this, _1, _2)); } void @@ -643,7 +635,7 @@ MachineControl::enable_send (bool yn) void MachineControl::send (MachineControlCommand const & c) { - if (_port == 0 || !_enable_send) { + if (_output_port == 0 || !_enable_send) { // cerr << "Not delivering MMC " << _mmc->port() << " - " << session_send_mmc << endl; return; } @@ -651,7 +643,7 @@ MachineControl::send (MachineControlCommand const & c) MIDI::byte buffer[32]; MIDI::byte* b = c.fill_buffer (this, buffer); - if (_port->midimsg (buffer, b - buffer, 0)) { + if (_output_port->midimsg (buffer, b - buffer, 0)) { error << "MMC: cannot send command" << endmsg; } } diff --git a/libs/midi++2/port.cc b/libs/midi++2/port.cc index 457ff1c358..c2fd4c99e2 100644 --- a/libs/midi++2/port.cc +++ b/libs/midi++2/port.cc @@ -44,6 +44,19 @@ pthread_t Port::_process_thread; Signal0 Port::JackHalted; Signal0 Port::MakeConnections; +Port::Port (string const & name, int mode, jack_client_t* jack_client) + : _currently_in_cycle (false) + , _nframes_this_cycle (0) + , _jack_client (jack_client) + , _jack_input_port (0) + , _jack_output_port (0) + , _last_read_index (0) + , output_fifo (512) + , input_fifo (1024) +{ + init (name, mode); +} + Port::Port (const XMLNode& node, jack_client_t* jack_client) : _currently_in_cycle (false) , _nframes_this_cycle (0) @@ -56,6 +69,14 @@ Port::Port (const XMLNode& node, jack_client_t* jack_client) { Descriptor desc (node); + init (desc.tag, desc.mode); + + set_state (node); +} + +void +Port::init (string const & name, int mode) +{ _ok = false; /* derived class must set to true if constructor succeeds. */ @@ -63,8 +84,8 @@ Port::Port (const XMLNode& node, jack_client_t* jack_client) input_parser = 0; output_parser = 0; - _tagname = desc.tag; - _mode = desc.mode; + _tagname = name; + _mode = mode; if (_mode == O_RDONLY || _mode == O_RDWR) { input_parser = new Parser (*this); @@ -90,14 +111,14 @@ Port::Port (const XMLNode& node, jack_client_t* jack_client) } } - if (!create_ports (node)) { + create_port_names (); + + if (!create_ports ()) { _ok = true; } MakeConnections.connect_same_thread (connect_connection, boost::bind (&Port::make_connections, this)); JackHalted.connect_same_thread (halt_connection, boost::bind (&Port::jack_halted, this)); - - set_state (node); } @@ -108,17 +129,17 @@ Port::~Port () } if (_jack_input_port) { - if (_jack_client) { + if (_jack_client && _jack_input_port) { jack_port_unregister (_jack_client, _jack_input_port); } _jack_input_port = 0; } if (_jack_output_port) { - if (_jack_client) { - jack_port_unregister (_jack_client, _jack_input_port); + if (_jack_client && _jack_output_port) { + jack_port_unregister (_jack_client, _jack_output_port); } - _jack_input_port = 0; + _jack_output_port = 0; } } @@ -407,23 +428,19 @@ Port::read (byte *, size_t) return 0; } -int -Port::create_ports(const XMLNode& node) +void +Port::create_port_names () { - Descriptor desc (node); - assert(!_jack_input_port); assert(!_jack_output_port); - if (desc.mode == O_RDWR || desc.mode == O_WRONLY) { - _jack_output_port_name = string(desc.tag).append ("_out"); + if (_mode == O_RDWR || _mode == O_WRONLY) { + _jack_output_port_name = _tagname.append ("_out"); } - if (desc.mode == O_RDWR || desc.mode == O_RDONLY) { - _jack_input_port_name = string(desc.tag).append ("_in"); + if (_mode == O_RDWR || _mode == O_RDONLY) { + _jack_input_port_name = _tagname.append ("_in"); } - - return create_ports (); } int diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc index 62cc93263b..de7c00171b 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc @@ -30,7 +30,6 @@ #include "pbd/xml++.h" #include "midi++/port.h" -#include "midi++/manager.h" #include "ardour/filesystem_paths.h" #include "ardour/session.h" @@ -57,20 +56,8 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s) , gui (0) { - MIDI::Manager* mm = MIDI::Manager::instance(); - - /* XXX it might be nice to run "control" through i18n, but thats a bit tricky because - the name is defined in ardour.rc which is likely not internationalized. - */ - - _port = mm->port (Config->get_midi_port_name()); - - if (_port == 0) { - error << string_compose (_("no MIDI port named \"%1\" exists - generic MIDI control disabled"), - Config->get_midi_port_name()) - << endmsg; - throw failed_constructor(); - } + _input_port = s.midi_input_port (); + _output_port = s.midi_output_port (); do_feedback = false; _feedback_interval = 10000; // microseconds @@ -274,7 +261,7 @@ GenericMidiControlProtocol::_send_feedback () return; } - _port->write (buf, (int32_t) (end - buf), 0); + _output_port->write (buf, (int32_t) (end - buf), 0); } bool @@ -324,7 +311,7 @@ GenericMidiControlProtocol::start_learning (Controllable* c) } if (!mc) { - mc = new MIDIControllable (*_port, *c, false); + mc = new MIDIControllable (*_input_port, *c, false); } { @@ -421,7 +408,7 @@ GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos, MIDI::byte value = control_number; // Create a MIDIControllable - MIDIControllable* mc = new MIDIControllable (*_port, *control, false); + MIDIControllable* mc = new MIDIControllable (*_input_port, *control, false); // Remove any old binding for this midi channel/type/value pair // Note: can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information @@ -533,7 +520,7 @@ GenericMidiControlProtocol::set_state (const XMLNode& node, int version) c = session->controllable_by_id (id); if (c) { - MIDIControllable* mc = new MIDIControllable (*_port, *c, false); + MIDIControllable* mc = new MIDIControllable (*_input_port, *c, false); if (mc->set_state (**niter, version) == 0) { controllables.push_back (mc); @@ -715,7 +702,7 @@ GenericMidiControlProtocol::create_binding (const XMLNode& node) prop = node.property (X_("uri")); uri = prop->value(); - MIDIControllable* mc = new MIDIControllable (*_port, momentary); + MIDIControllable* mc = new MIDIControllable (*_input_port, momentary); if (mc->init (uri)) { delete mc; @@ -832,7 +819,7 @@ GenericMidiControlProtocol::create_function (const XMLNode& node) prop = node.property (X_("function")); - MIDIFunction* mf = new MIDIFunction (*_port); + MIDIFunction* mf = new MIDIFunction (*_input_port); if (mf->init (*this, prop->value(), data, data_size)) { delete mf; @@ -928,7 +915,7 @@ GenericMidiControlProtocol::create_action (const XMLNode& node) prop = node.property (X_("action")); - MIDIAction* ma = new MIDIAction (*_port); + MIDIAction* ma = new MIDIAction (*_input_port); if (ma->init (*this, prop->value(), data, data_size)) { delete ma; diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.h b/libs/surfaces/generic_midi/generic_midi_control_protocol.h index 1ad2c681d4..7ad23d9373 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.h +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.h @@ -50,7 +50,8 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol { int set_active (bool yn); static bool probe() { return true; } - MIDI::Port* port () const { return _port; } + MIDI::Port* input_port () const { return _input_port; } + MIDI::Port* output_port () const { return _output_port; } void set_feedback_interval (ARDOUR::microseconds_t); int set_feedback (bool yn); @@ -81,7 +82,8 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol { void prev_bank (); private: - MIDI::Port* _port; + MIDI::Port* _input_port; + MIDI::Port* _output_port; ARDOUR::microseconds_t _feedback_interval; ARDOUR::microseconds_t last_feedback_time; diff --git a/libs/surfaces/mackie/interface.cc b/libs/surfaces/mackie/interface.cc index 067941484c..d3625cac51 100644 --- a/libs/surfaces/mackie/interface.cc +++ b/libs/surfaces/mackie/interface.cc @@ -31,36 +31,19 @@ using namespace std; ControlProtocol* new_mackie_protocol (ControlProtocolDescriptor*, Session* s) { - if ( Config->get_mmc_port_name().substr(0,3) == "mcu" ) - { - error << "mcu already used as mmc port" << endmsg; + MackieControlProtocol* mcp = 0; + + try { + mcp = new MackieControlProtocol (*s); + mcp->set_active (true); } - else if ( Config->get_mtc_port_name().substr(0,3) == "mcu" ) - { - error << "mcu already used as mtc port" << endmsg; + catch (exception & e) { + error << "Error instantiating MackieControlProtocol: " << e.what() << endmsg; + delete mcp; + mcp = 0; } - else if ( Config->get_midi_port_name().substr(0,3) == "mcu" ) - { - error << "mcu already used as midi port" << endmsg; - } - else - { - // no one else is using the port, so try instantiate the object - MackieControlProtocol * mcp = 0; - try - { - mcp = new MackieControlProtocol (*s); - mcp->set_active( true ); - } - catch( exception & e ) - { - error << "Error instantiating MackieControlProtocol: " << e.what() << endmsg; - delete mcp; - mcp = 0; - } - return mcp; - } - return 0; + + return mcp; } void