summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/ardour.menus.in1
-rw-r--r--gtk2_ardour/ardour_ui.cc15
-rw-r--r--gtk2_ardour/ardour_ui.h3
-rw-r--r--gtk2_ardour/ardour_ui_dialogs.cc3
-rw-r--r--gtk2_ardour/ardour_ui_options.cc27
-rw-r--r--gtk2_ardour/audio_clock.cc38
-rw-r--r--gtk2_ardour/midi_tracer.cc32
-rw-r--r--gtk2_ardour/midi_tracer.h5
-rw-r--r--gtk2_ardour/option_editor.cc14
-rw-r--r--gtk2_ardour/option_editor.h15
-rw-r--r--gtk2_ardour/port_group.cc20
-rw-r--r--gtk2_ardour/rc_option_editor.cc118
-rw-r--r--gtk2_ardour/rc_option_editor.h6
-rw-r--r--gtk2_ardour/transport_masters_dialog.cc395
-rw-r--r--gtk2_ardour/transport_masters_dialog.h129
-rw-r--r--gtk2_ardour/wscript1
16 files changed, 655 insertions, 167 deletions
diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in
index f952a410a7..858af01943 100644
--- a/gtk2_ardour/ardour.menus.in
+++ b/gtk2_ardour/ardour.menus.in
@@ -556,6 +556,7 @@
#endif
<menuitem action='toggle-big-clock'/>
<menuitem action='toggle-big-transport'/>
+ <menuitem action='toggle-transport-masters'/>
#if 0
<menuitem action='toggle-speaker-config'/>
#endif
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index 317c5d8d13..2a24685b14 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -105,7 +105,8 @@
#include "ardour/session_state_utils.h"
#include "ardour/session_utils.h"
#include "ardour/source_factory.h"
-#include "ardour/slave.h"
+#include "ardour/transport_master.h"
+#include "ardour/transport_master_manager.h"
#include "ardour/system_exec.h"
#include "ardour/track.h"
#include "ardour/vca_manager.h"
@@ -185,6 +186,7 @@ typedef uint64_t microseconds_t;
#include "time_axis_view_item.h"
#include "time_info_box.h"
#include "timers.h"
+#include "transport_masters_dialog.h"
#include "utils.h"
#include "utils_videotl.h"
#include "video_server_dialog.h"
@@ -314,6 +316,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
, export_video_dialog (X_("video-export"), _("Video Export Dialog"))
, lua_script_window (X_("script-manager"), _("Script Manager"))
, idleometer (X_("idle-o-meter"), _("Idle'o'Meter"))
+ , transport_masters_dialog (X_("transport-masters"), _("Transport Masters"))
, session_option_editor (X_("session-options-editor"), _("Properties"), boost::bind (&ARDOUR_UI::create_session_option_editor, this))
, add_video_dialog (X_("add-video"), _("Add Video"), boost::bind (&ARDOUR_UI::create_add_video_dialog, this))
, bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this))
@@ -473,6 +476,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
export_video_dialog.set_state (*ui_xml, 0);
lua_script_window.set_state (*ui_xml, 0);
idleometer.set_state (*ui_xml, 0);
+ transport_masters_dialog.set_state (*ui_xml, 0);
}
/* Separate windows */
@@ -494,6 +498,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
WM::Manager::instance().register_window (&audio_port_matrix);
WM::Manager::instance().register_window (&midi_port_matrix);
WM::Manager::instance().register_window (&idleometer);
+ WM::Manager::instance().register_window (&transport_masters_dialog);
/* do not retain position for add route dialog */
add_route_dialog.set_state_mask (WindowProxy::Size);
@@ -1801,11 +1806,11 @@ ARDOUR_UI::update_timecode_format ()
if (_session) {
bool matching;
- TimecodeSlave* tcslave;
- SyncSource sync_src = Config->get_sync_source();
+ boost::shared_ptr<TimecodeTransportMaster> tcmaster;
+ boost::shared_ptr<TransportMaster> tm = TransportMasterManager::instance().current();
- if ((sync_src == LTC || sync_src == MTC) && (tcslave = dynamic_cast<TimecodeSlave*>(_session->slave())) != 0) {
- matching = (tcslave->apparent_timecode_format() == _session->config.get_timecode_format());
+ if ((tm->type() == LTC || tm->type() == MTC) && (tcmaster = boost::dynamic_pointer_cast<TimecodeTransportMaster>(tm)) != 0) {
+ matching = (tcmaster->apparent_timecode_format() == _session->config.get_timecode_format());
} else {
matching = true;
}
diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h
index 0cf7c58815..a0b0b078b1 100644
--- a/gtk2_ardour/ardour_ui.h
+++ b/gtk2_ardour/ardour_ui.h
@@ -101,6 +101,7 @@
#include "route_params_ui.h"
#include "session_option_editor.h"
#include "speaker_dialog.h"
+#include "transport_masters_dialog.h"
#else
class About;
class AddRouteDialog;
@@ -119,6 +120,7 @@ class SessionOptionEditor;
class SpeakerDialog;
class GlobalPortMatrixWindow;
class IdleOMeter;
+class TransportMastersDialog;
#endif
class VideoTimeLine;
@@ -680,6 +682,7 @@ private:
WM::Proxy<ExportVideoDialog> export_video_dialog;
WM::Proxy<LuaScriptManager> lua_script_window;
WM::Proxy<IdleOMeter> idleometer;
+ WM::Proxy<TransportMastersDialog> transport_masters_dialog;
/* Windows/Dialogs that require a creator method */
diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc
index 931e7a5a50..b91470a145 100644
--- a/gtk2_ardour/ardour_ui_dialogs.cc
+++ b/gtk2_ardour/ardour_ui_dialogs.cc
@@ -72,6 +72,7 @@
#include "sfdb_ui.h"
#include "time_info_box.h"
#include "timers.h"
+#include "transport_masters_dialog.h"
#include "pbd/i18n.h"
@@ -127,6 +128,8 @@ ARDOUR_UI::set_session (Session *s)
big_clock->set_session (s);
video_timeline->set_session (s);
lua_script_window->set_session (s);
+ transport_masters_dialog->set_session (s);
+ rc_option_editor->set_session (s);
/* sensitize menu bar options that are now valid */
diff --git a/gtk2_ardour/ardour_ui_options.cc b/gtk2_ardour/ardour_ui_options.cc
index 15d9d560c5..3fec8c0be4 100644
--- a/gtk2_ardour/ardour_ui_options.cc
+++ b/gtk2_ardour/ardour_ui_options.cc
@@ -68,7 +68,7 @@ when the pull up/down setting is non-zero."));
* This is a UI limitation, imposed by audio-clock and
* status displays which combine RC-config & session-properties.
*
- * Notficy RCOptionEditor by emitting a signal if the active
+ * Notify RCOptionEditor by emitting a signal if the active
* status changed:
*/
Config->ParameterChanged("sync-source");
@@ -349,6 +349,8 @@ ARDOUR_UI::parameter_changed (std::string p)
{
if (p == "external-sync") {
+ /* session parameter */
+
ActionManager::map_some_state ("Transport", "ToggleExternalSync", sigc::mem_fun (_session->config, &SessionConfiguration::get_external_sync));
if (!_session->config.get_external_sync()) {
@@ -357,19 +359,27 @@ ARDOUR_UI::parameter_changed (std::string p)
ActionManager::get_action ("Transport", "ToggleAutoReturn")->set_sensitive (true);
ActionManager::get_action ("Transport", "ToggleFollowEdits")->set_sensitive (true);
} else {
- sync_button.set_text (sync_source_to_string (Config->get_sync_source(), true));
- if (_session && _session->locations()->auto_loop_location()) {
- // disable looping with external sync.
- // This is not necessary because session-transport ignores the loop-state,
- // but makes it clear to the user that it's disabled.
- _session->request_play_loop (false, false);
- }
/* XXX we need to make sure that auto-play is off as well as insensitive */
ActionManager::get_action ("Transport", "ToggleAutoPlay")->set_sensitive (false);
ActionManager::get_action ("Transport", "ToggleAutoReturn")->set_sensitive (false);
ActionManager::get_action ("Transport", "ToggleFollowEdits")->set_sensitive (false);
}
+ } else if (p == "sync-source") {
+
+ /* app parameter (RC config) */
+
+ if (_session) {
+ if (!_session->config.get_external_sync()) {
+ sync_button.set_text (S_("SyncSource|Int."));
+ } else {
+ sync_button.set_text (sync_source_to_string (Config->get_sync_source(), true));
+ }
+ } else {
+ /* changing sync source without a session is unlikely/impossible , except during startup */
+ sync_button.set_text (sync_source_to_string (Config->get_sync_source(), true));
+ }
+
} else if (p == "follow-edits") {
ActionManager::map_some_state ("Transport", "ToggleFollowEdits", &UIConfiguration::get_follow_edits);
@@ -598,4 +608,3 @@ ARDOUR_UI::synchronize_sync_source_and_video_pullup ()
}
}
-
diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc
index 6a7733ae5f..9bc7128ab2 100644
--- a/gtk2_ardour/audio_clock.cc
+++ b/gtk2_ardour/audio_clock.cc
@@ -34,7 +34,7 @@
#include "ardour/profile.h"
#include "ardour/lmath.h"
#include "ardour/session.h"
-#include "ardour/slave.h"
+#include "ardour/transport_master.h"
#include "ardour/tempo.h"
#include "ardour/types.h"
@@ -938,20 +938,21 @@ AudioClock::set_slave_info ()
return;
}
- SyncSource sync_src = Config->get_sync_source();
+ const SyncSource sync_src = Config->get_sync_source();
- if (_session->config.get_external_sync()) {
- Slave* slave = _session->slave();
+ if (_session->transport_master_is_external()) {
- switch (sync_src) {
+ boost::shared_ptr<TransportMaster> tm = _session->transport_master();
+
+ switch (tm->type()) {
case Engine:
- _left_btn.set_text (sync_source_to_string (sync_src, true), true);
+ _left_btn.set_text (tm->name(), true);
_right_btn.set_text ("", true);
break;
case MIDIClock:
- if (slave) {
- _left_btn.set_text (sync_source_to_string (sync_src, true), true);
- _right_btn.set_text (slave->approximate_current_delta (), true);
+ if (tm) {
+ _left_btn.set_text (sync_source_to_string (tm->type(), true), true);
+ _right_btn.set_text (tm->delta_string (), true);
} else {
_left_btn.set_text (_("--pending--"), true);
_right_btn.set_text ("", true);
@@ -959,17 +960,17 @@ AudioClock::set_slave_info ()
break;
case LTC:
case MTC:
- if (slave) {
+ if (tm) {
bool matching;
- TimecodeSlave* tcslave;
- if ((tcslave = dynamic_cast<TimecodeSlave*>(_session->slave())) != 0) {
- matching = (tcslave->apparent_timecode_format() == _session->config.get_timecode_format());
+ boost::shared_ptr<TimecodeTransportMaster> tcmaster;
+ if ((tcmaster = boost::dynamic_pointer_cast<TimecodeTransportMaster>(tm)) != 0) {
+ matching = (tcmaster->apparent_timecode_format() == _session->config.get_timecode_format());
_left_btn.set_text (string_compose ("%1<span face=\"monospace\" foreground=\"%3\">%2</span>",
- sync_source_to_string(sync_src, true)[0],
- dynamic_cast<TimecodeSlave*>(slave)->approximate_current_position (),
- matching ? "#66ff66" : "#ff3333"
+ sync_source_to_string(tm->type(), true)[0],
+ tcmaster->position_string (),
+ matching ? "#66ff66" : "#ff3333"
), true);
- _right_btn.set_text (slave->approximate_current_delta (), true);
+ _right_btn.set_text (tm->delta_string (), true);
}
} else {
_left_btn.set_text (_("--pending--"), true);
@@ -978,8 +979,7 @@ AudioClock::set_slave_info ()
break;
}
} else {
- _left_btn.set_text (string_compose ("%1/%2",
- _("INT"), sync_source_to_string(sync_src, true)), true);
+ _left_btn.set_text (string_compose ("%1/%2", _("INT"), sync_source_to_string (sync_src, true)), true);
_right_btn.set_text ("", true);
}
}
diff --git a/gtk2_ardour/midi_tracer.cc b/gtk2_ardour/midi_tracer.cc
index df99afbad8..7750d65caf 100644
--- a/gtk2_ardour/midi_tracer.cc
+++ b/gtk2_ardour/midi_tracer.cc
@@ -46,6 +46,7 @@ MidiTracer::MidiTracer ()
, line_count_adjustment (200, 1, 2000, 1, 10)
, line_count_spinner (line_count_adjustment)
, line_count_label (_("Line history: "))
+ , _last_receipt (0)
, autoscroll (true)
, show_hex (true)
, show_delta_time (false)
@@ -60,9 +61,6 @@ MidiTracer::MidiTracer ()
ARDOUR::AudioEngine::instance()->PortRegisteredOrUnregistered.connect
(_manager_connection, invalidator (*this), boost::bind (&MidiTracer::ports_changed, this), gui_context());
- _last_receipt.tv_sec = 0;
- _last_receipt.tv_usec = 0;
-
VBox* vbox = manage (new VBox);
vbox->set_spacing (4);
@@ -121,7 +119,6 @@ MidiTracer::MidiTracer ()
port_changed ();
}
-
MidiTracer::~MidiTracer()
{
}
@@ -178,13 +175,13 @@ MidiTracer::port_changed ()
boost::shared_ptr<ARDOUR::MidiPort> mp = boost::dynamic_pointer_cast<ARDOUR::MidiPort> (p);
if (mp) {
- mp->self_parser().any.connect_same_thread (_parser_connection, boost::bind (&MidiTracer::tracer, this, _1, _2, _3));
- mp->set_trace_on (true);
+ my_parser.any.connect_same_thread (_parser_connection, boost::bind (&MidiTracer::tracer, this, _1, _2, _3, _4));
+ mp->set_trace (&my_parser);
traced_port = mp;
}
} else {
- async->parser()->any.connect_same_thread (_parser_connection, boost::bind (&MidiTracer::tracer, this, _1, _2, _3));
+ async->parser()->any.connect_same_thread (_parser_connection, boost::bind (&MidiTracer::tracer, this, _1, _2, _3, _4));
}
}
@@ -194,40 +191,33 @@ MidiTracer::disconnect ()
_parser_connection.disconnect ();
if (traced_port) {
- traced_port->set_trace_on (false);
+ traced_port->set_trace (0);
traced_port.reset ();
}
}
void
-MidiTracer::tracer (Parser&, byte* msg, size_t len)
+MidiTracer::tracer (Parser&, byte* msg, size_t len, samplecnt_t now)
{
stringstream ss;
- struct timeval tv;
char* buf;
- struct tm now;
size_t bufsize;
size_t s;
- gettimeofday (&tv, 0);
+ std::cerr << "tracer msg " << len << " bytes, first = " << hex << (int) msg[0] << dec << std::endl;
buf = (char *) buffer_pool.alloc ();
bufsize = buffer_size;
- if (_last_receipt.tv_sec != 0 && show_delta_time) {
- struct timeval delta;
- timersub (&tv, &_last_receipt, &delta);
- s = snprintf (buf, bufsize, "+%02" PRId64 ":%06" PRId64, (int64_t) delta.tv_sec, (int64_t) delta.tv_usec);
+ if (_last_receipt != 0 && show_delta_time) {
+ s = snprintf (buf, bufsize, "+%12ld", now - _last_receipt);
bufsize -= s;
} else {
- localtime_r ((const time_t*)&tv.tv_sec, &now);
- s = strftime (buf, bufsize, "%H:%M:%S", &now);
- bufsize -= s;
- s += snprintf (&buf[s], bufsize, ".%06" PRId64, (int64_t) tv.tv_usec);
+ s = snprintf (buf, bufsize, "%12ld", now);
bufsize -= s;
}
- _last_receipt = tv;
+ _last_receipt = now;
switch ((eventType) msg[0]&0xf0) {
case off:
diff --git a/gtk2_ardour/midi_tracer.h b/gtk2_ardour/midi_tracer.h
index a221152cd7..83e99ef979 100644
--- a/gtk2_ardour/midi_tracer.h
+++ b/gtk2_ardour/midi_tracer.h
@@ -56,7 +56,7 @@ private:
Gtk::SpinButton line_count_spinner;
Gtk::Label line_count_label;
Gtk::HBox line_count_box;
- struct timeval _last_receipt;
+ MIDI::samplecnt_t _last_receipt;
bool autoscroll;
bool show_hex;
@@ -72,7 +72,7 @@ private:
Pool buffer_pool;
static const size_t buffer_size = 256;
- void tracer (MIDI::Parser&, MIDI::byte*, size_t);
+ void tracer (MIDI::Parser&, MIDI::byte*, size_t, MIDI::samplecnt_t);
void update ();
Gtk::CheckButton autoscroll_button;
@@ -91,6 +91,7 @@ private:
void disconnect ();
PBD::ScopedConnection _parser_connection;
PBD::ScopedConnection _manager_connection;
+ MIDI::Parser my_parser;
boost::shared_ptr<ARDOUR::MidiPort> traced_port;
};
diff --git a/gtk2_ardour/option_editor.cc b/gtk2_ardour/option_editor.cc
index 97912eab4c..b685e78947 100644
--- a/gtk2_ardour/option_editor.cc
+++ b/gtk2_ardour/option_editor.cc
@@ -608,6 +608,20 @@ ClockOption::set_session (Session* s)
/*--------------------------*/
+WidgetOption::WidgetOption (string const & i, string const & n, Gtk::Widget& w)
+ : Option (i, n)
+ , _widget (&w)
+{
+}
+
+void
+WidgetOption::add_to_page (OptionEditorPage* p)
+{
+ add_widget_to_page (p, _widget);
+}
+
+/*--------------------------*/
+
OptionEditorPage::OptionEditorPage ()
: table (1, 3)
{
diff --git a/gtk2_ardour/option_editor.h b/gtk2_ardour/option_editor.h
index 055ee9b8eb..132d260c05 100644
--- a/gtk2_ardour/option_editor.h
+++ b/gtk2_ardour/option_editor.h
@@ -558,6 +558,21 @@ private:
sigc::slot<bool, ARDOUR::gain_t> _set;
};
+class WidgetOption : public Option
+{
+ public:
+ WidgetOption (std::string const & i, std::string const & n, Gtk::Widget& w);
+
+ void add_to_page (OptionEditorPage*);
+ void parameter_changed (std::string const &) {}
+ void set_state_from_config () {}
+
+ Gtk::Widget& tip_widget() { return *_widget; }
+
+ private:
+ Gtk::Widget* _widget;
+};
+
class ClockOption : public Option
{
public:
diff --git a/gtk2_ardour/port_group.cc b/gtk2_ardour/port_group.cc
index 63291498e1..12af044d0b 100644
--- a/gtk2_ardour/port_group.cc
+++ b/gtk2_ardour/port_group.cc
@@ -436,9 +436,10 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
ltc->add_channel (_("LTC Out"), DataType::AUDIO, session->engine().make_port_name_non_relative (session->ltc_output_port()->name()));
program->add_bundle (ltc);
} else {
- boost::shared_ptr<Bundle> ltc (new Bundle (_("LTC In"), inputs));
- ltc->add_channel (_("LTC In"), DataType::AUDIO, session->engine().make_port_name_non_relative (session->ltc_input_port()->name()));
- program->add_bundle (ltc);
+ // XXX TRANSPORTMASTERS
+ //boost::shared_ptr<Bundle> ltc (new Bundle (_("LTC In"), inputs));
+ // ltc->add_channel (_("LTC In"), DataType::AUDIO, session->engine().make_port_name_non_relative (session->ltc_input_port()->name()));
+ // program->add_bundle (ltc);
}
}
@@ -470,12 +471,13 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
AudioEngine* ae = AudioEngine::instance();
if (inputs) {
- sync->add_channel (
- _("MTC in"), DataType::MIDI, ae->make_port_name_non_relative (session->mtc_input_port()->name())
- );
- sync->add_channel (
- _("MIDI clock in"), DataType::MIDI, ae->make_port_name_non_relative (session->midi_clock_input_port()->name())
- );
+ // XXX TRANSPORTMASTER
+ // sync->add_channel (
+ // _("MTC in"), DataType::MIDI, ae->make_port_name_non_relative (session->mtc_input_port()->name())
+ // );
+ // sync->add_channel (
+ // _("MIDI clock in"), DataType::MIDI, ae->make_port_name_non_relative (session->midi_clock_input_port()->name())
+ //);
sync->add_channel (
_("MMC in"), DataType::MIDI, ae->make_port_name_non_relative (session->mmc_input_port()->name())
);
diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc
index 8cca0227f8..4208e69247 100644
--- a/gtk2_ardour/rc_option_editor.cc
+++ b/gtk2_ardour/rc_option_editor.cc
@@ -43,12 +43,14 @@
#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/dB.h"
#include "ardour/port_manager.h"
#include "ardour/plugin_manager.h"
+#include "ardour/profile.h"
+#include "ardour/rc_configuration.h"
+#include "ardour/transport_master_manager.h"
+
#include "control_protocol/control_protocol.h"
#include "waveview/wave_view.h"
@@ -66,6 +68,7 @@
#include "midi_tracer.h"
#include "rc_option_editor.h"
#include "sfdb_ui.h"
+#include "transport_masters_dialog.h"
#include "ui_config.h"
#include "utils.h"
@@ -2109,14 +2112,7 @@ MidiPortOptions::pretty_name_edit (std::string const & path, string const & new_
return;
}
- boost::shared_ptr<ARDOUR::AudioBackend> 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;
- }
- }
+ AudioEngine::instance()->set_midi_port_pretty_name ((*iter)[midi_port_columns.name], new_text);
}
/*============*/
@@ -3213,16 +3209,9 @@ RCOptionEditor::RCOptionEditor ()
/* SYNC */
- add_option (_("Sync"), new OptionEditorHeading (_("External Synchronization")));
-
- _sync_source = new ComboOption<SyncSource> (
- "sync-source",
- _("External timecode source"),
- sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
- sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
- );
+ add_option (_("Sync"), new OptionEditorHeading (_("Transport Masters")));
- add_option (_("Sync"), _sync_source);
+ add_option (_("Sync"), new WidgetOption (X_("foo"), X_("Transport Masters"), _transport_masters_widget));
_sync_framerate = new BoolOption (
"timecode-sync-frame-rate",
@@ -3240,45 +3229,6 @@ RCOptionEditor::RCOptionEditor ()
add_option (_("Sync"), _sync_framerate);
- _sync_genlock = new BoolOption (
- "timecode-source-is-synced",
- _("Sync-lock timecode to clock (disable drift compensation)"),
- sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
- sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
- );
- Gtkmm2ext::UI::instance()->set_tip
- (_sync_genlock->tip_widget(),
- string_compose (_("<b>When enabled</b> %1 will never varispeed when slaved to external timecode. "
- "Sync Lock indicates that the selected external timecode source shares clock-sync "
- "(Black &amp; Burst, Wordclock, etc) with the audio interface. "
- "This option disables drift compensation. The transport speed is fixed at 1.0. "
- "Vari-speed LTC will be ignored and cause drift."
- "\n\n"
- "<b>When disabled</b> %1 will compensate for potential drift, regardless if the "
- "timecode sources shares clock sync."
- ), PROGRAM_NAME));
-
-
- add_option (_("Sync"), _sync_genlock);
-
- _sync_source_2997 = new BoolOption (
- "timecode-source-2997",
- _("Lock to 29.9700 fps instead of 30000/1001"),
- sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
- sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
- );
- Gtkmm2ext::UI::instance()->set_tip
- (_sync_source_2997->tip_widget(),
- _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
- "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
- "drop-sample timecode has an accumulated error of -86ms over a 24-hour period.\n"
- "Drop-sample timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
- "That is not the actual rate. However, some vendors use that rate - despite it being against the specs - "
- "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
- ));
-
- add_option (_("Sync"), _sync_source_2997);
-
add_option (_("Sync/LTC"), new OptionEditorHeading (_("Linear Timecode (LTC) Reader")));
_ltc_port = new ComboStringOption (
@@ -3293,9 +3243,6 @@ RCOptionEditor::RCOptionEditor ()
AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
_ltc_port->set_popdown_strings (physical_inputs);
- populate_sync_options ();
- AudioEngine::instance()->Running.connect (engine_started_connection, MISSING_INVALIDATOR, boost::bind (&RCOptionEditor::populate_sync_options, this), gui_context());
-
add_option (_("Sync/LTC"), _ltc_port);
add_option (_("Sync/LTC"), new OptionEditorHeading (_("Linear Timecode (LTC) Generator")));
@@ -4059,6 +4006,13 @@ These settings will only take effect after %1 is restarted.\n\
}
void
+RCOptionEditor::set_session (Session *s)
+{
+ SessionHandlePtr::set_session (s);
+ _transport_masters_widget.set_session (s);
+}
+
+void
RCOptionEditor::parameter_changed (string const & p)
{
OptionEditor::parameter_changed (p);
@@ -4072,22 +4026,11 @@ RCOptionEditor::parameter_changed (string const & p)
_solo_control_is_listen_control->set_sensitive (s);
_listen_position->set_sensitive (s);
} else if (p == "sync-source") {
- _sync_source->set_sensitive (true);
- if (_session) {
- _sync_source->set_sensitive (!_session->config.get_external_sync());
- }
- switch(Config->get_sync_source()) {
- case ARDOUR::MTC:
- case ARDOUR::LTC:
- _sync_genlock->set_sensitive (true);
+ boost::shared_ptr<TransportMaster> tm (TransportMasterManager::instance().current());
+ if (boost::dynamic_pointer_cast<TimecodeTransportMaster> (tm)) {
_sync_framerate->set_sensitive (true);
- _sync_source_2997->set_sensitive (true);
- break;
- default:
- _sync_genlock->set_sensitive (false);
+ } else {
_sync_framerate->set_sensitive (false);
- _sync_source_2997->set_sensitive (false);
- break;
}
} else if (p == "send-ltc") {
bool const s = Config->get_send_ltc ();
@@ -4164,29 +4107,6 @@ void RCOptionEditor::edit_vst_path () {
delete pd;
}
-
-void
-RCOptionEditor::populate_sync_options ()
-{
- vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
-
- _sync_source->clear ();
-
- for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
- _sync_source->add (*i, sync_source_to_string (*i));
- }
-
- if (sync_opts.empty()) {
- _sync_source->set_sensitive(false);
- } else {
- if (std::find(sync_opts.begin(), sync_opts.end(), _rc_config->get_sync_source()) == sync_opts.end()) {
- _rc_config->set_sync_source(sync_opts.front());
- }
- }
-
- parameter_changed ("sync-source");
-}
-
Gtk::Window*
RCOptionEditor::use_own_window (bool and_fill_it)
{
diff --git a/gtk2_ardour/rc_option_editor.h b/gtk2_ardour/rc_option_editor.h
index 3a3283e86c..27d261ba09 100644
--- a/gtk2_ardour/rc_option_editor.h
+++ b/gtk2_ardour/rc_option_editor.h
@@ -24,6 +24,7 @@
#include "option_editor.h"
#include "visibility_group.h"
+#include "transport_masters_dialog.h"
/** @file rc_option_editor.h
* @brief Editing of options which are obtained from and written back to one of the .rc files.
@@ -39,7 +40,7 @@ class RCOptionEditor : public OptionEditorContainer, public ARDOUR::SessionHandl
public:
RCOptionEditor ();
- void populate_sync_options ();
+ void set_session (ARDOUR::Session*);
Gtk::Window* use_own_window (bool and_fill_it);
XMLNode& get_state ();
@@ -53,13 +54,12 @@ private:
VisibilityGroup _mixer_strip_visibility;
ComboOption<ARDOUR::SyncSource>* _sync_source;
BoolOption* _sync_framerate;
- BoolOption* _sync_genlock;
- BoolOption* _sync_source_2997;
ComboStringOption* _ltc_port;
HSliderOption* _ltc_volume_slider;
Gtk::Adjustment* _ltc_volume_adjustment;
BoolOption* _ltc_send_continuously;
BoolOption* _plugin_prefer_inline;
+ TransportMastersWidget _transport_masters_widget;
PBD::ScopedConnection parameter_change_connection;
PBD::ScopedConnection engine_started_connection;
diff --git a/gtk2_ardour/transport_masters_dialog.cc b/gtk2_ardour/transport_masters_dialog.cc
new file mode 100644
index 0000000000..527717c264
--- /dev/null
+++ b/gtk2_ardour/transport_masters_dialog.cc
@@ -0,0 +1,395 @@
+/*
+ Copyright (C) 2018 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.
+
+*/
+
+#include "pbd/enumwriter.h"
+#include "pbd/i18n.h"
+
+#include "temporal/time.h"
+
+#include "ardour/audioengine.h"
+#include "ardour/session.h"
+#include "ardour/transport_master.h"
+#include "ardour/transport_master_manager.h"
+
+#include "widgets/tooltips.h"
+
+#include "gtkmm2ext/utils.h"
+#include "gtkmm2ext/gui_thread.h"
+
+#include "ardour_ui.h"
+#include "transport_masters_dialog.h"
+
+using namespace std;
+using namespace Gtk;
+using namespace Gtkmm2ext;
+using namespace ARDOUR;
+using namespace PBD;
+using namespace ArdourWidgets;
+
+TransportMastersWidget::TransportMastersWidget ()
+ : table (4, 9)
+{
+ pack_start (table, PACK_EXPAND_WIDGET, 12);
+
+ col_title[0].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Name")));
+ col_title[0].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Name")));
+ col_title[1].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Type")));
+ col_title[2].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Format")));
+ col_title[3].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Current")));
+ col_title[4].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Timestamp")));
+ col_title[5].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Delta")));
+ col_title[6].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Collect")));
+ col_title[7].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Use")));
+ col_title[8].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Data Source")));
+ col_title[9].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Accept")));
+ col_title[10].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Clock Synced")));
+ col_title[11].set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("29.97/30")));
+
+ set_tooltip (col_title[11], _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
+ "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
+ "drop-sample timecode has an accumulated error of -86ms over a 24-hour period.\n"
+ "Drop-sample timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
+ "That is not the actual rate. However, some vendors use that rate - despite it being against the specs - "
+ "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
+ ));
+
+
+ table.set_spacings (6);
+
+ TransportMasterManager::instance().CurrentChanged.connect (current_connection, invalidator (*this), boost::bind (&TransportMastersWidget::current_changed, this, _1, _2), gui_context());
+
+ rebuild ();
+}
+
+TransportMastersWidget::~TransportMastersWidget ()
+{
+ for (vector<Row*>::iterator r = rows.begin(); r != rows.end(); ++r) {
+ delete *r;
+ }
+}
+
+void
+TransportMastersWidget::current_changed (boost::shared_ptr<TransportMaster> old_master, boost::shared_ptr<TransportMaster> new_master)
+{
+ cerr << "master changed to " << new_master << endl;
+}
+
+void
+TransportMastersWidget::rebuild ()
+{
+ TransportMasterManager::TransportMasters const & masters (TransportMasterManager::instance().transport_masters());
+
+ container_clear (table);
+
+ for (vector<Row*>::iterator r = rows.begin(); r != rows.end(); ++r) {
+ delete *r;
+ }
+
+ rows.clear ();
+ table.resize (masters.size()+1, 12);
+
+ table.attach (col_title[0], 0, 1, 0, 1);
+ table.attach (col_title[1], 1, 2, 0, 1);
+ table.attach (col_title[2], 2, 3, 0, 1);
+ table.attach (col_title[3], 3, 4, 0, 1);
+ table.attach (col_title[4], 4, 5, 0, 1);
+ table.attach (col_title[5], 5, 6, 0, 1);
+ table.attach (col_title[6], 6, 7, 0, 1);
+ table.attach (col_title[7], 7, 8, 0, 1);
+ table.attach (col_title[8], 8, 9, 0, 1);
+ table.attach (col_title[9], 9, 10, 0, 1);
+ table.attach (col_title[10], 10, 11, 0, 1);
+ table.attach (col_title[11], 11, 12, 0, 1);
+
+ uint32_t n = 1;
+
+ for (TransportMasterManager::TransportMasters::const_iterator m = masters.begin(); m != masters.end(); ++m, ++n) {
+
+ Row* r = new Row;
+ rows.push_back (r);
+
+ r->tm = *m;
+ r->label.set_text ((*m)->name());
+ r->type.set_text (enum_2_string ((*m)->type()));
+
+ r->use_button.set_group (use_button_group);
+
+ if (TransportMasterManager::instance().current() == r->tm) {
+ r->use_button.set_active (true);
+ }
+
+ table.attach (r->type, 0, 1, n, n+1);
+ table.attach (r->label, 1, 2, n, n+1);
+ table.attach (r->format, 2, 3, n, n+1);
+ table.attach (r->current, 3, 4, n, n+1);
+ table.attach (r->timestamp, 4, 5, n, n+1);
+ table.attach (r->delta, 5, 6, n, n+1);
+ table.attach (r->collect_button, 6, 7, n, n+1);
+ table.attach (r->use_button, 7, 8, n, n+1);
+ table.attach (r->port_combo, 8, 9, n, n+1);
+ table.attach (r->request_options, 9, 10, n, n+1);
+
+ if (boost::dynamic_pointer_cast<TimecodeTransportMaster> (r->tm)) {
+ table.attach (r->sclock_synced_button, 10, 11, n, n+1);
+ r->sclock_synced_button.set_active (r->tm->sample_clock_synced());
+ r->sclock_synced_button.signal_toggled().connect (sigc::mem_fun (*r, &TransportMastersWidget::Row::sync_button_toggled));
+ table.attach (r->fps_299730_button, 11, 12, n, n+1);
+ }
+
+ r->port_combo.signal_changed().connect (sigc::mem_fun (*r, &TransportMastersWidget::Row::port_choice_changed));
+ ARDOUR::AudioEngine::instance()->PortRegisteredOrUnregistered.connect (*r, invalidator (*this), boost::bind (&TransportMastersWidget::Row::connection_handler, r), gui_context());
+
+ r->collect_button.set_active (r->tm->collect());
+
+ r->use_button.signal_toggled().connect (sigc::mem_fun (*r, &TransportMastersWidget::Row::use_button_toggled));
+ r->collect_button.signal_toggled().connect (sigc::mem_fun (*r, &TransportMastersWidget::Row::collect_button_toggled));
+ r->request_options.signal_button_press_event().connect (sigc::mem_fun (*r, &TransportMastersWidget::Row::request_option_press), false);
+
+ }
+}
+
+TransportMastersWidget::Row::Row ()
+ : request_option_menu (0)
+ , ignore_active_change (false)
+{
+}
+
+void
+TransportMastersWidget::Row::use_button_toggled ()
+{
+ if (use_button.get_active()) {
+ Config->set_sync_source (tm->type());
+ }
+}
+
+void
+TransportMastersWidget::Row::collect_button_toggled ()
+{
+ tm->set_collect (collect_button.get_active());
+}
+
+void
+TransportMastersWidget::Row::sync_button_toggled ()
+{
+ tm->set_sample_clock_synced (sclock_synced_button.get_active());
+}
+
+bool
+TransportMastersWidget::Row::request_option_press (GdkEventButton* ev)
+{
+ if (ev->button == 1) {
+ if (!request_option_menu) {
+ build_request_options ();
+ }
+ request_option_menu->popup (1, ev->time);
+ return true;
+ }
+ return false;
+}
+
+void
+TransportMastersWidget::Row::build_request_options ()
+{
+ using namespace Gtk::Menu_Helpers;
+
+ request_option_menu = manage (new Menu);
+
+ MenuList& items (request_option_menu->items());
+
+ items.push_back (CheckMenuElem (_("Accept speed-changing commands (start/stop)")));
+ CheckMenuItem* i = dynamic_cast<CheckMenuItem *> (&items.back ());
+ i->set_active (tm->request_mask() & TR_Speed);
+ items.push_back (CheckMenuElem (_("Accept locate commands")));
+ i = dynamic_cast<CheckMenuItem *> (&items.back ());
+ i->set_active (tm->request_mask() & TR_Locate);
+}
+
+void
+TransportMastersWidget::Row::connection_handler ()
+{
+}
+
+Glib::RefPtr<Gtk::ListStore>
+TransportMastersWidget::Row::build_port_list (vector<string> const & ports)
+{
+ Glib::RefPtr<Gtk::ListStore> store = ListStore::create (port_columns);
+ TreeModel::Row row;
+
+ row = *store->append ();
+ row[port_columns.full_name] = string();
+ row[port_columns.short_name] = _("Disconnected");
+
+ for (vector<string>::const_iterator p = ports.begin(); p != ports.end(); ++p) {
+
+ if (AudioEngine::instance()->port_is_mine (*p)) {
+ continue;
+ }
+
+ row = *store->append ();
+ row[port_columns.full_name] = *p;
+
+ std::string pn = ARDOUR::AudioEngine::instance()->get_pretty_name_by_name (*p);
+ if (pn.empty ()) {
+ pn = (*p).substr ((*p).find (':') + 1);
+ }
+ row[port_columns.short_name] = pn;
+ }
+
+ return store;
+}
+
+void
+TransportMastersWidget::Row::populate_port_combo ()
+{
+ if (!tm->port()) {
+ port_combo.hide ();
+ return;
+ } else {
+ port_combo.show ();
+ }
+
+ vector<string> inputs;
+
+ if (tm->port()->type() == DataType::MIDI) {
+ ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsOutput), inputs);
+ } else {
+ ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::AUDIO, ARDOUR::PortFlags (ARDOUR::IsOutput), inputs);
+ }
+
+ Glib::RefPtr<Gtk::ListStore> input = build_port_list (inputs);
+ bool input_found = false;
+ int n;
+
+ port_combo.set_model (input);
+
+ Gtk::TreeModel::Children children = input->children();
+ Gtk::TreeModel::Children::iterator i;
+ i = children.begin();
+ ++i; /* skip "Disconnected" */
+
+
+ for (n = 1; i != children.end(); ++i, ++n) {
+ string port_name = (*i)[port_columns.full_name];
+ if (tm->port()->connected_to (port_name)) {
+ port_combo.set_active (n);
+ input_found = true;
+ break;
+ }
+ }
+
+ if (!input_found) {
+ port_combo.set_active (0); /* disconnected */
+ }
+}
+
+void
+TransportMastersWidget::Row::port_choice_changed ()
+{
+ if (ignore_active_change) {
+ return;
+ }
+
+ TreeModel::iterator active = port_combo.get_active ();
+ string new_port = (*active)[port_columns.full_name];
+
+ if (new_port.empty()) {
+ tm->port()->disconnect_all ();
+ return;
+ }
+
+ if (!tm->port()->connected_to (new_port)) {
+ tm->port()->disconnect_all ();
+ tm->port()->connect (new_port);
+ }
+}
+
+void
+TransportMastersWidget::Row::update (Session* s, samplepos_t now)
+{
+ using namespace Timecode;
+
+ samplepos_t pos;
+ double speed;
+ stringstream ss;
+ Time t;
+ boost::shared_ptr<TimecodeTransportMaster> ttm;
+ boost::shared_ptr<MIDIClock_TransportMaster> mtm;
+
+ if (s) {
+
+ if (tm->speed_and_position (speed, pos, now)) {
+
+ sample_to_timecode (pos, t, false, false, 25, false, AudioEngine::instance()->sample_rate(), 100, false, 0);
+
+ if ((ttm = boost::dynamic_pointer_cast<TimecodeTransportMaster> (tm))) {
+ format.set_text (timecode_format_name (ttm->apparent_timecode_format()));
+ } else if ((mtm = boost::dynamic_pointer_cast<MIDIClock_TransportMaster> (tm))) {
+ char buf[8];
+ snprintf (buf, sizeof (buf), "%.1f", mtm->bpm());
+ format.set_text (buf);
+ } else {
+ format.set_text ("");
+ }
+ current.set_text (Timecode::timecode_format_time (t));
+ timestamp.set_markup (tm->position_string());
+ delta.set_markup (tm->delta_string ());
+
+ }
+ }
+
+ populate_port_combo ();
+}
+
+void
+TransportMastersWidget::update (samplepos_t audible)
+{
+ samplepos_t now = AudioEngine::instance()->sample_time ();
+
+ for (vector<Row*>::iterator r = rows.begin(); r != rows.end(); ++r) {
+ (*r)->update (_session, now);
+ }
+}
+
+void
+TransportMastersWidget::on_map ()
+{
+ update_connection = ARDOUR_UI::Clock.connect (sigc::mem_fun (*this, &TransportMastersWidget::update));
+ Gtk::VBox::on_map ();
+}
+
+void
+TransportMastersWidget::on_unmap ()
+{
+ update_connection.disconnect ();
+ Gtk::VBox::on_unmap ();
+}
+
+TransportMastersDialog::TransportMastersDialog ()
+ : ArdourDialog (_("Transport Masters"))
+{
+ get_vbox()->pack_start (w);
+ w.show ();
+}
+
+void
+TransportMastersDialog::set_session (ARDOUR::Session* s)
+{
+ ArdourDialog::set_session (s);
+ w.set_session (s);
+}
diff --git a/gtk2_ardour/transport_masters_dialog.h b/gtk2_ardour/transport_masters_dialog.h
new file mode 100644
index 0000000000..838e021a5a
--- /dev/null
+++ b/gtk2_ardour/transport_masters_dialog.h
@@ -0,0 +1,129 @@
+/*
+ Copyright (C) 2018 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.
+
+*/
+
+#ifndef __ardour_gtk_transport_masters_dialog_h__
+#define __ardour_gtk_transport_masters_dialog_h__
+
+#include <vector>
+#include <string>
+
+#include <gtkmm/button.h>
+#include <gtkmm/radiobutton.h>
+#include <gtkmm/label.h>
+#include <gtkmm/table.h>
+#include <gtkmm/treestore.h>
+
+#include "ardour_dialog.h"
+
+namespace Gtk {
+ class Menu;
+}
+
+namespace ARDOUR {
+ class TransportMaster;
+}
+
+class TransportMastersWidget : public Gtk::VBox, public ARDOUR::SessionHandlePtr
+{
+ public:
+ TransportMastersWidget ();
+ ~TransportMastersWidget ();
+
+ void update (ARDOUR::samplepos_t);
+
+ protected:
+ void on_map ();
+ void on_unmap ();
+
+ private:
+
+ struct Row : sigc::trackable, PBD::ScopedConnectionList {
+ Gtk::Label label;
+ Gtk::Label type;
+ Gtk::Label format;
+ Gtk::Label current;
+ Gtk::Label timestamp;
+ Gtk::Label delta;
+ Gtk::CheckButton collect_button;
+ Gtk::RadioButton use_button;
+ Gtk::ComboBoxText port_combo;
+ Gtk::CheckButton sclock_synced_button;
+ Gtk::CheckButton fps_299730_button;
+ Gtk::Button request_options;
+ Gtk::Menu* request_option_menu;
+
+ void build_request_options();
+
+ boost::shared_ptr<ARDOUR::TransportMaster> tm;
+
+ void update (ARDOUR::Session*, ARDOUR::samplepos_t);
+
+ Row ();
+
+ struct PortColumns : public Gtk::TreeModel::ColumnRecord {
+ PortColumns() {
+ add (short_name);
+ add (full_name);
+ }
+ Gtk::TreeModelColumn<std::string> short_name;
+ Gtk::TreeModelColumn<std::string> full_name;
+ };
+
+ PortColumns port_columns;
+
+ void populate_port_combo ();
+ Glib::RefPtr<Gtk::ListStore> build_port_list (std::vector<std::string> const & ports);
+
+ void use_button_toggled ();
+ void collect_button_toggled ();
+ void sync_button_toggled ();
+ void port_choice_changed ();
+ void connection_handler ();
+ bool request_option_press (GdkEventButton*);
+
+ bool ignore_active_change;
+ };
+
+ std::vector<Row*> rows;
+
+ Gtk::RadioButtonGroup use_button_group;
+ Gtk::Table table;
+ Gtk::Label col_title[12];
+
+ sigc::connection update_connection;
+ PBD::ScopedConnection current_connection;
+
+ void rebuild ();
+ void current_changed (boost::shared_ptr<ARDOUR::TransportMaster> old_master, boost::shared_ptr<ARDOUR::TransportMaster> new_master);
+
+};
+
+class TransportMastersDialog : public ArdourDialog
+{
+ public:
+ TransportMastersDialog ();
+
+ void set_session (ARDOUR::Session*);
+
+ private:
+ TransportMastersWidget w;
+};
+
+
+#endif /* __ardour_gtk_transport_masters_dialog_h__ */
diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript
index ad61135d32..aadf185b2a 100644
--- a/gtk2_ardour/wscript
+++ b/gtk2_ardour/wscript
@@ -262,6 +262,7 @@ gtk2_ardour_sources = [
'transform_dialog.cc',
'transport_control.cc',
'transport_control_ui.cc',
+ 'transport_masters_dialog.cc',
'transpose_dialog.cc',
'ui_config.cc',
'utils.cc',