mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-10 00:34:59 +01:00
create and manage a new config parameter that defines where LTC originates (still some tweaks to be done here and there)
git-svn-id: svn://localhost/ardour2/branches/3.0@13280 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
6ab663342d
commit
cb84e71caa
7 changed files with 154 additions and 20 deletions
|
|
@ -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
|
/** Component which provides the UI to handle a boolean option which needs
|
||||||
* to be represented as a ComboBox to be clear to the user.
|
* to be represented as a ComboBox to be clear to the user.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1068,8 +1068,23 @@ RCOptionEditor::RCOptionEditor ()
|
||||||
(_sync_genlock->tip_widget(),
|
(_sync_genlock->tip_widget(),
|
||||||
_("<b>When enabled</b> indicates that the selected external timecode source shares sync (Black & Burst, Wordclock, etc) with the audio interface"));
|
_("<b>When enabled</b> indicates that the selected external timecode source shares sync (Black & Burst, Wordclock, etc) with the audio interface"));
|
||||||
|
|
||||||
|
|
||||||
add_option (_("Transport"), _sync_genlock);
|
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");
|
parameter_changed ("sync-source");
|
||||||
|
|
||||||
/* EDITOR */
|
/* EDITOR */
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ private:
|
||||||
ComboOption<ARDOUR::SyncSource>* _sync_source;
|
ComboOption<ARDOUR::SyncSource>* _sync_source;
|
||||||
BoolOption* _sync_framerate;
|
BoolOption* _sync_framerate;
|
||||||
BoolOption* _sync_genlock;
|
BoolOption* _sync_genlock;
|
||||||
|
ComboStringOption* _ltc_port;
|
||||||
|
|
||||||
PBD::ScopedConnection parameter_change_connection;
|
PBD::ScopedConnection parameter_change_connection;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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);
|
int create_process_thread (boost::function<void()>, pthread_t*, size_t stacksize);
|
||||||
|
|
||||||
#ifdef HAVE_LTC
|
boost::shared_ptr<Port> ltc_input_port() const { return _ltc_input; }
|
||||||
Port *ltc_input_port() const { return _ltc_input; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static AudioEngine* _instance;
|
static AudioEngine* _instance;
|
||||||
|
|
@ -293,9 +291,8 @@ private:
|
||||||
Glib::Threads::Thread* m_meter_thread;
|
Glib::Threads::Thread* m_meter_thread;
|
||||||
ProcessThread* _main_thread;
|
ProcessThread* _main_thread;
|
||||||
|
|
||||||
#ifdef HAVE_LTC
|
boost::shared_ptr<Port> _ltc_input;
|
||||||
Port* _ltc_input;
|
void reconnect_ltc ();
|
||||||
#endif
|
|
||||||
|
|
||||||
SerializedRCUManager<Ports> ports;
|
SerializedRCUManager<Ports> ports;
|
||||||
|
|
||||||
|
|
@ -329,6 +326,7 @@ private:
|
||||||
int jack_bufsize_callback (pframes_t);
|
int jack_bufsize_callback (pframes_t);
|
||||||
int jack_sample_rate_callback (pframes_t);
|
int jack_sample_rate_callback (pframes_t);
|
||||||
void freewheel_callback (int);
|
void freewheel_callback (int);
|
||||||
|
void connect_callback (jack_port_id_t, jack_port_id_t, int);
|
||||||
|
|
||||||
void set_jack_callbacks ();
|
void set_jack_callbacks ();
|
||||||
|
|
||||||
|
|
@ -356,6 +354,8 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
static void* _start_process_thread (void*);
|
static void* _start_process_thread (void*);
|
||||||
|
void parameter_changed (const std::string&);
|
||||||
|
PBD::ScopedConnection config_connection;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ARDOUR
|
} // namespace ARDOUR
|
||||||
|
|
|
||||||
|
|
@ -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_sync_frame_rate, "timecode-sync-frame-rate", true)
|
||||||
CONFIG_VARIABLE (bool, timecode_source_is_synced, "timecode-source-is-synced", true)
|
CONFIG_VARIABLE (bool, timecode_source_is_synced, "timecode-source-is-synced", true)
|
||||||
CONFIG_VARIABLE (SyncSource, sync_source, "sync-source", JACK)
|
CONFIG_VARIABLE (SyncSource, sync_source, "sync-source", JACK)
|
||||||
|
CONFIG_VARIABLE (std::string, ltc_source_port, "ltc-source-port", "system:capture_1")
|
||||||
|
|
||||||
/* control surfaces */
|
/* control surfaces */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,13 +89,24 @@ AudioEngine::AudioEngine (string client_name, string session_uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
Port::set_engine (this);
|
Port::set_engine (this);
|
||||||
|
|
||||||
#ifdef HAVE_LTC
|
#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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioEngine::~AudioEngine ()
|
AudioEngine::~AudioEngine ()
|
||||||
{
|
{
|
||||||
|
config_connection.disconnect ();
|
||||||
|
|
||||||
{
|
{
|
||||||
Glib::Threads::Mutex::Lock tm (_process_lock);
|
Glib::Threads::Mutex::Lock tm (_process_lock);
|
||||||
session_removed.signal ();
|
session_removed.signal ();
|
||||||
|
|
@ -210,6 +221,9 @@ AudioEngine::start ()
|
||||||
_running = true;
|
_running = true;
|
||||||
_has_run = true;
|
_has_run = true;
|
||||||
Running(); /* EMIT SIGNAL */
|
Running(); /* EMIT SIGNAL */
|
||||||
|
|
||||||
|
reconnect_ltc ();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// error << _("cannot activate JACK client") << endmsg;
|
// 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::_connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn, void* arg)
|
||||||
{
|
{
|
||||||
AudioEngine* ae = static_cast<AudioEngine*> (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;
|
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_a = jack_port_by_id (_priv_jack, id_a);
|
||||||
jack_port_t* jack_port_b = jack_port_by_id (_priv_jack, id_b);
|
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_a;
|
||||||
boost::shared_ptr<Port> port_b;
|
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 ();
|
x = pr->find (make_port_name_relative (jack_port_name (jack_port_a)));
|
||||||
while (i != pr->end() && (port_a == 0 || port_b == 0)) {
|
if (x != pr->end()) {
|
||||||
if (jack_port_a == i->second->jack_port()) {
|
port_a = x->second;
|
||||||
port_a = i->second;
|
|
||||||
} else if (jack_port_b == i->second->jack_port()) {
|
|
||||||
port_b = i->second;
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ae->PortConnectedOrDisconnected (
|
x = pr->find (make_port_name_relative (jack_port_name (jack_port_b)));
|
||||||
|
if (x != pr->end()) {
|
||||||
|
port_b = x->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
PortConnectedOrDisconnected (
|
||||||
port_a, jack_port_name (jack_port_a),
|
port_a, jack_port_name (jack_port_a),
|
||||||
port_b, jack_port_name (jack_port_b),
|
port_b, jack_port_name (jack_port_b),
|
||||||
conn == 0 ? false : true
|
conn == 0 ? false : true
|
||||||
|
|
@ -1470,6 +1491,8 @@ AudioEngine::reconnect_to_jack ()
|
||||||
|
|
||||||
MIDI::Manager::instance()->reconnect ();
|
MIDI::Manager::instance()->reconnect ();
|
||||||
|
|
||||||
|
reconnect_ltc ();
|
||||||
|
|
||||||
Running (); /* EMIT SIGNAL*/
|
Running (); /* EMIT SIGNAL*/
|
||||||
|
|
||||||
start_metering_thread ();
|
start_metering_thread ();
|
||||||
|
|
@ -1613,3 +1636,27 @@ AudioEngine::destroy ()
|
||||||
delete _instance;
|
delete _instance;
|
||||||
_instance = 0;
|
_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -307,7 +307,7 @@ LTC_Slave::speed_and_position (double& speed, framepos_t& pos)
|
||||||
jack_default_audio_sample_t *in;
|
jack_default_audio_sample_t *in;
|
||||||
jack_latency_range_t ltc_latency;
|
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);
|
ltcport->get_connected_latency_range(ltc_latency, false);
|
||||||
in = (jack_default_audio_sample_t*) jack_port_get_buffer (ltcport->jack_port(), nframes);
|
in = (jack_default_audio_sample_t*) jack_port_get_buffer (ltcport->jack_port(), nframes);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue