summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/option_editor.h70
-rw-r--r--gtk2_ardour/rc_option_editor.cc15
-rw-r--r--gtk2_ardour/rc_option_editor.h1
-rw-r--r--libs/ardour/ardour/audioengine.h12
-rw-r--r--libs/ardour/ardour/rc_configuration_vars.h1
-rw-r--r--libs/ardour/audioengine.cc73
-rw-r--r--libs/ardour/ltc_slave.cc2
7 files changed, 154 insertions, 20 deletions
diff --git a/gtk2_ardour/option_editor.h b/gtk2_ardour/option_editor.h
index 3e64e4f125..6ea38648b0 100644
--- a/gtk2_ardour/option_editor.h
+++ b/gtk2_ardour/option_editor.h
@@ -285,6 +285,76 @@ private:
};
+/** Component which provides the UI to handle an enumerated option using a GTK ComboBox.
+ * The template parameter is the enumeration.
+ */
+class ComboStringOption : public Option
+{
+public:
+
+ /** Construct an ComboOption.
+ * @param i id
+ * @param n User-visible name.
+ * @param g Slot to get the variable's value.
+ * @param s Slot to set the variable's value.
+ */
+ ComboStringOption (
+ std::string const & i,
+ std::string const & n,
+ sigc::slot<std::string> g,
+ sigc::slot<bool, std::string> s
+ )
+ : Option (i, n),
+ _get (g),
+ _set (s)
+ {
+ _label = manage (new Gtk::Label (n + ":"));
+ _label->set_alignment (0, 0.5);
+ _combo = manage (new Gtk::ComboBoxText);
+ _combo->signal_changed().connect (sigc::mem_fun (*this, &ComboStringOption::changed));
+ }
+
+ void set_state_from_config () {
+ _combo->set_active_text (_get());
+ }
+
+ void add_to_page (OptionEditorPage* p)
+ {
+ add_widgets_to_page (p, _label, _combo);
+ }
+
+ /** Set the allowed strings for this option
+ * @param strings a vector of allowed strings
+ */
+ void set_popdown_strings (const std::vector<std::string>& strings) {
+ _combo->clear_items ();
+ for (std::vector<std::string>::const_iterator i = strings.begin(); i != strings.end(); ++i) {
+ _combo->append_text (*i);
+ }
+ }
+
+ void clear () {
+ _combo->clear_items();
+ }
+
+ void changed () {
+ _set (_combo->get_active_text ());
+ }
+
+ void set_sensitive (bool yn) {
+ _combo->set_sensitive (yn);
+ }
+
+ Gtk::Widget& tip_widget() { return *_combo; }
+
+private:
+ sigc::slot<std::string> _get;
+ sigc::slot<bool, std::string> _set;
+ Gtk::Label* _label;
+ Gtk::ComboBoxText* _combo;
+};
+
+
/** Component which provides the UI to handle a boolean option which needs
* to be represented as a ComboBox to be clear to the user.
*/
diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc
index 6b59e8718e..c889962158 100644
--- a/gtk2_ardour/rc_option_editor.cc
+++ b/gtk2_ardour/rc_option_editor.cc
@@ -1068,8 +1068,23 @@ RCOptionEditor::RCOptionEditor ()
(_sync_genlock->tip_widget(),
_("<b>When enabled</b> indicates that the selected external timecode source shares sync (Black &amp; Burst, Wordclock, etc) with the audio interface"));
+
add_option (_("Transport"), _sync_genlock);
+ _ltc_port = new ComboStringOption (
+ "ltc-source-port",
+ _("LTC incoming port"),
+ sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
+ sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
+ );
+
+ vector<string> physical_inputs;
+ physical_inputs.push_back (_("None"));
+ AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
+ _ltc_port->set_popdown_strings (physical_inputs);
+
+ add_option (_("Transport"), _ltc_port);
+
parameter_changed ("sync-source");
/* EDITOR */
diff --git a/gtk2_ardour/rc_option_editor.h b/gtk2_ardour/rc_option_editor.h
index eae27d323b..76978d4317 100644
--- a/gtk2_ardour/rc_option_editor.h
+++ b/gtk2_ardour/rc_option_editor.h
@@ -45,6 +45,7 @@ private:
ComboOption<ARDOUR::SyncSource>* _sync_source;
BoolOption* _sync_framerate;
BoolOption* _sync_genlock;
+ ComboStringOption* _ltc_port;
PBD::ScopedConnection parameter_change_connection;
};
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h
index 4e55ea2140..49e3c15457 100644
--- a/libs/ardour/ardour/audioengine.h
+++ b/libs/ardour/ardour/audioengine.h
@@ -260,9 +260,7 @@ _ the regular process() call to session->process() is not made.
int create_process_thread (boost::function<void()>, pthread_t*, size_t stacksize);
-#ifdef HAVE_LTC
- Port *ltc_input_port() const { return _ltc_input; }
-#endif
+ boost::shared_ptr<Port> ltc_input_port() const { return _ltc_input; }
private:
static AudioEngine* _instance;
@@ -293,9 +291,8 @@ private:
Glib::Threads::Thread* m_meter_thread;
ProcessThread* _main_thread;
-#ifdef HAVE_LTC
- Port* _ltc_input;
-#endif
+ boost::shared_ptr<Port> _ltc_input;
+ void reconnect_ltc ();
SerializedRCUManager<Ports> ports;
@@ -329,6 +326,7 @@ private:
int jack_bufsize_callback (pframes_t);
int jack_sample_rate_callback (pframes_t);
void freewheel_callback (int);
+ void connect_callback (jack_port_id_t, jack_port_id_t, int);
void set_jack_callbacks ();
@@ -356,6 +354,8 @@ private:
};
static void* _start_process_thread (void*);
+ void parameter_changed (const std::string&);
+ PBD::ScopedConnection config_connection;
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/rc_configuration_vars.h b/libs/ardour/ardour/rc_configuration_vars.h
index adcc00ec87..9432b7230f 100644
--- a/libs/ardour/ardour/rc_configuration_vars.h
+++ b/libs/ardour/ardour/rc_configuration_vars.h
@@ -51,6 +51,7 @@ CONFIG_VARIABLE (int, mtc_qf_speed_tolerance, "mtc-qf-speed-tolerance", 5)
CONFIG_VARIABLE (bool, timecode_sync_frame_rate, "timecode-sync-frame-rate", true)
CONFIG_VARIABLE (bool, timecode_source_is_synced, "timecode-source-is-synced", true)
CONFIG_VARIABLE (SyncSource, sync_source, "sync-source", JACK)
+CONFIG_VARIABLE (std::string, ltc_source_port, "ltc-source-port", "system:capture_1")
/* control surfaces */
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 9fb1d1d706..ba7666f3e4 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -89,13 +89,24 @@ AudioEngine::AudioEngine (string client_name, string session_uuid)
}
Port::set_engine (this);
+
#ifdef HAVE_LTC
- _ltc_input = new AudioPort ("LTC in", Port::IsInput);
+ _ltc_input = register_port (DataType::AUDIO, _("LTC in"), Port::IsInput);
+
+ /* As of October 2012, the LTC source port is the only thing that needs
+ * to care about Config parameters, so don't bother to listen if we're
+ * not doing LTC stuff. This might change if other parameters show up
+ * in the future that we need to care about with or without LTC.
+ */
+
+ Config->ParameterChanged.connect_same_thread (config_connection, boost::bind (&AudioEngine::parameter_changed, this, _1));
#endif
}
AudioEngine::~AudioEngine ()
{
+ config_connection.disconnect ();
+
{
Glib::Threads::Mutex::Lock tm (_process_lock);
session_removed.signal ();
@@ -210,6 +221,9 @@ AudioEngine::start ()
_running = true;
_has_run = true;
Running(); /* EMIT SIGNAL */
+
+ reconnect_ltc ();
+
} else {
// error << _("cannot activate JACK client") << endmsg;
}
@@ -377,31 +391,38 @@ void
AudioEngine::_connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn, void* arg)
{
AudioEngine* ae = static_cast<AudioEngine*> (arg);
+ ae->connect_callback (id_a, id_b, conn);
+}
- if (ae->port_remove_in_progress) {
+void
+AudioEngine::connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn)
+{
+ if (port_remove_in_progress) {
return;
}
- GET_PRIVATE_JACK_POINTER (ae->_jack);
+ GET_PRIVATE_JACK_POINTER (_jack);
jack_port_t* jack_port_a = jack_port_by_id (_priv_jack, id_a);
jack_port_t* jack_port_b = jack_port_by_id (_priv_jack, id_b);
boost::shared_ptr<Port> port_a;
boost::shared_ptr<Port> port_b;
+ Ports::iterator x;
+ boost::shared_ptr<Ports> pr = ports.reader ();
- boost::shared_ptr<Ports> pr = ae->ports.reader ();
- Ports::iterator i = pr->begin ();
- while (i != pr->end() && (port_a == 0 || port_b == 0)) {
- if (jack_port_a == i->second->jack_port()) {
- port_a = i->second;
- } else if (jack_port_b == i->second->jack_port()) {
- port_b = i->second;
- }
- ++i;
+
+ x = pr->find (make_port_name_relative (jack_port_name (jack_port_a)));
+ if (x != pr->end()) {
+ port_a = x->second;
+ }
+
+ x = pr->find (make_port_name_relative (jack_port_name (jack_port_b)));
+ if (x != pr->end()) {
+ port_b = x->second;
}
- ae->PortConnectedOrDisconnected (
+ PortConnectedOrDisconnected (
port_a, jack_port_name (jack_port_a),
port_b, jack_port_name (jack_port_b),
conn == 0 ? false : true
@@ -1470,6 +1491,8 @@ AudioEngine::reconnect_to_jack ()
MIDI::Manager::instance()->reconnect ();
+ reconnect_ltc ();
+
Running (); /* EMIT SIGNAL*/
start_metering_thread ();
@@ -1613,3 +1636,27 @@ AudioEngine::destroy ()
delete _instance;
_instance = 0;
}
+
+void
+AudioEngine::parameter_changed (const std::string& s)
+{
+ if (s == "ltc-source-port") {
+ reconnect_ltc ();
+ }
+
+}
+
+void
+AudioEngine::reconnect_ltc ()
+{
+ if (_ltc_input) {
+
+ string src = Config->get_ltc_source_port();
+
+ _ltc_input->disconnect_all ();
+
+ if (src != _("None") && !src.empty()) {
+ _ltc_input->connect (src);
+ }
+ }
+}
diff --git a/libs/ardour/ltc_slave.cc b/libs/ardour/ltc_slave.cc
index 292426ed04..52c49737e0 100644
--- a/libs/ardour/ltc_slave.cc
+++ b/libs/ardour/ltc_slave.cc
@@ -307,7 +307,7 @@ LTC_Slave::speed_and_position (double& speed, framepos_t& pos)
jack_default_audio_sample_t *in;
jack_latency_range_t ltc_latency;
- Port *ltcport = session.engine().ltc_input_port();
+ boost::shared_ptr<Port> ltcport = session.engine().ltc_input_port();
ltcport->get_connected_latency_range(ltc_latency, false);
in = (jack_default_audio_sample_t*) jack_port_get_buffer (ltcport->jack_port(), nframes);